LCOV - code coverage report
Current view: top level - lib_enc - ivas_masa_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 2279 2558 89.1 %
Date: 2025-05-03 01:55:50 Functions: 33 34 97.1 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdint.h>
      34             : #include <math.h>
      35             : #include "options.h"
      36             : #include "ivas_cnst.h"
      37             : #include "ivas_rom_com.h"
      38             : #include "ivas_stat_enc.h"
      39             : #include "wmc_auto.h"
      40             : #include "prot_fx.h"
      41             : #include "prot_fx_enc.h"
      42             : #include "ivas_prot_fx.h"
      43             : #include "ivas_rom_com_fx.h"
      44             : 
      45             : 
      46             : /*-----------------------------------------------------------------------*
      47             :  * Local function prototypes
      48             :  *-----------------------------------------------------------------------*/
      49             : 
      50             : static void combine_freqbands_and_subframes_fx( MASA_ENCODER_HANDLE hMasa );
      51             : 
      52             : static void find_n_largest_fx( const Word32 *input_fx, Word16 exp_input, Word16 *largestIndices, const Word16 numElements, const Word16 numLargest );
      53             : 
      54             : static void move_metadata_to_qmetadata_fx( const MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMeta );
      55             : 
      56             : static void detect_metadata_composition_fx(
      57             :     const MASA_ENCODER_HANDLE hMasa, /* i  : MASA encoder data              */
      58             :     UWord8 *joinedSubframes,         /* o  : Result of subframe composition */
      59             :     UWord8 *coherencePresent,        /* o  : Result of coherence presence   */
      60             :     UWord8 *isTwoDir                 /* o  : Result of two direction check  */
      61             : );
      62             : 
      63             : static void compensate_energy_ratios_fx( MASA_ENCODER_HANDLE hMasa );
      64             : 
      65             : static Word16 encode_lfe_to_total_energy_ratio_fx( MASA_ENCODER_HANDLE hMasa, BSTR_ENC_HANDLE hMetaData, const Word32 ivas_total_brate );
      66             : 
      67             : static void ivas_encode_masaism_metadata_fx( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMetaData, BSTR_ENC_HANDLE hMetaData, ISM_METADATA_HANDLE hIsmMeta[], const Word16 nchan_ism, const Word16 low_bitrate_mode, const Word16 omasa_nbands, const Word16 omasa_nblocks, const Word16 idx_separated_object, const Word16 ism_imp );
      68             : 
      69             : static void reduce_metadata_further_fx( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hqmetadata, const IVAS_FORMAT ivas_format );
      70             : 
      71             : static void average_masa_metadata_fx(
      72             :     MASA_METADATA_FRAME *hMeta,
      73             :     Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
      74             :     Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
      75             :     const SPHERICAL_GRID_DATA *Sph_Grid16,
      76             :     const UWord8 useSphGrid );
      77             : 
      78             : static void copy_masa_metadata_subframe_fx(
      79             :     const MASA_METADATA_HANDLE hMetaFrom, /* i  : MASA frame metdata to be copied      */
      80             :     const UWord8 sfFrom,                  /* i  : subframe index of the copy source    */
      81             :     MASA_METADATA_HANDLE hMetaTo,         /* o  : MASA frame metadata copy destination */
      82             :     const UWord8 sfTo                     /* i  : subframe index of the copy target    */
      83             : );
      84             : 
      85             : static void copy_masa_metadata_fx( const MASA_METADATA_HANDLE hMetaFrom, MASA_METADATA_HANDLE hMetaTo );
      86             : 
      87             : static UWord8 are_masa_subframes_similar_fx(
      88             :     const MASA_METADATA_HANDLE frame1, /* i  : MASA metadata frame 1                      */
      89             :     const UWord8 sf1_idx,              /* i  : index of the subframe of frame1 to inspect */
      90             :     const MASA_METADATA_HANDLE frame2, /* i  : MASA metadata frame 2                      */
      91             :     const UWord8 sf2_idx               /* i  : index of the subframe of frame2 to inspect */
      92             : );
      93             : 
      94             : static void detect_framing_async_fx(
      95             :     MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder structure */
      96             : );
      97             : 
      98             : static void masa_metadata_direction_alignment_fx( MASA_ENCODER_HANDLE hMasa );
      99             : 
     100             : 
     101             : /*-----------------------------------------------------------------------*
     102             :  * Local constants
     103             :  *-----------------------------------------------------------------------*/
     104             : 
     105             : #define LOWBITRATE_ONSET_ALPHA     0.2f /* Onset values are for processing in frames */
     106             : #define LOWBITRATE_ONSET_BETA      0.92f
     107             : #define LOWBITRATE_ONSET_GAIN      1.4f
     108             : #define LOWBITRATE_ONSET_ALPHA_Q31 429496730 /* Onset values are for processing in frames */
     109             : #define LOWBITRATE_ONSET_BETA_Q31  1975684956
     110             : #define LOWBITRATE_ONSET_GAIN_Q30  1503238554
     111             : #define LOWBITRATE_NUM_BANDS       5
     112             : 
     113             : 
     114             : /*-----------------------------------------------------------------------*
     115             :  * ivas_masa_enc_open()
     116             :  *
     117             :  * open and initialize MASA encoder
     118             :  *-----------------------------------------------------------------------*/
     119         396 : ivas_error ivas_masa_enc_open_fx(
     120             :     Encoder_Struct *st_ivas /* i/o: IVAS encoder handle          */
     121             : )
     122             : {
     123             :     Word16 i;
     124             :     MASA_ENCODER_HANDLE hMasa;
     125             :     ENCODER_CONFIG_HANDLE hEncoderConfig;
     126             :     ivas_error error;
     127             :     Word32 ism_total_brate;
     128             : 
     129         396 :     error = IVAS_ERR_OK;
     130         396 :     move32();
     131             : 
     132         396 :     IF( ( hMasa = (MASA_ENCODER_HANDLE) malloc( sizeof( MASA_ENCODER ) ) ) == NULL )
     133             :     {
     134           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA encoder\n" ) );
     135             :     }
     136             : 
     137         396 :     hEncoderConfig = st_ivas->hEncoderConfig;
     138             : 
     139         396 :     generate_gridEq_fx( &( hMasa->data.Sph_Grid16 ) );
     140             : 
     141         396 :     test();
     142         396 :     IF( EQ_32( hEncoderConfig->ivas_format, MASA_FORMAT ) || EQ_32( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) )
     143             :     {
     144         119 :         hMasa->data.num_Cldfb_instances = st_ivas->nchan_transport;
     145         119 :         move16();
     146             :     }
     147             :     ELSE
     148             :     {
     149         277 :         hMasa->data.num_Cldfb_instances = 0;
     150         277 :         move16();
     151             :     }
     152             : 
     153         603 :     FOR( i = 0; i < hMasa->data.num_Cldfb_instances; i++ )
     154             :     {
     155         207 :         IF( NE_32( ( error = openCldfb_ivas_fx( &( hMasa->data.cldfbAnaEnc[i] ), CLDFB_ANALYSIS, hEncoderConfig->input_Fs, CLDFB_PROTOTYPE_5_00MS, ENC ) ), IVAS_ERR_OK ) )
     156             :         {
     157           0 :             return error;
     158             :         }
     159             :     }
     160             : 
     161         396 :     ism_total_brate = 0;
     162         396 :     move32();
     163         396 :     test();
     164         396 :     test();
     165         396 :     test();
     166         396 :     test();
     167         396 :     IF( EQ_32( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) && st_ivas->nSCE > 0 && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) )
     168             :     {
     169         104 :         FOR( i = 0; i < st_ivas->nSCE; i++ )
     170             :         {
     171          67 :             ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[i]->element_brate );
     172             :         }
     173             :     }
     174             : 
     175         396 :     ivas_masa_set_elements_fx( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, hEncoderConfig->ivas_format, st_ivas->ism_mode, ism_total_brate );
     176             : 
     177         396 :     Copy( DirAC_block_grouping, hMasa->config.block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
     178         396 :     Copy( MASA_band_grouping_24, hMasa->config.band_grouping, MASA_FREQUENCY_BANDS + 1 );
     179             : 
     180         396 :     hMasa->data.onset_detector_1_fx = 0; // hMasa->data.q_onset_detector
     181         396 :     hMasa->data.onset_detector_2_fx = 0; // hMasa->data.q_onset_detector
     182         396 :     hMasa->data.q_onset_detector = 0;
     183         396 :     move32();
     184         396 :     move32();
     185         396 :     move16();
     186             : 
     187         396 :     set32_fx( hMasa->data.lfeToTotalEnergyRatio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); // hMasa->data.lfeToTotalEnergyRatio_e
     188         396 :     set16_fx( hMasa->data.lfeToTotalEnergyRatio_e, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     189         396 :     hMasa->data.prevq_lfeToTotalEnergyRatio_fx = 0; // Q31
     190         396 :     move32();
     191             : 
     192         396 :     hMasa->data.prevq_lfeIndex = 0;
     193         396 :     move16();
     194             : 
     195         396 :     hMasa->data.sync_state.prev_sim_stop = 0;
     196         396 :     hMasa->data.sync_state.prev_offset = 0;
     197         396 :     hMasa->data.sync_state.frame_mode = MASA_FRAME_4SF;
     198         396 :     move16();
     199         396 :     move16();
     200         396 :     move32();
     201             : 
     202         396 :     set_zero_fx( hMasa->data.dir_align_state.previous_azi_dir1_fx, MASA_FREQUENCY_BANDS ); // Q22
     203         396 :     set_zero_fx( hMasa->data.dir_align_state.previous_ele_dir1_fx, MASA_FREQUENCY_BANDS ); // Q22
     204         396 :     set_zero_fx( hMasa->data.dir_align_state.previous_azi_dir2_fx, MASA_FREQUENCY_BANDS ); // Q22
     205         396 :     set_zero_fx( hMasa->data.dir_align_state.previous_ele_dir2_fx, MASA_FREQUENCY_BANDS ); // Q22
     206             : 
     207         396 :     IF( EQ_32( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) )
     208             :     {
     209             :         OMASA_ENCODER_DATA_HANDLE hOmasaData;
     210             : 
     211          44 :         IF( ( hOmasaData = (OMASA_ENCODER_DATA_HANDLE) malloc( sizeof( OMASA_ENCODER_DATA_STATE ) ) ) == NULL )
     212             :         {
     213           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data encoder\n" ) );
     214             :         }
     215             : 
     216         220 :         FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
     217             :         {
     218         176 :             set32_fx( hOmasaData->masa_to_total_energy_ratio_fx[i], 0, MASA_FREQUENCY_BANDS ); // Q30
     219             :         }
     220             : 
     221          44 :         hOmasaData->lp_noise_CPE_fx = -256; /* -1 in Q8 */
     222          44 :         move16();
     223          44 :         hOmasaData->omasa_stereo_sw_cnt = OMASA_STEREO_SW_CNT_MAX;
     224          44 :         move16();
     225             : 
     226         220 :         FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
     227             :         {
     228         176 :             set_zero_fx( hOmasaData->energy_ism_fx[i], MASA_FREQUENCY_BANDS ); // hOmasaData->energy_ism_fx_e
     229         176 :             set16_fx( hOmasaData->energy_ism_fx_e[i], 0, MASA_FREQUENCY_BANDS );
     230             :         }
     231             : 
     232          44 :         hMasa->data.hOmasaData = hOmasaData;
     233             :     }
     234             :     ELSE
     235             :     {
     236         352 :         hMasa->data.hOmasaData = NULL;
     237             :     }
     238             : 
     239         396 :     st_ivas->hMasa = hMasa;
     240             : 
     241         396 :     return error;
     242             : }
     243             : 
     244             : /*-----------------------------------------------------------------------*
     245             :  * ivas_masa_enc_close()
     246             :  *
     247             :  * close MASA encoder
     248             :  *-----------------------------------------------------------------------*/
     249        1052 : void ivas_masa_enc_close_fx(
     250             :     MASA_ENCODER_HANDLE *hMasa /* i/o: MASA metadata structure      */
     251             : )
     252             : {
     253             :     Word16 i;
     254             : 
     255        1052 :     test();
     256        1052 :     IF( hMasa == NULL || *hMasa == NULL )
     257             :     {
     258         656 :         return;
     259             :     }
     260             : 
     261         603 :     FOR( i = 0; i < ( *hMasa )->data.num_Cldfb_instances; i++ )
     262             :     {
     263         207 :         deleteCldfb_ivas_fx( &( ( *hMasa )->data.cldfbAnaEnc[i] ) );
     264             :     }
     265             : 
     266         396 :     IF( ( *hMasa )->data.hOmasaData != NULL )
     267             :     {
     268          44 :         free( ( *hMasa )->data.hOmasaData );
     269          44 :         ( *hMasa )->data.hOmasaData = NULL;
     270             :     }
     271             : 
     272         396 :     free( ( *hMasa ) );
     273         396 :     ( *hMasa ) = NULL;
     274             : 
     275         396 :     return;
     276             : }
     277             : 
     278             : /*-----------------------------------------------------------------------*
     279             :  * ivas_masa_encode()
     280             :  *
     281             :  * main MASA encoder function
     282             :  *-----------------------------------------------------------------------*/
     283             : 
     284       51096 : ivas_error ivas_masa_encode_fx(
     285             :     MASA_ENCODER_HANDLE hMasa,                         /* i/o: MASA encoder structure                  */
     286             :     IVAS_QMETADATA_HANDLE hQMetaData,                  /* i/o: q_metadata handle                       */
     287             :     BSTR_ENC_HANDLE hMetaData,                         /* i/o: Metadata bitstream handle               */
     288             :     Word16 *nb_bits_metadata,                          /* o  : number of metadata bits written         */
     289             :     const Word16 nchan_transport,                      /* i  : number of MASA input/transport channels */
     290             :     const IVAS_FORMAT ivas_format,                     /* i  : IVAS format                             */
     291             :     const Word32 ivas_total_brate,                     /* i  : IVAS total bitrate                      */
     292             :     const Word16 Opt_DTX_ON,                           /* i  : DTX on flag                             */
     293             :     const Word16 element_mode,                         /* i  : element mode                            */
     294             :     const ISM_MODE ism_mode,                           /* i  : ISM format mode                         */
     295             :     const Word16 nchan_ism,                            /* i  : number of ISM channels                  */
     296             :     ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i  : ISM metadata handle                     */
     297             :     const Word16 idx_separated_object,                 /* i  : index of the separated object           */
     298             :     OMASA_ENC_HANDLE hOMasa,                           /* i  : OMASA encoder handle                    */
     299             :     const Word16 ism_imp,                              /* i  : importance of separated object          */
     300             :     const Word16 flag_omasa_ener_brate                 /* i  : less bitrate for objects in OMASA flag  */
     301             : )
     302             : {
     303             :     MASA_DIRECTIONAL_SPATIAL_META *h_orig_metadata;
     304             :     Word16 i, j, s;
     305             :     Word16 masa_sid_descriptor;
     306             :     Word16 low_bitrate_mode;
     307             :     Word32 masa_total_brate;
     308             :     ivas_error error;
     309             :     Word16 guard_bits, tmp;
     310             : 
     311       51096 :     guard_bits = find_guarded_bits_fx( 9 );
     312             : 
     313       51096 :     masa_sid_descriptor = -1;
     314       51096 :     h_orig_metadata = NULL;
     315       51096 :     low_bitrate_mode = 0;
     316       51096 :     move16();
     317       51096 :     move16();
     318             : 
     319       51096 :     test();
     320       51096 :     IF( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) )
     321             :     {
     322             :         /* Create the MASA SID descriptor for the metadata and CPE mode, in order to have the SID frame self-contained. */
     323       39626 :         IF( Opt_DTX_ON && hQMetaData != NULL )
     324             :         {
     325        7028 :             IF( EQ_16( nchan_transport, 2 ) ) /* this is MASA format in CPE only */
     326             :             {
     327        4016 :                 masa_sid_descriptor = 0; /* for IVAS_CPE_DFT */
     328        4016 :                 move16();
     329        4016 :                 if ( EQ_16( element_mode, IVAS_CPE_MDCT ) )
     330             :                 {
     331        1648 :                     masa_sid_descriptor = 1;
     332        1648 :                     move16();
     333             :                 }
     334             :             }
     335             :         }
     336             : 
     337             :         /* Validate and compensate ratios as necessary */
     338       39626 :         compensate_energy_ratios_fx( hMasa );
     339             : 
     340       39626 :         IF( Opt_DTX_ON )
     341             :         {
     342        7028 :             IF( ( h_orig_metadata = (MASA_DIRECTIONAL_SPATIAL_META *) malloc( MASA_MAXIMUM_DIRECTIONS * sizeof( MASA_DIRECTIONAL_SPATIAL_META ) ) ) == NULL )
     343             :             {
     344           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA encoder\n" ) );
     345             :             }
     346             : 
     347       21084 :             FOR( i = 0; i < MASA_MAXIMUM_DIRECTIONS; i++ )
     348             :             {
     349       70280 :                 FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     350             :                 {
     351       56224 :                     Copy32( hMasa->masaMetadata.directional_meta[i].azimuth_fx[j], h_orig_metadata[i].azimuth_fx[j], MASA_FREQUENCY_BANDS );           // Q22
     352       56224 :                     Copy32( hMasa->masaMetadata.directional_meta[i].elevation_fx[j], h_orig_metadata[i].elevation_fx[j], MASA_FREQUENCY_BANDS );       // Q22
     353       56224 :                     Copy32( hMasa->masaMetadata.directional_meta[i].energy_ratio_fx[j], h_orig_metadata[i].energy_ratio_fx[j], MASA_FREQUENCY_BANDS ); // Q30
     354       56224 :                     Copy( (Word16 *) ( hMasa->masaMetadata.directional_meta[i].spherical_index[j] ), (Word16 *) ( h_orig_metadata[i].spherical_index[j] ), MASA_FREQUENCY_BANDS );
     355             :                 }
     356             :             }
     357             :         }
     358             : 
     359       39626 :         test();
     360       39626 :         test();
     361       39626 :         if ( ( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) ) && GE_32( ivas_total_brate, IVAS_384k ) )
     362             :         {
     363        2636 :             hMasa->config.mergeRatiosOverSubframes = 0;
     364        2636 :             move16();
     365             :         }
     366             : 
     367             :         /* Combine frequency bands and sub-frames */
     368       39626 :         combine_freqbands_and_subframes_fx( hMasa );
     369             :     }
     370             : 
     371             :     /* aligning the exponents of energy_fx */
     372       51096 :     s = 0;
     373       51096 :     move16();
     374      255480 :     FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
     375             :     {
     376      204384 :         maximum_s( hMasa->data.energy_e[i], MASA_FREQUENCY_BANDS, &tmp );
     377      204384 :         s = s_max( s, tmp );
     378             :     }
     379       51096 :     s = add( s, guard_bits );
     380      255480 :     FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
     381             :     {
     382     5109600 :         FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ )
     383             :         {
     384     4905216 :             hMasa->data.energy_fx[i][j] = L_shr( hMasa->data.energy_fx[i][j], sub( s, hMasa->data.energy_e[i][j] ) ); // hMasa->data.energy_e[i][j] -> s
     385     4905216 :             hMasa->data.energy_e[i][j] = s;
     386     4905216 :             move32();
     387     4905216 :             move16();
     388             :         }
     389             :     }
     390       51096 :     hMasa->data.q_energy = sub( 31, s );
     391       51096 :     move16();
     392             : 
     393       51096 :     test();
     394       51096 :     test();
     395       51096 :     test();
     396       51096 :     IF( EQ_16( hMasa->config.numberOfDirections, 2 ) && LT_16( hMasa->config.numTwoDirBands, hMasa->config.numCodingBands ) && ( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) ) )
     397             :     {
     398        9520 :         test();
     399        9520 :         test();
     400        9520 :         test();
     401        9520 :         IF( ( EQ_32( ivas_format, MASA_ISM_FORMAT ) && NE_32( ism_mode, ISM_MODE_NONE ) && NE_32( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) || NE_32( ivas_format, MASA_ISM_FORMAT ) )
     402             :         {
     403             :             /* Combine directions */
     404        7322 :             ivas_masa_combine_directions_fx( hMasa );
     405             :         }
     406             : 
     407             :         /* If we joined all bands, then metadata is now one directional. */
     408        9520 :         IF( hMasa->config.numTwoDirBands == 0 )
     409             :         {
     410        4064 :             hMasa->config.numberOfDirections = 1;
     411        4064 :             hMasa->masaMetadata.descriptive_meta.numberOfDirections = 0;
     412        4064 :             hQMetaData->no_directions = 1;
     413        4064 :             move16();
     414        4064 :             move16();
     415        4064 :             move16();
     416             :         }
     417             :     }
     418             : 
     419             :     /* Reset qmetadata bit budget */
     420       51096 :     hQMetaData->metadata_max_bits = hMasa->config.max_metadata_bits;
     421       51096 :     move16();
     422       51096 :     test();
     423       51096 :     IF( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) )
     424             :     {
     425       39626 :         test();
     426       39626 :         IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && NE_32( ism_mode, ISM_MODE_NONE ) )
     427             :         {
     428             :             /* write the number of objects in ISM_MASA format*/
     429        7058 :             push_next_indice( hMetaData, sub( nchan_ism, 1 ), NO_BITS_MASA_ISM_NO_OBJ );
     430        7058 :             hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, NO_BITS_MASA_ISM_NO_OBJ );
     431        7058 :             move16();
     432             : 
     433             :             /* write index of separated object if needed */
     434        7058 :             test();
     435        7058 :             IF( EQ_32( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) && GT_16( nchan_ism, 1 ) )
     436             :             {
     437        1862 :                 push_next_indice( hMetaData, idx_separated_object, NO_BITS_MASA_ISM_NO_OBJ );
     438        1862 :                 hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, NO_BITS_MASA_ISM_NO_OBJ );
     439        1862 :                 move16();
     440             :             }
     441             : 
     442             :             /* write ISM importance flag (one per object) */
     443        7058 :             IF( EQ_32( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     444             :             {
     445        1862 :                 push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
     446        1862 :                 hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
     447        1862 :                 move16();
     448             :             }
     449        5196 :             ELSE IF( EQ_32( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     450             :             {
     451        2054 :                 IF( hIsmMetaData[0]->ism_md_null_flag )
     452             :                 {
     453             :                     /* signal NULL metadata frame */
     454           0 :                     push_next_indice( hMetaData, 1, ISM_METADATA_MD_FLAG_BITS );
     455           0 :                     hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_MD_FLAG_BITS );
     456           0 :                     move16();
     457             : 
     458             :                     /* write the ISM class to ISM_NO_META and again the true ISM class */
     459           0 :                     push_next_indice( hMetaData, ISM_NO_META, ISM_METADATA_FLAG_BITS );
     460           0 :                     hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
     461           0 :                     move16();
     462           0 :                     push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
     463           0 :                     hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
     464           0 :                     move16();
     465             :                 }
     466             :                 ELSE
     467             :                 {
     468        2054 :                     push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
     469        2054 :                     hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
     470        2054 :                     move16();
     471             : 
     472        2054 :                     IF( EQ_16( hIsmMetaData[0]->ism_imp, ISM_NO_META ) )
     473             :                     {
     474             :                         /* signal low-rate ISM_NO_META frame */
     475           0 :                         push_next_indice( hMetaData, 0, ISM_METADATA_MD_FLAG_BITS );
     476           0 :                         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_MD_FLAG_BITS );
     477           0 :                         move16();
     478             : 
     479             :                         /* signal presence of MD in low-rate ISM_NO_META frame */
     480           0 :                         push_next_indice( hMetaData, hIsmMetaData[0]->ism_md_lowrate_flag, ISM_METADATA_INACTIVE_FLAG_BITS );
     481           0 :                         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_INACTIVE_FLAG_BITS );
     482           0 :                         move16();
     483             :                     }
     484             :                 }
     485             :             }
     486        3142 :             ELSE IF( EQ_32( ism_mode, ISM_MASA_MODE_DISC ) )
     487             :             {
     488       11602 :                 FOR( i = 0; i < nchan_ism; i++ )
     489             :                 {
     490        8460 :                     IF( hIsmMetaData[i]->ism_md_null_flag )
     491             :                     {
     492             :                         /* signal NULL metadata frame */
     493           0 :                         push_next_indice( hMetaData, 1, ISM_METADATA_MD_FLAG_BITS );
     494           0 :                         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_MD_FLAG_BITS );
     495           0 :                         move16();
     496             : 
     497             :                         /* write the ISM class to ISM_NO_META and again the true ISM class */
     498           0 :                         push_next_indice( hMetaData, ISM_NO_META, ISM_METADATA_FLAG_BITS );
     499           0 :                         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
     500           0 :                         move16();
     501           0 :                         push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS );
     502           0 :                         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
     503           0 :                         move16();
     504             :                     }
     505             :                     ELSE
     506             :                     {
     507        8460 :                         push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS );
     508        8460 :                         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
     509        8460 :                         move16();
     510             : 
     511        8460 :                         IF( EQ_16( hIsmMetaData[i]->ism_imp, ISM_NO_META ) )
     512             :                         {
     513             :                             /* signal low-rate ISM_NO_META frame */
     514           0 :                             push_next_indice( hMetaData, 0, ISM_METADATA_MD_FLAG_BITS );
     515           0 :                             hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_MD_FLAG_BITS );
     516           0 :                             move16();
     517             : 
     518             :                             /* signal presence of MD in low-rate ISM_NO_META frame */
     519           0 :                             push_next_indice( hMetaData, hIsmMetaData[i]->ism_md_lowrate_flag, ISM_METADATA_INACTIVE_FLAG_BITS );
     520           0 :                             hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_INACTIVE_FLAG_BITS );
     521           0 :                             move16();
     522             :                         }
     523             :                     }
     524             :                 }
     525        3142 :                 test();
     526        3142 :                 IF( EQ_32( ivas_total_brate, IVAS_128k ) && GE_16( nchan_ism, 3 ) )
     527             :                 {
     528         126 :                     push_next_indice( hMetaData, flag_omasa_ener_brate, 1 );
     529         126 :                     hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, 1 );
     530         126 :                     move16();
     531             :                 }
     532             :             }
     533             :         }
     534             :         ELSE
     535             :         {
     536             :             /* write the number of MASA transport channels */
     537       32568 :             push_next_indice( hMetaData, sub( nchan_transport, 1 ), MASA_TRANSP_BITS );
     538       32568 :             hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_TRANSP_BITS );
     539       32568 :             move16();
     540             :         }
     541             : 
     542       39626 :         test();
     543       39626 :         IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MODE_NONE ) )
     544             :         {
     545             :             /* signal MASA_ISM_FORMAT to decoder */
     546        1942 :             push_next_indice( hMetaData, 1, 1 );
     547             :             /* write reserved bit */
     548        1942 :             push_next_indice( hMetaData, 0, MASA_HEADER_BITS - 1 );
     549        1942 :             hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_HEADER_BITS );
     550        1942 :             move16();
     551             :         }
     552             :         ELSE
     553             :         {
     554             :             /* the MASA_ISM_FORMAT is not signalled here */
     555             :             /* write reserved bits */
     556       37684 :             push_next_indice( hMetaData, 0, MASA_HEADER_BITS );
     557       37684 :             hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_HEADER_BITS );
     558       37684 :             move16();
     559             :         }
     560             :         /* write number of directions */
     561       39626 :         push_next_indice( hMetaData, sub( hQMetaData->no_directions, 1 ), 1 );
     562       39626 :         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, 1 );
     563       39626 :         move16();
     564             : 
     565             :         /* write subframe mode */
     566       39626 :         IF( EQ_16( hQMetaData->q_direction[0].cfg.nblocks, 1 ) )
     567             :         {
     568        5550 :             push_next_indice( hMetaData, 1, MASA_SUBFRAME_BITS );
     569             :         }
     570             :         ELSE
     571             :         {
     572       34076 :             push_next_indice( hMetaData, 0, MASA_SUBFRAME_BITS );
     573             :         }
     574       39626 :         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_SUBFRAME_BITS );
     575       39626 :         move16();
     576             :     }
     577             : 
     578             : 
     579       51096 :     IF( EQ_32( ivas_format, MC_FORMAT ) )
     580             :     {
     581             :         Word16 lfeBitsWritten;
     582             : 
     583       11470 :         lfeBitsWritten = encode_lfe_to_total_energy_ratio_fx( hMasa, hMetaData, ivas_total_brate );
     584             : 
     585       11470 :         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, lfeBitsWritten );
     586       11470 :         move16();
     587             :     }
     588             : 
     589             :     /* Move data from encoder to qmetadata */
     590       51096 :     test();
     591       51096 :     IF( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) )
     592             :     {
     593       39626 :         move_metadata_to_qmetadata_fx( hMasa, hQMetaData );
     594             :     }
     595             : 
     596       51096 :     test();
     597       51096 :     IF( LT_16( hMasa->config.max_metadata_bits, MINIMUM_BIT_BUDGET_NORMAL_META ) && !hMasa->config.joinedSubframes )
     598             :     {
     599       24911 :         reduce_metadata_further_fx( hMasa, hQMetaData, ivas_format );
     600             : 
     601       24911 :         low_bitrate_mode = (Word16) LE_32( ivas_total_brate, 32000 );
     602             : 
     603             :         /* Write low bitrate mode. 1 signals that we have merged through time, 0 signals merge through frequency. */
     604       24911 :         IF( EQ_16( hQMetaData->q_direction[0].cfg.nblocks, 1 ) )
     605             :         {
     606       20938 :             push_next_indice( hMetaData, 1, MASA_LOWBITRATE_MODE_BITS );
     607             :         }
     608             :         ELSE
     609             :         {
     610        3973 :             push_next_indice( hMetaData, 0, MASA_LOWBITRATE_MODE_BITS );
     611             :         }
     612       24911 :         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_LOWBITRATE_MODE_BITS );
     613       24911 :         move16();
     614             :     }
     615             : 
     616             :     /* Encode MASA+ISM metadata */
     617       51096 :     test();
     618       51096 :     IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     619             :     {
     620             :         /* encode MASA/ISM energy ratios */
     621        1862 :         ivas_encode_masaism_metadata_fx( hMasa, hQMetaData, hMetaData, hIsmMetaData, nchan_ism, low_bitrate_mode, hOMasa->nCodingBands, hOMasa->nSubframes, idx_separated_object, ism_imp );
     622             :     }
     623             :     ELSE
     624             :     {
     625       49234 :         if ( EQ_32( ivas_format, MASA_ISM_FORMAT ) )
     626             :         {
     627        7138 :             hMasa->data.hOmasaData->masa_to_total_energy_ratio_fx[0][0] = -ONE_IN_Q30; /* signals NOT to adjust the energy ratios */
     628        7138 :             move32();
     629             :         }
     630             :     }
     631             : 
     632             :     /* Encode metadata */
     633       51096 :     masa_total_brate = ivas_total_brate;
     634       51096 :     move32();
     635       51096 :     test();
     636       51096 :     IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MASA_MODE_DISC ) )
     637             :     {
     638        3142 :         masa_total_brate = calculate_cpe_brate_MASA_ISM_fx( ism_mode, ivas_total_brate, nchan_ism );
     639             :     }
     640             : 
     641       51096 :     IF( GE_32( masa_total_brate, IVAS_384k ) )
     642             :     {
     643        2276 :         IF( GE_32( masa_total_brate, IVAS_512k ) )
     644             :         {
     645         800 :             IF( NE_32( ( error = ivas_qmetadata_enc_encode_hr_384_512_fx( hMetaData, hQMetaData, 16, 4 ) ), IVAS_ERR_OK ) )
     646             :             {
     647           0 :                 return error;
     648             :             }
     649             :         }
     650             :         ELSE
     651             :         {
     652        1476 :             IF( NE_32( ( error = ivas_qmetadata_enc_encode_hr_384_512_fx( hMetaData, hQMetaData, 11, 3 ) ), IVAS_ERR_OK ) )
     653             :             {
     654           0 :                 return error;
     655             :             }
     656             :         }
     657             :     }
     658             :     ELSE
     659             :     {
     660       48820 :         IF( NE_32( ( error = ivas_qmetadata_enc_encode_fx( hMetaData, hQMetaData, 0 ) ), IVAS_ERR_OK ) )
     661             :         {
     662           0 :             return error;
     663             :         }
     664             :     }
     665             : 
     666       51096 :     test();
     667       51096 :     IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     668             :     {
     669             :         /* Modify spatial metadata based on the MASA-to-total energy ratios */
     670        1862 :         ivas_omasa_modify_masa_energy_ratios_fx( hQMetaData, hMasa->data.hOmasaData->masa_to_total_energy_ratio_fx );
     671             :     }
     672             : 
     673       51096 :     *nb_bits_metadata = hMetaData->nb_bits_tot;
     674       51096 :     move16();
     675             : 
     676       51096 :     test();
     677       51096 :     IF( EQ_32( ivas_format, MASA_FORMAT ) && Opt_DTX_ON )
     678             :     {
     679             :         /* save old values */
     680        7028 :         UWord8 numCodingBands = hMasa->config.numCodingBands;
     681        7028 :         UWord8 numTwoDirBands = hMasa->config.numTwoDirBands;
     682        7028 :         Word16 nbands = hQMetaData->q_direction[0].cfg.nbands;
     683        7028 :         UWord8 numberOfDirections = hMasa->config.numberOfDirections;
     684        7028 :         UWord8 numberOfDirectionsMeta = hMasa->masaMetadata.descriptive_meta.numberOfDirections;
     685        7028 :         UWord16 numberOfDirectionsQMetaData = hQMetaData->no_directions;
     686        7028 :         move16();
     687        7028 :         move16();
     688        7028 :         move16();
     689        7028 :         move16();
     690        7028 :         move16();
     691        7028 :         move16();
     692             : 
     693        7028 :         test();
     694        7028 :         IF( !( EQ_16( hMasa->config.numberOfDirections, 1 ) && EQ_16( hQMetaData->q_direction->cfg.nbands, 5 ) ) )
     695             :         {
     696        5937 :             FOR( i = 0; i < MASA_MAXIMUM_DIRECTIONS; i++ )
     697             :             {
     698       19790 :                 FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     699             :                 {
     700       15832 :                     Copy32( h_orig_metadata[i].azimuth_fx[j], hMasa->masaMetadata.directional_meta[i].azimuth_fx[j], MASA_FREQUENCY_BANDS );           // Q22
     701       15832 :                     Copy32( h_orig_metadata[i].elevation_fx[j], hMasa->masaMetadata.directional_meta[i].elevation_fx[j], MASA_FREQUENCY_BANDS );       // Q22
     702       15832 :                     Copy32( h_orig_metadata[i].energy_ratio_fx[j], hMasa->masaMetadata.directional_meta[i].energy_ratio_fx[j], MASA_FREQUENCY_BANDS ); // Q30
     703             :                 }
     704             :             }
     705             : 
     706             :             /* Force to have 5 bands and 1 direction */
     707        1979 :             hMasa->config.numCodingBands = 5;
     708        1979 :             hMasa->config.numTwoDirBands = 0;
     709        1979 :             move16();
     710        1979 :             move16();
     711             : 
     712        1979 :             combine_freqbands_and_subframes_fx( hMasa );
     713             : 
     714        1979 :             hQMetaData->q_direction[0].cfg.nbands = 5;
     715        1979 :             move16();
     716             : 
     717        1979 :             test();
     718        1979 :             IF( EQ_16( hMasa->config.numberOfDirections, 2 ) && LT_16( hMasa->config.numTwoDirBands, hMasa->config.numCodingBands ) )
     719             :             {
     720             :                 /* Combine directions */
     721           0 :                 ivas_masa_combine_directions_fx( hMasa );
     722             : 
     723             :                 /* If we joined all bands, then metadata is now one directional. */
     724           0 :                 IF( hMasa->config.numTwoDirBands == 0 )
     725             :                 {
     726           0 :                     hMasa->config.numberOfDirections = 1;
     727           0 :                     hMasa->masaMetadata.descriptive_meta.numberOfDirections = 0;
     728           0 :                     hQMetaData->no_directions = 1;
     729           0 :                     move16();
     730           0 :                     move16();
     731           0 :                     move16();
     732             :                 }
     733             :             }
     734             : 
     735        1979 :             move_metadata_to_qmetadata_fx( hMasa, hQMetaData );
     736             : 
     737       11874 :             FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j )
     738             :             {
     739        9895 :                 hQMetaData->q_direction[0].band_data[j].energy_ratio_index[0] = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
     740        9895 :                 move32();
     741             :             }
     742             :         }
     743             : 
     744        7028 :         free( h_orig_metadata );
     745             : 
     746        7028 :         ivas_qmetadata_enc_sid_encode_fx( hMetaData, hQMetaData, masa_sid_descriptor, ivas_format );
     747             : 
     748             :         /* restore old values */
     749        7028 :         hMasa->config.numCodingBands = numCodingBands;
     750        7028 :         hMasa->config.numTwoDirBands = numTwoDirBands;
     751        7028 :         hQMetaData->q_direction[0].cfg.nbands = nbands;
     752        7028 :         hMasa->config.numberOfDirections = numberOfDirections;
     753        7028 :         hMasa->masaMetadata.descriptive_meta.numberOfDirections = numberOfDirectionsMeta;
     754        7028 :         hQMetaData->no_directions = numberOfDirectionsQMetaData;
     755        7028 :         move16();
     756        7028 :         move16();
     757        7028 :         move16();
     758        7028 :         move16();
     759        7028 :         move16();
     760        7028 :         move16();
     761             :     }
     762             : 
     763       51096 :     return IVAS_ERR_OK;
     764             : }
     765             : /*-----------------------------------------------------------------------*
     766             :  * ivas_masa_estimate_energy_fx()
     767             :  *
     768             :  *
     769             :  *-----------------------------------------------------------------------*/
     770             : 
     771       39626 : void ivas_masa_estimate_energy_fx(
     772             :     MASA_ENCODER_HANDLE hMasa,    /* i/o: MASA encoder structure                    */
     773             :     Word32 *data_fx[],            /* i  : Input audio channels        Q(q_data)     */
     774             :     const Word16 input_frame,     /* i  : frame length                              */
     775             :     const Word16 nchan_transport, /* i  : number of MASA input/transport channels   */
     776             :     Word16 q_data                 /* i  : q for data_fx */
     777             : )
     778             : {
     779             :     Word32 Input_RealBuffer[MASA_MAX_TRANSPORT_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     780             :     Word32 Input_ImagBuffer[MASA_MAX_TRANSPORT_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     781             :     Word16 block_m_idx, band_m_idx;
     782             :     Word16 mrange[2], brange[2];
     783             :     Word16 i, j, ts, l_ts, maxBin;
     784             :     Word64 energy_fx_temp[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     785       39626 :     Word16 scale = 63;
     786       39626 :     move16();
     787             :     Word16 q_buf;
     788       39626 :     maxBin = extract_l( Mpy_32_32( 134217728 /*CLDFB_NO_CHANNELS_MAX / L_FRAME48k in Q31*/, input_frame ) );
     789       39626 :     l_ts = idiv1616( input_frame, CLDFB_NO_COL_MAX );
     790             : 
     791      198130 :     FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
     792             :     {
     793     3962600 :         FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ )
     794             :         {
     795     3804096 :             energy_fx_temp[i][j] = 0;
     796     3804096 :             move64();
     797             :         }
     798             :     }
     799             : 
     800      198130 :     FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
     801             :     {
     802      158504 :         mrange[0] = hMasa->config.block_grouping[block_m_idx];
     803      158504 :         move16();
     804      158504 :         mrange[1] = hMasa->config.block_grouping[block_m_idx + 1];
     805      158504 :         move16();
     806      158504 :         set_zero_fx( hMasa->data.energy_fx[block_m_idx], MASA_FREQUENCY_BANDS );
     807      158504 :         set16_fx( hMasa->data.energy_e[block_m_idx], 0, MASA_FREQUENCY_BANDS );
     808             : 
     809      792520 :         FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
     810             :         {
     811     1676608 :             FOR( i = 0; i < nchan_transport; i++ )
     812             :             {
     813     1042592 :                 q_buf = q_data;
     814     1042592 :                 move16();
     815     1042592 :                 scale_sig32( hMasa->data.cldfbAnaEnc[i]->cldfb_state_fx, hMasa->data.cldfbAnaEnc[i]->cldfb_state_length, sub( q_buf, hMasa->data.cldfbAnaEnc[i]->Q_cldfb_state ) );
     816     1042592 :                 hMasa->data.cldfbAnaEnc[i]->Q_cldfb_state = q_buf;
     817     1042592 :                 move16();
     818     1042592 :                 cldfbAnalysis_ts_fx_fixed_q( &( data_fx[i][l_ts * ts] ), Input_RealBuffer[i], Input_ImagBuffer[i], l_ts, hMasa->data.cldfbAnaEnc[i], &q_buf ); // (q_data - 5)  for Input_RealBuffer[i], Input_ImagBuffer[i]
     819             :             }
     820             : 
     821    15850400 :             FOR( band_m_idx = 0; band_m_idx < MASA_FREQUENCY_BANDS; band_m_idx++ )
     822             :             {
     823    15216384 :                 brange[0] = hMasa->config.band_grouping[band_m_idx];
     824    15216384 :                 move16();
     825    15216384 :                 brange[1] = hMasa->config.band_grouping[band_m_idx + 1];
     826    15216384 :                 move16();
     827             : 
     828    40238592 :                 FOR( i = 0; i < nchan_transport; i++ )
     829             :                 {
     830    25022208 :                     IF( GT_16( brange[0], maxBin ) )
     831             :                     {
     832       72000 :                         hMasa->data.energy_fx[block_m_idx][band_m_idx] = 0;
     833       72000 :                         move32();
     834       72000 :                         CONTINUE;
     835             :                     }
     836    24950208 :                     ELSE IF( GE_16( brange[1], maxBin ) )
     837             :                     {
     838     1116992 :                         brange[1] = maxBin;
     839     1116992 :                         move16();
     840             :                     }
     841             : 
     842    85537728 :                     FOR( j = brange[0]; j < brange[1]; j++ )
     843             :                     {
     844    60587520 :                         energy_fx_temp[block_m_idx][band_m_idx] = W_add( energy_fx_temp[block_m_idx][band_m_idx], W_mac_32_32( W_mult_32_32( Input_RealBuffer[i][j], Input_RealBuffer[i][j] ), Input_ImagBuffer[i][j], Input_ImagBuffer[i][j] ) ); // Q: 2 * (q_data - 5) + 1 for energy_fx_temp
     845    60587520 :                         move64();
     846             :                     }
     847    24950208 :                     IF( energy_fx_temp[block_m_idx][band_m_idx] != 0 )
     848             :                     {
     849    24875808 :                         scale = s_min( scale, W_norm( energy_fx_temp[block_m_idx][band_m_idx] ) ); // scale calculates minimum shift can be done across a buffer
     850             :                     }
     851             :                 }
     852             :             }
     853             :         }
     854             :     }
     855             : 
     856      198130 :     FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
     857             :     {
     858     3962600 :         FOR( band_m_idx = 0; band_m_idx < MASA_FREQUENCY_BANDS; band_m_idx++ )
     859             :         {
     860     3804096 :             energy_fx_temp[block_m_idx][band_m_idx] = W_shl( energy_fx_temp[block_m_idx][band_m_idx], scale ); //  Q: 2 * (q_data - 5) + 1 + scale
     861     3804096 :             move64();
     862     3804096 :             hMasa->data.energy_fx[block_m_idx][band_m_idx] = W_extract_h( energy_fx_temp[block_m_idx][band_m_idx] ); // Q: 2 * (q_data - 5) + 1 + scale - 32
     863     3804096 :             move32();
     864     3804096 :             hMasa->data.energy_e[block_m_idx][band_m_idx] = sub( 31, add( add( imult1616( 2, q_data ), scale ), 1 - 10 - 32 ) );
     865     3804096 :             move16();
     866             :         }
     867             :     }
     868       39626 :     hMasa->data.q_energy = add( add( imult1616( 2, q_data ), scale ), 1 - 10 - 32 );
     869       39626 :     move16();
     870             : 
     871       39626 :     return;
     872             : }
     873             : 
     874             : 
     875             : /*-----------------------------------------------------------------------*
     876             :  * ivas_masa_enc_config()
     877             :  *
     878             :  * Frame-by-frame configuration of MASA encoder
     879             :  *-----------------------------------------------------------------------*/
     880             : 
     881       39903 : ivas_error ivas_masa_enc_config_fx(
     882             :     Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
     883             : )
     884             : {
     885             :     Word16 i;
     886             :     MASA_ENCODER_HANDLE hMasa;
     887             :     IVAS_QMETADATA_HANDLE hQMetaData;
     888             :     IVAS_FORMAT ivas_format;
     889             :     UWord8 joinedSubframes;
     890             :     UWord8 coherencePresent;
     891             :     UWord8 isActualTwoDir; /* Flag to tell that when there are two directions present in metadata, they both contain meaningful information. */
     892             :     Word32 ivas_total_brate;
     893             :     UWord8 maxBand;
     894             :     Word16 maxBin, sf;
     895             :     ivas_error error;
     896             :     Word32 ism_total_brate;
     897             :     Word32 masa_total_brate;
     898             : 
     899       39903 :     error = IVAS_ERR_OK;
     900       39903 :     move16();
     901             : 
     902       39903 :     hMasa = st_ivas->hMasa;
     903       39903 :     hQMetaData = st_ivas->hQMetaData;
     904       39903 :     ivas_format = st_ivas->hEncoderConfig->ivas_format;
     905       39903 :     ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate;
     906       39903 :     move16();
     907       39903 :     move32();
     908             : 
     909       39903 :     ism_total_brate = 0;
     910       39903 :     move32();
     911       39903 :     test();
     912       39903 :     test();
     913       39903 :     test();
     914       39903 :     test();
     915       39903 :     IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) && st_ivas->nSCE > 0 && ( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) )
     916             :     {
     917       19434 :         FOR( i = 0; i < st_ivas->nSCE; i++ )
     918             :         {
     919       12376 :             ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[i]->element_brate );
     920             :         }
     921             :     }
     922             : 
     923       39903 :     ivas_masa_set_elements_fx( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, ivas_format, st_ivas->ism_mode, ism_total_brate );
     924             : 
     925       39903 :     hQMetaData->is_masa_ivas_format = 1;
     926       39903 :     move16();
     927             : 
     928       39903 :     test();
     929       39903 :     test();
     930       39903 :     IF( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) )
     931             :     {
     932       39626 :         masa_metadata_direction_alignment_fx( hMasa );
     933             : 
     934       39626 :         detect_framing_async_fx( hMasa ); /* detect the offset, set 1sf/4sf mode based on this. potentially also shift the metadata using a history buffer */
     935       39626 :         test();
     936       39626 :         IF( EQ_16( hMasa->data.sync_state.frame_mode, MASA_FRAME_1SF ) && hMasa->data.sync_state.prev_offset != 0 )
     937             :         {
     938             :             /* average over sub-frames */
     939           0 :             IF( EQ_32( ivas_total_brate, IVAS_512k ) )
     940             :             {
     941           0 :                 average_masa_metadata_fx( &( hMasa->masaMetadata ), hMasa->data.energy_fx, hMasa->data.energy_e, &( hMasa->data.Sph_Grid16 ), TRUE );
     942             :             }
     943             :             ELSE
     944             :             {
     945           0 :                 average_masa_metadata_fx( &( hMasa->masaMetadata ), hMasa->data.energy_fx, hMasa->data.energy_e, &( hMasa->data.Sph_Grid16 ), FALSE );
     946             :             }
     947             :         }
     948             : 
     949             : 
     950             :         /* Inspect metadata for parameter changes that affect coding. */
     951       39626 :         detect_metadata_composition_fx( hMasa, &joinedSubframes, &coherencePresent, &isActualTwoDir );
     952             : 
     953       39626 :         hMasa->config.joinedSubframes = joinedSubframes;
     954       39626 :         hMasa->config.coherencePresent = coherencePresent;
     955       39626 :         move16();
     956       39626 :         move16();
     957       39626 :         test();
     958       39626 :         IF( EQ_16( add( hMasa->masaMetadata.descriptive_meta.numberOfDirections, 1 ), 2 ) && isActualTwoDir )
     959             :         {
     960        9900 :             hMasa->config.numberOfDirections = 2;
     961             :         }
     962             :         ELSE
     963             :         {
     964       29726 :             hMasa->config.numberOfDirections = 1;
     965             :         }
     966       39626 :         move16();
     967             :     }
     968         277 :     ELSE IF( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) )
     969             :     {
     970             :         /* For McMASA, these are set only once as this function is called only once. */
     971         277 :         hMasa->config.joinedSubframes = 0;
     972         277 :         hMasa->config.numberOfDirections = 1;
     973         277 :         move16();
     974         277 :         move16();
     975             :     }
     976             : 
     977       39903 :     IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) )
     978             :     {
     979        9000 :         ivas_masa_set_coding_config_fx( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hCPE[0]->element_brate, st_ivas->nchan_transport, MC_MODE_NONE );
     980             :     }
     981             :     ELSE
     982             :     {
     983       30903 :         test();
     984       30903 :         ivas_masa_set_coding_config_fx( &( hMasa->config ), hMasa->data.band_mapping, ivas_total_brate, st_ivas->nchan_transport, ( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) );
     985             :     }
     986             : 
     987             :     /* Setup importance weights for two-direction band selection. */
     988       39903 :     IF( EQ_16( hMasa->config.numberOfDirections, 2 ) )
     989             :     {
     990        9900 :         set32_fx( hMasa->data.importanceWeight_fx, ONE_IN_Q30 /*1.0f Q30*/, MASA_FREQUENCY_BANDS );
     991             : 
     992             : 
     993        9900 :         IF( EQ_16( hMasa->config.numCodingBands, 5 ) )
     994             :         {
     995        6670 :             hMasa->data.importanceWeight_fx[4] = 751619277 /*0.7f q30*/;
     996        6670 :             move32();
     997             :         }
     998        3230 :         ELSE IF( EQ_16( hMasa->config.numCodingBands, 8 ) )
     999             :         {
    1000         354 :             hMasa->data.importanceWeight_fx[7] = 751619277 /*0.7f q30*/;
    1001         354 :             move32();
    1002             :         }
    1003        2876 :         ELSE IF( EQ_16( hMasa->config.numCodingBands, 10 ) )
    1004             :         {
    1005           0 :             hMasa->data.importanceWeight_fx[8] = 751619277 /*0.7f q30*/;
    1006           0 :             hMasa->data.importanceWeight_fx[9] = 107374182 /*0.1f q30*/;
    1007           0 :             move32();
    1008           0 :             move32();
    1009             :         }
    1010        2876 :         ELSE IF( EQ_16( hMasa->config.numCodingBands, 12 ) )
    1011             :         {
    1012         794 :             hMasa->data.importanceWeight_fx[10] = 751619277 /*0.7f q30*/;
    1013         794 :             hMasa->data.importanceWeight_fx[11] = 107374182 /*0.1f q30*/;
    1014         794 :             move32();
    1015         794 :             move32();
    1016             :         }
    1017        2082 :         ELSE IF( EQ_16( hMasa->config.numCodingBands, 18 ) )
    1018             :         {
    1019         798 :             hMasa->data.importanceWeight_fx[14] = 858993459 /*0.8f q30*/;
    1020         798 :             hMasa->data.importanceWeight_fx[15] = 536870912 /*0.5f q30*/;
    1021         798 :             hMasa->data.importanceWeight_fx[16] = 214748365 /*0.2f q30*/;
    1022         798 :             hMasa->data.importanceWeight_fx[17] = 0 /*0 q30*/;
    1023         798 :             move32();
    1024         798 :             move32();
    1025         798 :             move32();
    1026         798 :             move32();
    1027             :         }
    1028        1284 :         ELSE IF( EQ_16( hMasa->config.numCodingBands, 24 ) )
    1029             :         {
    1030        1284 :             hMasa->data.importanceWeight_fx[20] = 858993459 /*0.8f q30*/;
    1031        1284 :             hMasa->data.importanceWeight_fx[21] = 536870912 /*0.5f q30*/;
    1032        1284 :             hMasa->data.importanceWeight_fx[22] = 214748365 /*0.2f q30*/;
    1033        1284 :             hMasa->data.importanceWeight_fx[23] = 0 /*0 q30*/;
    1034        1284 :             move32();
    1035        1284 :             move32();
    1036        1284 :             move32();
    1037        1284 :             move32();
    1038             :         }
    1039             : 
    1040        9900 :         IF( EQ_16( hMasa->config.numTwoDirBands, hMasa->config.numCodingBands ) )
    1041             :         {
    1042         380 :             set8_fx( (Word8 *) hMasa->data.twoDirBands, 1, hMasa->config.numCodingBands );
    1043             :         }
    1044             :     }
    1045             :     ELSE
    1046             :     {
    1047       30003 :         set8_fx( (Word8 *) hMasa->data.twoDirBands, 0, hMasa->config.numCodingBands );
    1048             :     }
    1049             : 
    1050             :     /* Set qmeta to correct values */
    1051       39903 :     test();
    1052       39903 :     IF( EQ_16( hMasa->config.numberOfDirections, 2 ) && hMasa->config.numTwoDirBands != 0 )
    1053             :     {
    1054        5836 :         IF( NE_32( ( error = ivas_qmetadata_allocate_memory_fx( hQMetaData, hMasa->config.numCodingBands, 2, hMasa->config.useCoherence ) ), IVAS_ERR_OK ) )
    1055             :         {
    1056           0 :             return error;
    1057             :         }
    1058             :     }
    1059             :     ELSE
    1060             :     {
    1061       34067 :         IF( NE_32( ( error = ivas_qmetadata_allocate_memory_fx( hQMetaData, hMasa->config.numCodingBands, 1, hMasa->config.useCoherence ) ), IVAS_ERR_OK ) )
    1062             :         {
    1063           0 :             return error;
    1064             :         }
    1065             :     }
    1066             : 
    1067       85642 :     FOR( i = 0; i < hQMetaData->no_directions; i++ )
    1068             :     {
    1069       45739 :         hQMetaData->q_direction[i].cfg.nbands = hMasa->config.numCodingBands;
    1070       45739 :         move16();
    1071       45739 :         IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
    1072             :         {
    1073        6546 :             hQMetaData->q_direction[i].cfg.nblocks = 1;
    1074             :         }
    1075             :         ELSE
    1076             :         {
    1077       39193 :             hQMetaData->q_direction[i].cfg.nblocks = 4;
    1078             :         }
    1079       45739 :         move16();
    1080             : 
    1081       45739 :         IF( EQ_16( ivas_format, MC_FORMAT ) )
    1082             :         {
    1083         277 :             hQMetaData->q_direction[i].cfg.mc_ls_setup = st_ivas->hEncoderConfig->mc_input_setup;
    1084         277 :             move16();
    1085             :         }
    1086             :         ELSE
    1087             :         {
    1088             :             /* Just to be sure that this default value is maintained */
    1089       45462 :             hQMetaData->q_direction[i].cfg.mc_ls_setup = MC_LS_SETUP_INVALID;
    1090       45462 :             move16();
    1091             :         }
    1092             :     }
    1093             : 
    1094       39903 :     hQMetaData->all_coherence_zero = !hMasa->config.coherencePresent;
    1095       39903 :     move16();
    1096             : 
    1097       39903 :     ivas_set_qmetadata_maxbit_req_fx( hQMetaData, ivas_format );
    1098             : 
    1099             :     /* Find maximum band usable */
    1100       39903 :     maxBin = extract_l( Mpy_32_32( st_ivas->hEncoderConfig->input_Fs /*q0*/, INV_CLDFB_BANDWIDTH_Q31 /*Q31*/ ) ); /*q0+q31-q31->q0*/
    1101       39903 :     maxBand = 0;
    1102       39903 :     move16();
    1103       39903 :     test();
    1104     1032788 :     WHILE( ( maxBand <= MASA_FREQUENCY_BANDS ) && ( MASA_band_grouping_24[maxBand] <= maxBin ) )
    1105             :     {
    1106      992885 :         test();
    1107      992885 :         maxBand = (UWord8) add( maxBand, 1 );
    1108      992885 :         move16(); /*because typecasting word16 to uword8*/
    1109             :     }
    1110       39903 :     maxBand = (UWord8) sub( maxBand, 1 );
    1111       39903 :     move16(); /*because typecasting word16 to uword8*/
    1112             : 
    1113       39903 :     st_ivas->hQMetaData->q_direction->cfg.inactiveBands = 0;
    1114       39903 :     masa_total_brate = ivas_total_brate;
    1115       39903 :     move16();
    1116       39903 :     move32();
    1117       39903 :     test();
    1118       39903 :     IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
    1119             :     {
    1120        3142 :         masa_total_brate = calculate_cpe_brate_MASA_ISM_fx( st_ivas->ism_mode, ivas_total_brate, st_ivas->hEncoderConfig->nchan_ism ); /*q0*/
    1121             :     }
    1122       39903 :     test();
    1123       39903 :     test();
    1124       39903 :     IF( GE_32( masa_total_brate, IVAS_384k ) && ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) )
    1125             :     {
    1126             :         Word16 continueLoop;
    1127        2276 :         continueLoop = 1;
    1128        2276 :         move16();
    1129        2276 :         test();
    1130        4552 :         WHILE( ( maxBand > 5 ) && continueLoop )
    1131             :         {
    1132        2276 :             test();
    1133        2276 :             FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1134             :             {
    1135        2276 :                 IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( hMasa->data.energy_fx[sf][maxBand - 1], hMasa->data.energy_e[sf][maxBand - 1], 100000 /*q0*/, 31 ), 1 ) )
    1136             :                 {
    1137        2276 :                     continueLoop = 0;
    1138        2276 :                     move16();
    1139        2276 :                     BREAK;
    1140             :                 }
    1141             :             }
    1142        2276 :             IF( continueLoop )
    1143             :             {
    1144           0 :                 maxBand = (UWord8) sub( maxBand, 1 );
    1145           0 :                 move16(); /*because typecasting word16 to uword8*/
    1146             :             }
    1147             :         }
    1148             : 
    1149        2276 :         IF( LT_16( maxBand, MASA_MAXIMUM_CODING_SUBBANDS ) )
    1150             :         {
    1151         300 :             st_ivas->hQMetaData->q_direction->cfg.inactiveBands = (UWord8) sub( MASA_MAXIMUM_CODING_SUBBANDS, maxBand );
    1152         300 :             move16(); /*because typecasting word16 to uword8*/
    1153             :         }
    1154             :         ELSE
    1155             :         {
    1156        1976 :             st_ivas->hQMetaData->q_direction->cfg.inactiveBands = 0;
    1157        1976 :             move16();
    1158             :         }
    1159             :     }
    1160             : 
    1161             : 
    1162       39903 :     masa_sample_rate_band_correction_fx( &( hMasa->config ), hMasa->data.band_mapping, hQMetaData, maxBand, (UWord8) GE_32( masa_total_brate, IVAS_384k ), NULL );
    1163             : 
    1164             : 
    1165       39903 :     IF( GE_16( hMasa->config.numTwoDirBands, hMasa->config.numCodingBands ) )
    1166             :     {
    1167         380 :         hMasa->config.numTwoDirBands = hMasa->config.numCodingBands;
    1168         380 :         move16();
    1169         380 :         set8_fx( (Word8 *) hMasa->data.twoDirBands, 1, hMasa->config.numCodingBands );
    1170             :     }
    1171             : 
    1172       39903 :     test();
    1173       39903 :     test();
    1174       39903 :     test();
    1175       39903 :     test();
    1176             :     /* Transmit stereo signals using a mono downmix at lowest bitrates */
    1177       39903 :     IF( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && EQ_16( st_ivas->nCPE, 1 ) && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL )
    1178             :     {
    1179       11938 :         IF( LT_32( L_sub( ivas_total_brate, ism_total_brate ), MASA_STEREO_MIN_BITRATE ) )
    1180             :         {
    1181        5484 :             st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 1;
    1182             :         }
    1183             :         ELSE
    1184             :         {
    1185        6454 :             st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0;
    1186             :         }
    1187       11938 :         move16();
    1188             :     }
    1189             : 
    1190       39903 :     test();
    1191       39903 :     test();
    1192       39903 :     test();
    1193       39903 :     IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) && ( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) )
    1194             :     {
    1195        7058 :         test();
    1196        7058 :         IF( EQ_16( st_ivas->hCPE[0]->element_mode, IVAS_CPE_DFT ) || LT_16( st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt, OMASA_STEREO_SW_CNT_MAX ) )
    1197             :         {
    1198        3051 :             st_ivas->hMasa->data.hOmasaData->lp_noise_CPE_fx = st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise_fx; /*Q8*/
    1199             :         }
    1200             :         ELSE
    1201             :         {
    1202             :             /* ( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise + st_ivas->hCPE[0]->hCoreCoder[1]->lp_noise ) / CPE_CHANNELS; */
    1203        4007 :             st_ivas->hMasa->data.hOmasaData->lp_noise_CPE_fx = extract_h( L_mac( L_mult( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise_fx, ONE_IN_Q14 ), st_ivas->hCPE[0]->hCoreCoder[1]->lp_noise_fx, ONE_IN_Q14 ) ); /*Q8*/
    1204             :         }
    1205        7058 :         move16();
    1206             :     }
    1207       39903 :     return error;
    1208             : }
    1209             : /*-----------------------------------------------------------------------*
    1210             :  * ivas_masa_surrcoh_signicant()
    1211             :  *
    1212             :  * Determine if surrounding coherence is significant in this frame and should be encoded
    1213             :  *-----------------------------------------------------------------------*/
    1214        2589 : UWord8 ivas_masa_surrcoh_signicant_fx(
    1215             :     Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   /* i  : Surround coherence     Q31 */
    1216             :     Word32 diffuse_to_total_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i  : Diffuse to total ratio Q31 */
    1217             :     const Word16 nSubFrames,                                                          /* i  : Number of sub frames       */
    1218             :     const Word16 nBands                                                               /* i  : Number of frequency bands  */
    1219             : )
    1220             : {
    1221             :     Word32 significanceMeasure1, significanceMeasure2, significanceMeasure;
    1222             :     Word32 surrCohToTotal, surrCohToTotalSum, surrCohToTotalTimesDiffSum, diffSum;
    1223             :     Word32 sf, band;
    1224             :     Word16 surrCohToTotalSum_e, surrCohToTotalTimesDiffSum_e, diffSum_e;
    1225             : 
    1226             :     // input buffers Q=31
    1227        2589 :     Word32 surrCohSignificanceCoef = 858993459; //( 0.4 * ( 1 << q ) ) 0.4 scaled to Q=31
    1228        2589 :     move32();
    1229        2589 :     Word32 threshold = 214748365; //( 0.1 * ( 1 << q ) )  0.1 scaled to Q=31
    1230        2589 :     move32();
    1231        5802 :     FOR( sf = 0; sf < nSubFrames; sf++ )
    1232             :     {
    1233        3630 :         surrCohToTotalSum = 0;
    1234        3630 :         move32();
    1235        3630 :         surrCohToTotalSum_e = 0;
    1236        3630 :         move16();
    1237        3630 :         surrCohToTotalTimesDiffSum = 0;
    1238        3630 :         move32();
    1239        3630 :         surrCohToTotalTimesDiffSum_e = 0;
    1240        3630 :         move16();
    1241        3630 :         diffSum = 0;
    1242        3630 :         move32();
    1243        3630 :         diffSum_e = 0;
    1244        3630 :         move16();
    1245             : 
    1246       75702 :         FOR( band = 0; band < nBands; band++ )
    1247             :         {
    1248       72072 :             surrCohToTotal = Mpy_32_32( diffuse_to_total_ratio[sf][band], surroundingCoherence[sf][band] ); // Q31
    1249       72072 :             surrCohToTotalSum = BASOP_Util_Add_Mant32Exp( surrCohToTotalSum, surrCohToTotalSum_e, surrCohToTotal, 0, &surrCohToTotalSum_e );
    1250       72072 :             surrCohToTotalTimesDiffSum = BASOP_Util_Add_Mant32Exp( surrCohToTotalTimesDiffSum, surrCohToTotalTimesDiffSum_e, Mpy_32_32( (Word32) diffuse_to_total_ratio[sf][band], surrCohToTotal ), 0, &surrCohToTotalTimesDiffSum_e );
    1251       72072 :             diffSum = BASOP_Util_Add_Mant32Exp( diffSum, diffSum_e, diffuse_to_total_ratio[sf][band], 0, &diffSum_e );
    1252             :         }
    1253             : 
    1254             :         Word16 significanceMeasure1_e, significanceMeasure2_e;
    1255             :         Word16 significanceMeasure_e;
    1256        3630 :         significanceMeasure1 = L_deposit_h( BASOP_Util_Divide3216_Scale( surrCohToTotalSum, nBands, &significanceMeasure1_e ) );
    1257        3630 :         significanceMeasure1_e = add( significanceMeasure1_e, sub( surrCohToTotalSum_e, 15 ) );
    1258        3630 :         significanceMeasure2 = L_deposit_h( BASOP_Util_Divide3232_Scale( Mpy_32_32( surrCohSignificanceCoef, surrCohToTotalTimesDiffSum ), L_add( diffSum, EPSILON_FX ), &significanceMeasure2_e ) );
    1259        3630 :         significanceMeasure2_e = add( significanceMeasure2_e, sub( surrCohToTotalTimesDiffSum_e, diffSum_e ) );
    1260             : 
    1261        3630 :         IF( BASOP_Util_Cmp_Mant32Exp( significanceMeasure1, significanceMeasure1_e, significanceMeasure2, significanceMeasure2_e ) > 0 )
    1262             :         {
    1263        3605 :             significanceMeasure = significanceMeasure1;
    1264        3605 :             move32();
    1265        3605 :             significanceMeasure_e = significanceMeasure1_e;
    1266        3605 :             move16();
    1267             :         }
    1268             :         ELSE
    1269             :         {
    1270          25 :             significanceMeasure = significanceMeasure2;
    1271          25 :             move32();
    1272          25 :             significanceMeasure_e = significanceMeasure2_e;
    1273          25 :             move16();
    1274             :         }
    1275        3630 :         IF( BASOP_Util_Cmp_Mant32Exp( significanceMeasure, significanceMeasure_e, threshold, 0 ) > 0 )
    1276             :         {
    1277         417 :             return 1;
    1278             :         }
    1279             :     }
    1280             : 
    1281        2172 :     return 0;
    1282             : }
    1283             : 
    1284             : /*-----------------------------------------------------------------------*
    1285             :  * Local functions
    1286             :  *-----------------------------------------------------------------------*/
    1287             : 
    1288       41605 : static void combine_freqbands_and_subframes_fx(
    1289             :     MASA_ENCODER_HANDLE hMasa )
    1290             : {
    1291             :     Word16 i, j, k, m;
    1292             :     Word16 aziRad, eleRad;
    1293             :     Word32 x[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1294             :     Word32 y[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1295             :     Word32 z[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1296             :     Word16 x_e[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1297             :     Word16 y_e[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1298             :     Word16 z_e[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1299             :     Word32 vecLen;
    1300             :     Word16 vecLen_e;
    1301             :     Word32 xSum, ySum, zSum;
    1302             :     Word16 xSum_e, ySum_e, zSum_e, common_e;
    1303             :     Word64 xSum_sq, ySum_sq, zSum_sq;
    1304             :     Word32 energySum;
    1305             :     Word16 energySum_e;
    1306             :     Word32 spreadCohSum;
    1307             :     Word16 spreadCohSum_e;
    1308             :     Word32 surrCohSum;
    1309             :     Word16 surrCohSum_e;
    1310             :     Word32 energyRatioSum;
    1311             :     Word16 energyRatioSum_e;
    1312             :     Word16 surrCohTemp;
    1313             :     Word32 energyRatioTemp;
    1314             :     Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1315             :     Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1316             :     Word16 brange[2];
    1317             :     UWord8 numCodingBands;
    1318             :     UWord8 numSf;
    1319             :     UWord8 numDirections;
    1320             :     MASA_METADATA_HANDLE hMeta;
    1321             :     UWord8 mergeRatiosOverSubframes;
    1322             :     UWord8 computeCoherence;
    1323             :     Word16 exp_diff;
    1324             :     Word32 L_tmp;
    1325             :     Word64 W_tmp;
    1326             :     Word16 q_shift;
    1327             : 
    1328       41605 :     numCodingBands = hMasa->config.numCodingBands;
    1329       41605 :     move16();
    1330       41605 :     numDirections = hMasa->config.numberOfDirections;
    1331       41605 :     move16();
    1332       41605 :     IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
    1333             :     {
    1334        5550 :         numSf = 1;
    1335        5550 :         move16();
    1336             :     }
    1337             :     ELSE
    1338             :     {
    1339       36055 :         numSf = MAX_PARAM_SPATIAL_SUBFRAMES;
    1340       36055 :         move16();
    1341             :     }
    1342       41605 :     hMeta = &( hMasa->masaMetadata );
    1343             : 
    1344       41605 :     mergeRatiosOverSubframes = hMasa->config.mergeRatiosOverSubframes;
    1345       41605 :     move16();
    1346       41605 :     test();
    1347       41605 :     IF( hMasa->config.useCoherence && hMasa->config.coherencePresent )
    1348             :     {
    1349       20604 :         computeCoherence = 1;
    1350       20604 :         move16();
    1351             :     }
    1352             :     ELSE
    1353             :     {
    1354       21001 :         computeCoherence = 0;
    1355       21001 :         move16();
    1356             :     }
    1357             : 
    1358             :     /* If metadata subframes are joined then we need all energy to be in the first subframe for combining.
    1359             :      * This optimizes following computations a bit.
    1360             :      * Note: If energy is used elsewhere, then this can cause problems and local energy should be used. */
    1361       41605 :     IF( EQ_16( numSf, 1 ) )
    1362             :     {
    1363       22200 :         FOR( j = 1; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
    1364             :         {
    1365      416250 :             FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
    1366             :             {
    1367      399600 :                 hMasa->data.energy_fx[0][k] = BASOP_Util_Add_Mant32Exp( hMasa->data.energy_fx[0][k], hMasa->data.energy_e[0][k], hMasa->data.energy_fx[j][k], hMasa->data.energy_e[j][k], &hMasa->data.energy_e[0][k] ); // 31-hMasa->data.energy_e[0][k]
    1368      399600 :                 move32();
    1369             :             }
    1370             :         }
    1371             :     }
    1372             : 
    1373       41605 :     IF( LE_16( numCodingBands, MAX_REDUCED_NBANDS ) )
    1374             :     {
    1375             :         /* reduce metadata *frequency* resolution. time resolution is not touched */
    1376       84542 :         FOR( i = 0; i < numDirections; i++ )
    1377             :         {
    1378      212303 :             FOR( j = 0; j < numSf; j++ ) /* NB: for numSf==1, operates only on first sub-frame */
    1379             :             {
    1380     4143100 :                 FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
    1381             :                 {
    1382     3977376 :                     aziRad = extract_l( L_shl( Mpy_32_32( hMeta->directional_meta[i].azimuth_fx[j][k], PI_OVER_180_FX ), Q13 - Q22 ) );   // ((Q22, Q31) -> Q22) >> Q9 -> Q13
    1383     3977376 :                     eleRad = extract_l( L_shl( Mpy_32_32( hMeta->directional_meta[i].elevation_fx[j][k], PI_OVER_180_FX ), Q13 - Q22 ) ); // ((Q22, Q31) -> Q22) >> Q9 -> Q13
    1384     3977376 :                     vecLen = Mpy_32_32( hMeta->directional_meta[i].energy_ratio_fx[j][k], hMasa->data.energy_fx[j][k] );                  // (Q30, 31-hMasa->data.energy_e[j][k]) -> (31-hMasa->data.energy_e[j][k]) - Q1
    1385             : 
    1386             :                     /* Need more precision for some DTX cases with low energy frames */
    1387     3977376 :                     W_tmp = W_mult0_32_32( L_mult( getCosWord16( aziRad ), getCosWord16( eleRad ) ), vecLen ); // (Q29, (31-hMasa->data.energy_e[j][k]) - Q1) -> (Q59 - hMasa->data.energy_e[j][k])
    1388     3977376 :                     q_shift = W_norm( W_tmp );
    1389     3977376 :                     x[i][j][k] = W_extract_h( W_shl( W_tmp, q_shift ) );
    1390     3977376 :                     move32();
    1391     3977376 :                     x_e[i][j][k] = sub( Q31, add( sub( 59, hMasa->data.energy_e[j][k] ), sub( q_shift, 32 ) ) );
    1392     3977376 :                     move16();
    1393             : 
    1394     3977376 :                     W_tmp = W_mult0_32_32( L_mult0( getSinWord16( aziRad ), getCosWord16( eleRad ) ), vecLen ); // (Q29, (31-hMasa->data.energy_e[j][k]) - Q1) -> (Q59 - hMasa->data.energy_e[j][k])
    1395     3977376 :                     q_shift = W_norm( W_tmp );
    1396     3977376 :                     y[i][j][k] = W_extract_h( W_shl( W_tmp, q_shift ) );
    1397     3977376 :                     move32();
    1398     3977376 :                     y_e[i][j][k] = sub( Q31, add( sub( 59, hMasa->data.energy_e[j][k] ), sub( q_shift, 32 ) ) );
    1399     3977376 :                     move16();
    1400             : 
    1401     3977376 :                     W_tmp = W_mult0_32_32( L_mult0( getSinWord16( eleRad ), ONE_IN_Q14 ), vecLen ); // (Q29, (31-hMasa->data.energy_e[j][k]) - Q1) -> (Q59 - hMasa->data.energy_e[j][k])
    1402     3977376 :                     q_shift = W_norm( W_tmp );
    1403     3977376 :                     z[i][j][k] = W_extract_h( W_shl( W_tmp, q_shift ) );
    1404     3977376 :                     move32();
    1405     3977376 :                     z_e[i][j][k] = sub( Q31, add( sub( 59, hMasa->data.energy_e[j][k] ), sub( q_shift, 32 ) ) );
    1406     3977376 :                     move16();
    1407             :                 }
    1408             :             }
    1409             :         }
    1410             : 
    1411       84542 :         FOR( i = 0; i < numDirections; i++ )
    1412             :         {
    1413      212303 :             FOR( j = 0; j < numSf; j++ )
    1414             :             {
    1415     1155432 :                 FOR( k = 0; k < numCodingBands; k++ )
    1416             :                 {
    1417      989708 :                     brange[0] = hMasa->data.band_mapping[k];
    1418      989708 :                     move16();
    1419      989708 :                     brange[1] = hMasa->data.band_mapping[k + 1];
    1420      989708 :                     move16();
    1421             : 
    1422      989708 :                     xSum = 0;
    1423      989708 :                     ySum = 0;
    1424      989708 :                     zSum = 0;
    1425      989708 :                     energySum = 0;
    1426      989708 :                     spreadCohSum = 0;
    1427      989708 :                     xSum_e = 0;
    1428      989708 :                     ySum_e = 0;
    1429      989708 :                     zSum_e = 0;
    1430      989708 :                     energySum_e = 0;
    1431      989708 :                     spreadCohSum_e = 0;
    1432      989708 :                     move32();
    1433      989708 :                     move32();
    1434      989708 :                     move32();
    1435      989708 :                     move32();
    1436      989708 :                     move32();
    1437      989708 :                     move16();
    1438      989708 :                     move16();
    1439      989708 :                     move16();
    1440      989708 :                     move16();
    1441      989708 :                     move16();
    1442             : 
    1443     4860002 :                     FOR( m = brange[0]; m < brange[1]; m++ )
    1444             :                     {
    1445     3870294 :                         xSum = BASOP_Util_Add_Mant32Exp( xSum, xSum_e, x[i][j][m], x_e[i][j][m], &xSum_e );                                                    // xSum_e
    1446     3870294 :                         ySum = BASOP_Util_Add_Mant32Exp( ySum, ySum_e, y[i][j][m], y_e[i][j][m], &ySum_e );                                                    // ySum_e
    1447     3870294 :                         zSum = BASOP_Util_Add_Mant32Exp( zSum, zSum_e, z[i][j][m], z_e[i][j][m], &zSum_e );                                                    // zSum_e
    1448     3870294 :                         energySum = BASOP_Util_Add_Mant32Exp( energySum, energySum_e, hMasa->data.energy_fx[j][m], hMasa->data.energy_e[j][m], &energySum_e ); // energySum_e
    1449             :                     }
    1450      989708 :                     common_e = add( s_max( xSum_e, s_max( ySum_e, zSum_e ) ), 2 ); /*2 is guard bit for addition operations*/
    1451      989708 :                     xSum = L_shr( xSum, sub( common_e, xSum_e ) );                 /*common_e*/
    1452      989708 :                     ySum = L_shr( ySum, sub( common_e, ySum_e ) );                 /*common_e*/
    1453      989708 :                     zSum = L_shr( zSum, sub( common_e, zSum_e ) );                 /*common_e*/
    1454      989708 :                     aziRad = BASOP_util_atan2( ySum, xSum, 0 );                    // Q13
    1455      989708 :                     xSum_sq = W_mult0_32_32( xSum, xSum );                         // 2 * (31-common_e)
    1456      989708 :                     ySum_sq = W_mult0_32_32( ySum, ySum );                         // 2 *  (31-common_e)
    1457      989708 :                     zSum_sq = W_mult0_32_32( zSum, zSum );                         // 2 * (31-common_e)
    1458      989708 :                     W_tmp = W_add( xSum_sq, ySum_sq );                             // 2 *  (31-common_e)
    1459      989708 :                     q_shift = W_norm( W_tmp );
    1460      989708 :                     L_tmp = W_extract_h( W_shl( W_tmp, q_shift ) ); // 2 *  (31-common_e) + (q_shift -32)
    1461      989708 :                     exp_diff = sub( Q31, add( imult1616( 2, sub( 31, common_e ) ), sub( q_shift, 32 ) ) );
    1462      989708 :                     L_tmp = Sqrt32( L_tmp, &exp_diff );
    1463      989708 :                     eleRad = BASOP_util_atan2( zSum, L_tmp, sub( common_e, exp_diff ) ); // Q13
    1464             : 
    1465      989708 :                     hMeta->directional_meta[i].azimuth_fx[j][k] = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, aziRad ), Q1 ); // ((Q25, Q13) -> Q23) >> Q1 -> Q22
    1466      989708 :                     move32();
    1467      989708 :                     hMeta->directional_meta[i].elevation_fx[j][k] = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, eleRad ), Q1 ); // ((Q25, Q13) -> Q23) >> Q1 -> Q22
    1468      989708 :                     move32();
    1469             : 
    1470      989708 :                     W_tmp = W_add( xSum_sq, ySum_sq ); // 2 *  (31-common_e)
    1471      989708 :                     W_tmp = W_add( W_tmp, zSum_sq );   // 2 *  (31-common_e)
    1472      989708 :                     q_shift = W_norm( W_tmp );
    1473      989708 :                     vecLen = W_extract_h( W_shl( W_tmp, q_shift ) ); // 2 *  (31-common_e) + (q_shift -32)
    1474      989708 :                     exp_diff = sub( Q31, add( imult1616( 2, sub( 31, common_e ) ), sub( q_shift, 32 ) ) );
    1475      989708 :                     vecLen = Sqrt32( vecLen, &exp_diff );
    1476      989708 :                     vecLen_e = exp_diff;
    1477      989708 :                     move16();
    1478             : 
    1479     1979416 :                     hMeta->directional_meta[i].energy_ratio_fx[j][k] =
    1480      989708 :                         BASOP_Util_Divide3232_Scale_newton( vecLen, L_add( energySum, EPSILON_FX ), &exp_diff ); /*exp_diff+vecLen_e-energySum_e*/
    1481      989708 :                     move32();
    1482      989708 :                     exp_diff = add( exp_diff, sub( vecLen_e, energySum_e ) );
    1483     1979416 :                     hMeta->directional_meta[i].energy_ratio_fx[j][k] =
    1484      989708 :                         L_shl( hMeta->directional_meta[i].energy_ratio_fx[j][k], sub( exp_diff, Q1 ) ); // (Q31 - exp_diff ) -> Q30
    1485      989708 :                     move32();
    1486             : 
    1487      989708 :                     IF( computeCoherence )
    1488             :                     {
    1489     2379466 :                         FOR( m = brange[0]; m < brange[1]; m++ )
    1490             :                         {
    1491     1827408 :                             spreadCohSum = BASOP_Util_Add_Mant32Exp( spreadCohSum, spreadCohSum_e, Mpy_32_16_1( hMasa->data.energy_fx[j][m], hMeta->directional_meta[i].spread_coherence_fx[j][m] ), hMasa->data.energy_e[j][m], &spreadCohSum_e ); // 31-spreadCohSum_e
    1492             :                         }
    1493      552058 :                         hMeta->directional_meta[i].spread_coherence_fx[j][k] = BASOP_Util_Divide3232_Scale( spreadCohSum, L_add( energySum, EPSILON_FX ), &exp_diff ); /*exp_diff+spreadCohSum_e-energySum_e*/
    1494      552058 :                         exp_diff = add( exp_diff, sub( spreadCohSum_e, energySum_e ) );
    1495      552058 :                         move16();
    1496             :                         /* Saturation - LTV fix for values close to 1.0f+ */
    1497      552058 :                         hMeta->directional_meta[i].spread_coherence_fx[j][k] = shl_sat( hMeta->directional_meta[i].spread_coherence_fx[j][k], exp_diff ); // Q15
    1498      552058 :                         move16();
    1499             : 
    1500      552058 :                         IF( i == 0 )
    1501             :                         {
    1502      427914 :                             surrCohSum = 0;
    1503      427914 :                             surrCohSum_e = 0;
    1504      427914 :                             move32();
    1505      427914 :                             move16();
    1506     1833186 :                             FOR( m = brange[0]; m < brange[1]; m++ )
    1507             :                             {
    1508     1405272 :                                 surrCohSum = BASOP_Util_Add_Mant32Exp( surrCohSum, surrCohSum_e, Mpy_32_16_1( hMasa->data.energy_fx[j][m], hMeta->common_meta.surround_coherence_fx[j][m] ), hMasa->data.energy_e[j][m], &surrCohSum_e ); // 31-surrCohSum_e
    1509             :                             }
    1510      427914 :                             hMeta->common_meta.surround_coherence_fx[j][k] = BASOP_Util_Divide3232_Scale( surrCohSum, L_add( energySum, EPSILON_FX ), &exp_diff ); /*exp_diff+surrCohSum_e-energySum_e*/
    1511      427914 :                             move16();
    1512      427914 :                             exp_diff = add( exp_diff, sub( surrCohSum_e, energySum_e ) );
    1513             :                             /* Saturation - LTV fix for values close to 1.0f+ */
    1514      427914 :                             hMeta->common_meta.surround_coherence_fx[j][k] = shl_sat( hMeta->common_meta.surround_coherence_fx[j][k], exp_diff ); // Q15
    1515      427914 :                             move16();
    1516             :                         }
    1517             :                     }
    1518             : 
    1519      989708 :                     IF( i == 0 )
    1520             :                     {
    1521      805350 :                         energy[j][k] = energySum; // 31-energySum_e
    1522      805350 :                         energy_e[j][k] = energySum_e;
    1523      805350 :                         move32();
    1524      805350 :                         move16();
    1525             :                     }
    1526             :                 }
    1527             :             }
    1528             :         }
    1529             :     }
    1530        3642 :     ELSE IF( mergeRatiosOverSubframes ) /* keep frequency resolution */
    1531             :     {
    1532        5700 :         FOR( j = 0; j < numSf; j++ )
    1533             :         {
    1534      114000 :             FOR( k = 0; k < numCodingBands; k++ )
    1535             :             {
    1536      109440 :                 energy[j][k] = hMasa->data.energy_fx[j][k]; // 31-hMasa->data.energy_e[j][k]
    1537      109440 :                 energy_e[j][k] = hMasa->data.energy_e[j][k];
    1538      109440 :                 move32();
    1539      109440 :                 move16();
    1540             :             }
    1541             :         }
    1542             :     }
    1543             : 
    1544       41605 :     IF( mergeRatiosOverSubframes )
    1545             :     {
    1546      244114 :         FOR( k = 0; k < numCodingBands; k++ )
    1547             :         {
    1548      210663 :             energySum = 0;
    1549      210663 :             move32();
    1550      210663 :             energySum_e = 0;
    1551      210663 :             move16();
    1552     1053315 :             FOR( j = 0; j < numSf; j++ )
    1553             :             {
    1554      842652 :                 energySum = BASOP_Util_Add_Mant32Exp( energySum, energySum_e, energy[j][k], energy_e[j][k], &energySum_e ); // 31-energySum_e
    1555             :             }
    1556             : 
    1557      210663 :             IF( computeCoherence )
    1558             :             {
    1559      122333 :                 surrCohSum = 0;
    1560      122333 :                 surrCohSum_e = 0;
    1561      122333 :                 move32();
    1562      122333 :                 move16();
    1563      611665 :                 FOR( j = 0; j < numSf; j++ )
    1564             :                 {
    1565      489332 :                     surrCohSum = BASOP_Util_Add_Mant32Exp( surrCohSum, surrCohSum_e, Mpy_32_16_1( energy[j][k], hMeta->common_meta.surround_coherence_fx[j][k] ), energy_e[j][k], &surrCohSum_e ); // 31-surrCohSum_e
    1566             :                 }
    1567      122333 :                 surrCohTemp = BASOP_Util_Divide3232_Scale( surrCohSum, L_add( energySum, EPSILON_FX ), &exp_diff );
    1568      122333 :                 exp_diff = add( exp_diff, sub( surrCohSum_e, energySum_e ) );
    1569      122333 :                 surrCohTemp = shl_sat( surrCohTemp, exp_diff ); // Q15
    1570             : 
    1571      611665 :                 FOR( j = 0; j < numSf; j++ )
    1572             :                 {
    1573      489332 :                     hMeta->common_meta.surround_coherence_fx[j][k] = surrCohTemp; // Q15
    1574      489332 :                     move16();
    1575             :                 }
    1576             :             }
    1577             : 
    1578      459874 :             FOR( i = 0; i < numDirections; i++ )
    1579             :             {
    1580      249211 :                 energyRatioSum = 0;
    1581      249211 :                 energyRatioSum_e = 0;
    1582      249211 :                 move32();
    1583      249211 :                 move16();
    1584     1246055 :                 FOR( j = 0; j < numSf; j++ )
    1585             :                 {
    1586      996844 :                     energyRatioSum = BASOP_Util_Add_Mant32Exp( energyRatioSum, energyRatioSum_e, Mpy_32_32( energy[j][k], hMeta->directional_meta[i].energy_ratio_fx[j][k] ), add( energy_e[j][k], 1 ), &energyRatioSum_e ); // 31-energyRatioSum_e
    1587             :                 }
    1588      249211 :                 energyRatioTemp = BASOP_Util_Divide3232_Scale_newton( energyRatioSum, L_add( energySum, EPSILON_FX ), &exp_diff );
    1589      249211 :                 exp_diff = add( exp_diff, sub( energyRatioSum_e, energySum_e ) );
    1590      249211 :                 energyRatioTemp = L_shl( energyRatioTemp, sub( exp_diff, 1 ) ); // Q30
    1591             : 
    1592     1246055 :                 FOR( j = 0; j < numSf; j++ )
    1593             :                 {
    1594      996844 :                     hMeta->directional_meta[i].energy_ratio_fx[j][k] = energyRatioTemp; // Q30
    1595      996844 :                     move32();
    1596             :                 }
    1597             :             }
    1598             :         }
    1599             :     }
    1600             : 
    1601       41605 :     return;
    1602             : }
    1603             : 
    1604             : 
    1605             : /*-------------------------------------------------------------------*
    1606             :  * ivas_masa_combine_directions()
    1607             :  *
    1608             :  *
    1609             :  *-------------------------------------------------------------------*/
    1610        9520 : void ivas_masa_combine_directions_fx(
    1611             :     MASA_ENCODER_HANDLE hMasa )
    1612             : {
    1613             :     Word16 i, j, k;
    1614             :     UWord8 numCodingBands;
    1615             :     UWord8 numSf;
    1616             :     UWord8 numDirections;
    1617             :     UWord8 computeCoherence;
    1618             :     MASA_METADATA_HANDLE hMeta;
    1619             : 
    1620             :     Word16 aziRad_fx;
    1621             :     Word16 eleRad_fx;
    1622             :     Word32 x_fx[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1623             :     Word32 y_fx[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1624             :     Word32 z_fx[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1625             :     Word32 vecLen_fx;
    1626             :     Word32 xSum_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1627             :     Word32 ySum_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1628             :     Word32 zSum_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1629             :     Word32 sumVecLen_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1630        9520 :     Word16 exp_sumVecLen_buff[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], exp_sumVecLen = MIN16B_FLT_FX;
    1631        9520 :     move16();
    1632             :     Word32 tempImportance_fx;
    1633             :     Word32 importance_fx[MASA_FREQUENCY_BANDS];
    1634             :     Word16 exp_importance;
    1635             :     Word16 indicesOfLargest[MASA_FREQUENCY_BANDS];
    1636             : 
    1637             :     Word32 ratioSum_fx;
    1638             :     Word32 ambience1dir_fx;
    1639             :     Word32 ambience2dir_fx;
    1640             :     Word32 ambienceIncrease_fx;
    1641             :     Word32 origSurrCohEne_fx;
    1642             :     Word32 newSurrCohEne_fx;
    1643             : 
    1644        9520 :     numCodingBands = hMasa->config.numCodingBands;
    1645        9520 :     numDirections = hMasa->config.numberOfDirections;
    1646        9520 :     move16();
    1647        9520 :     move16();
    1648             : 
    1649        9520 :     IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
    1650             :     {
    1651        1800 :         numSf = 1;
    1652             :     }
    1653             :     ELSE
    1654             :     {
    1655        7720 :         numSf = MAX_PARAM_SPATIAL_SUBFRAMES;
    1656             :     }
    1657        9520 :     move16();
    1658        9520 :     hMeta = &( hMasa->masaMetadata );
    1659             : 
    1660        9520 :     computeCoherence = hMasa->config.useCoherence && hMasa->config.coherencePresent;
    1661        9520 :     move16();
    1662        9520 :     Word16 azi_cos = 0, azi_sine = 0, ele_cos = 0, ele_sine = 0;
    1663        9520 :     move16();
    1664        9520 :     move16();
    1665        9520 :     move16();
    1666        9520 :     move16();
    1667       28560 :     FOR( i = 0; i < numDirections; i++ )
    1668             :     {
    1669       84400 :         FOR( j = 0; j < numSf; j++ )
    1670             :         {
    1671      865744 :             FOR( k = 0; k < numCodingBands; k++ )
    1672             :             {
    1673      800384 :                 aziRad_fx = extract_l( L_shr( Mpy_32_32( hMeta->directional_meta[i].azimuth_fx[j][k], PI_OVER_180_Q25 ), 3 ) ); // (Q22 + Q25 - 31) - 3 = Q13
    1674      800384 :                 azi_cos = getCosWord16( aziRad_fx );                                                                            // Q14
    1675      800384 :                 azi_sine = getSinWord16( aziRad_fx );                                                                           // Q15
    1676             : 
    1677      800384 :                 eleRad_fx = extract_l( L_shr( Mpy_32_32( hMeta->directional_meta[i].elevation_fx[j][k], PI_OVER_180_Q25 ), 3 ) ); // (Q22 + Q25 - 31) - 3 = Q13
    1678      800384 :                 ele_sine = getSinWord16( eleRad_fx );                                                                             // Q15
    1679      800384 :                 ele_cos = getCosWord16( eleRad_fx );                                                                              // Q14
    1680             : 
    1681      800384 :                 vecLen_fx = hMeta->directional_meta[i].energy_ratio_fx[j][k];
    1682      800384 :                 move32();
    1683             : 
    1684      800384 :                 x_fx[i][j][k] = L_mult0( azi_cos, ele_cos );                     // Q14+Q14
    1685      800384 :                 x_fx[i][j][k] = Mpy_32_32( x_fx[i][j][k], vecLen_fx );           // Q28+Q30-31
    1686      800384 :                 y_fx[i][j][k] = L_mult0( azi_sine, ele_cos );                    // Q15+Q14
    1687      800384 :                 y_fx[i][j][k] = Mpy_32_32( y_fx[i][j][k], vecLen_fx );           // Q29+Q30-31
    1688      800384 :                 z_fx[i][j][k] = Mpy_32_32( L_deposit_h( ele_sine ), vecLen_fx ); // Q16+Q15+Q30 - 31
    1689      800384 :                 move32();
    1690      800384 :                 move32();
    1691      800384 :                 move32();
    1692      800384 :                 move32();
    1693      800384 :                 move32();
    1694             :             }
    1695             :         }
    1696             :     }
    1697             : 
    1698             :     /* Compute sum vector */
    1699       42200 :     FOR( j = 0; j < numSf; j++ )
    1700             :     {
    1701      432872 :         FOR( k = 0; k < numCodingBands; k++ )
    1702             :         {
    1703      400192 :             xSum_fx[j][k] = L_add( x_fx[0][j][k], x_fx[1][j][k] ); // Q27
    1704      400192 :             ySum_fx[j][k] = L_add( y_fx[0][j][k], y_fx[1][j][k] ); // Q28
    1705      400192 :             zSum_fx[j][k] = L_add( z_fx[0][j][k], z_fx[1][j][k] ); // Q30
    1706      400192 :             move32();
    1707      400192 :             move32();
    1708      400192 :             move32();
    1709             : 
    1710      400192 :             Word32 var1 = Mpy_32_32( xSum_fx[j][k], xSum_fx[j][k] );                  // Q27 + Q27 - 31 //Q23
    1711      400192 :             Word32 var2 = Mpy_32_32( ySum_fx[j][k], ySum_fx[j][k] );                  // Q28 + Q28 - 31 //Q25
    1712      400192 :             Word32 var3 = Mpy_32_32( zSum_fx[j][k], zSum_fx[j][k] );                  // Q30 + Q30 - 31 //Q29
    1713      400192 :             Word32 var4 = L_add( L_add( var1, L_shr( var2, 2 ) ), L_shr( var3, 6 ) ); // Q23
    1714      400192 :             Word16 exp_var4 = 31 - Q23;
    1715      400192 :             move16();
    1716             : 
    1717      400192 :             Word16 exp_var5 = exp_var4;
    1718      400192 :             move16();
    1719      400192 :             Word32 var5 = 0;
    1720      400192 :             move32();
    1721             : 
    1722      400192 :             IF( var4 != 0 )
    1723             :             {
    1724      400192 :                 var5 = Sqrt32( var4, &exp_var5 );
    1725             :             }
    1726      400192 :             sumVecLen_fx[j][k] = var5;
    1727      400192 :             move32();
    1728      400192 :             exp_sumVecLen_buff[j][k] = exp_var5;
    1729      400192 :             move16();
    1730             :         }
    1731             :     }
    1732             : 
    1733             :     /*make commen exp for sumVecLen_fx buffer*/
    1734       42200 :     FOR( j = 0; j < numSf; j++ )
    1735             :     {
    1736      432872 :         FOR( k = 0; k < numCodingBands; k++ )
    1737             :         {
    1738      400192 :             exp_sumVecLen = s_max( exp_sumVecLen_buff[j][k], exp_sumVecLen );
    1739             :         }
    1740             :     }
    1741             : 
    1742       42200 :     FOR( j = 0; j < numSf; j++ )
    1743             :     {
    1744      432872 :         FOR( k = 0; k < numCodingBands; k++ )
    1745             :         {
    1746      400192 :             sumVecLen_fx[j][k] = L_shr( sumVecLen_fx[j][k], sub( exp_sumVecLen, exp_sumVecLen_buff[j][k] ) );
    1747      400192 :             move32();
    1748             :         }
    1749             :     }
    1750             : 
    1751             :     /* Estimate the importance of having two directions instead of one */
    1752             :     /* Reduced precision of importance_fx intentionally to Q13 to maintatin 0.0001f resolution */
    1753      132644 :     FOR( i = 0; i < numCodingBands; i++ )
    1754             :     {
    1755      123124 :         importance_fx[i] = 0;
    1756      123124 :         move32();
    1757      523316 :         FOR( j = 0; j < numSf; j++ )
    1758             :         {
    1759      400192 :             tempImportance_fx = L_shr( L_add( hMeta->directional_meta[0].energy_ratio_fx[j][i], hMeta->directional_meta[1].energy_ratio_fx[j][i] ), Q30 - Q13 ); // Q13
    1760      400192 :             tempImportance_fx = L_sub( tempImportance_fx, L_shr( sumVecLen_fx[j][i], sub( sub( Q31, exp_sumVecLen ), Q13 ) ) );                                  // Q13
    1761      400192 :             importance_fx[i] = L_add( importance_fx[i], tempImportance_fx );                                                                                     // Q13
    1762      400192 :             move32();
    1763             :         }
    1764             : 
    1765      123124 :         IF( NE_16( numSf, 1 ) )
    1766             :         {
    1767       92356 :             importance_fx[i] = L_shr( importance_fx[i], 2 ); // Q13
    1768       92356 :             move32();
    1769             :         }
    1770      123124 :         importance_fx[i] = Mpy_32_32( importance_fx[i], hMasa->data.importanceWeight_fx[i] ); //(Q13, Q30) -> Q12
    1771      123124 :         move32();
    1772             :     }
    1773        9520 :     exp_importance = Q31 - Q12;
    1774        9520 :     move16();
    1775             : 
    1776             :     /* Determine bands where to use two directions */
    1777        9520 :     find_n_largest_fx( importance_fx, exp_importance, indicesOfLargest, numCodingBands, hMasa->config.numTwoDirBands );
    1778             : 
    1779      132644 :     FOR( i = 0; i < numCodingBands; i++ )
    1780             :     {
    1781      123124 :         hMasa->data.twoDirBands[i] = 0;
    1782      123124 :         move16();
    1783             :     }
    1784             : 
    1785       31054 :     FOR( i = 0; i < hMasa->config.numTwoDirBands; i++ )
    1786             :     {
    1787       21534 :         hMasa->data.twoDirBands[indicesOfLargest[i]] = 1;
    1788       21534 :         move16();
    1789             :     }
    1790             : 
    1791             :     /* Combine directions on the remaining bands */
    1792      132644 :     FOR( i = 0; i < numCodingBands; i++ )
    1793             :     {
    1794      123124 :         IF( hMasa->data.twoDirBands[i] == 0 )
    1795             :         {
    1796      430178 :             FOR( j = 0; j < numSf; j++ )
    1797             :             {
    1798      328588 :                 aziRad_fx = BASOP_util_atan2( ySum_fx[j][i], xSum_fx[j][i], Q27 - Q28 ); // Q13
    1799      328588 :                 Word32 tmp1 = Mpy_32_32( xSum_fx[j][i], xSum_fx[j][i] );                 // Q27+Q27-31 //Q23
    1800      328588 :                 Word32 tmp2 = Mpy_32_32( ySum_fx[j][i], ySum_fx[j][i] );                 // Q28+Q28-31 //Q25
    1801      328588 :                 Word32 tmp3 = L_add( tmp1, L_shr( tmp2, 2 ) );                           // Q23
    1802      328588 :                 Word16 exp_tmp3 = 31 - Q23;
    1803      328588 :                 move16();
    1804      328588 :                 Word32 tmp4 = Sqrt32( tmp3, &exp_tmp3 );
    1805      328588 :                 eleRad_fx = BASOP_util_atan2( zSum_fx[j][i], tmp4, sub( sub( 31, Q30 ), exp_tmp3 ) );
    1806             : 
    1807      328588 :                 Word16 exp_tmp5 = 0;
    1808      328588 :                 move16();
    1809      328588 :                 Word16 tmp5 = BASOP_Util_Divide1616_Scale( aziRad_fx, EVS_PI_FX, &exp_tmp5 );
    1810      328588 :                 Word16 Q_tmp6 = 0;
    1811      328588 :                 move16();
    1812      328588 :                 Word32 tmp6 = L_mult( tmp5, 23040 /*180.0f in Q7*/ );
    1813      328588 :                 Q_tmp6 = sub( 31, add( exp_tmp5, 8 ) );
    1814             : 
    1815      328588 :                 Word16 exp_tmp7 = 0;
    1816      328588 :                 move16();
    1817      328588 :                 Word16 tmp7 = BASOP_Util_Divide1616_Scale( eleRad_fx, EVS_PI_FX, &exp_tmp7 );
    1818      328588 :                 Word16 Q_tmp8 = 0;
    1819      328588 :                 move16();
    1820      328588 :                 Word32 tmp8 = L_mult( tmp7, 23040 /*180.0f in Q7*/ );
    1821      328588 :                 Q_tmp8 = sub( 31, add( exp_tmp7, 8 ) );
    1822             : 
    1823      328588 :                 Scale_sig32( &tmp6, 1, Q22 - Q_tmp6 );
    1824      328588 :                 Scale_sig32( &tmp8, 1, Q22 - Q_tmp8 );
    1825             : 
    1826      328588 :                 hMeta->directional_meta[0].azimuth_fx[j][i] = tmp6;   // Q22
    1827      328588 :                 hMeta->directional_meta[0].elevation_fx[j][i] = tmp8; // Q22
    1828      328588 :                 move32();
    1829      328588 :                 move32();
    1830      328588 :                 ratioSum_fx = L_add( hMeta->directional_meta[0].energy_ratio_fx[j][i], hMeta->directional_meta[1].energy_ratio_fx[j][i] ); // Q30
    1831      328588 :                 IF( computeCoherence )
    1832             :                 {
    1833      127198 :                     Word32 var1 = Mpy_32_16_1( hMeta->directional_meta[0].energy_ratio_fx[j][i], hMeta->directional_meta[0].spread_coherence_fx[j][i] );
    1834      127198 :                     Word32 var2 = Mpy_32_16_1( hMeta->directional_meta[1].energy_ratio_fx[j][i], hMeta->directional_meta[1].spread_coherence_fx[j][i] );
    1835      127198 :                     Word32 var3 = L_add( var1, var2 ); // Q30
    1836      127198 :                     Word16 exp_var4 = 0;
    1837      127198 :                     move16();
    1838      127198 :                     Word32 var4 = BASOP_Util_Add_Mant32Exp( ratioSum_fx, 31 - Q30, EPSILON_FX_M, EPSILON_FX_E, &exp_var4 );
    1839      127198 :                     Word16 exp_var5 = 0;
    1840      127198 :                     move16();
    1841      127198 :                     Word16 var5 = BASOP_Util_Divide3232_Scale( var3, var4, &exp_var5 );
    1842      127198 :                     exp_var5 = add( exp_var5, ( sub( sub( 31, Q30 ), exp_var4 ) ) );
    1843      127198 :                     Scale_sig( &var5, 1, sub( Q15, sub( 15, exp_var5 ) ) );
    1844      127198 :                     hMeta->directional_meta[0].spread_coherence_fx[j][i] = var5; // Q15
    1845      127198 :                     move16();
    1846             :                 }
    1847             : 
    1848      328588 :                 ambience2dir_fx = L_sub( ONE_IN_Q30, ratioSum_fx ); // Q30
    1849      328588 :                 Word32 ambience2dir_fx_by_2 = L_shr( ambience2dir_fx, 1 );
    1850      328588 :                 Word32 var_a = L_add( L_add( hMeta->directional_meta[0].energy_ratio_fx[j][i], hMeta->directional_meta[1].energy_ratio_fx[j][i] ), ambience2dir_fx_by_2 ); // Q30
    1851      328588 :                 Word16 exp_var_b = 0;
    1852      328588 :                 move16();
    1853      328588 :                 Word16 var_b = BASOP_Util_Divide3232_Scale( sumVecLen_fx[j][i], var_a, &exp_var_b );
    1854      328588 :                 exp_var_b = add( exp_var_b, sub( exp_sumVecLen, 1 ) );
    1855      328588 :                 Word32 var_b_32 = L_deposit_h( var_b );
    1856      328588 :                 hMeta->directional_meta[0].energy_ratio_fx[j][i] = L_shr( var_b_32, 1 - exp_var_b ); // Q30
    1857      328588 :                 hMeta->directional_meta[1].energy_ratio_fx[j][i] = 0;                                // Q30
    1858      328588 :                 move16();
    1859      328588 :                 move16();
    1860             : 
    1861      328588 :                 IF( computeCoherence )
    1862             :                 {
    1863      127198 :                     ambience1dir_fx = L_sub( ONE_IN_Q30, hMeta->directional_meta[0].energy_ratio_fx[j][i] );                                     // Q30
    1864      127198 :                     ambienceIncrease_fx = L_max( L_sub( ambience1dir_fx, ambience2dir_fx ), 0 );                                                 // Q30
    1865      127198 :                     origSurrCohEne_fx = Mpy_32_16_1( ambience2dir_fx /*Q30*/, hMeta->common_meta.surround_coherence_fx[j][i] /*Q15*/ );          // Q30
    1866      127198 :                     newSurrCohEne_fx = Mpy_32_16_1( ambienceIncrease_fx /*Q30*/, hMeta->directional_meta[0].spread_coherence_fx[j][i] /*Q15*/ ); // Q30
    1867             : 
    1868      127198 :                     Word16 exp_y = 0, exp_z = 0;
    1869      127198 :                     move16();
    1870      127198 :                     move16();
    1871      127198 :                     Word32 x = L_add( origSurrCohEne_fx, newSurrCohEne_fx ); // Q30
    1872      127198 :                     Word32 y = BASOP_Util_Add_Mant32Exp( ambience1dir_fx, 1, EPSILON_FX_M, EPSILON_FX_E, &exp_y );
    1873      127198 :                     Word16 z = BASOP_Util_Divide3232_Scale( x, y, &exp_z );
    1874      127198 :                     exp_z = add( exp_z, ( sub( 31 - Q30, exp_y ) ) );
    1875      127198 :                     z = shl_sat( z, exp_z ); // Q15
    1876      127198 :                     hMeta->common_meta.surround_coherence_fx[j][i] = s_min( MAX16B, z );
    1877      127198 :                     move16();
    1878             :                 }
    1879             :             }
    1880             :         }
    1881             :     }
    1882             : 
    1883        9520 :     return;
    1884             : }
    1885             : 
    1886        9520 : static void find_n_largest_fx(
    1887             :     const Word32 *input_fx, // Q(31 - exp_input)
    1888             :     Word16 exp_input,
    1889             :     Word16 *largestIndices,
    1890             :     const Word16 numElements,
    1891             :     const Word16 numLargest )
    1892             : {
    1893             :     Word16 i, j;
    1894             :     Word32 largestValue;
    1895             :     Word16 largestIndex;
    1896             :     Word32 values[MASA_FREQUENCY_BANDS];
    1897             : 
    1898      132644 :     FOR( j = 0; j < numElements; j++ )
    1899             :     {
    1900      123124 :         values[j] = input_fx[j]; // Q(31 - exp_input)
    1901      123124 :         move32();
    1902             :     }
    1903             : 
    1904       31054 :     FOR( i = 0; i < numLargest; i++ )
    1905             :     {
    1906       21534 :         largestValue = values[0]; // Q(31 - exp_input)
    1907       21534 :         move32();
    1908       21534 :         largestIndex = 0;
    1909       21534 :         move16();
    1910      342038 :         FOR( j = 1; j < numElements; j++ )
    1911             :         {
    1912      320504 :             IF( GT_32( values[j], largestValue ) )
    1913             :             {
    1914       41074 :                 largestValue = values[j]; // Q(31 - exp_input)
    1915       41074 :                 largestIndex = j;
    1916       41074 :                 move32();
    1917       41074 :                 move16();
    1918             :             }
    1919             :         }
    1920       21534 :         largestIndices[i] = largestIndex;
    1921       21534 :         move16();
    1922       21534 :         IF( exp_input != 0 )
    1923             :         {
    1924       21534 :             values[largestIndex] = L_negate( 1 << ( sub( 31, exp_input ) ) ); // Q(31 - exp_input)
    1925       21534 :             move32();
    1926             :         }
    1927             :         ELSE
    1928             :         {
    1929           0 :             values[largestIndex] = 1 << ( sub( 31, exp_input ) ); // Q(31 - exp_input)
    1930           0 :             move32();
    1931             :         }
    1932             :     }
    1933             : 
    1934        9520 :     return;
    1935             : }
    1936             : 
    1937       41605 : static void move_metadata_to_qmetadata_fx(
    1938             :     const MASA_ENCODER_HANDLE hMasa,
    1939             :     IVAS_QMETADATA_HANDLE hQMeta )
    1940             : {
    1941             :     Word16 dir, sf, band;
    1942             :     UWord8 numCodingBands;
    1943             :     UWord8 numDirections;
    1944             :     UWord8 numSf;
    1945             :     MASA_METADATA_HANDLE hMeta;
    1946             : 
    1947       41605 :     numCodingBands = hMasa->config.numCodingBands;
    1948       41605 :     numDirections = hMasa->config.numberOfDirections;
    1949       41605 :     move16();
    1950       41605 :     move16();
    1951       41605 :     move16();
    1952       41605 :     numSf = 4;
    1953       41605 :     if ( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
    1954             :     {
    1955        5550 :         numSf = 1;
    1956        5550 :         move16();
    1957             :     }
    1958       41605 :     hMeta = &( hMasa->masaMetadata );
    1959             : 
    1960       89046 :     FOR( dir = 0; dir < numDirections; dir++ )
    1961             :     {
    1962      217567 :         FOR( sf = 0; sf < numSf; sf++ )
    1963             :         {
    1964     1526120 :             FOR( band = 0; band < numCodingBands; band++ )
    1965             :             {
    1966     1355994 :                 hQMeta->q_direction[dir].band_data[band].azimuth_fx[sf] = hMeta->directional_meta[dir].azimuth_fx[sf][band];           // Q22
    1967     1355994 :                 hQMeta->q_direction[dir].band_data[band].elevation_fx[sf] = hMeta->directional_meta[dir].elevation_fx[sf][band];       // Q22
    1968     1355994 :                 hQMeta->q_direction[dir].band_data[band].energy_ratio_fx[sf] = hMeta->directional_meta[dir].energy_ratio_fx[sf][band]; // Q30
    1969     1355994 :                 hQMeta->q_direction[dir].band_data[band].spherical_index[sf] = hMeta->directional_meta[dir].spherical_index[sf][band];
    1970     1355994 :                 move32();
    1971     1355994 :                 move32();
    1972     1355994 :                 move32();
    1973     1355994 :                 move16();
    1974             : 
    1975     1355994 :                 IF( hQMeta->q_direction[dir].coherence_band_data != NULL )
    1976             :                 {
    1977      990540 :                     hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[sf] = (UWord8) mult_r( hMeta->directional_meta[dir].spread_coherence_fx[sf][band], UINT8_MAX ); // Q15
    1978      990540 :                     move16();
    1979             :                 }
    1980             :             }
    1981             :         }
    1982             :     }
    1983             : 
    1984      191375 :     FOR( sf = 0; sf < numSf; sf++ )
    1985             :     {
    1986     1280362 :         FOR( band = 0; band < numCodingBands; band++ )
    1987             :         {
    1988     1130592 :             IF( hQMeta->surcoh_band_data != NULL )
    1989             :             {
    1990      765138 :                 hQMeta->surcoh_band_data[band].surround_coherence[sf] = (UWord8) mult_r( hMeta->common_meta.surround_coherence_fx[sf][band], UINT8_MAX ); // Q15
    1991      765138 :                 move16();
    1992             :             }
    1993             :         }
    1994             :     }
    1995             : 
    1996       41605 :     IF( GT_16( numDirections, 1 ) )
    1997             :     {
    1998       75232 :         FOR( band = 0; band < numCodingBands; band++ )
    1999             :         {
    2000       69396 :             hQMeta->twoDirBands[band] = hMasa->data.twoDirBands[band];
    2001       69396 :             move16();
    2002             :         }
    2003        5836 :         hQMeta->numTwoDirBands = hMasa->config.numTwoDirBands;
    2004        5836 :         move16();
    2005             :     }
    2006             : 
    2007             :     /* Copy spread coherence for DCT-based coding */
    2008       41605 :     test();
    2009       41605 :     IF( EQ_16( numSf, 1 ) && hMasa->config.useCoherence )
    2010             :     {
    2011        6620 :         FOR( dir = 0; dir < numDirections; dir++ )
    2012             :         {
    2013       15232 :             FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2014             :             {
    2015      200268 :                 FOR( band = 0; band < numCodingBands; band++ )
    2016             :                 {
    2017      188844 :                     hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[sf] = hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[0];
    2018      188844 :                     move16();
    2019             :                 }
    2020             :             }
    2021             :         }
    2022             :     }
    2023             : 
    2024       41605 :     return;
    2025             : }
    2026             : 
    2027             : 
    2028             : /* This function studies parametric MASA metadata to provide information for codec configuration */
    2029       39626 : static void detect_metadata_composition_fx(
    2030             :     const MASA_ENCODER_HANDLE hMasa, /* i  : MASA encoder data              */
    2031             :     UWord8 *joinedSubframes,         /* o  : Result of subframe composition */
    2032             :     UWord8 *coherencePresent,        /* o  : Result of coherence presence   */
    2033             :     UWord8 *isTwoDir                 /* o  : Result of two direction check  */
    2034             : )
    2035             : {
    2036             :     MASA_METADATA_FRAME *hMeta;
    2037             :     Word8 sf, band, dir, numDir;
    2038             :     Word16 nSubFrames;
    2039       39626 :     UWord8 dirValid[2] = { FALSE, FALSE };
    2040       39626 :     UWord8 cohPresent = FALSE;
    2041       39626 :     UWord8 sfDiffer = FALSE;
    2042             :     UWord8 sfSimilar;
    2043       39626 :     move16(); /*dirValid[0]*/
    2044       39626 :     move16(); /*dirValid[1]*/
    2045       39626 :     move16(); /*cohPresent*/
    2046       39626 :     move16(); /*sfDiffer*/
    2047             : 
    2048       39626 :     hMeta = &( hMasa->masaMetadata );
    2049       39626 :     numDir = (Word8) add( hMeta->descriptive_meta.numberOfDirections, 1 );
    2050       39626 :     move16();
    2051             : 
    2052       39626 :     *isTwoDir = FALSE;
    2053       39626 :     move16();
    2054             : 
    2055             :     /* First check for valid two directions */
    2056       39626 :     IF( EQ_16( numDir, 1 ) )
    2057             :     {
    2058       29726 :         dirValid[0] = TRUE;
    2059       29726 :         move16();
    2060             :     }
    2061             :     ELSE
    2062             :     {
    2063             :         /* Default assumption */
    2064        9900 :         *isTwoDir = TRUE;
    2065        9900 :         move16();
    2066             : 
    2067             :         /* Check for direct-to-total ratio values */
    2068       29700 :         FOR( dir = 0; dir < numDir; dir++ )
    2069             :         {
    2070       19800 :             sf = 0;
    2071       19800 :             move16();
    2072       39600 :             WHILE( !dirValid[dir] && ( sf < MAX_PARAM_SPATIAL_SUBFRAMES ) )
    2073             :             {
    2074       19800 :                 test();
    2075       19800 :                 band = 0;
    2076       19800 :                 move16();
    2077       40824 :                 WHILE( !dirValid[dir] && ( band < MASA_FREQUENCY_BANDS ) )
    2078             :                 {
    2079       21024 :                     test();
    2080       21024 :                     IF( GE_32( hMeta->directional_meta[dir].energy_ratio_fx[sf][band] /*q30*/, MASA_RATIO_THRESHOLD_FX >> 1 /*q30*/ ) )
    2081             :                     {
    2082       19800 :                         dirValid[dir] = TRUE;
    2083       19800 :                         move16();
    2084             :                     }
    2085       21024 :                     band = (Word8) add( band, 1 );
    2086             :                 }
    2087       19800 :                 sf = (Word8) add( sf, 1 );
    2088             :             }
    2089             :         }
    2090             : 
    2091        9900 :         test();
    2092        9900 :         IF( dirValid[1] == FALSE )
    2093             :         {
    2094             :             /* This handles also case where both are false. Then we just use first dir metadata. */
    2095           0 :             *isTwoDir = FALSE;
    2096           0 :             move16();
    2097             :         }
    2098        9900 :         ELSE IF( dirValid[0] == FALSE && EQ_16( dirValid[1], TRUE ) )
    2099             :         {
    2100           0 :             *isTwoDir = FALSE;
    2101           0 :             move16();
    2102             :             /* Copy data to first direction */
    2103           0 :             FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2104             :             {
    2105           0 :                 FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
    2106             :                 {
    2107           0 :                     hMeta->directional_meta[0].azimuth_fx[sf][band] = hMeta->directional_meta[1].azimuth_fx[sf][band];                   /*q22*/
    2108           0 :                     hMeta->directional_meta[0].elevation_fx[sf][band] = hMeta->directional_meta[1].elevation_fx[sf][band];               /*q22*/
    2109           0 :                     hMeta->directional_meta[0].energy_ratio_fx[sf][band] = hMeta->directional_meta[1].energy_ratio_fx[sf][band];         /*q30*/
    2110           0 :                     hMeta->directional_meta[0].spread_coherence_fx[sf][band] = hMeta->directional_meta[1].spread_coherence_fx[sf][band]; /*q15*/
    2111           0 :                     move32();
    2112           0 :                     move16();
    2113           0 :                     move16();
    2114           0 :                     move16();
    2115             :                 }
    2116             :             }
    2117             :         }
    2118             : 
    2119        9900 :         if ( *isTwoDir == FALSE )
    2120             :         {
    2121             :             /* Further checks will be done with just one direction */
    2122           0 :             numDir = 1;
    2123           0 :             move16();
    2124             :         }
    2125             :     }
    2126             : 
    2127             :     /* Check if data over subframes is identical. Check is done by comparing to first subframe. */
    2128       39626 :     sfSimilar = TRUE;
    2129       39626 :     sf = 1;
    2130       39626 :     move16();
    2131       39626 :     move16();
    2132             : 
    2133       39626 :     test();
    2134       90352 :     WHILE( ( sfSimilar == TRUE ) && ( sf < MAX_PARAM_SPATIAL_SUBFRAMES ) )
    2135             :     {
    2136       50726 :         sfSimilar = are_masa_subframes_similar_fx( hMeta, 0, hMeta, sf );
    2137       50726 :         sf = (Word8) add( sf, 1 );
    2138       50726 :         move16();
    2139             :     }
    2140       39626 :     IF( sfSimilar == TRUE )
    2141        5550 :     sfDiffer = FALSE;
    2142             :     ELSE
    2143       34076 :         sfDiffer = TRUE;
    2144       39626 :     move16();
    2145             : 
    2146             :     /* Further checks can be done with just one subframe if they are identical */
    2147       39626 :     IF( EQ_16( sfDiffer, TRUE ) )
    2148       34076 :     nSubFrames = MAX_PARAM_SPATIAL_SUBFRAMES;
    2149             :     ELSE
    2150        5550 :         nSubFrames = 1;
    2151       39626 :     move16();
    2152             : 
    2153             :     /* Check spread coherence */
    2154       39626 :     dir = 0;
    2155       39626 :     move16();
    2156       39626 :     test();
    2157       79252 :     WHILE( cohPresent == FALSE && ( dir < numDir ) )
    2158             :     {
    2159       39626 :         sf = 0;
    2160       39626 :         move16();
    2161       39626 :         test();
    2162       82138 :         WHILE( cohPresent == FALSE && ( sf < nSubFrames ) )
    2163             :         {
    2164       42512 :             band = 0;
    2165       42512 :             move16();
    2166       42512 :             test();
    2167      277843 :             WHILE( cohPresent == FALSE /*has value zero*/ && ( band < MASA_FREQUENCY_BANDS ) )
    2168             :             {
    2169             :                 /* Check coherences for presence of coherence */
    2170      235331 :                 IF( GT_16( hMeta->directional_meta[dir].spread_coherence_fx[sf][band] /*Q15*/, MASA_COHERENCE_THRESHOLD_FX >> 16 ) ) /*Q15*/
    2171             :                 {
    2172       37829 :                     cohPresent = TRUE;
    2173       37829 :                     move16();
    2174             :                 }
    2175      235331 :                 band = (Word8) add( band, 1 );
    2176      235331 :                 move16();
    2177             :             }
    2178       42512 :             sf = (Word8) add( sf, 1 );
    2179       42512 :             move16();
    2180             :         }
    2181       39626 :         dir = (Word8) add( dir, 1 );
    2182       39626 :         move16();
    2183             :     }
    2184             : 
    2185             :     /* Check surround coherence separately if we do not have already knowledge of coherence */
    2186       39626 :     IF( cohPresent == FALSE )
    2187             :     {
    2188             :         Word32 surround_coherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    2189             :         Word32 diffuse_to_total_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    2190             :         Word16 i, j;
    2191        8985 :         FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    2192             :         {
    2193      179700 :             FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ )
    2194             :             {
    2195      172512 :                 surround_coherence_fx[i][j] = L_deposit_h( hMeta->common_meta.surround_coherence_fx[i][j] );          /*q31*/
    2196      172512 :                 diffuse_to_total_ratio_fx[i][j] = L_shl_sat( hMeta->common_meta.diffuse_to_total_ratio_fx[i][j], 1 ); /*q31*/
    2197             :             }
    2198             :         }
    2199        1797 :         cohPresent = ivas_masa_surrcoh_signicant_fx( surround_coherence_fx, diffuse_to_total_ratio_fx, nSubFrames, MASA_FREQUENCY_BANDS );
    2200             :     }
    2201             : 
    2202             :     /* Set output flags */
    2203       39626 :     IF( EQ_16( sfDiffer, TRUE ) )
    2204             :     {
    2205       34076 :         *joinedSubframes = FALSE;
    2206             :     }
    2207             :     ELSE
    2208             :     {
    2209        5550 :         *joinedSubframes = TRUE;
    2210             :     }
    2211       39626 :     move16();
    2212       39626 :     *coherencePresent = cohPresent;
    2213       39626 :     move16();
    2214             : 
    2215       39626 :     return;
    2216             : }
    2217             : 
    2218             : 
    2219             : /* Check and compensate energy ratios. This function verifies that energy ratios follow the principle of summing to one.
    2220             :  * In addition, it implements simple remainder-to-total handling where remainder energy is proportionally added to other
    2221             :  * ratios. */
    2222       39626 : static void compensate_energy_ratios_fx(
    2223             :     MASA_ENCODER_HANDLE hMasa )
    2224             : {
    2225             :     Word16 sf, band, dir;
    2226             :     Word32 ratioSum;
    2227             :     MASA_METADATA_HANDLE hMeta;
    2228             :     UWord8 numDirs;
    2229             : 
    2230       39626 :     hMeta = &( hMasa->masaMetadata );
    2231       39626 :     numDirs = (UWord8) add( hMeta->descriptive_meta.numberOfDirections, 1 );
    2232             : 
    2233      198130 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2234             :     {
    2235     3962600 :         FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
    2236             :         {
    2237             :             /* Remainder is always set to zero and energy removal is compensated in following steps
    2238             :              * to other ratios. */
    2239     3804096 :             hMeta->common_meta.remainder_to_total_ratio_fx[sf][band] = 0; // Q30
    2240     3804096 :             move32();
    2241             : 
    2242     3804096 :             ratioSum = 0;
    2243     3804096 :             move32();
    2244     8558592 :             FOR( dir = 0; dir < numDirs; dir++ )
    2245             :             {
    2246     4754496 :                 ratioSum = L_add( ratioSum, hMeta->directional_meta[dir].energy_ratio_fx[sf][band] ); // Q30
    2247             :             }
    2248     3804096 :             ratioSum = L_add( ratioSum, hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] ); // Q30
    2249             : 
    2250     3804096 :             IF( ratioSum == 0 )
    2251             :             {
    2252           0 :                 FOR( dir = 0; dir < numDirs; dir++ )
    2253             :                 {
    2254           0 :                     hMeta->directional_meta[dir].energy_ratio_fx[sf][band] = 0; // Q30
    2255           0 :                     move32();
    2256             :                 }
    2257           0 :                 hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] = ONE_IN_Q30; // Q30
    2258           0 :                 move32();
    2259             :             }
    2260             :             // ELSE IF( NE_32( ratioSum, ONE_IN_Q30 ) )
    2261             :             ELSE /* Removing the check against 1 works well!!! */
    2262             :             {
    2263             :                 Word16 exp_diff;
    2264     8558592 :                 FOR( dir = 0; dir < numDirs; dir++ )
    2265             :                 {
    2266     9508992 :                     hMeta->directional_meta[dir].energy_ratio_fx[sf][band] =
    2267     4754496 :                         BASOP_Util_Divide3232_Scale_newton( hMeta->directional_meta[dir].energy_ratio_fx[sf][band], ratioSum, &exp_diff );
    2268     4754496 :                     move32();
    2269     4754496 :                     hMeta->directional_meta[dir].energy_ratio_fx[sf][band] = L_shl( hMeta->directional_meta[dir].energy_ratio_fx[sf][band], sub( exp_diff, Q1 ) ); // Q30
    2270     4754496 :                     move32();
    2271             :                 }
    2272     7608192 :                 hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] =
    2273     3804096 :                     BASOP_Util_Divide3232_Scale_newton( hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band], ratioSum, &exp_diff );
    2274     3804096 :                 move32();
    2275     3804096 :                 hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] = L_shl( hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band], sub( exp_diff, Q1 ) ); // Q30
    2276     3804096 :                 move32();
    2277             :             }
    2278             :         }
    2279             :     }
    2280             : 
    2281       39626 :     return;
    2282             : }
    2283             : 
    2284             : /* If the bit budget is very low, reduce metadata further to either 1 subframe and 5 bands, or 1 band and 4 subframes, based on which works better */
    2285       24911 : static void reduce_metadata_further_fx(
    2286             :     MASA_ENCODER_HANDLE hMasa,
    2287             :     IVAS_QMETADATA_HANDLE hqmetadata,
    2288             :     const IVAS_FORMAT ivas_format )
    2289             : {
    2290             :     Word16 sf;
    2291             :     Word16 band;
    2292             :     Word16 selectedBand;
    2293             :     Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][LOWBITRATE_NUM_BANDS];
    2294             :     Word64 W_tmp;
    2295             :     Word32 totalEnergySum;
    2296             :     UWord8 numCodingBands;
    2297             :     UWord8 computeCoherence;
    2298             :     Word32 onset_filter;
    2299             :     Word16 onset_filter_e, exp;
    2300             :     Word64 bandEnergy;
    2301             :     Word32 bandEnergy32;
    2302             :     Word16 bandEnergy_exp, shift;
    2303             :     UWord8 mergeOverFreqBands;
    2304             :     Word32 meanRatio;
    2305             :     Word16 tmp, tmp2, q_totalEnergySum;
    2306             : 
    2307       24911 :     numCodingBands = hMasa->config.numCodingBands;
    2308       24911 :     test();
    2309       24911 :     computeCoherence = hMasa->config.useCoherence && hMasa->config.coherencePresent;
    2310       24911 :     move16();
    2311       24911 :     move16();
    2312             : 
    2313             :     /* Set default values */
    2314       24911 :     selectedBand = 0;
    2315       24911 :     mergeOverFreqBands = 0;
    2316       24911 :     move16();
    2317       24911 :     move16();
    2318             : 
    2319             :     /* Get energy for the input data in 4-subframe, 5-band format */
    2320       24911 :     W_tmp = 0;
    2321       24911 :     move64();
    2322       24911 :     test();
    2323       24911 :     IF( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) ) /* Energy data is in 4-subframe, 24-band format */
    2324             :     {
    2325       84280 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2326             :         {
    2327             :             Word16 brange[2];
    2328             :             Word32 eneSum;
    2329             :             Word16 m;
    2330             : 
    2331      404544 :             FOR( band = 0; band < numCodingBands; band++ )
    2332             :             {
    2333      337120 :                 brange[0] = hMasa->data.band_mapping[band];
    2334      337120 :                 brange[1] = hMasa->data.band_mapping[band + 1];
    2335      337120 :                 move16();
    2336      337120 :                 move16();
    2337             : 
    2338      337120 :                 eneSum = 0;
    2339      337120 :                 move32();
    2340     1949840 :                 FOR( m = brange[0]; m < brange[1]; m++ )
    2341             :                 {
    2342     1612720 :                     eneSum = L_add( eneSum, hMasa->data.energy_fx[sf][m] ); // hMasa->data.q_energy
    2343             :                 }
    2344      337120 :                 energy[sf][band] = eneSum; // hMasa->data.q_energy
    2345      337120 :                 move32();
    2346      337120 :                 W_tmp = W_add( W_tmp, eneSum ); // hMasa->data.q_energy
    2347             :             }
    2348             :         }
    2349             :     }
    2350             :     ELSE /* Energy data is already in 4-subframe, 5-band format */
    2351             :     {
    2352       40275 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2353             :         {
    2354      193320 :             FOR( band = 0; band < numCodingBands; band++ )
    2355             :             {
    2356      161100 :                 energy[sf][band] = hMasa->data.energy_fx[sf][band]; // hMasa->data.q_energy
    2357      161100 :                 move32();
    2358      161100 :                 W_tmp = W_add( W_tmp, energy[sf][band] ); // hMasa->data.q_energy
    2359             :             }
    2360             :         }
    2361             :     }
    2362             : 
    2363       24911 :     IF( W_tmp != 0 )
    2364             :     {
    2365       24911 :         tmp2 = sub( W_norm( W_tmp ), 1 ); // Usage of guard bits to avoid the large values of onset_detector in multiplication
    2366             :     }
    2367             :     ELSE
    2368             :     {
    2369           0 :         tmp2 = 0;
    2370           0 :         move16();
    2371             :     }
    2372             : 
    2373       24911 :     tmp2 = s_min( 32, tmp2 );
    2374       24911 :     totalEnergySum = W_extract_h( W_shl( W_tmp, tmp2 ) );
    2375       24911 :     tmp2 = sub( tmp2, 32 );
    2376       24911 :     q_totalEnergySum = add( hMasa->data.q_energy, tmp2 );
    2377             : 
    2378             :     /* Determine onsets */
    2379       24911 :     hMasa->data.onset_detector_1_fx = Mpy_32_32( hMasa->data.onset_detector_1_fx, LOWBITRATE_ONSET_ALPHA_Q31 );
    2380       24911 :     move32();
    2381             : 
    2382       24911 :     tmp = hMasa->data.q_onset_detector;
    2383       24911 :     move16();
    2384       24911 :     IF( BASOP_Util_Cmp_Mant32Exp( hMasa->data.onset_detector_1_fx, sub( 31, hMasa->data.q_onset_detector ), totalEnergySum, sub( 31, q_totalEnergySum ) ) < 0 )
    2385             :     {
    2386       24389 :         hMasa->data.onset_detector_1_fx = totalEnergySum; // hMasa->data.q_energy
    2387       24389 :         hMasa->data.q_onset_detector = add( hMasa->data.q_energy, tmp2 );
    2388       24389 :         move32();
    2389       24389 :         move16();
    2390             : 
    2391       24389 :         shift = norm_l( hMasa->data.onset_detector_2_fx );
    2392       24389 :         hMasa->data.onset_detector_2_fx = L_shl( hMasa->data.onset_detector_2_fx, shift );
    2393       24389 :         move32();
    2394       24389 :         tmp = add( tmp, shift );
    2395             :     }
    2396       24911 :     IF( LT_16( tmp, hMasa->data.q_onset_detector ) )
    2397             :     {
    2398         234 :         hMasa->data.onset_detector_1_fx = L_shr( hMasa->data.onset_detector_1_fx, sub( hMasa->data.q_onset_detector, tmp ) );                                                                                         // tmp
    2399         234 :         hMasa->data.onset_detector_2_fx = L_add( Mpy_32_32( LOWBITRATE_ONSET_BETA_Q31, hMasa->data.onset_detector_2_fx ), Mpy_32_32( ( ONE_IN_Q31 - LOWBITRATE_ONSET_BETA_Q31 ), hMasa->data.onset_detector_1_fx ) ); // tmp
    2400         234 :         hMasa->data.q_onset_detector = tmp;
    2401         234 :         move32();
    2402         234 :         move32();
    2403         234 :         move16();
    2404             :     }
    2405             :     ELSE
    2406             :     {
    2407       24677 :         hMasa->data.onset_detector_2_fx = L_add( L_shr( Mpy_32_32( LOWBITRATE_ONSET_BETA_Q31, hMasa->data.onset_detector_2_fx ), sub( tmp, hMasa->data.q_onset_detector ) ), Mpy_32_32( ( ONE_IN_Q31 - LOWBITRATE_ONSET_BETA_Q31 ), hMasa->data.onset_detector_1_fx ) ); // hMasa->data.q_onset_detector
    2408       24677 :         move32();
    2409             :     }
    2410       24911 :     hMasa->data.onset_detector_2_fx = L_shl( Mpy_32_32( LOWBITRATE_ONSET_GAIN_Q30, L_min( hMasa->data.onset_detector_1_fx, hMasa->data.onset_detector_2_fx ) ), 1 ); // hMasa->data.q_onset_detector
    2411       24911 :     move32();
    2412             : 
    2413       24911 :     IF( hMasa->data.onset_detector_1_fx != 0 )
    2414             :     {
    2415       24911 :         onset_filter = L_max( BASOP_Util_Divide3232_Scale_newton( hMasa->data.onset_detector_2_fx, hMasa->data.onset_detector_1_fx, &onset_filter_e ), 0 );
    2416             : 
    2417       24911 :         IF( BASOP_Util_Cmp_Mant32Exp( onset_filter, onset_filter_e, ONE_IN_Q31, 0 ) > 0 )
    2418             :         {
    2419       19233 :             onset_filter = ONE_IN_Q31;
    2420       19233 :             onset_filter_e = 0;
    2421       19233 :             move32();
    2422       19233 :             move16();
    2423             :         }
    2424             :     }
    2425             :     ELSE
    2426             :     {
    2427           0 :         onset_filter = ONE_IN_Q31;
    2428           0 :         onset_filter_e = 0;
    2429           0 :         move32();
    2430           0 :         move16();
    2431             :     }
    2432             :     /* If we have onset, continue checking if we should reduce in frequency instead of time. */
    2433       24911 :     IF( BASOP_Util_Cmp_Mant32Exp( onset_filter, onset_filter_e, 2126008812 /* 0.99f in Q31 */, 0 ) < 0 )
    2434             :     {
    2435             :         /* Determine one frequency band to use to represent all frequency bands */
    2436       23245 :         FOR( band = numCodingBands - 1; band >= 0; band-- )
    2437             :         {
    2438             :             Word32 threshold;
    2439             :             Word32 bandRatio;
    2440             : 
    2441             :             // threshold = totalEnergySum / ( MAX_PARAM_SPATIAL_SUBFRAMES * LOWBITRATE_NUM_BANDS ) * 0.5f; /* Average energy multiplied with energy ratio of 0.5f */
    2442       23168 :             threshold = BASOP_Util_Divide3232_Scale_newton( totalEnergySum, ( MAX_PARAM_SPATIAL_SUBFRAMES * LOWBITRATE_NUM_BANDS ) * 2, &exp ); /* Average energy multiplied with energy ratio of 0.5f */
    2443       23168 :             exp = add( exp, sub( sub( 31, add( hMasa->data.q_energy, tmp2 ) ), 31 ) );
    2444       23168 :             bandRatio = hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[0]; // Q30
    2445       23168 :             move32();
    2446             : 
    2447       23168 :             bandEnergy = 0;
    2448       23168 :             move64();
    2449      115840 :             FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2450             :             {
    2451       92672 :                 bandEnergy = W_mac_32_32( bandEnergy, energy[sf][band], 1 );
    2452             :             }
    2453       23168 :             shift = W_norm( bandEnergy );
    2454       23168 :             bandEnergy32 = W_extract_h( W_shl( bandEnergy, shift ) );
    2455       23168 :             bandEnergy_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
    2456             : 
    2457       23168 :             IF( BASOP_Util_Cmp_Mant32Exp( Mpy_32_32( L_shr( bandEnergy32, 2 ), bandRatio ), add( 1, bandEnergy_exp ), threshold, exp ) > 0 )
    2458             :             {
    2459        5542 :                 selectedBand = band;
    2460        5542 :                 move16();
    2461        5542 :                 BREAK;
    2462             :             }
    2463             :         }
    2464             : 
    2465             :         /* Determine if to merge over frequency instead of time */
    2466        5619 :         meanRatio = 0;
    2467        5619 :         move32();
    2468       28095 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2469             :         {
    2470      134856 :             FOR( band = 0; band < numCodingBands; band++ )
    2471             :             {
    2472      112380 :                 meanRatio = L_add( meanRatio, Mpy_32_32( hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[sf], energy[sf][band] ) ); // hMasa->data.q_energy - 1
    2473             :             }
    2474             :         }
    2475        5619 :         IF( totalEnergySum != 0 )
    2476             :         {
    2477        5619 :             meanRatio = BASOP_Util_Divide3232_Scale_newton( meanRatio, totalEnergySum, &exp );
    2478        5619 :             exp = add( add( exp, 1 ), tmp2 ); // 31 - (hMasa->data.q_energy - 1) - 31 - hMasa->data.q_energy - tmp2 => 1 + tmp2
    2479             :         }
    2480             :         ELSE
    2481             :         {
    2482           0 :             meanRatio = MAX_32;
    2483           0 :             exp = 31;
    2484           0 :             move32();
    2485           0 :             move16();
    2486             :         }
    2487             : 
    2488             :         /* If the ratio of the selected band is larger than the average ratio of all bands and if there is an onset, merge over frequency bands.
    2489             :          * Otherwise, merge over subframes. */
    2490        5619 :         IF( BASOP_Util_Cmp_Mant32Exp( hqmetadata->q_direction[0].band_data[selectedBand].energy_ratio_fx[0], 1, meanRatio, exp ) > 0 )
    2491             :         {
    2492        3973 :             mergeOverFreqBands = 1;
    2493        3973 :             move16();
    2494             :         }
    2495             :         ELSE
    2496             :         {
    2497        1646 :             mergeOverFreqBands = 0;
    2498        1646 :             move16();
    2499             :         }
    2500             :     }
    2501             :     ELSE
    2502             :     {
    2503       19292 :         mergeOverFreqBands = 0;
    2504       19292 :         move16();
    2505             :     }
    2506             : 
    2507             :     /* Merge values over subframes or frequency bands, depending on which one is less important */
    2508       24911 :     IF( !mergeOverFreqBands ) /* Merge values over subframes */
    2509             :     {
    2510             :         Word32 xSum, ySum, zSum;
    2511             :         Word64 W_xSum_sq, W_ySum_sq;
    2512             :         Word32 bandSumEnergy;
    2513             :         Word16 aziRad, eleRad, q_shift, exp_diff;
    2514             :         Word32 x, y, z;
    2515             :         Word32 veclen, L_tmp;
    2516             : 
    2517       20938 :         W_tmp = 0;
    2518       20938 :         move64();
    2519      104156 :         FOR( band = 0; band < numCodingBands; band++ )
    2520             :         {
    2521       83218 :             xSum = 0;
    2522       83218 :             ySum = 0;
    2523       83218 :             zSum = 0;
    2524       83218 :             bandSumEnergy = 0;
    2525       83218 :             move32();
    2526       83218 :             move32();
    2527       83218 :             move32();
    2528       83218 :             move32();
    2529             : 
    2530      416090 :             FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2531             :             {
    2532      332872 :                 aziRad = extract_l( Mpy_32_32( hqmetadata->q_direction[0].band_data[band].azimuth_fx[sf], PI_OVER_180_Q22 ) );
    2533      332872 :                 eleRad = extract_l( Mpy_32_32( hqmetadata->q_direction[0].band_data[band].elevation_fx[sf], PI_OVER_180_Q22 ) );
    2534      332872 :                 veclen = Mpy_32_32( hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[sf], energy[sf][band] ); // hMasa->data.q_energy - 1
    2535             : 
    2536      332872 :                 x = Mpy_32_32( L_mult( getCosWord16( aziRad ), getCosWord16( eleRad ) ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
    2537      332872 :                 move32();
    2538      332872 :                 y = Mpy_32_32( L_mult0( getSinWord16( aziRad ), getCosWord16( eleRad ) ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
    2539      332872 :                 move32();
    2540      332872 :                 z = Mpy_32_32( L_mult0( getSinWord16( eleRad ), ONE_IN_Q14 ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
    2541      332872 :                 move32();
    2542             : 
    2543      332872 :                 xSum = L_add( xSum, x );
    2544      332872 :                 ySum = L_add( ySum, y );
    2545      332872 :                 zSum = L_add( zSum, z );
    2546             : 
    2547      332872 :                 W_tmp = W_add( W_tmp, energy[sf][band] );
    2548             :             }
    2549             : 
    2550       83218 :             tmp2 = W_norm( W_tmp );
    2551       83218 :             tmp2 = s_min( 32, tmp2 );
    2552       83218 :             bandSumEnergy = W_extract_h( W_shl( W_tmp, tmp2 ) );
    2553       83218 :             tmp2 = sub( add( hMasa->data.q_energy, tmp2 ), 32 );
    2554             : 
    2555       83218 :             aziRad = BASOP_util_atan2( ySum, xSum, 0 ); // Q13
    2556       83218 :             W_xSum_sq = W_mult0_32_32( xSum, xSum );    // 2 * hMasa->data.q_energy - Q6
    2557       83218 :             W_ySum_sq = W_mult0_32_32( ySum, ySum );    // 2 * hMasa->data.q_energy - Q6
    2558       83218 :             W_tmp = W_add( W_xSum_sq, W_ySum_sq );      // 2 * hMasa->data.q_energy - Q6
    2559       83218 :             q_shift = W_norm( W_tmp );
    2560       83218 :             L_tmp = W_extract_h( W_shl( W_tmp, q_shift ) ); // 2 * hMasa->data.q_energy - Q6 + (q_shift -32)
    2561       83218 :             exp_diff = sub( Q31, add( sub( imult1616( 2, hMasa->data.q_energy ), Q6 ), sub( q_shift, 32 ) ) );
    2562       83218 :             L_tmp = Sqrt32( L_tmp, &exp_diff );
    2563       83218 :             eleRad = BASOP_util_atan2( zSum, L_tmp, sub( sub( 34, hMasa->data.q_energy ), exp_diff ) ); // Q13
    2564             : 
    2565       83218 :             hqmetadata->q_direction[0].band_data[band].azimuth_fx[0] = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, aziRad ), Q1 );   // ((Q25, Q13) -> Q23) >> Q1 -> Q22
    2566       83218 :             hqmetadata->q_direction[0].band_data[band].elevation_fx[0] = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, eleRad ), Q1 ); // ((Q25, Q13) -> Q23) >> Q1 -> Q22
    2567             : 
    2568             :             /* Energy ratio is already merged through time */
    2569       83218 :             test();
    2570       83218 :             IF( computeCoherence && hqmetadata->q_direction[0].coherence_band_data != NULL )
    2571             :             {
    2572             :                 Word16 spreadCoh;
    2573        5368 :                 Word32 spreadCohSum = 0;
    2574        5368 :                 move32();
    2575       26840 :                 FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2576             :                 {
    2577       21472 :                     spreadCoh = div_s( (Word16) hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf], 255 ); // Q15
    2578       21472 :                     spreadCohSum = L_add( spreadCohSum, Mpy_32_16_1( energy[sf][band], spreadCoh ) );
    2579             :                 }
    2580             :                 // hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0] = (uint8_t) roundf( spreadCohSum / ( bandSumEnergy + EPSILON ) * 255.0f );
    2581        5368 :                 tmp = BASOP_Util_Divide3232_Scale( spreadCohSum, bandSumEnergy, &exp );
    2582        5368 :                 exp = add( exp, sub( tmp2, hMasa->data.q_energy ) );
    2583        5368 :                 tmp = mult_r( tmp, 32640 /* 255 in Q7 */ );                                                                    // 15 - exp + 7 - 15 => 7 - exp
    2584        5368 :                 hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0] = (UWord8) shr( tmp, sub( 7, exp ) ); // Q0
    2585        5368 :                 move16();
    2586             : 
    2587             :                 /* Copy spread coherence to the rest of subframes for the coherence coding algorithm. */
    2588       21472 :                 FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2589             :                 {
    2590       96624 :                     FOR( band = 0; band < numCodingBands; band++ )
    2591             :                     {
    2592       80520 :                         hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0]; // Q0
    2593       80520 :                         move16();
    2594             :                     }
    2595             :                 }
    2596             : 
    2597             :                 /* Surround coherence is already merged through time */
    2598             :             }
    2599             :         }
    2600             : 
    2601       20938 :         hqmetadata->q_direction->cfg.nblocks = 1;
    2602       20938 :         hMasa->config.joinedSubframes = 1;
    2603       20938 :         move16();
    2604       20938 :         move16();
    2605             :     }
    2606             :     ELSE /* Merge values over frequency bands */
    2607             :     {
    2608             :         /* Use the selected frequency band to represent all data */
    2609       19865 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2610             :         {
    2611       15892 :             hqmetadata->q_direction[0].band_data[0].azimuth_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].azimuth_fx[sf];           // Q22
    2612       15892 :             hqmetadata->q_direction[0].band_data[0].elevation_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].elevation_fx[sf];       // Q22
    2613       15892 :             hqmetadata->q_direction[0].band_data[0].energy_ratio_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].energy_ratio_fx[sf]; // Q30
    2614       15892 :             move32();
    2615       15892 :             move32();
    2616       15892 :             move32();
    2617       15892 :             IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
    2618             :             {
    2619        5280 :                 hqmetadata->q_direction[0].coherence_band_data[0].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[selectedBand].spread_coherence[sf]; // Q0
    2620        5280 :                 move16();
    2621             :             }
    2622       15892 :             IF( hqmetadata->surcoh_band_data != NULL )
    2623             :             {
    2624        5280 :                 hqmetadata->surcoh_band_data[0].surround_coherence[sf] = hqmetadata->surcoh_band_data[selectedBand].surround_coherence[sf];
    2625        5280 :                 move16();
    2626             :             }
    2627             :         }
    2628             : 
    2629             :         /* Copy coherence to rest of bands for the coherence coding algorithm. */
    2630       19865 :         FOR( band = 1; band < numCodingBands; band++ )
    2631             :         {
    2632       15892 :             IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
    2633             :             {
    2634       26400 :                 FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2635             :                 {
    2636       21120 :                     hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[0].spread_coherence[sf]; // Q0
    2637       21120 :                     move16();
    2638             :                 }
    2639             :             }
    2640       15892 :             IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
    2641             :             {
    2642       26400 :                 FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2643             :                 {
    2644       21120 :                     hqmetadata->surcoh_band_data[band].surround_coherence[sf] = hqmetadata->surcoh_band_data[0].surround_coherence[sf];
    2645       21120 :                     move16();
    2646             :                 }
    2647             :             }
    2648             :         }
    2649             : 
    2650        3973 :         hqmetadata->q_direction[0].cfg.nbands = 1;
    2651        3973 :         move16();
    2652             :     }
    2653             : 
    2654       24911 :     return;
    2655             : }
    2656             : 
    2657             : 
    2658       11470 : static Word16 encode_lfe_to_total_energy_ratio_fx(
    2659             :     MASA_ENCODER_HANDLE hMasa,    /* i/o: MASA encoder structure       */
    2660             :     BSTR_ENC_HANDLE hMetaData,    /* i/o: Metadata bitstream handle    */
    2661             :     const Word32 ivas_total_brate /* i  : IVAS total bitrate           */
    2662             : )
    2663             : {
    2664             :     Word16 i;
    2665             :     Word16 xq;
    2666             :     Word16 VQLevels;
    2667             :     Word32 maxLFESubFrameEner;
    2668             :     Word16 maxLFESubFrameEner_e;
    2669             :     Word32 log2LFEaverage;
    2670             :     Word32 log2LFEratio[4];
    2671             :     Word32 xqv[4];
    2672             :     Word32 linearLFEaverage;
    2673             :     Word16 linearLFEaverage_e;
    2674             :     Word16 lfeToTotalEnergyRatioIndices[3];
    2675             :     Word16 lfeAdaptiveVQBits;
    2676             :     Word16 lfeBitsWritten;
    2677             :     Word32 maxVal;
    2678             :     Word16 maxVal_e;
    2679             : 
    2680       11470 :     VQLevels = 0;
    2681       11470 :     move16();
    2682       11470 :     lfeAdaptiveVQBits = 0;
    2683       11470 :     move16();
    2684             : 
    2685             :     /* Determine maximum amount of LFE energy in any subframe */
    2686       11470 :     maxLFESubFrameEner = 0; // maxLFESubFrameEner_e
    2687       11470 :     move32();
    2688       11470 :     maxLFESubFrameEner_e = 0;
    2689       11470 :     move16();
    2690       57350 :     FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    2691             :     {
    2692       45880 :         IF( BASOP_Util_Cmp_Mant32Exp( hMasa->data.lfeToTotalEnergyRatio_fx[i], hMasa->data.lfeToTotalEnergyRatio_e[i], maxLFESubFrameEner, maxLFESubFrameEner_e ) > 0 )
    2693             :         {
    2694        4563 :             maxLFESubFrameEner = hMasa->data.lfeToTotalEnergyRatio_fx[i]; // hMasa->data.lfeToTotalEnergyRatio_e[i]
    2695        4563 :             move32();
    2696        4563 :             maxLFESubFrameEner_e = hMasa->data.lfeToTotalEnergyRatio_e[i];
    2697        4563 :             move16();
    2698             :         }
    2699             :     }
    2700             : 
    2701             :     /* Set default values for the indices */
    2702       45880 :     FOR( i = 0; i < 3; i++ )
    2703             :     {
    2704       34410 :         lfeToTotalEnergyRatioIndices[i] = 0;
    2705       34410 :         move16();
    2706             :     }
    2707             : 
    2708             :     /* Check if there is enough energy in any subframe. If not, send only 1 bit (0) and abort. */
    2709             :     /* If there is enough LFE energy at least in one subframe, quantize it. */
    2710       11470 :     IF( BASOP_Util_Cmp_Mant32Exp( maxLFESubFrameEner, maxLFESubFrameEner_e, 10737418 /* 0.005f in Q31 */, 0 ) > 0 )
    2711             :     {
    2712             :         /* Convert energy to log2 domain, and clamp it to reasonable values */
    2713        1884 :         log2LFEaverage = 0; // Q25
    2714        1884 :         move32();
    2715        9420 :         FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    2716             :         {
    2717             :             // log2LFEratio[i] = log2f( max( 0.001f, hMasa->data.lfeToTotalEnergyRatio[i] ) );
    2718        7536 :             maxVal = 2147484 /* 0.001f in Q31 */;
    2719        7536 :             move32();
    2720        7536 :             maxVal_e = 0;
    2721        7536 :             move16();
    2722        7536 :             IF( BASOP_Util_Cmp_Mant32Exp( hMasa->data.lfeToTotalEnergyRatio_fx[i], hMasa->data.lfeToTotalEnergyRatio_e[i], maxVal, maxVal_e ) > 0 )
    2723             :             {
    2724        7297 :                 maxVal = hMasa->data.lfeToTotalEnergyRatio_fx[i];
    2725        7297 :                 move32();
    2726        7297 :                 maxVal_e = hMasa->data.lfeToTotalEnergyRatio_e[i];
    2727        7297 :                 move16();
    2728             :             }
    2729        7536 :             log2LFEratio[i] = L_add( BASOP_Util_Log2( maxVal ), L_shl( maxVal_e, Q25 ) ); // Q25
    2730        7536 :             move32();
    2731        7536 :             IF( GT_32( log2LFEratio[i], ONE_IN_Q25 ) ) /* Corresponds to linear value 2.0f */
    2732             :             {
    2733           0 :                 log2LFEratio[i] = ONE_IN_Q25; // Q25
    2734           0 :                 move32();
    2735             :             }
    2736        7536 :             ELSE IF( LT_32( log2LFEratio[i], -301989888 /* -9.0f in Q25 */ ) )
    2737             :             {
    2738         286 :                 log2LFEratio[i] = -301989888 /* -9.0f in Q25 */; // Q25
    2739         286 :                 move32();
    2740             :             }
    2741        7536 :             log2LFEaverage = L_add( log2LFEaverage, Mpy_32_32( 536870912 /* 0.25f in Q31 */, log2LFEratio[i] ) ); // Q25
    2742             :         }
    2743             : 
    2744        1884 :         IF( EQ_32( ivas_total_brate, IVAS_13k2 ) )
    2745             :         {
    2746             :             /* Calculate adaptive 1-bit LFE quantizer index */
    2747             :             // linearLFEaverage = exp2f( log2LFEaverage ); /* Convert back to linear domain */
    2748         175 :             linearLFEaverage = BASOP_util_Pow2( log2LFEaverage, Q31 - Q25, &linearLFEaverage_e ); /* Convert back to linear domain */
    2749         175 :             linearLFEaverage = L_shl_sat( linearLFEaverage, sub( linearLFEaverage_e, Q1 ) );      // Q30
    2750         175 :             test();
    2751         175 :             IF( GT_32( linearLFEaverage, MCMASA_LFE_1BIT_THRES_Q30 ) &&
    2752             :                 GT_32( linearLFEaverage, L_add( L_add( MCMASA_LFE_BETA_Q30 >> Q1, L_shr( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q2 ) ),
    2753             :                                                 L_shr( Mpy_32_32( MCMASA_LFE_ALPHA_Q30, hMasa->data.prevq_lfeToTotalEnergyRatio_fx ), Q1 ) ) ) )
    2754             :             {
    2755         128 :                 lfeToTotalEnergyRatioIndices[0] = 1;
    2756         128 :                 move16();
    2757         128 :                 IF( EQ_16( hMasa->data.prevq_lfeIndex, 1 ) )
    2758             :                 {
    2759          86 :                     hMasa->data.prevq_lfeToTotalEnergyRatio_fx = L_add( L_shr( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q1 ), 125627793 /* MCMASA_LFE_THETA * MCMASA_LFE_BETA in Q30 */ ); /* larger "bump-up" to LFE-to-total energy ratio */ // Q30
    2760          86 :                     move32();
    2761             :                 }
    2762             :                 ELSE
    2763             :                 {
    2764          42 :                     hMasa->data.prevq_lfeToTotalEnergyRatio_fx = L_add( L_shr( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q1 ), MCMASA_LFE_BETA_Q30 ); /* default "bump-up" to LFE-to-total energy ratio */ // Q30
    2765          42 :                     move32();
    2766             :                 }
    2767             :             }
    2768             :             ELSE
    2769             :             {
    2770          47 :                 hMasa->data.prevq_lfeToTotalEnergyRatio_fx = Mpy_32_32( MCMASA_LFE_ALPHA_Q30, hMasa->data.prevq_lfeToTotalEnergyRatio_fx ); /* exponential decay */ // Q30
    2771          47 :                 move32();
    2772             :             }
    2773             : 
    2774         175 :             IF( GE_32( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, ONE_IN_Q30 ) )
    2775             :             {
    2776           0 :                 hMasa->data.prevq_lfeToTotalEnergyRatio_fx = ONE_IN_Q31; // Q31
    2777           0 :                 move32();
    2778             :             }
    2779             :             ELSE
    2780             :             {
    2781         175 :                 hMasa->data.prevq_lfeToTotalEnergyRatio_fx = L_shl( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q1 ); // Q31
    2782         175 :                 move32();
    2783             :             }
    2784         175 :             hMasa->data.prevq_lfeIndex = lfeToTotalEnergyRatioIndices[0]; /* Update to previous frame's index memories */
    2785         175 :             move16();
    2786             :         }
    2787             :         ELSE /* Bitrate >= 16.4 kbps */
    2788             :         {
    2789             :             /* Do 1st stage scalar quantization */
    2790        1709 :             lfeToTotalEnergyRatioIndices[0] = 1;
    2791        1709 :             move16();
    2792        1709 :             lfeToTotalEnergyRatioIndices[1] = usquant_fx( extract_l( L_shr( log2LFEaverage, Q14 ) ), &xq, MCMASA_LFE_QLOW_Q11, MCMASA_LFE_DELTA_Q10, 8 );
    2793        1709 :             move16();
    2794             : 
    2795        1709 :             IF( GE_32( ivas_total_brate, IVAS_24k4 ) ) /* Vector quantization is applied if bitrate >= 24.4 kbps */
    2796             :             {
    2797             :                 /* Remove scalar value from the vector*/
    2798        8020 :                 FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    2799             :                 {
    2800        6416 :                     log2LFEratio[i] = L_sub( log2LFEratio[i], L_shl( xq, Q14 ) ); // Q25
    2801        6416 :                     move32();
    2802             :                 }
    2803             : 
    2804             :                 /* Vector quantize residual with energy adaptive bit allocation */
    2805        1604 :                 SWITCH( lfeToTotalEnergyRatioIndices[1] )
    2806             :                 {
    2807         222 :                     case 0:
    2808             :                     case 1:
    2809         222 :                         VQLevels = 0;
    2810         222 :                         move16();
    2811         222 :                         lfeAdaptiveVQBits = 0;
    2812         222 :                         move16();
    2813         222 :                         BREAK;
    2814          97 :                     case 2:
    2815          97 :                         VQLevels = 2;
    2816          97 :                         move16();
    2817          97 :                         lfeAdaptiveVQBits = 1;
    2818          97 :                         move16();
    2819          97 :                         BREAK;
    2820          97 :                     case 3:
    2821          97 :                         VQLevels = 4;
    2822          97 :                         move16();
    2823          97 :                         lfeAdaptiveVQBits = 2;
    2824          97 :                         move16();
    2825          97 :                         BREAK;
    2826         242 :                     case 4:
    2827         242 :                         VQLevels = 8;
    2828         242 :                         move16();
    2829         242 :                         lfeAdaptiveVQBits = 3;
    2830         242 :                         move16();
    2831         242 :                         BREAK;
    2832         946 :                     default:
    2833         946 :                         VQLevels = 16;
    2834         946 :                         move16();
    2835         946 :                         lfeAdaptiveVQBits = 4;
    2836         946 :                         move16();
    2837             :                 }
    2838             : 
    2839        1604 :                 IF( VQLevels > 0 )
    2840             :                 {
    2841        1382 :                     lfeToTotalEnergyRatioIndices[2] = vquant_ivas_fx( log2LFEratio, 0, xqv, McMASA_LFEGain_vectors_fx_q25, 4, VQLevels );
    2842        1382 :                     move16();
    2843             :                 }
    2844             :             }
    2845             :         }
    2846             :     }
    2847             : 
    2848             :     /* Write first LFE bit */
    2849       11470 :     lfeBitsWritten = 0;
    2850       11470 :     move16();
    2851       11470 :     push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[0], 1 );
    2852       11470 :     lfeBitsWritten = add( lfeBitsWritten, 1 );
    2853             : 
    2854       11470 :     test();
    2855       11470 :     IF( EQ_16( lfeToTotalEnergyRatioIndices[0], 1 ) && GE_32( ivas_total_brate, IVAS_16k4 ) )
    2856             :     {
    2857             :         /* If bitrate >= 16.4kbit/s, send 1-bit on/off + 3-bit scalar */
    2858        1709 :         push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[1], 3 );
    2859        1709 :         lfeBitsWritten = add( lfeBitsWritten, 3 );
    2860             : 
    2861             :         /*  If bitrate >= 24.4kbit/s, use adaptive 1 + (3.. 7) bit quantizer */
    2862        1709 :         IF( GE_32( ivas_total_brate, IVAS_24k4 ) )
    2863             :         {
    2864             :             /* Vector quantize residual with energy adaptive bit allocation */
    2865        1604 :             IF( lfeAdaptiveVQBits > 0 )
    2866             :             {
    2867        1382 :                 push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[2], lfeAdaptiveVQBits );
    2868        1382 :                 lfeBitsWritten = add( lfeBitsWritten, lfeAdaptiveVQBits );
    2869             :             }
    2870             :         }
    2871             :     }
    2872             : 
    2873       11470 :     return lfeBitsWritten;
    2874             : }
    2875             : 
    2876             : 
    2877             : /*-------------------------------------------------------------------*
    2878             :  * ivas_masa_enc_reconfigure()
    2879             :  *
    2880             :  * Reconfigure IVAS MASA encoder
    2881             :  *-------------------------------------------------------------------*/
    2882       30626 : void ivas_masa_enc_reconfigure_fx(
    2883             :     Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
    2884             : )
    2885             : {
    2886             :     Word16 n, tmp;
    2887             :     Word16 sce_id, cpe_id;
    2888             :     Word32 ivas_total_brate;
    2889             :     Word32 ism_total_brate;
    2890             :     Word32 tmp_br, tmp_mod;
    2891             : 
    2892       30626 :     ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate;
    2893       30626 :     move32();
    2894             : 
    2895       30626 :     ism_total_brate = 0;
    2896       30626 :     move32();
    2897       30626 :     test();
    2898       30626 :     test();
    2899       30626 :     test();
    2900       30626 :     test();
    2901       30626 :     IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) && st_ivas->nSCE > 0 && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) )
    2902             :     {
    2903           0 :         FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
    2904             :         {
    2905           0 :             ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[sce_id]->element_brate );
    2906             :         }
    2907             :     }
    2908             : 
    2909       30626 :     IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) )
    2910             :     {
    2911        1269 :         iDiv_and_mod_32( ivas_total_brate, st_ivas->nchan_transport, &tmp_br, &tmp_mod, 0 );
    2912        1934 :         FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
    2913             :         {
    2914         665 :             copy_encoder_config_fx( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 );
    2915         665 :             st_ivas->hSCE[sce_id]->element_brate = tmp_br;
    2916         665 :             st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */
    2917         665 :             move32();
    2918         665 :             move32();
    2919             :         }
    2920             : 
    2921        1873 :         FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ )
    2922             :         {
    2923         604 :             st_ivas->hCPE[cpe_id]->element_brate = imult3216( tmp_br, 2 ); //( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS;
    2924         604 :             move32();
    2925             : 
    2926         604 :             IF( GT_16( st_ivas->nCPE, 1 ) )
    2927             :             {
    2928           0 :                 tmp = 1;
    2929             :             }
    2930             :             ELSE
    2931             :             {
    2932         604 :                 tmp = CPE_CHANNELS;
    2933             :             }
    2934         604 :             move16();
    2935             :             /* prepare bitstream buffers */
    2936        1812 :             FOR( n = 0; n < CPE_CHANNELS; n++ )
    2937             :             {
    2938        1208 :                 copy_encoder_config_fx( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 );
    2939             :                 /* st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); */
    2940        1208 :                 st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = L_shr( st_ivas->hCPE[cpe_id]->element_brate, sub( tmp, 1 ) ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */
    2941        1208 :                 move32();
    2942             :             }
    2943             : 
    2944         604 :             IF( LT_32( L_sub( ivas_total_brate, ism_total_brate ), MIN_BRATE_MDCT_STEREO ) )
    2945             :             {
    2946         218 :                 st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_DFT;
    2947             :             }
    2948             :             ELSE
    2949             :             {
    2950         386 :                 st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_MDCT;
    2951             :             }
    2952         604 :             move16();
    2953             :         }
    2954             : 
    2955        1269 :         ivas_masa_set_elements_fx( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp, st_ivas->hEncoderConfig->ivas_format, st_ivas->ism_mode, ism_total_brate );
    2956             :     }
    2957             : 
    2958       30626 :     return;
    2959             : }
    2960             : 
    2961             : /*-------------------------------------------------------------------*
    2962             :  * average_masa_metadata()
    2963             :  *
    2964             :  * Average MASA metadata frame subframe contents: applies aggregation over time
    2965             :  *-------------------------------------------------------------------*/
    2966           0 : static void average_masa_metadata_fx(
    2967             :     MASA_METADATA_FRAME *hMeta,
    2968             :     Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   /*i Q(31 - energy_e) */
    2969             :     Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*i:stores exponent values for energy_e*/
    2970             :     const SPHERICAL_GRID_DATA *Sph_Grid16,
    2971             :     const UWord8 useSphGrid )
    2972             : {
    2973             :     Word16 i, j, k;
    2974             :     Word16 azi_rad_fx, ele_rad_fx;
    2975             :     UWord8 numDirections;
    2976             : 
    2977             :     /* use the nominal values without data-adaptivity */
    2978           0 :     numDirections = (UWord8) add( hMeta->descriptive_meta.numberOfDirections, 1 );
    2979           0 :     move16();
    2980             : 
    2981             :     /* azi/ele/nrg into vectors for each sub-frame and band */
    2982           0 :     FOR( i = 0; i < numDirections; i++ )
    2983             :     {
    2984           0 :         FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
    2985             :         {
    2986             :             Word32 x_sum_fx, y_sum_fx, z_sum_fx, energy_sum_fx, vec_len_fx, spread_coh_sum_fx, surr_coh_sum_fx, temp1, temp2;
    2987             :             Word16 vec_len_e, x_sum_e, y_sum_e, z_sum_e, energy_sum_e, spread_coh_sum_e, surr_coh_sum_e, temp1_e, temp2_e;
    2988           0 :             x_sum_fx = 0;
    2989           0 :             y_sum_fx = 0;
    2990           0 :             z_sum_fx = 0;
    2991           0 :             energy_sum_fx = 0;
    2992           0 :             spread_coh_sum_fx = 0;
    2993           0 :             surr_coh_sum_fx = 0;
    2994           0 :             x_sum_e = 0;          /*exponent for x_sum_fx*/
    2995           0 :             y_sum_e = 0;          /*exponent for y_sum_fx*/
    2996           0 :             z_sum_e = 0;          /*exponent for z_sum_fx*/
    2997           0 :             energy_sum_e = 0;     /*exponent for energy_sum_fx*/
    2998           0 :             spread_coh_sum_e = 0; /*exponent for spread_coh_sum_fx*/
    2999           0 :             surr_coh_sum_e = 0;   /*exponent for surr_coh_sum_fx*/
    3000           0 :             temp1 = 0;            /* to store temporary computations*/
    3001           0 :             temp2 = 0;            /* to store temporary computations*/
    3002           0 :             temp1_e = 0;          /*to store temporary exponents*/
    3003           0 :             temp2_e = 0;          /*to store temporary exponents*/
    3004           0 :             move32();
    3005           0 :             move32();
    3006           0 :             move32();
    3007           0 :             move32();
    3008           0 :             move32();
    3009           0 :             move32();
    3010           0 :             move32();
    3011           0 :             move32();
    3012           0 :             move16();
    3013           0 :             move16();
    3014           0 :             move16();
    3015           0 :             move16();
    3016           0 :             move16();
    3017           0 :             move16();
    3018           0 :             move16();
    3019           0 :             move16();
    3020             : 
    3021           0 :             FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
    3022             :             {
    3023           0 :                 azi_rad_fx = extract_l( Mpy_32_32( hMeta->directional_meta[i].azimuth_fx[j][k], 46603 /*1/(360) in Q24*/ ) ); /*=angle *(1/2pi) brings the azi_rad_fx in -32767 to 32767 in q15 (this argument is further passed in cos and sin functions)*/   /*22+24-31=15*/
    3024           0 :                 ele_rad_fx = extract_l( Mpy_32_32( hMeta->directional_meta[i].elevation_fx[j][k], 46603 /*1/(360) in Q24*/ ) ); /*=angle *(1/2pi) brings the azi_rad_fx in -32767 to 32767 in q15 (this argument is further passed in cos and sin functions)*/ /*22+24-31=15*/
    3025           0 :                 vec_len_fx = Mpy_32_32( hMeta->directional_meta[i].energy_ratio_fx[j][k] /*q30*/, energy[j][k] );                                                                                                                                              /*exponent=energy_e+1*/
    3026           0 :                 vec_len_e = add( energy_e[j][k], 1 );
    3027             : 
    3028             :                 /* energy-weighted sum over subframes */
    3029           0 :                 x_sum_fx = BASOP_Util_Add_Mant32Exp( x_sum_fx, x_sum_e, Mpy_32_32( L_mult( getCosWord16R2( azi_rad_fx ), getCosWord16R2( ele_rad_fx ) ) /*q31*/, vec_len_fx ), vec_len_e, &x_sum_e );  /*x_sum_e*/
    3030           0 :                 y_sum_fx = BASOP_Util_Add_Mant32Exp( y_sum_fx, y_sum_e, Mpy_32_32( L_mult( getSineWord16R2( azi_rad_fx ), getCosWord16R2( ele_rad_fx ) ) /*q31*/, vec_len_fx ), vec_len_e, &y_sum_e ); /*y_sum_e*/
    3031           0 :                 z_sum_fx = BASOP_Util_Add_Mant32Exp( z_sum_fx, z_sum_e, Mpy_32_16_1( vec_len_fx, getSineWord16R2( ele_rad_fx ) /*q15*/ ), vec_len_e, &z_sum_e );                                       /*z_sum_e*/
    3032             : 
    3033           0 :                 energy_sum_fx = BASOP_Util_Add_Mant32Exp( energy_sum_fx, energy_sum_e, energy[j][k], energy_e[j][k], &energy_sum_e ); /*energy_sum_e*/
    3034             : 
    3035           0 :                 spread_coh_sum_fx = BASOP_Util_Add_Mant32Exp( spread_coh_sum_fx, spread_coh_sum_e, Mpy_32_16_1( energy[j][k], hMeta->directional_meta[i].spread_coherence_fx[j][k] ), energy_e[j][k], &spread_coh_sum_e ); /*spread_coh_sum_e*/
    3036           0 :                 IF( i == 0 )
    3037             :                 {
    3038             :                     /* this is in common metadata and not in each direction */
    3039           0 :                     surr_coh_sum_fx = BASOP_Util_Add_Mant32Exp( surr_coh_sum_fx, surr_coh_sum_e, Mpy_32_16_1( energy[j][k], hMeta->common_meta.surround_coherence_fx[j][k] ), energy_e[j][k], &surr_coh_sum_e ); /*surr_coh_sum_e*/
    3040             :                 }
    3041             :             }
    3042             : 
    3043             :             /* the data from the combined sub-frames is written into the first sub-frame band */
    3044           0 :             j = 0;
    3045           0 :             move16();
    3046           0 :             hMeta->directional_meta[i].azimuth_fx[j][k] = Mpy_32_16_1( 961263669 /*(1/ EVS_PI * 180.0f) in Q24*/, BASOP_util_atan2( y_sum_fx, x_sum_fx, sub( y_sum_e, x_sum_e ) ) /*q13*/ ); /*24+13-15=22*/
    3047           0 :             move32();
    3048           0 :             temp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( x_sum_fx, x_sum_fx ), shl( x_sum_e, 1 ), Mpy_32_32( y_sum_fx, y_sum_fx ), shl( y_sum_e, 1 ), &temp1_e ); /*temp1_e*/
    3049           0 :             temp2_e = temp1_e;
    3050           0 :             temp2 = Sqrt32( temp1, &temp2_e );                                                                                                                                              /*temp2_e*/
    3051           0 :             hMeta->directional_meta[i].elevation_fx[j][k] = Mpy_32_16_1( 961263669 /*(1/ EVS_PI * 180.0f) in Q24*/, BASOP_util_atan2( z_sum_fx, temp2, sub( z_sum_e, temp2_e ) ) /*q13*/ ); /*24+13-15=22*/
    3052           0 :             move32();
    3053           0 :             IF( EQ_16( useSphGrid, TRUE ) )
    3054             :             {
    3055             : 
    3056           0 :                 hMeta->directional_meta[i].spherical_index[j][k] = index_theta_phi_16_fx( &( hMeta->directional_meta[i].elevation_fx[j][k] ),
    3057           0 :                                                                                           &( hMeta->directional_meta[i].azimuth_fx[j][k] ), Sph_Grid16 );
    3058           0 :                 move16();
    3059             :             }
    3060           0 :             vec_len_fx = BASOP_Util_Add_Mant32Exp( temp1, temp1_e, Mpy_32_32( z_sum_fx, z_sum_fx ), shl( z_sum_e, 1 ), &vec_len_e ); /*vec_len_e*/      /*x_sum * x_sum + y_sum * y_sum + z_sum * z_sum*/
    3061           0 :             vec_len_fx = Sqrt32( vec_len_fx, &vec_len_e );                                                                                              /*vec_len_e*/
    3062           0 :             hMeta->directional_meta[i].energy_ratio_fx[j][k] = BASOP_Util_Divide3232_Scale( vec_len_fx, L_add( energy_sum_fx, EPSILON_FX ), &temp2_e ); /*temp2_e*/
    3063           0 :             move32();
    3064           0 :             temp2_e = add( temp2_e, sub( vec_len_e, energy_sum_e ) );
    3065           0 :             hMeta->directional_meta[i].energy_ratio_fx[j][k] = L_shl( hMeta->directional_meta[i].energy_ratio_fx[j][k], add( temp2_e, 15 ) ); /*changing q from 15-temp2_e to q30*/
    3066           0 :             move32();
    3067           0 :             hMeta->directional_meta[i].spread_coherence_fx[j][k] = BASOP_Util_Divide3232_Scale( spread_coh_sum_fx, L_add( energy_sum_fx, EPSILON_FX ), &temp2_e );
    3068           0 :             move16();
    3069           0 :             temp2_e = add( temp2_e, sub( spread_coh_sum_e, energy_sum_e ) );
    3070           0 :             hMeta->directional_meta[i].spread_coherence_fx[j][k] = shl( hMeta->directional_meta[i].spread_coherence_fx[j][k], temp2_e ); /*changing q from 15-temp2_e to q15*/
    3071           0 :             move16();
    3072           0 :             IF( i == 0 )
    3073             :             {
    3074           0 :                 hMeta->common_meta.surround_coherence_fx[j][k] = BASOP_Util_Divide3232_Scale( surr_coh_sum_fx, L_add( energy_sum_fx, EPSILON_FX ), &temp2_e );
    3075           0 :                 move16();
    3076           0 :                 temp2_e = add( temp2_e, sub( surr_coh_sum_e, energy_sum_e ) );
    3077           0 :                 hMeta->common_meta.surround_coherence_fx[j][k] = shl_sat( hMeta->common_meta.surround_coherence_fx[j][k], temp2_e ); /*changing q from 15-temp2_e to q15*/
    3078           0 :                 move16();
    3079             :             }
    3080             : 
    3081             :             /* copy the same value to all subframes */
    3082           0 :             FOR( j = 1; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
    3083             :             {
    3084           0 :                 hMeta->directional_meta[i].azimuth_fx[j][k] = hMeta->directional_meta[i].azimuth_fx[0][k];                   /*q22*/
    3085           0 :                 hMeta->directional_meta[i].elevation_fx[j][k] = hMeta->directional_meta[i].elevation_fx[0][k];               /*q22*/
    3086           0 :                 hMeta->directional_meta[i].energy_ratio_fx[j][k] = hMeta->directional_meta[i].energy_ratio_fx[0][k];         /*q30*/
    3087           0 :                 hMeta->directional_meta[i].spread_coherence_fx[j][k] = hMeta->directional_meta[i].spread_coherence_fx[0][k]; /*q15*/
    3088           0 :                 move32();
    3089           0 :                 move32();
    3090           0 :                 move32();
    3091           0 :                 move16();
    3092           0 :                 IF( i == 0 )
    3093             :                 {
    3094           0 :                     hMeta->common_meta.surround_coherence_fx[j][k] = hMeta->common_meta.surround_coherence_fx[0][k]; /*q15*/
    3095           0 :                     move16();
    3096             :                 }
    3097             :             }
    3098             :         }
    3099             :     }
    3100             : 
    3101           0 :     FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
    3102             :     {
    3103           0 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
    3104             :         {
    3105           0 :             IF( EQ_16( numDirections, 2 ) )
    3106             :             {
    3107           0 :                 hMeta->common_meta.diffuse_to_total_ratio_fx[j][k] = L_max( 0, L_sub( L_sub( ONE_IN_Q30, hMeta->directional_meta[1].energy_ratio_fx[j][k] ), hMeta->directional_meta[0].energy_ratio_fx[j][k] ) ); /*q30*/
    3108             :             }
    3109             :             ELSE
    3110             :             {
    3111           0 :                 hMeta->common_meta.diffuse_to_total_ratio_fx[j][k] = L_max( 0, L_sub( ONE_IN_Q30, hMeta->directional_meta[0].energy_ratio_fx[j][k] ) ); /*q30*/
    3112             :             }
    3113           0 :             move32();
    3114           0 :             hMeta->common_meta.remainder_to_total_ratio_fx[j][k] = 0; /*q30*/
    3115           0 :             move32();
    3116             :         }
    3117             :     }
    3118             : 
    3119           0 :     return;
    3120             : }
    3121             : 
    3122             : 
    3123             : /*-------------------------------------------------------------------*
    3124             :  * copy_masa_metadata_subframe()
    3125             :  *
    3126             :  * Copy MASA metadata frame subframe contents
    3127             :  *-------------------------------------------------------------------*/
    3128      158504 : static void copy_masa_metadata_subframe_fx(
    3129             :     const MASA_METADATA_HANDLE hMetaFrom, /* i  : MASA frame metdata to be copied      */
    3130             :     const UWord8 sfFrom,                  /* i  : subframe index of the copy source    */
    3131             :     MASA_METADATA_HANDLE hMetaTo,         /* o  : MASA frame metadata copy destination */
    3132             :     const UWord8 sfTo                     /* i  : subframe index of the copy target    */
    3133             : )
    3134             : {
    3135             :     UWord8 dir;
    3136             : 
    3137             :     /* directional metadata */
    3138      475512 :     FOR( dir = 0; dir < MASA_MAXIMUM_DIRECTIONS; dir++ )
    3139             :     {
    3140      317008 :         Copy32( hMetaFrom->directional_meta[dir].azimuth_fx[sfFrom], hMetaTo->directional_meta[dir].azimuth_fx[sfTo], MASA_FREQUENCY_BANDS );                 // Q22
    3141      317008 :         Copy32( hMetaFrom->directional_meta[dir].elevation_fx[sfFrom], hMetaTo->directional_meta[dir].elevation_fx[sfTo], MASA_FREQUENCY_BANDS );             // Q22
    3142      317008 :         Copy32( hMetaFrom->directional_meta[dir].energy_ratio_fx[sfFrom], hMetaTo->directional_meta[dir].energy_ratio_fx[sfTo], MASA_FREQUENCY_BANDS );       // Q30
    3143      317008 :         Copy( hMetaFrom->directional_meta[dir].spread_coherence_fx[sfFrom], hMetaTo->directional_meta[dir].spread_coherence_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q15
    3144             :     }
    3145             : 
    3146             :     /* common metadata */
    3147      158504 :     Copy32( hMetaFrom->common_meta.diffuse_to_total_ratio_fx[sfFrom], hMetaTo->common_meta.diffuse_to_total_ratio_fx[sfTo], MASA_FREQUENCY_BANDS );     // Q30
    3148      158504 :     Copy( hMetaFrom->common_meta.surround_coherence_fx[sfFrom], hMetaTo->common_meta.surround_coherence_fx[sfTo], MASA_FREQUENCY_BANDS );               // Q15
    3149      158504 :     Copy32( hMetaFrom->common_meta.remainder_to_total_ratio_fx[sfFrom], hMetaTo->common_meta.remainder_to_total_ratio_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q30
    3150             : 
    3151      158504 :     return;
    3152             : }
    3153             : 
    3154             : /*-------------------------------------------------------------------*
    3155             :  * copy_masa_metadata()
    3156             :  *
    3157             :  * Copy MASA metada frame contents
    3158             :  *-------------------------------------------------------------------*/
    3159       39626 : static void copy_masa_metadata_fx(
    3160             :     const MASA_METADATA_HANDLE hMetaFrom, /* i  : MASA frame metadata to be copied     */
    3161             :     MASA_METADATA_HANDLE hMetaTo          /* o  : MASA frame metadata copy destination */
    3162             : )
    3163             : {
    3164             :     UWord8 sf, byte_idx;
    3165             : 
    3166             :     /* descriptive metadata */
    3167      356634 :     FOR( byte_idx = 0; byte_idx < 8; byte_idx++ )
    3168             :     {
    3169      317008 :         hMetaTo->descriptive_meta.formatDescriptor[byte_idx] = hMetaFrom->descriptive_meta.formatDescriptor[byte_idx];
    3170      317008 :         move16();
    3171             :     }
    3172             : 
    3173       39626 :     hMetaTo->descriptive_meta.numberOfDirections = hMetaFrom->descriptive_meta.numberOfDirections;
    3174       39626 :     hMetaTo->descriptive_meta.numberOfChannels = hMetaFrom->descriptive_meta.numberOfChannels;
    3175       39626 :     hMetaTo->descriptive_meta.sourceFormat = hMetaFrom->descriptive_meta.sourceFormat;
    3176       39626 :     hMetaTo->descriptive_meta.transportDefinition = hMetaFrom->descriptive_meta.transportDefinition;
    3177       39626 :     hMetaTo->descriptive_meta.channelAngle = hMetaFrom->descriptive_meta.channelAngle;
    3178       39626 :     hMetaTo->descriptive_meta.channelDistance = hMetaFrom->descriptive_meta.channelDistance;
    3179       39626 :     hMetaTo->descriptive_meta.channelLayout = hMetaFrom->descriptive_meta.channelLayout;
    3180       39626 :     move16();
    3181       39626 :     move16();
    3182       39626 :     move16();
    3183       39626 :     move16();
    3184       39626 :     move16();
    3185       39626 :     move16();
    3186       39626 :     move16();
    3187             : 
    3188             :     /* directional and common metadata */
    3189      198130 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    3190             :     {
    3191      158504 :         copy_masa_metadata_subframe_fx( hMetaFrom, sf, hMetaTo, sf );
    3192             :     }
    3193             : 
    3194       39626 :     return;
    3195             : }
    3196             : 
    3197             : /*-------------------------------------------------------------------*
    3198             :  * are_masa_subframes_similar()
    3199             :  *
    3200             :  * Compare the similarity of MASA metadata in two sub-frames
    3201             :  *-------------------------------------------------------------------*/
    3202             : 
    3203             : /* r: similarity decision */
    3204      175035 : static UWord8 are_masa_subframes_similar_fx(
    3205             :     const MASA_METADATA_HANDLE frame1, /* i  : MASA metadata frame 1                      */
    3206             :     const UWord8 sf1_idx,              /* i  : index of the subframe of frame1 to inspect */
    3207             :     const MASA_METADATA_HANDLE frame2, /* i  : MASA metadata frame 2                      */
    3208             :     const UWord8 sf2_idx               /* i  : index of the subframe of frame2 to inspect */
    3209             : )
    3210             : {
    3211             :     UWord8 num_dir;
    3212             :     UWord8 dir;
    3213             :     UWord8 band_idx;
    3214             :     UWord8 sf_differ;
    3215             : 
    3216      175035 :     num_dir = frame1->descriptive_meta.numberOfDirections;
    3217      175035 :     dir = 0;
    3218      175035 :     band_idx = 0;
    3219      175035 :     sf_differ = FALSE;
    3220      175035 :     move16();
    3221      175035 :     move16();
    3222      175035 :     move16();
    3223      175035 :     move16();
    3224             : 
    3225      175035 :     IF( NE_16( num_dir, frame2->descriptive_meta.numberOfDirections ) )
    3226             :     {
    3227           0 :         sf_differ = TRUE;
    3228           0 :         move16();
    3229             :     }
    3230             :     ELSE
    3231             :     {
    3232             :         /* check per-direction metadata */
    3233      175035 :         dir = 0;
    3234      175035 :         band_idx = 0;
    3235      175035 :         move16();
    3236      175035 :         move16();
    3237             : 
    3238      360870 :         WHILE( ( sf_differ == FALSE ) && ( dir <= num_dir ) )
    3239             :         {
    3240      185835 :             test();
    3241      185835 :             band_idx = 0;
    3242      185835 :             move16();
    3243     1244235 :             WHILE( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) )
    3244             :             {
    3245     1200135 :                 test();
    3246             :                 Word32 azi_dif_fx;
    3247     1200135 :                 azi_dif_fx = L_abs( L_sub( frame1->directional_meta[dir].azimuth_fx[sf1_idx][band_idx], frame2->directional_meta[dir].azimuth_fx[sf2_idx][band_idx] ) ); // Q22
    3248     1200135 :                 IF( GT_32( azi_dif_fx, 180 << Q22 ) )
    3249       16892 :                 azi_dif_fx = L_sub( 360 << Q22, azi_dif_fx ); // Q22
    3250             : 
    3251     1200135 :                 IF( GT_32( azi_dif_fx, ONE_IN_Q21 /*0.5 in Q22*/ ) )
    3252             :                 {
    3253      139100 :                     sf_differ = TRUE;
    3254      139100 :                     move16();
    3255      139100 :                     BREAK;
    3256             :                 }
    3257             : 
    3258     1061035 :                 IF( GT_32( L_abs( L_sub( frame1->directional_meta[dir].elevation_fx[sf1_idx][band_idx], frame2->directional_meta[dir].elevation_fx[sf2_idx][band_idx] ) ), MASA_ANGLE_TOLERANCE_FX ) )
    3259             :                 {
    3260        2616 :                     sf_differ = TRUE;
    3261        2616 :                     move16();
    3262        2616 :                     BREAK;
    3263             :                 }
    3264             : 
    3265     1058419 :                 IF( GT_32( L_abs( L_sub( frame1->directional_meta[dir].energy_ratio_fx[sf1_idx][band_idx], frame2->directional_meta[dir].energy_ratio_fx[sf2_idx][band_idx] ) ), MASA_RATIO_TOLERANCE_FX ) )
    3266             :                 {
    3267          19 :                     sf_differ = TRUE;
    3268          19 :                     move16();
    3269          19 :                     BREAK;
    3270             :                 }
    3271             : 
    3272     1058400 :                 IF( GT_32( L_abs( L_sub( frame1->directional_meta[dir].spread_coherence_fx[sf1_idx][band_idx], frame2->directional_meta[dir].spread_coherence_fx[sf2_idx][band_idx] ) ), MASA_COHERENCE_TOLERANCE_FX ) )
    3273             :                 {
    3274           0 :                     sf_differ = TRUE;
    3275           0 :                     move16();
    3276           0 :                     BREAK;
    3277             :                 }
    3278             : 
    3279     1058400 :                 band_idx = (UWord8) add( band_idx, 1 );
    3280     1058400 :                 move16();
    3281             :             }
    3282      185835 :             dir = (UWord8) add( dir, 1 );
    3283      185835 :             move16();
    3284             :         }
    3285             : 
    3286             :         /* check the common metadata */
    3287      175035 :         WHILE( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) )
    3288             :         {
    3289           0 :             test();
    3290           0 :             IF( GT_32( L_abs( L_sub( frame1->common_meta.surround_coherence_fx[sf1_idx][band_idx], frame2->common_meta.surround_coherence_fx[sf2_idx][band_idx] ) ), MASA_COHERENCE_TOLERANCE_FX ) )
    3291             :             {
    3292           0 :                 sf_differ = TRUE;
    3293           0 :                 move16();
    3294           0 :                 BREAK;
    3295             :             }
    3296             : 
    3297           0 :             band_idx = (UWord8) add( band_idx, 1 );
    3298           0 :             move16();
    3299             :         }
    3300             :     }
    3301             : 
    3302      175035 :     IF( sf_differ )
    3303             :     {
    3304      141735 :         return FALSE;
    3305             :     }
    3306             :     ELSE
    3307             :     {
    3308       33300 :         return TRUE;
    3309             :     }
    3310             : }
    3311             : 
    3312             : /*-------------------------------------------------------------------*
    3313             :  * detect_framing_async()
    3314             :  *
    3315             :  * Compare the similarity of MASA metadata in two sub-frames
    3316             :  * Analysis result is stored in hMasa->data.sync_state, and
    3317             :  * potentially hMasa->masaMetadata is modified
    3318             :  *-------------------------------------------------------------------*/
    3319       39626 : static void detect_framing_async_fx(
    3320             :     MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder structure */
    3321             : )
    3322             : {
    3323             :     MASA_METADATA_HANDLE current_meta;
    3324             :     MASA_METADATA_HANDLE previous_meta;
    3325             :     MASA_SYNC_HANDLE sync_state;
    3326             :     MASA_FRAME_MODE frame_mode;
    3327             :     UWord8 n_sim_start, n_sim_stop, sf_idx;
    3328             :     UWord8 found_offset;
    3329             : 
    3330       39626 :     current_meta = &( hMasa->masaMetadata );  /* metadata from current frame */
    3331       39626 :     sync_state = &( hMasa->data.sync_state ); /* synchronization structure */
    3332       39626 :     previous_meta = &( sync_state->previous_metadata );
    3333             : 
    3334             :     /* check current frame, how many are similar from the start and from the end */
    3335       39626 :     n_sim_start = 1;
    3336       39626 :     move16();
    3337       56276 :     FOR( sf_idx = n_sim_start; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
    3338             :     {
    3339       50726 :         IF( EQ_16( are_masa_subframes_similar_fx( current_meta, 0, current_meta, sf_idx ), TRUE ) )
    3340             :         {
    3341       16650 :             n_sim_start = (UWord8) add( sf_idx, 1 );
    3342       16650 :             move16();
    3343             :         }
    3344             :         ELSE
    3345             :         {
    3346       34076 :             BREAK;
    3347             :         }
    3348             :     }
    3349             : 
    3350             :     /* number of similar sub-frames starting from the end of the frame */
    3351       39626 :     IF( EQ_16( n_sim_start, MAX_PARAM_SPATIAL_SUBFRAMES ) ) /* shortcut */
    3352             :     {
    3353        5550 :         n_sim_stop = n_sim_start;
    3354        5550 :         move16();
    3355             :     }
    3356             :     ELSE
    3357             :     {
    3358       34076 :         n_sim_stop = 1;
    3359       34076 :         move16();
    3360       34076 :         FOR( sf_idx = 2; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
    3361             :         {
    3362             :             /* we need to check only the two middle sub-frames, as all being the same would have taken the shortcut above */
    3363       34076 :             IF( EQ_16( are_masa_subframes_similar_fx( current_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1, current_meta, (UWord8) sub( MAX_PARAM_SPATIAL_SUBFRAMES, sf_idx ) ), TRUE ) )
    3364             :             {
    3365           0 :                 n_sim_stop = sf_idx;
    3366           0 :                 move16();
    3367             :             }
    3368             :             ELSE
    3369             :             {
    3370       34076 :                 BREAK;
    3371             :             }
    3372             :         }
    3373             :     }
    3374             : 
    3375       39626 :     frame_mode = MASA_FRAME_4SF; /* default mode: 4sf */
    3376       39626 :     move16();
    3377       39626 :     IF( GT_16( sync_state->prev_offset, MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) )
    3378             :     {
    3379             :         /* earlier offset was large => reset the offset */
    3380           0 :         found_offset = 0;
    3381             :     }
    3382             :     ELSE
    3383             :     {
    3384             :         /* keep previous offset unless something else is found. alternatively, we could reset always */
    3385       39626 :         found_offset = sync_state->prev_offset;
    3386             :     }
    3387       39626 :     move16();
    3388             : 
    3389       39626 :     test();
    3390       39626 :     test();
    3391       39626 :     IF( EQ_16( n_sim_start, MAX_PARAM_SPATIAL_SUBFRAMES ) && EQ_16( n_sim_stop, MAX_PARAM_SPATIAL_SUBFRAMES ) )
    3392             :     {
    3393             :         /* full frame consists of similar sub-frames */
    3394        5550 :         frame_mode = MASA_FRAME_1SF;
    3395        5550 :         move16();
    3396        5550 :         test();
    3397        5550 :         IF( ( sync_state->prev_sim_stop != 0 ) && EQ_16( are_masa_subframes_similar_fx( current_meta, 0, previous_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1 ), TRUE ) )
    3398             :         {
    3399             :             /* > 4 sub-frames of similar data */
    3400           0 :             IF( LT_16( sync_state->prev_sim_stop, 3 ) )
    3401             :             {
    3402             :                 /* can nicely align the framing with the earlier data and a small offset */
    3403           0 :                 found_offset = sync_state->prev_sim_stop;
    3404             :             }
    3405             :             ELSE
    3406             :             {
    3407             :                 /* too many similar sub-frames to determine the offset accurately => keep earlier value */
    3408           0 :                 found_offset = sync_state->prev_offset;
    3409             :             }
    3410           0 :             move16();
    3411             :         }
    3412             :         ELSE
    3413             :         {
    3414             :             /* earlier window was different => reset the offset */
    3415        5550 :             found_offset = 0;
    3416        5550 :             move16();
    3417             :         }
    3418             :     }
    3419       34076 :     ELSE IF( EQ_16( n_sim_stop, 3 ) )
    3420             :     {
    3421             :         /* first sub-frame different that the rest 3
    3422             :                        => make a risky guess that the future sf would be the same too and we're in an offset case */
    3423           0 :         frame_mode = MASA_FRAME_1SF;
    3424           0 :         found_offset = 3;
    3425           0 :         move16();
    3426           0 :         move16();
    3427             :     }
    3428       34076 :     ELSE IF( ( sync_state->prev_sim_stop > 0 ) && EQ_16( are_masa_subframes_similar_fx( current_meta, 0, previous_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1 ), TRUE ) )
    3429             :     {
    3430             :         /* seeing data similar to past */
    3431           0 :         test();
    3432           0 :         IF( GT_16( n_sim_start, 1 ) && ( GE_16( add( n_sim_start, sync_state->prev_sim_stop ), MAX_PARAM_SPATIAL_SUBFRAMES ) ) )
    3433             :         {
    3434             :             /* with the past, would have at least one long frame similar subframes */
    3435           0 :             frame_mode = MASA_FRAME_1SF;
    3436           0 :             move16();
    3437             : 
    3438           0 :             IF( sync_state->prev_offset == 0 )
    3439             :             {
    3440           0 :                 found_offset = (UWord8) s_min( 2, sync_state->prev_sim_stop );
    3441             :             }
    3442             :             ELSE
    3443             :             {
    3444           0 :                 found_offset = sync_state->prev_offset;
    3445           0 :                 move16();
    3446             :             }
    3447             :         }
    3448             :     }
    3449             : 
    3450             :     /* keep the original contents of the frame, but then perform interpolation later */
    3451             :     /* just copy current frame to storage */
    3452       39626 :     copy_masa_metadata_fx( current_meta, previous_meta );
    3453             : 
    3454       39626 :     sync_state->prev_sim_stop = n_sim_stop;
    3455       39626 :     sync_state->prev_offset = found_offset;
    3456       39626 :     sync_state->frame_mode = frame_mode;
    3457       39626 :     move16();
    3458       39626 :     move16();
    3459       39626 :     move16();
    3460             : 
    3461       39626 :     return;
    3462             : }
    3463             : 
    3464             : /*-------------------------------------------------------------------*
    3465             :  * masa_metadata_direction_alignment()
    3466             :  *
    3467             :  * In 2dir MASA metadata, determine the ordering of the directional
    3468             :  * fields such that the azi/ele change across time is minimized.
    3469             :  *-------------------------------------------------------------------*/
    3470       39626 : static void masa_metadata_direction_alignment_fx(
    3471             :     MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder handle */
    3472             : )
    3473             : {
    3474             :     UWord8 band, n_dirs;
    3475             :     MASA_DIR_ALIGN_HANDLE hAlignState;
    3476             :     MASA_METADATA_HANDLE hMeta;
    3477       39626 :     hAlignState = &( hMasa->data.dir_align_state );
    3478       39626 :     hMeta = &( hMasa->masaMetadata );
    3479             : 
    3480       39626 :     n_dirs = (UWord8) add( hMeta->descriptive_meta.numberOfDirections, 1 ); /* 1-based */
    3481       39626 :     move16();
    3482      990650 :     FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
    3483             :     {
    3484             :         UWord8 sf;
    3485             :         Word32 diff_swap_fx;
    3486             :         Word32 diff_no_swap_fx;
    3487             : 
    3488             :         /* trade 2*(cos+sin) against storing the values between frames */
    3489             :         Word16 prev_ele_dir1_sin_fx, prev_ele_dir2_sin_fx;
    3490             :         Word16 prev_ele_dir1_cos_fx, prev_ele_dir2_cos_fx;
    3491             : 
    3492      951024 :         prev_ele_dir1_sin_fx = getSineWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir1_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3493      951024 :         prev_ele_dir2_sin_fx = getSineWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir2_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3494             : 
    3495      951024 :         prev_ele_dir1_cos_fx = getCosWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir1_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3496      951024 :         prev_ele_dir2_cos_fx = getCosWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir2_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3497             : 
    3498     4755120 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    3499             :         {
    3500             :             Word32 azi_rad1_fx, ele_rad1_fx;
    3501             :             Word32 azi_rad2_fx, ele_rad2_fx;
    3502             :             Word16 cos_ele1_fx, cos_ele2_fx;
    3503             :             Word16 sin_ele1_fx, sin_ele2_fx;
    3504             :             Word16 temp1;
    3505             :             Word32 temp2;
    3506             :             Word16 temp1_e;
    3507             : 
    3508             : 
    3509     3804096 :             azi_rad1_fx = Mpy_32_16_1( hMeta->directional_meta[0].azimuth_fx[sf][band], 572 /*PI_OVER_180 q15*/ );   /*q22*/
    3510     3804096 :             ele_rad1_fx = Mpy_32_16_1( hMeta->directional_meta[0].elevation_fx[sf][band], 572 /*PI_OVER_180 q15*/ ); /*q22*/
    3511             : 
    3512     3804096 :             IF( GT_16( n_dirs, 1 ) )
    3513             :             {
    3514      950400 :                 azi_rad2_fx = Mpy_32_16_1( hMeta->directional_meta[1].azimuth_fx[sf][band], 572 /*PI_OVER_180 q15*/ );   /*q22*/
    3515      950400 :                 ele_rad2_fx = Mpy_32_16_1( hMeta->directional_meta[1].elevation_fx[sf][band], 572 /*PI_OVER_180 q15*/ ); /*q22*/
    3516             : 
    3517      950400 :                 test();
    3518      950400 :                 test();
    3519      950400 :                 test();
    3520      950400 :                 test();
    3521      950400 :                 test();
    3522      950400 :                 test();
    3523             :                 /* quick checks to detect constant data and earlier flip */
    3524      950400 :                 IF( LT_32( L_abs( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir1_fx[band] ) ), EPSILON_FX ) &&
    3525             :                     LT_32( L_abs( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir2_fx[band] ) ), EPSILON_FX ) &&
    3526             :                     LT_32( L_abs( L_sub( ele_rad1_fx, hAlignState->previous_ele_dir1_fx[band] ) ), EPSILON_FX ) &&
    3527             :                     LT_32( L_abs( L_sub( ele_rad2_fx, hAlignState->previous_ele_dir2_fx[band] ) ), EPSILON_FX ) )
    3528             :                 {
    3529       91800 :                     diff_swap_fx = ONE_IN_Q13; /*1 q13*/
    3530       91800 :                     move32();
    3531       91800 :                     diff_no_swap_fx = 0;
    3532       91800 :                     move32();
    3533             :                     /* cached values that will be used for the short-cuts and over-written by the real computations, if done */
    3534       91800 :                     sin_ele1_fx = prev_ele_dir1_sin_fx; /*q15*/
    3535       91800 :                     sin_ele2_fx = prev_ele_dir2_sin_fx; /*q15*/
    3536       91800 :                     cos_ele1_fx = prev_ele_dir1_cos_fx; /*q15*/
    3537       91800 :                     cos_ele2_fx = prev_ele_dir2_cos_fx; /*q15*/
    3538       91800 :                     move16();
    3539       91800 :                     move16();
    3540       91800 :                     move16();
    3541       91800 :                     move16();
    3542             :                 }
    3543      858600 :                 ELSE IF( LT_32( L_abs( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir2_fx[band] ) ), EPSILON_FX ) &&
    3544             :                          LT_32( L_abs( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir1_fx[band] ) ), EPSILON_FX ) &&
    3545             :                          LT_32( L_abs( L_sub( ele_rad1_fx, hAlignState->previous_ele_dir2_fx[band] ) ), EPSILON_FX ) &&
    3546             :                          LT_32( L_abs( L_sub( ele_rad2_fx, hAlignState->previous_ele_dir1_fx[band] ) ), EPSILON_FX ) )
    3547             :                 {
    3548       37800 :                     diff_swap_fx = 0;
    3549       37800 :                     move32();
    3550       37800 :                     diff_no_swap_fx = ONE_IN_Q13; /*1.0 q13*/
    3551       37800 :                     move32();
    3552             :                     /* cached values that will be used for the short-cuts and over-written by the real computations, if done */
    3553       37800 :                     sin_ele1_fx = prev_ele_dir2_sin_fx; /*q15*/
    3554       37800 :                     sin_ele2_fx = prev_ele_dir1_sin_fx; /*q15*/
    3555       37800 :                     cos_ele1_fx = prev_ele_dir2_cos_fx; /*q15*/
    3556       37800 :                     cos_ele2_fx = prev_ele_dir1_cos_fx; /*q15*/
    3557       37800 :                     move16();
    3558       37800 :                     move16();
    3559       37800 :                     move16();
    3560       37800 :                     move16();
    3561             :                 }
    3562             :                 ELSE
    3563             :                 {
    3564             :                     /* angular distance of the two vectors */
    3565             :                     /* pre-compute values for re-use */
    3566      820800 :                     sin_ele1_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3567      820800 :                     sin_ele2_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad2_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3568             : 
    3569      820800 :                     cos_ele1_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3570      820800 :                     cos_ele2_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad2_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3571             : 
    3572      820800 :                     temp1 = getCosWord16R2( extract_l( Mpy_32_32( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir1_fx[band] ), 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3573      820800 :                     temp1 = mult( mult( temp1, cos_ele1_fx ) /*q31*/, prev_ele_dir1_cos_fx /*q15*/ );                                                           /*q15*/
    3574      820800 :                     temp1 = add_sat( mult( sin_ele1_fx, prev_ele_dir1_sin_fx ), temp1 );                                                                        /*q15*/
    3575      820800 :                     temp1_e = 1;                                                                                                                                /*stores expoenent for square root operation*/
    3576      820800 :                     move16();
    3577      820800 :                     temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
    3578      820800 :                     temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) );             /*q13*/
    3579      820800 :                     diff_no_swap_fx = L_deposit_l( temp1 );                                   /*q13*/
    3580             : 
    3581      820800 :                     temp1 = getCosWord16R2( extract_l( Mpy_32_32( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir2_fx[band] ), 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3582      820800 :                     temp1 = mult( mult( temp1, cos_ele2_fx ) /*q31*/, prev_ele_dir2_cos_fx /*q15*/ );                                                           /*q15*/
    3583      820800 :                     temp1 = add_sat( mult( sin_ele2_fx, prev_ele_dir2_sin_fx ), temp1 );                                                                        /*q15*/
    3584      820800 :                     temp1_e = 1;                                                                                                                                /*stores expoenent for square root operation*/
    3585      820800 :                     move16();
    3586      820800 :                     temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
    3587      820800 :                     temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) );             /*q13*/
    3588      820800 :                     diff_no_swap_fx = L_add( diff_no_swap_fx, temp1 );                        /*q13*/
    3589             : 
    3590      820800 :                     temp1 = getCosWord16R2( extract_l( Mpy_32_32( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir2_fx[band] ), 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3591      820800 :                     temp1 = mult( mult( temp1, cos_ele1_fx ) /*q31*/, prev_ele_dir2_cos_fx /*q15*/ );                                                           /*q15*/
    3592      820800 :                     temp1 = add_sat( mult( sin_ele1_fx, prev_ele_dir2_sin_fx ), temp1 );                                                                        /*q15*/
    3593      820800 :                     temp1_e = 1;                                                                                                                                /*stores expoenent for square root operation*/
    3594      820800 :                     move16();
    3595      820800 :                     temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
    3596      820800 :                     temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) );             /*q13*/
    3597      820800 :                     diff_swap_fx = L_deposit_l( temp1 );                                      /*q13*/
    3598             : 
    3599      820800 :                     temp1 = getCosWord16R2( extract_l( Mpy_32_32( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir1_fx[band] ), 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3600      820800 :                     temp1 = mult( mult( temp1, cos_ele2_fx ) /*q31*/, prev_ele_dir1_cos_fx /*q15*/ );                                                           /*q15*/
    3601      820800 :                     temp1 = add_sat( mult( sin_ele2_fx, prev_ele_dir1_sin_fx ), temp1 );                                                                        /*q15*/
    3602      820800 :                     temp1_e = 1;                                                                                                                                /*stores expoenent for square root operation*/
    3603      820800 :                     move16();
    3604      820800 :                     temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
    3605      820800 :                     temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) );             /*q13*/
    3606      820800 :                     diff_swap_fx = L_add( diff_swap_fx, temp1 );                              /*q13*/
    3607             :                 }
    3608             :             }
    3609             :             ELSE
    3610             :             {
    3611             :                 /* 1dir */
    3612     2853696 :                 sin_ele1_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3613     2853696 :                 cos_ele1_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) );  /*q15*/
    3614             : 
    3615     2853696 :                 azi_rad2_fx = 0;
    3616     2853696 :                 ele_rad2_fx = 0;
    3617     2853696 :                 move32();
    3618     2853696 :                 move32();
    3619             : 
    3620     2853696 :                 sin_ele2_fx = 0;      /* sin(0) */
    3621     2853696 :                 cos_ele2_fx = MAX_16; /* cos(0) in Q15*/
    3622     2853696 :                 move16();
    3623     2853696 :                 move16();
    3624             : 
    3625     2853696 :                 diff_swap_fx = ONE_IN_Q13; /*1.0 in Q13*/
    3626     2853696 :                 diff_no_swap_fx = 0;
    3627     2853696 :                 move32();
    3628     2853696 :                 move32();
    3629             :             }
    3630             : 
    3631     3804096 :             test();
    3632     3804096 :             IF( GT_16( n_dirs, 1 ) && GT_32( diff_no_swap_fx, diff_swap_fx ) )
    3633      121788 :             {
    3634             :                 /* swap the metadata of the two directions in this TF-tile */
    3635             :                 Word32 tmp_val;
    3636             :                 Word16 tmp_val_16;
    3637             :                 UWord16 tmp_int_val;
    3638      121788 :                 tmp_val = hMeta->directional_meta[0].azimuth_fx[sf][band];                                         /*q22*/
    3639      121788 :                 hMeta->directional_meta[0].azimuth_fx[sf][band] = hMeta->directional_meta[1].azimuth_fx[sf][band]; /*q22*/
    3640      121788 :                 hMeta->directional_meta[1].azimuth_fx[sf][band] = tmp_val;                                         /*q22*/
    3641      121788 :                 move32();
    3642      121788 :                 move32();
    3643      121788 :                 move32();
    3644             : 
    3645      121788 :                 tmp_val = hMeta->directional_meta[0].elevation_fx[sf][band];                                           /*q22*/
    3646      121788 :                 hMeta->directional_meta[0].elevation_fx[sf][band] = hMeta->directional_meta[1].elevation_fx[sf][band]; /*q22*/
    3647      121788 :                 hMeta->directional_meta[1].elevation_fx[sf][band] = tmp_val;                                           /*q22*/
    3648      121788 :                 move32();
    3649      121788 :                 move32();
    3650      121788 :                 move32();
    3651             : 
    3652      121788 :                 tmp_int_val = hMeta->directional_meta[0].spherical_index[sf][band];                                          /*q0*/
    3653      121788 :                 hMeta->directional_meta[0].spherical_index[sf][band] = hMeta->directional_meta[1].spherical_index[sf][band]; /*q0*/
    3654      121788 :                 hMeta->directional_meta[1].spherical_index[sf][band] = tmp_int_val;                                          /*q0*/
    3655      121788 :                 move32();
    3656      121788 :                 move32();
    3657      121788 :                 move32();
    3658             : 
    3659      121788 :                 tmp_val = hMeta->directional_meta[0].energy_ratio_fx[sf][band];                                              /*q30*/
    3660      121788 :                 hMeta->directional_meta[0].energy_ratio_fx[sf][band] = hMeta->directional_meta[1].energy_ratio_fx[sf][band]; /*q30*/
    3661      121788 :                 hMeta->directional_meta[1].energy_ratio_fx[sf][band] = tmp_val;                                              /*q30*/
    3662      121788 :                 move32();
    3663      121788 :                 move32();
    3664      121788 :                 move32();
    3665             : 
    3666      121788 :                 tmp_val_16 = hMeta->directional_meta[0].spread_coherence_fx[sf][band];                                               /*q15*/
    3667      121788 :                 hMeta->directional_meta[0].spread_coherence_fx[sf][band] = hMeta->directional_meta[1].spread_coherence_fx[sf][band]; /*q15*/
    3668      121788 :                 hMeta->directional_meta[1].spread_coherence_fx[sf][band] = tmp_val_16;                                               /*q15*/
    3669      121788 :                 move16();
    3670      121788 :                 move16();
    3671      121788 :                 move16();
    3672             : 
    3673      121788 :                 hAlignState->previous_azi_dir1_fx[band] = azi_rad2_fx; /*q22*/
    3674      121788 :                 hAlignState->previous_ele_dir1_fx[band] = ele_rad2_fx; /*q22*/
    3675      121788 :                 move32();
    3676      121788 :                 move32();
    3677             : 
    3678      121788 :                 hAlignState->previous_azi_dir2_fx[band] = azi_rad1_fx; /*q22*/
    3679      121788 :                 hAlignState->previous_ele_dir2_fx[band] = ele_rad1_fx; /*q22*/
    3680      121788 :                 move32();
    3681      121788 :                 move32();
    3682             : 
    3683      121788 :                 prev_ele_dir1_cos_fx = cos_ele2_fx; /*q15*/
    3684      121788 :                 prev_ele_dir1_sin_fx = sin_ele2_fx; /*q15*/
    3685      121788 :                 move16();
    3686      121788 :                 move16();
    3687             : 
    3688      121788 :                 prev_ele_dir2_cos_fx = cos_ele1_fx; /*q15*/
    3689      121788 :                 prev_ele_dir2_sin_fx = sin_ele1_fx; /*q15*/
    3690      121788 :                 move16();
    3691      121788 :                 move16();
    3692             :             }
    3693             :             ELSE
    3694             :             {
    3695     3682308 :                 hAlignState->previous_azi_dir1_fx[band] = azi_rad1_fx; /*q22*/
    3696     3682308 :                 hAlignState->previous_ele_dir1_fx[band] = ele_rad1_fx; /*q22*/
    3697     3682308 :                 move32();
    3698     3682308 :                 move32();
    3699             : 
    3700     3682308 :                 hAlignState->previous_azi_dir2_fx[band] = azi_rad2_fx; /*q22*/
    3701     3682308 :                 hAlignState->previous_ele_dir2_fx[band] = ele_rad2_fx; /*q22*/
    3702     3682308 :                 move32();
    3703     3682308 :                 move32();
    3704             : 
    3705     3682308 :                 prev_ele_dir1_cos_fx = cos_ele1_fx; /*q15*/
    3706     3682308 :                 prev_ele_dir1_sin_fx = sin_ele1_fx; /*q15*/
    3707     3682308 :                 move16();
    3708     3682308 :                 move16();
    3709             : 
    3710     3682308 :                 prev_ele_dir2_cos_fx = cos_ele2_fx; /*q15*/
    3711     3682308 :                 prev_ele_dir2_sin_fx = sin_ele2_fx; /*q15*/
    3712     3682308 :                 move16();
    3713     3682308 :                 move16();
    3714             :             }
    3715             :         } /* sf */
    3716             :     }     /* band */
    3717             : 
    3718       39626 :     return;
    3719             : }
    3720             : 
    3721             : /*-------------------------------------------------------------------*
    3722             :  * ivas_merge_masa_metadata()
    3723             :  *
    3724             :  *
    3725             :  *-------------------------------------------------------------------*/
    3726        3996 : void ivas_merge_masa_metadata_fx(
    3727             :     MASA_ENCODER_HANDLE hMasa,           /* i/o: MASA enc handle. source for MASA metadata and combined metadata will be here */
    3728             :     OMASA_SPATIAL_META_HANDLE hOMasaMeta /* i  : ISM-object metadata to be merged with the MASA metadata                      */
    3729             : )
    3730             : {
    3731             :     Word16 sf, band;
    3732             :     UWord8 numCodingBands;
    3733             :     UWord8 numDirections;
    3734             :     UWord8 numSf;
    3735             :     MASA_METADATA_HANDLE hMeta;
    3736             :     Word16 energyTimesRatioMASA_e[2];
    3737             :     Word16 total_diff_nrg_e;
    3738             :     Word16 energyMerged_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    3739             :     Word32 energyTimesRatioISM_fx; /*energyTimesRatioISM_e*/
    3740             :     Word16 energyTimesRatioISM_e;
    3741             :     Word32 energyTimesRatioMASA_fx[2]; /*energyTimesRatioMASA_e*/
    3742             :     Word32 total_diff_nrg_fx;
    3743             :     Word32 eneBand_fx; /*eneBand_e*/
    3744             :     Word16 eneBand_e;
    3745             :     Word32 energyMerged_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; /*energyMerged_e*/
    3746             :     Word32 temp1 /*temp1_e*/, temp2 /*temp2_e*/;
    3747             :     Word16 temp1_e, temp2_e;
    3748             : 
    3749        3996 :     numCodingBands = hMasa->config.numCodingBands;
    3750        3996 :     numDirections = hMasa->config.numberOfDirections;
    3751        3996 :     IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
    3752             :     {
    3753           0 :         numSf = 1;
    3754             :     }
    3755             :     ELSE
    3756             :     {
    3757        3996 :         numSf = 4;
    3758             :     }
    3759        3996 :     move16();
    3760        3996 :     move16();
    3761        3996 :     move16();
    3762        3996 :     hMeta = &( hMasa->masaMetadata );
    3763             : 
    3764       19980 :     FOR( sf = 0; sf < numSf; sf++ )
    3765             :     {
    3766      396000 :         FOR( band = 0; band < numCodingBands; band++ )
    3767             :         {
    3768             :             Word16 merge_dest;
    3769             :             Word32 dir_sum_fx; /*dir_sum_e*/
    3770             :             Word16 dir_sum_e;
    3771             :             UWord8 band_n_dirs;
    3772      380016 :             test();
    3773      380016 :             test();
    3774      380016 :             IF( EQ_16( numDirections, 1 ) || ( EQ_16( numDirections, 2 ) && hMasa->data.twoDirBands[band] == 0 ) )
    3775             :             {
    3776      380016 :                 band_n_dirs = 1;
    3777             :             }
    3778             :             ELSE
    3779             :             {
    3780           0 :                 band_n_dirs = 2;
    3781             :             }
    3782      380016 :             move16();
    3783             : 
    3784             :             /* Compute energies */
    3785      380016 :             eneBand_fx = hMasa->data.energy_fx[sf][band];
    3786      380016 :             eneBand_e = hMasa->data.energy_e[sf][band];
    3787      380016 :             move32();
    3788      380016 :             move16();
    3789      380016 :             energyMerged_fx[sf][band] = BASOP_Util_Add_Mant32Exp( eneBand_fx, eneBand_e, hMasa->data.hOmasaData->energy_ism_fx[sf][band], hMasa->data.hOmasaData->energy_ism_fx_e[sf][band], &energyMerged_e[sf][band] );
    3790      380016 :             move32();
    3791             : 
    3792             :             /* Compute weights */
    3793      380016 :             energyTimesRatioMASA_fx[0] = Mpy_32_32( eneBand_fx, hMeta->directional_meta[0].energy_ratio_fx[sf][band] );
    3794      380016 :             energyTimesRatioMASA_e[0] = add( eneBand_e, 1 );
    3795      380016 :             move32();
    3796      380016 :             move16();
    3797      380016 :             IF( EQ_16( band_n_dirs, 2 ) )
    3798             :             {
    3799           0 :                 energyTimesRatioMASA_fx[1] = Mpy_32_32( eneBand_fx, hMeta->directional_meta[1].energy_ratio_fx[sf][band] ); // energyTimesRatioMASA_e
    3800           0 :                 energyTimesRatioMASA_e[1] = add( eneBand_e, 1 );
    3801             :             }
    3802             :             ELSE
    3803             :             {
    3804      380016 :                 energyTimesRatioMASA_fx[1] = 0; // energyTimesRatioMASA_e
    3805      380016 :                 energyTimesRatioMASA_e[1] = 0;
    3806             :             }
    3807      380016 :             move32();
    3808      380016 :             move16();
    3809             : 
    3810             :             /* target is original MASA diffuseness */
    3811      380016 :             total_diff_nrg_fx = Mpy_32_32( eneBand_fx, hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] ); // total_diff_nrg_e
    3812      380016 :             total_diff_nrg_e = add( eneBand_e, 1 );
    3813             : 
    3814             :             /* criterion is mean of ISM ratio and new ratio */
    3815      380016 :             temp1 = BASOP_Util_Add_Mant32Exp( L_add( EPSILON_FX, eneBand_fx ), eneBand_e, hMasa->data.hOmasaData->energy_ism_fx[sf][band], hMasa->data.hOmasaData->energy_ism_fx_e[sf][band], &temp1_e ); /* EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band]*/
    3816      380016 :             temp2 = L_deposit_h( BASOP_Util_Divide3232_Scale( total_diff_nrg_fx, temp1, &temp2_e ) ); /*temp2_e*/                                                                                         /*total_diff_nrg / ( EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band] )*/
    3817      380016 :             temp2_e = add( temp2_e, sub( total_diff_nrg_e, temp1_e ) );
    3818      380016 :             IF( temp2_e < 0 )
    3819             :             {
    3820      305004 :                 temp2 = L_shl( temp2, temp2_e );
    3821      305004 :                 temp2_e = 0;
    3822      305004 :                 move16();
    3823             :             }
    3824      380016 :             temp2 = L_sub( L_shl_sat( 1, sub( 31, temp2_e ) ), temp2 );                                                                 /*( 1.0f - total_diff_nrg / ( EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band] ) )*/
    3825      380016 :             temp2 = BASOP_Util_Add_Mant32Exp( hOMasaMeta->directional_meta[0].energy_ratio_fx[sf][band], 1, temp2, temp2_e, &temp2_e ); /*( 1.0f - total_diff_nrg / ( EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band] ) )*/
    3826      380016 :             energyTimesRatioISM_fx = Mpy_32_32( L_shr( temp2, 1 ), hMasa->data.hOmasaData->energy_ism_fx[sf][band] );                   /*energyTimesRatioISM_e*/
    3827      380016 :             energyTimesRatioISM_e = add( temp2_e, hMasa->data.hOmasaData->energy_ism_fx_e[sf][band] );
    3828             :             /*energyTimesRatioISM = ( hOMasaMeta->directional_meta[0].energy_ratio[sf][band] + ( 1.0f - total_diff_nrg / ( EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band] ) ) ) / 2.0f * hMasa->data.hOmasaData->energy_ism[sf][band];*/
    3829             : 
    3830             :             /* Determine combined metadata based on the weights */
    3831      380016 :             merge_dest = -1;
    3832      380016 :             move16();
    3833      380016 :             test();
    3834      380016 :             test();
    3835      380016 :             test();
    3836      380016 :             test();
    3837      380016 :             test();
    3838      380016 :             test();
    3839      380016 :             IF( ( EQ_16( band_n_dirs, 1 ) && EQ_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[0], energyTimesRatioMASA_e[0], energyTimesRatioISM_fx, energyTimesRatioISM_e ), -1 ) ) ||
    3840             :                 ( EQ_16( band_n_dirs, 2 ) && EQ_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[0], energyTimesRatioMASA_e[0], energyTimesRatioMASA_fx[1], energyTimesRatioMASA_e[1] ), -1 ) && EQ_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[0], energyTimesRatioMASA_e[0], energyTimesRatioISM_fx, energyTimesRatioISM_e ), -1 ) ) )
    3841             :             {
    3842             :                 /* 1dir and ISM the most energetic, or 2dir and ISM the more energetic than MASA1 */
    3843      140970 :                 merge_dest = 0;
    3844             :             }
    3845      239046 :             ELSE IF( EQ_16( band_n_dirs, 2 ) && NE_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[1], energyTimesRatioMASA_e[1], energyTimesRatioMASA_fx[0], energyTimesRatioMASA_e[0] ), 1 ) && EQ_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[1], energyTimesRatioMASA_e[1], energyTimesRatioISM_fx, energyTimesRatioISM_e ), -1 ) )
    3846             :             {
    3847             :                 /* 2dir and ISM the most energetic and MASA2 the least energetic */
    3848           0 :                 merge_dest = 1;
    3849             :             }
    3850      380016 :             move16();
    3851             : 
    3852      380016 :             IF( merge_dest >= 0 ) /* replace one MASA with ISM */
    3853             :             {
    3854      140970 :                 hMeta->directional_meta[merge_dest].azimuth_fx[sf][band] = hOMasaMeta->directional_meta[0].azimuth_fx[sf][band];     /*q22*/
    3855      140970 :                 hMeta->directional_meta[merge_dest].elevation_fx[sf][band] = hOMasaMeta->directional_meta[0].elevation_fx[sf][band]; /*q22*/
    3856      140970 :                 move32();
    3857      140970 :                 move32();
    3858             :                 /* limit with the earlier direct-energy ratio */
    3859      140970 :                 dir_sum_fx = temp2; /* new dir ratio */
    3860      140970 :                 dir_sum_e = temp2_e;
    3861      140970 :                 move32();
    3862      140970 :                 move16();
    3863             :                 /*dir_sum = 1.0f - total_diff_nrg / ( EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band] )*/
    3864      140970 :                 IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( dir_sum_fx, dir_sum_e, hOMasaMeta->directional_meta[0].energy_ratio_fx[sf][band], 1 ), -1 ) )
    3865             :                 {
    3866           0 :                     hMeta->directional_meta[merge_dest].energy_ratio_fx[sf][band] = L_shl( dir_sum_fx, sub( dir_sum_e, 1 ) ); /*scaling to Q30*/
    3867             :                 }
    3868             :                 ELSE
    3869             :                 {
    3870      140970 :                     hMeta->directional_meta[merge_dest].energy_ratio_fx[sf][band] = hOMasaMeta->directional_meta[0].energy_ratio_fx[sf][band]; /*q30*/
    3871      140970 :                     move32();
    3872             :                 }
    3873             :                 /* clip with original ISM dir */
    3874      140970 :                 hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] = L_sub( ONE_IN_Q30, hMeta->directional_meta[merge_dest].energy_ratio_fx[sf][band] ); /*q30*/
    3875      140970 :                 move32();
    3876      140970 :                 move32(); /*hMeta->directional_meta[merge_dest].energy_ratio_fx*/
    3877             : 
    3878      140970 :                 IF( hMasa->config.useCoherence )
    3879             :                 {
    3880           0 :                     hMeta->directional_meta[merge_dest].spread_coherence_fx[sf][band] = hOMasaMeta->directional_meta[0].spread_coherence_fx[sf][band]; /*q15*/
    3881           0 :                     hMeta->common_meta.surround_coherence_fx[sf][band] = hOMasaMeta->common_meta.surround_coherence_fx[sf][band];                      /*q15*/
    3882           0 :                     move16();
    3883           0 :                     move16();
    3884             :                 }
    3885             : 
    3886             :                 /* recompute direct energy ratios to match the diffuse ratio */
    3887             :                 Word32 direct_quota_fx, direct_scaler_fx;
    3888             :                 Word16 direct_scaler_e;
    3889      140970 :                 direct_quota_fx = L_sub( ONE_IN_Q30, hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] );
    3890      140970 :                 IF( EQ_16( band_n_dirs, 1 ) )
    3891             :                 {
    3892      140970 :                     hMeta->directional_meta[0].energy_ratio_fx[sf][band] = direct_quota_fx; /*q30*/
    3893      140970 :                     move32();
    3894             :                 }
    3895             :                 ELSE
    3896             :                 {
    3897           0 :                     dir_sum_fx = L_add( hMeta->directional_meta[0].energy_ratio_fx[sf][band], hMeta->directional_meta[1].energy_ratio_fx[sf][band] ); /*q30*/
    3898           0 :                     direct_scaler_fx = BASOP_Util_Divide3232_Scale( direct_quota_fx, L_add( EPSILON_FX, dir_sum_fx ), &direct_scaler_e );
    3899           0 :                     direct_scaler_fx = L_shl( direct_scaler_fx, direct_scaler_e ); /*q31*/
    3900           0 :                     direct_scaler_e = 0;
    3901           0 :                     move16();
    3902           0 :                     hMeta->directional_meta[0].energy_ratio_fx[sf][band] = Mpy_32_32( direct_scaler_fx, hMeta->directional_meta[0].energy_ratio_fx[sf][band] ); /*q30*/
    3903           0 :                     hMeta->directional_meta[1].energy_ratio_fx[sf][band] = Mpy_32_32( direct_scaler_fx, hMeta->directional_meta[0].energy_ratio_fx[sf][band] ); /*q30*/
    3904           0 :                     move32();
    3905           0 :                     move32();
    3906             :                 }
    3907             :             }
    3908             :         }
    3909             :     }
    3910             : 
    3911       19980 :     FOR( sf = 0; sf < numSf; sf++ )
    3912             :     {
    3913      396000 :         FOR( band = 0; band < numCodingBands; band++ )
    3914             :         {
    3915      380016 :             hMasa->data.energy_fx[sf][band] = energyMerged_fx[sf][band];
    3916      380016 :             hMasa->data.energy_e[sf][band] = energyMerged_e[sf][band];
    3917      380016 :             move32();
    3918      380016 :             move16();
    3919             :         }
    3920             :     }
    3921             : 
    3922        3996 :     return;
    3923             : }
    3924       30442 : static void quantize_ratio_ism_vector_ivas_fx(
    3925             :     const Word16 *ratio_ism, /* ratio_ism_e */
    3926             :     Word16 ratio_ism_e,
    3927             :     Word16 *idx, /* Q0 */
    3928             :     const Word16 nchan_ism,
    3929             :     const Word32 masa_to_total_energy_ratio,
    3930             :     const Word16 idx_sep_object )
    3931             : {
    3932             :     Word16 i, j, best_i, best_i2;
    3933             :     Word16 dist, div, tmp, dist2, best_dist, temp, temp_e, tmp_e, idx_e, best_dist_e, dist_e, dist2_e;
    3934             :     Word16 part_idx_sum, max_sum_idx;
    3935             :     Word16 ratio_ism_loc[MAX_NUM_OBJECTS];
    3936             :     Word16 no_ism_loc;
    3937             : 
    3938       30442 :     max_sum_idx = sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 );
    3939             : 
    3940       30442 :     test();
    3941       30442 :     IF( GT_16( idx_sep_object, -1 ) )
    3942             :     {
    3943       30442 :         temp = BASOP_Util_Divide1616_Scale( 1, max_sum_idx, &temp_e );
    3944       30442 :         BASOP_Util_Add_MantExp( ratio_ism[idx_sep_object], ratio_ism_e, negate( temp ), temp_e, &tmp );
    3945             : 
    3946       30442 :         test();
    3947       30442 :         IF( tmp < 0 )
    3948             :         {
    3949             :             /* take it out from quantize function  */
    3950       28839 :             Copy( ratio_ism, ratio_ism_loc, idx_sep_object ); // Q(15 - ratio_ism_e)
    3951       28839 :             Copy( &ratio_ism[idx_sep_object + 1], &ratio_ism_loc[idx_sep_object], nchan_ism - idx_sep_object - 1 );
    3952       28839 :             no_ism_loc = sub( nchan_ism, 1 );
    3953             :         }
    3954             :         ELSE
    3955             :         {
    3956        1603 :             no_ism_loc = nchan_ism;
    3957        1603 :             move16();
    3958        1603 :             Copy( ratio_ism, ratio_ism_loc, nchan_ism );
    3959             :         }
    3960             :     }
    3961             :     ELSE
    3962             :     {
    3963           0 :         no_ism_loc = nchan_ism;
    3964           0 :         move16();
    3965           0 :         Copy( ratio_ism, ratio_ism_loc, nchan_ism );
    3966             :     }
    3967             : 
    3968       30442 :     test();
    3969       30442 :     IF( GT_16( nchan_ism, 1 ) )
    3970             :     {
    3971       30442 :         test();
    3972       30442 :         IF( GE_32( masa_to_total_energy_ratio, MASA2TOTAL_THR_Q30 ) )
    3973             :         {
    3974        3593 :             distribute_evenly_ism_fx( idx, max_sum_idx, nchan_ism );
    3975             :         }
    3976             :         ELSE
    3977             :         {
    3978       26849 :             test();
    3979       26849 :             IF( GT_16( no_ism_loc, 1 ) )
    3980             :             {
    3981             : 
    3982       26135 :                 dist = 0;
    3983       26135 :                 dist_e = 0;
    3984       26135 :                 div = div_s( 1, max_sum_idx ); // Q15
    3985       26135 :                 move16();
    3986       26135 :                 move16();
    3987             : 
    3988       26135 :                 part_idx_sum = 0;
    3989       26135 :                 move16();
    3990             : 
    3991       95154 :                 FOR( i = 0; i < no_ism_loc; i++ )
    3992             :                 {
    3993       69019 :                     idx[i] = extract_l( L_shr( L_mult0( ratio_ism_loc[i], max_sum_idx ), sub( 15, ratio_ism_e ) ) ); // Q0
    3994       69019 :                     move16();
    3995       69019 :                     part_idx_sum = add( part_idx_sum, idx[i] );
    3996             : 
    3997       69019 :                     tmp_e = BASOP_Util_Add_MantExp( ratio_ism_loc[i], ratio_ism_e, negate( imult1616( idx[i], div ) ), 0, &tmp ); // tmp_e
    3998       69019 :                     dist_e = BASOP_Util_Add_MantExp( dist, dist_e, mult( tmp, tmp ), add( tmp_e, tmp_e ), &dist );                // dist_e
    3999             :                 }
    4000             : 
    4001       26135 :                 best_dist = dist;
    4002       26135 :                 best_dist_e = dist_e;
    4003       26135 :                 best_i2 = -1;
    4004       26135 :                 move16();
    4005       26135 :                 move16();
    4006       26135 :                 move16();
    4007             : 
    4008       54119 :                 WHILE( ( part_idx_sum < max_sum_idx ) )
    4009             :                 {
    4010       27984 :                     best_i = -1;
    4011       27984 :                     move16();
    4012             :                     /* check which index to increase by 1 for a possible improvement */
    4013             : 
    4014      102676 :                     FOR( i = 0; i < no_ism_loc; i++ )
    4015             :                     {
    4016       74692 :                         idx[i] = add( idx[i], 1 );
    4017       74692 :                         move16();
    4018       74692 :                         dist2 = 0;
    4019       74692 :                         dist2_e = 0;
    4020       74692 :                         move16();
    4021       74692 :                         move16();
    4022             : 
    4023      282124 :                         FOR( j = 0; j < no_ism_loc; j++ )
    4024             :                         {
    4025      207432 :                             Word32 temp1 = L_mult( idx[i], div ); // Q : 15 + 0 + 1
    4026      207432 :                             Word16 temp1_n = norm_l( temp1 );
    4027      207432 :                             Word16 temp1_16 = extract_h( L_shl( temp1, temp1_n ) );                                                        // Q : Q + temp1_n - 16
    4028      207432 :                             tmp_e = BASOP_Util_Add_MantExp( ratio_ism_loc[i], ratio_ism_e, negate( temp1_16 ), sub( 15, temp1_n ), &tmp ); // tmp_e
    4029      207432 :                             dist2_e = BASOP_Util_Add_MantExp( dist2, dist2_e, mult_sat( tmp, tmp ), add( tmp_e, tmp_e ), &dist2 );         // dist_e
    4030             :                         }
    4031             : 
    4032       74692 :                         BASOP_Util_Add_MantExp( dist2, dist2_e, negate( best_dist ), best_dist_e, &tmp );
    4033       74692 :                         test();
    4034       74692 :                         IF( tmp < 0 )
    4035             :                         {
    4036       22944 :                             best_i2 = best_i;
    4037       22944 :                             best_i = i;
    4038       22944 :                             best_dist = dist2;
    4039       22944 :                             best_dist_e = dist2_e;
    4040       22944 :                             move16();
    4041       22944 :                             move16();
    4042       22944 :                             move16();
    4043       22944 :                             move16();
    4044             :                         }
    4045       74692 :                         idx[i] = sub( idx[i], 1 );
    4046       74692 :                         move16();
    4047             :                     }
    4048             : 
    4049       27984 :                     test();
    4050       27984 :                     IF( GT_16( best_i, -1 ) )
    4051             :                     {
    4052       21738 :                         idx[best_i] = add( idx[best_i], 1 );
    4053       21738 :                         move16();
    4054       21738 :                         part_idx_sum = add( part_idx_sum, 1 );
    4055             :                     }
    4056             :                     ELSE
    4057             :                     {
    4058        6246 :                         test();
    4059        6246 :                         IF( GT_16( best_i2, -1 ) )
    4060             :                         {
    4061        1043 :                             idx[best_i2] = add( idx[best_i2], 1 );
    4062        1043 :                             move16();
    4063        1043 :                             part_idx_sum = add( part_idx_sum, 1 );
    4064             :                         }
    4065             :                         ELSE
    4066             :                         {
    4067        5203 :                             idx[no_ism_loc - 1] = add( idx[no_ism_loc - 1], sub( max_sum_idx, part_idx_sum ) );
    4068        5203 :                             move16();
    4069        5203 :                             part_idx_sum = max_sum_idx;
    4070        5203 :                             move16();
    4071             :                         }
    4072             :                     }
    4073             :                 }
    4074       26135 :                 assert( sum_s( idx, no_ism_loc ) == max_sum_idx );
    4075             :             }
    4076             :             ELSE
    4077             :             {
    4078         714 :                 idx[0] = max_sum_idx;
    4079         714 :                 move16();
    4080             :             }
    4081             : 
    4082       26849 :             test();
    4083       26849 :             IF( LT_16( no_ism_loc, nchan_ism ) )
    4084             :             {
    4085             :                 /*  insert back the ratio of the separated object  */
    4086       70971 :                 FOR( i = nchan_ism - 1; i > idx_sep_object; i-- )
    4087             :                 {
    4088       45655 :                     idx[i] = idx[i - 1];
    4089       45655 :                     move16();
    4090             :                 }
    4091       25316 :                 idx[idx_sep_object] = 0;
    4092       25316 :                 move16();
    4093             :             }
    4094             :         }
    4095             :     }
    4096             :     ELSE
    4097             :     {
    4098             :         // idx[0] = (int16_t) ( ( ratio_ism[0] ) * ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) + 0.5f );
    4099           0 :         tmp = imult1616( ratio_ism[0], sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 ) ); // tmp_e
    4100           0 :         tmp_e = ratio_ism_e;
    4101           0 :         move16();
    4102           0 :         idx_e = BASOP_Util_Add_MantExp( tmp, tmp_e, 16384 /* 0.5 in Q15 */, 0, &idx[0] ); // idx_e
    4103           0 :         idx[0] = shl( idx[0], sub( idx_e, 15 ) );                                         // Q0
    4104           0 :         move16();
    4105             :     }
    4106             : 
    4107       30442 :     return;
    4108             : }
    4109        6665 : static Word16 index_slice_enum_fx(
    4110             :     const Word16 *ratio_ism_idx,
    4111             :     const Word16 nchan_ism )
    4112             : {
    4113             :     Word16 i;
    4114             :     Word16 x, index;
    4115             :     Word16 base;
    4116             : 
    4117        6665 :     IF( EQ_16( nchan_ism, 2 ) )
    4118             :     {
    4119         308 :         index = ratio_ism_idx[0];
    4120         308 :         move16();
    4121             :     }
    4122             :     ELSE
    4123             :     {
    4124        6357 :         x = ratio_ism_idx[nchan_ism - 2];
    4125        6357 :         base = 10;
    4126        6357 :         move16();
    4127        6357 :         move16();
    4128       17248 :         FOR( i = nchan_ism - 3; i >= 0; i-- )
    4129             :         {
    4130       10891 :             x = add( x, imult1616( ratio_ism_idx[i], base ) );
    4131       10891 :             base = imult1616( base, 10 );
    4132             :         }
    4133             : 
    4134        6357 :         index = 0;
    4135        6357 :         i = 0;
    4136        6357 :         move16();
    4137        6357 :         move16();
    4138      928936 :         WHILE( LE_16( i, x ) )
    4139             :         {
    4140      922579 :             IF( valid_ratio_index_fx( i, 7, nchan_ism - 1 ) )
    4141             :             {
    4142      252732 :                 index = add( index, 1 );
    4143             :             }
    4144      922579 :             i = add( i, 1 );
    4145             :         }
    4146        6357 :         index = sub( index, 1 );
    4147             :     }
    4148             : 
    4149        6665 :     return index;
    4150             : }
    4151             : 
    4152       61502 : static void transform_difference_index_ivas_fx(
    4153             :     const Word16 *diff_idx,
    4154             :     Word16 *idx,
    4155             :     const Word16 len )
    4156             : {
    4157             :     Word16 i;
    4158      189070 :     FOR( i = 0; i < len; i++ )
    4159             :     {
    4160      127568 :         IF( diff_idx[i] <= 0 )
    4161             :         {
    4162       99612 :             idx[i] = negate( shl( diff_idx[i], 1 ) );
    4163       99612 :             move16();
    4164             :         }
    4165             :         ELSE
    4166             :         {
    4167       27956 :             idx[i] = sub( shl( diff_idx[i], 1 ), 1 );
    4168       27956 :             move16();
    4169             :         }
    4170             :     }
    4171             : 
    4172       61502 :     return;
    4173             : }
    4174       20139 : static void transform_index_and_GR_encode_ivas_fx(
    4175             :     Word16 *diff_idx,         /* i  : differenc eindex to encode    */
    4176             :     const Word16 len,         /* i  : input length                  */
    4177             :     const Word16 GR_order,    /* i  : GR order                      */
    4178             :     BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle     */
    4179             : )
    4180             : {
    4181             :     Word16 i;
    4182             :     Word16 idx[IVAS_MAX_NUM_OBJECTS];
    4183             : 
    4184             :     /* transform difference index into positive */
    4185       20139 :     transform_difference_index_ivas_fx( diff_idx, idx, len );
    4186             : 
    4187             :     /* GR encoding */
    4188       61030 :     FOR( i = 0; i < len; i++ )
    4189             :     {
    4190       40891 :         ivas_qmetadata_encode_extended_gr_fx( hMetaData, idx[i], 100, GR_order );
    4191             :     }
    4192             : 
    4193       20139 :     return;
    4194             : }
    4195        1862 : static Word16 try_differential_fx(
    4196             :     const Word16 numCodingBands,
    4197             :     const Word32 *masa_to_total_energy_ratio, /* Q30 */
    4198             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
    4199             :     const Word16 nchan_ism,
    4200             :     const Word16 bits_index,
    4201             :     Word16 *p_b_signif )
    4202             : {
    4203             :     Word16 b, i;
    4204             :     Word16 nbits0;
    4205             :     Word16 b_signif;
    4206             :     Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
    4207             :     Word16 diff_idx[MAX_NUM_OBJECTS];
    4208             : 
    4209        1862 :     b_signif = 0;
    4210        1862 :     move16();
    4211        2162 :     WHILE( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR_Q30 ) )
    4212             :     {
    4213         300 :         test();
    4214         300 :         b_signif = add( b_signif, 1 );
    4215             :     }
    4216             : 
    4217        1862 :     nbits0 = 0;
    4218        1862 :     move16();
    4219             : 
    4220        1862 :     IF( LT_16( b_signif, numCodingBands ) )
    4221             :     {
    4222        1806 :         nbits0 = bits_index;
    4223        1806 :         move16();
    4224        1806 :         Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
    4225             : 
    4226       11560 :         FOR( b = b_signif + 1; b < numCodingBands; b++ )
    4227             :         {
    4228        9754 :             IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4229             :             {
    4230        8627 :                 v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
    4231        8627 :                 Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
    4232             : 
    4233             :                 /* transform difference index into positive */
    4234        8627 :                 transform_difference_index_ivas_fx( diff_idx, diff_idx, sub( nchan_ism, 1 ) );
    4235             : 
    4236             :                 /* GR encoding */
    4237       30122 :                 FOR( i = 0; i < nchan_ism - 1; i++ )
    4238             :                 {
    4239       21495 :                     nbits0 = add( nbits0, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 0 ) );
    4240             :                 }
    4241             :             }
    4242             :         }
    4243             :     }
    4244        1862 :     *p_b_signif = b_signif;
    4245        1862 :     move16();
    4246             : 
    4247        1862 :     return nbits0;
    4248             : }
    4249             : 
    4250         666 : static void differential_coding_first_subframe_ivas_fx(
    4251             :     BSTR_ENC_HANDLE hMetaData,
    4252             :     const Word32 *masa_to_total_energy_ratio, // Q30
    4253             :     const Word16 b_signif,
    4254             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
    4255             :     const Word16 nchan_ism,
    4256             :     const Word16 numCodingBands,
    4257             :     const Word16 bits_index )
    4258             : {
    4259             :     Word16 index, b;
    4260             :     Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
    4261             :     Word16 diff_idx[MAX_NUM_OBJECTS];
    4262             : 
    4263             :     /* differential encoding*/
    4264         666 :     push_next_indice( hMetaData, 0, 1 );
    4265             : 
    4266         666 :     IF( LT_16( b_signif, numCodingBands ) )
    4267             :     {
    4268         666 :         index = index_slice_enum_fx( ratio_ism_idx[b_signif], nchan_ism );
    4269         666 :         push_next_indice( hMetaData, index, bits_index );
    4270             : 
    4271         666 :         Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
    4272             : 
    4273        4892 :         FOR( b = b_signif + 1; b < numCodingBands; b++ )
    4274             :         {
    4275        4226 :             IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4276             :             {
    4277        3768 :                 v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
    4278        3768 :                 Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
    4279             : 
    4280             :                 /* transform difference index into positive */
    4281        3768 :                 transform_index_and_GR_encode_ivas_fx( diff_idx, sub( nchan_ism, 1 ), 0, hMetaData );
    4282             :             }
    4283             :         }
    4284             :     }
    4285             : 
    4286         666 :     return;
    4287             : }
    4288        1140 : static void independent_coding_ratio_ism_idx_fx(
    4289             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* i  : ISM ratios                */
    4290             :     const Word32 *masa_to_total_energy_ratio,                    /* i  : MASA to total ratios, Q30 */
    4291             :     const Word16 nchan_ism,                                      /* i  : number of objects         */
    4292             :     const Word16 numCodingBands,                                 /* i  : number of subbands        */
    4293             :     const Word16 bits_index,                                     /* i  : number of bits per index  */
    4294             :     BSTR_ENC_HANDLE hMetaData                                    /* i/o: metadata bitstream handle */
    4295             : )
    4296             : {
    4297             :     Word16 b, index;
    4298             : 
    4299        7844 :     FOR( b = 0; b < numCodingBands; b++ )
    4300             :     {
    4301        6704 :         IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4302             :         {
    4303        5999 :             index = index_slice_enum_fx( ratio_ism_idx[b], nchan_ism );
    4304        5999 :             push_next_indice( hMetaData, index, bits_index );
    4305             :         }
    4306             :     }
    4307             : 
    4308        1140 :     return;
    4309             : }
    4310             : 
    4311       29124 : static void remove_sep_obj_fx(
    4312             :     Word16 *diff_idx,        /* i/o: array of difference of indexes                        */
    4313             :     const Word16 nchan_ism,  /* i  : number of objects                                     */
    4314             :     const Word16 idx_sep_obj /* i  : index of separated object, to be taken out of array   */
    4315             : )
    4316             : {
    4317             :     Word16 i;
    4318             : 
    4319       88197 :     FOR( i = idx_sep_obj; i < nchan_ism - 1; i++ )
    4320             :     {
    4321       59073 :         diff_idx[i] = diff_idx[i + 1];
    4322       59073 :         move16();
    4323             :     }
    4324             : 
    4325       29124 :     return;
    4326             : }
    4327             : 
    4328       32736 : static void estimate_bits_subband_ism_ratio_fx(
    4329             :     const Word16 *ratio_ism_idx,
    4330             :     const Word16 *ratio_ism_idx_ref, /* ( i/o ) */
    4331             :     const Word16 nchan_ism,
    4332             :     const Word16 shift_one,
    4333             :     const Word16 idx_sep_obj,
    4334             :     Word16 *p_nbits0,
    4335             :     Word16 *p_nbits1 )
    4336             : {
    4337             :     Word16 diff_idx[MAX_NUM_OBJECTS];
    4338             :     Word16 nbits0, nbits1;
    4339             :     Word16 i;
    4340             : 
    4341       32736 :     nbits0 = 0;
    4342       32736 :     nbits1 = 0;
    4343       32736 :     move16();
    4344       32736 :     move16();
    4345             : 
    4346             :     /* take difference with respect to previous subframe */
    4347       32736 :     v_sub_s16_fx( ratio_ism_idx, ratio_ism_idx_ref, diff_idx, nchan_ism );
    4348             : 
    4349       32736 :     IF( shift_one )
    4350             :     {
    4351       19416 :         remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj );
    4352             :     }
    4353             : 
    4354             :     /* transform difference index into positive */
    4355       32736 :     transform_difference_index_ivas_fx( diff_idx, diff_idx, sub( sub( nchan_ism, 1 ), shift_one ) );
    4356             : 
    4357             :     /* GR encoding */
    4358       97918 :     FOR( i = 0; i < nchan_ism - 1 - shift_one; i++ )
    4359             :     {
    4360       65182 :         nbits0 = add( nbits0, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 0 ) );
    4361       65182 :         nbits1 = add( nbits1, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 1 ) );
    4362             :     }
    4363             : 
    4364       32736 :     *p_nbits0 = nbits0;
    4365       32736 :     *p_nbits1 = nbits1;
    4366       32736 :     move16();
    4367       32736 :     move16();
    4368             : 
    4369       32736 :     return;
    4370             : }
    4371             : 
    4372        5636 : static Word16 encode_ratio_ism_subframe_fx(
    4373             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
    4374             :     const Word16 nchan_ism,
    4375             :     const UWord8 numCodingBands,
    4376             :     const Word16 sf,
    4377             :     Word16 ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
    4378             :     BSTR_ENC_HANDLE hMetaData,
    4379             :     const Word32 *masa_to_total_energy_ratio, /* Q30 */
    4380             :     const Word16 shift_one,
    4381             :     const Word16 idx_separated_obj )
    4382             : {
    4383             :     Word16 b, b_signif;
    4384             :     Word16 diff_idx[MAX_NUM_OBJECTS];
    4385             :     Word16 nbits, nbits0, nbits1, GR_order, GR_order_sb;
    4386             :     Word16 differential_subframe;
    4387             :     Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
    4388             :     Word16 bits_index;
    4389             :     Word16 nbits00, nbits11;
    4390             :     Word16 idx_sep_obj_local;
    4391             : 
    4392        5636 :     idx_sep_obj_local = idx_separated_obj;
    4393        5636 :     move16();
    4394        5636 :     IF( GT_16( idx_separated_obj, -1 ) )
    4395             :     {
    4396        5636 :         if ( EQ_16( idx_separated_obj, sub( nchan_ism, 1 ) ) )
    4397             :         {
    4398         803 :             idx_sep_obj_local = 0;
    4399         803 :             move16();
    4400             :         }
    4401             :     }
    4402        5636 :     nbits = 0;
    4403        5636 :     nbits0 = 0;
    4404        5636 :     nbits1 = 0;
    4405        5636 :     move16();
    4406        5636 :     move16();
    4407        5636 :     move16();
    4408             : 
    4409        5636 :     differential_subframe = 1; /* the differences are taken with respect to previous subframe */
    4410        5636 :     move16();
    4411             : 
    4412             :     /* first subframe */
    4413        5636 :     bits_index = 0;
    4414        5636 :     move16();
    4415        5636 :     IF( sf == 0 )
    4416             :     {
    4417        1862 :         bits_index = bits_index_ism_ratio_fx( nchan_ism );
    4418             : 
    4419        1862 :         nbits = 0;
    4420        1862 :         move16();
    4421       13722 :         FOR( b = 0; b < numCodingBands; b++ )
    4422             :         {
    4423       11860 :             IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4424             :             {
    4425       10433 :                 nbits = add( nbits, bits_index );
    4426             :             }
    4427             :         }
    4428             : 
    4429        1862 :         nbits0 = try_differential_fx( numCodingBands, masa_to_total_energy_ratio, ratio_ism_idx, nchan_ism, bits_index, &b_signif );
    4430             : 
    4431        1862 :         test();
    4432        1862 :         IF( LE_16( nbits, nbits0 ) && nbits > 0 )
    4433             :         {
    4434             :             /* independent encoding */
    4435        1140 :             push_next_indice( hMetaData, 1, 1 );
    4436        1140 :             independent_coding_ratio_ism_idx_fx( ratio_ism_idx, masa_to_total_energy_ratio, nchan_ism, numCodingBands, bits_index, hMetaData );
    4437        1140 :             nbits = add( nbits, 1 );
    4438             :         }
    4439             :         ELSE
    4440             :         {
    4441         722 :             IF( nbits > 0 )
    4442             :             {
    4443         666 :                 differential_coding_first_subframe_ivas_fx( hMetaData, masa_to_total_energy_ratio, b_signif, ratio_ism_idx, nchan_ism, numCodingBands, bits_index );
    4444             : 
    4445         666 :                 nbits = add( nbits0, 1 );
    4446             :             }
    4447             :         }
    4448             :     }
    4449             :     ELSE
    4450             :     {
    4451             :         /* not first subframe */
    4452        3774 :         test();
    4453        3774 :         IF( EQ_16( shift_one, 1 ) && EQ_16( nchan_ism, 2 ) )
    4454             :         {
    4455          45 :             nbits = 0;
    4456          45 :             move16();
    4457             :         }
    4458             :         ELSE
    4459             :         {
    4460        3729 :             nbits0 = 0;
    4461        3729 :             nbits1 = 0;
    4462        3729 :             move16();
    4463        3729 :             move16();
    4464             : 
    4465       22266 :             FOR( b = 0; b < numCodingBands; b++ )
    4466             :             {
    4467       18537 :                 IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4468             :                 {
    4469       16371 :                     estimate_bits_subband_ism_ratio_fx( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], nchan_ism, shift_one, idx_sep_obj_local, &nbits00, &nbits11 );
    4470       16371 :                     nbits0 = add( nbits0, nbits00 );
    4471       16371 :                     nbits1 = add( nbits1, nbits11 );
    4472             :                 }
    4473             :             }
    4474        3729 :             IF( LT_16( nbits0, nbits1 ) )
    4475             :             {
    4476        2691 :                 GR_order = 0;
    4477        2691 :                 nbits = nbits0;
    4478        2691 :                 move16();
    4479        2691 :                 move16();
    4480             :             }
    4481             :             ELSE
    4482             :             {
    4483        1038 :                 GR_order = 1;
    4484        1038 :                 nbits = nbits1;
    4485        1038 :                 move16();
    4486        1038 :                 move16();
    4487             :             }
    4488             : 
    4489        3729 :             IF( GT_16( numCodingBands, 1 ) )
    4490             :             {
    4491             :                 /* try the difference from subband to subband; first subband is compared to previous subframe first subband*/
    4492             :                 /* take difference with respect to previous subframe only for first subband */
    4493        3702 :                 nbits0 = 0;
    4494        3702 :                 nbits1 = 0;
    4495        3702 :                 b_signif = 0;
    4496        3702 :                 move16();
    4497        3702 :                 move16();
    4498        3702 :                 move16();
    4499        3963 :                 WHILE( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR_Q30 ) )
    4500             :                 {
    4501         261 :                     test();
    4502         261 :                     b_signif = add( b_signif, 1 );
    4503             :                 }
    4504             : 
    4505        3702 :                 IF( LT_16( b_signif, numCodingBands ) )
    4506             :                 {
    4507        3690 :                     estimate_bits_subband_ism_ratio_fx( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], nchan_ism, shift_one, idx_sep_obj_local, &nbits0, &nbits1 );
    4508             : 
    4509        3690 :                     Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
    4510             : 
    4511       18249 :                     FOR( b = b_signif + 1; b < numCodingBands; b++ )
    4512             :                     {
    4513       14559 :                         IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4514             :                         {
    4515       12675 :                             estimate_bits_subband_ism_ratio_fx( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism, shift_one, idx_sep_obj_local, &nbits00, &nbits11 );
    4516       12675 :                             nbits0 = add( nbits0, nbits00 );
    4517       12675 :                             nbits1 = add( nbits1, nbits11 );
    4518       12675 :                             Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
    4519             :                         }
    4520             :                     }
    4521             : 
    4522        3690 :                     IF( LT_16( nbits0, nbits1 ) )
    4523             :                     {
    4524         529 :                         GR_order_sb = 0;
    4525         529 :                         move16();
    4526             :                     }
    4527             :                     ELSE
    4528             :                     {
    4529        3161 :                         GR_order_sb = 1;
    4530        3161 :                         nbits0 = nbits1;
    4531        3161 :                         move16();
    4532        3161 :                         move16();
    4533             :                     }
    4534             : 
    4535        3690 :                     IF( LT_16( nbits0, nbits ) )
    4536             :                     {
    4537         343 :                         differential_subframe = 0;
    4538         343 :                         nbits = nbits0;
    4539         343 :                         GR_order = GR_order_sb;
    4540         343 :                         move16();
    4541         343 :                         move16();
    4542         343 :                         move16();
    4543             :                     }
    4544             : 
    4545        3690 :                     IF( nbits > 0 )
    4546             :                     {
    4547             :                         /* write prediction type */
    4548        3690 :                         push_next_indice( hMetaData, differential_subframe, 1 );
    4549             :                         /* write GR order */
    4550        3690 :                         push_next_indice( hMetaData, GR_order, 1 );
    4551        3690 :                         nbits = add( nbits, 1 ); /* for the prediction type */
    4552        3690 :                         nbits = add( nbits, 1 ); /* for GR_order */
    4553             : 
    4554             :                         /* write data */
    4555        3690 :                         IF( differential_subframe )
    4556             :                         {
    4557       20082 :                             FOR( b = 0; b < numCodingBands; b++ )
    4558             :                             {
    4559       16735 :                                 IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4560             :                                 {
    4561             :                                     /* take difference with respect to previous subframe */
    4562       14850 :                                     v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], diff_idx, nchan_ism );
    4563             : 
    4564       14850 :                                     IF( shift_one )
    4565             :                                     {
    4566        9289 :                                         remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
    4567             :                                     }
    4568             : 
    4569       14850 :                                     transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
    4570             :                                 }
    4571             :                             }
    4572             :                         }
    4573             :                         ELSE
    4574             :                         {
    4575         343 :                             v_sub_s16_fx( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], diff_idx, nchan_ism );
    4576             : 
    4577         343 :                             IF( shift_one )
    4578             :                             {
    4579          87 :                                 remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
    4580             :                             }
    4581             : 
    4582         343 :                             transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
    4583             : 
    4584         343 :                             Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, sub( nchan_ism, shift_one ) );
    4585             : 
    4586        1709 :                             FOR( b = b_signif + 1; b < numCodingBands; b++ )
    4587             :                             {
    4588             :                                 /* take difference with respect to previous subband */
    4589        1366 :                                 IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4590             :                                 {
    4591        1172 :                                     v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
    4592             : 
    4593        1172 :                                     IF( shift_one )
    4594             :                                     {
    4595         332 :                                         remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
    4596             :                                     }
    4597             : 
    4598        1172 :                                     transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
    4599             : 
    4600        1172 :                                     Copy( ratio_ism_idx[b], ratio_ism_idx_ref, sub( nchan_ism, shift_one ) );
    4601             :                                 }
    4602             :                             }
    4603             :                         }
    4604             :                     }
    4605             :                 }
    4606             :             }
    4607             :             ELSE
    4608             :             {
    4609             :                 /* only differential wrt previous subframe is possible  */
    4610             :                 /* write the differential to subframe case and no bit to signal the difference type */
    4611             : 
    4612          27 :                 IF( nbits > 0 )
    4613             :                 {
    4614             :                     /* write GR order */
    4615           6 :                     push_next_indice( hMetaData, GR_order, 1 );
    4616           6 :                     nbits = add( nbits, 1 ); /* for GR_order */
    4617             :                     /* write data */
    4618             :                     /* only one subband */
    4619           6 :                     IF( LT_32( masa_to_total_energy_ratio[0], MASA2TOTAL_THR_Q30 ) )
    4620             :                     {
    4621             :                         /* take difference with respect to previous subframe */
    4622           6 :                         v_sub_s16_fx( ratio_ism_idx[0], ratio_ism_idx_prev_sf[0], diff_idx, nchan_ism );
    4623             : 
    4624           6 :                         IF( shift_one )
    4625             :                         {
    4626           0 :                             remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
    4627             :                         }
    4628             : 
    4629           6 :                         transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
    4630             :                     }
    4631             :                 }
    4632             :             }
    4633             :         }
    4634             :     }
    4635             : 
    4636        5636 :     return nbits;
    4637             : }
    4638        1862 : static void ivas_encode_masaism_metadata_fx(
    4639             :     MASA_ENCODER_HANDLE hMasa,
    4640             :     IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle             */
    4641             :     BSTR_ENC_HANDLE hMetaData,        /* i/o: metadata bitstream handle     */
    4642             :     ISM_METADATA_HANDLE hIsmMeta[],   /* i/o: ISM metadata handles          */
    4643             :     const Word16 nchan_ism,           /* i  : number of ISM channels        */
    4644             :     const Word16 low_bitrate_mode,    /* i  : is low bitrate more? 1/0      */
    4645             :     const Word16 omasa_nbands,
    4646             :     const Word16 omasa_nblocks,
    4647             :     const Word16 idx_separated_object,
    4648             :     const Word16 ism_imp )
    4649             : {
    4650             :     Word16 sf, band;
    4651             :     UWord8 numCodingBands;
    4652             :     UWord8 numSf;
    4653             :     Word16 brange[2];
    4654             :     Word64 eneBand;
    4655             :     Word32 eneBand32;
    4656             :     Word16 eneBand_exp, shift;
    4657             :     Word16 bin;
    4658             :     Word16 obj;
    4659             :     Word16 bits_ism[MAX_NUM_OBJECTS];
    4660             :     UWord16 idx_sph;
    4661             :     Word32 theta_q, phi_q;
    4662             :     UWord16 index_theta, index_phi;
    4663             :     Word16 ratio_ism_fx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
    4664             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
    4665             :     Word16 step;
    4666             :     Word32 energy_ism, energy_ism_ind[MAX_NUM_OBJECTS];
    4667             :     Word16 tmp, rotate, energy_ism_e, energy_ism_ind_e[MAX_NUM_OBJECTS];
    4668             :     Word16 n_ism_tmp, i;
    4669        1862 :     OMASA_ENCODER_DATA_HANDLE hOmasaData = hMasa->data.hOmasaData;
    4670             :     Word16 nbands_work;
    4671             :     Word32 L_tmp;
    4672             :     Word16 L_tmp_e;
    4673             : 
    4674             :     /* use the values from hQMetaData */
    4675        1862 :     numCodingBands = (UWord8) hQMetaData->q_direction->cfg.nbands;
    4676        1862 :     numSf = (Word8) hQMetaData->q_direction->cfg.nblocks;
    4677        1862 :     nbands_work = s_min( numCodingBands, omasa_nbands );
    4678        1862 :     move16();
    4679        1862 :     move16();
    4680        1862 :     IF( EQ_16( numCodingBands, 1 ) )
    4681             :     {
    4682         120 :         FOR( sf = 0; sf < numSf; sf++ )
    4683             :         {
    4684          96 :             L_tmp = 0;
    4685          96 :             L_tmp_e = 0;
    4686          96 :             move32();
    4687          96 :             move16();
    4688         576 :             FOR( i = 0; i < omasa_nbands; i++ )
    4689             :             {
    4690         480 :                 L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, L_tmp_e, hOmasaData->energy_ism_fx[sf][i], hOmasaData->energy_ism_fx_e[sf][i], &L_tmp_e );
    4691             :             }
    4692             :             /* if ( sum_f( hOmasaData->energy_ism[sf], omasa_nbands ) == 0.0f ) */
    4693          96 :             IF( L_tmp == 0 )
    4694             :             {
    4695           0 :                 hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30; // 1.0f in Q30
    4696           0 :                 move32();
    4697             :             }
    4698             :             ELSE
    4699             :             {
    4700          96 :                 brange[0] = hMasa->data.band_mapping[0];
    4701          96 :                 brange[1] = hMasa->data.band_mapping[omasa_nbands];
    4702          96 :                 eneBand = 0;
    4703          96 :                 move16();
    4704          96 :                 move16();
    4705          96 :                 move64();
    4706        2400 :                 FOR( bin = brange[0]; bin < brange[1]; bin++ )
    4707             :                 {
    4708        2304 :                     eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
    4709             :                 }
    4710          96 :                 shift = W_norm( eneBand );
    4711          96 :                 eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
    4712          96 :                 eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
    4713             : 
    4714          96 :                 energy_ism = 0;
    4715          96 :                 energy_ism_e = 0;
    4716          96 :                 move32();
    4717          96 :                 move16();
    4718         288 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4719             :                 {
    4720         192 :                     energy_ism_ind[obj] = 0;
    4721         192 :                     energy_ism_ind_e[obj] = 0;
    4722         192 :                     move32();
    4723         192 :                     move16();
    4724             :                 }
    4725             : 
    4726         576 :                 FOR( band = 0; band < omasa_nbands; band++ )
    4727             :                 {
    4728         480 :                     energy_ism = BASOP_Util_Add_Mant32Exp( energy_ism, energy_ism_e, hOmasaData->energy_ism_fx[sf][band], hOmasaData->energy_ism_fx_e[sf][band], &energy_ism_e );
    4729        1440 :                     FOR( obj = 0; obj < nchan_ism; obj++ )
    4730             :                     {
    4731             : 
    4732         960 :                         hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30; // 1.0f in Q30
    4733         960 :                         move32();
    4734             :                     }
    4735             :                 }
    4736             : 
    4737         288 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4738             :                 {
    4739         192 :                     hOmasaData->energy_ratio_ism_fx[sf][0][obj] = BASOP_Util_Divide3232_Scale_newton( energy_ism_ind[obj], energy_ism, &L_tmp_e );
    4740         192 :                     move32();
    4741         192 :                     L_tmp_e = add( L_tmp_e, sub( energy_ism_ind_e[obj], energy_ism_e ) );
    4742             :                     /* Scaling to Q30 */
    4743         192 :                     hOmasaData->energy_ratio_ism_fx[sf][0][obj] = L_shl( hOmasaData->energy_ratio_ism_fx[sf][0][obj], sub( L_tmp_e, 1 ) ); // Q30
    4744         192 :                     move32();
    4745             :                 }
    4746          96 :                 L_tmp = BASOP_Util_Add_Mant32Exp( eneBand32, eneBand_exp, energy_ism, energy_ism_e, &L_tmp_e );
    4747          96 :                 IF( L_tmp != 0 )
    4748             :                 {
    4749          96 :                     hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
    4750          96 :                     move32();
    4751          96 :                     tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
    4752             :                     /* Scaling to Q30 */
    4753          96 :                     hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = L_shl( hOmasaData->masa_to_total_energy_ratio_fx[sf][0], sub( tmp, 1 ) ); // Q30
    4754          96 :                     move32();
    4755             :                 }
    4756             :                 ELSE
    4757             :                 {
    4758           0 :                     hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30;
    4759           0 :                     move32();
    4760             :                 }
    4761             :             }
    4762             :         }
    4763             :     }
    4764        1838 :     ELSE IF( EQ_16( numSf, 1 ) )
    4765             :     {
    4766        6270 :         FOR( band = 0; band < nbands_work; band++ )
    4767             :         {
    4768        5666 :             energy_ism = 0; /* ISM energy for current subband */ // energy_ism_e
    4769        5666 :             energy_ism_e = 0;                                    /* ISM energy for current subband */
    4770        5666 :             move32();
    4771        5666 :             move16();
    4772       24246 :             FOR( obj = 0; obj < nchan_ism; obj++ )
    4773             :             {
    4774       18580 :                 energy_ism_ind[obj] = 0;
    4775       18580 :                 energy_ism_ind_e[obj] = 0;
    4776       18580 :                 move32();
    4777       18580 :                 move16();
    4778             :             }
    4779       14722 :             FOR( sf = 0; sf < omasa_nblocks; sf++ )
    4780             :             {
    4781        9056 :                 energy_ism = BASOP_Util_Add_Mant32Exp( energy_ism, energy_ism_e, hOmasaData->energy_ism_fx[sf][band], hOmasaData->energy_ism_fx_e[sf][band], &energy_ism_e );
    4782       34416 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4783             :                 {
    4784       25360 :                     L_tmp = Mpy_32_32( hOmasaData->energy_ism_fx[sf][band], hOmasaData->energy_ratio_ism_fx[sf][band][obj] ); // Q = (31 - hOmasaData->energy_ism_fx_e[sf][band]) + Q30 - 31
    4785       25360 :                     L_tmp_e = add( 1, hOmasaData->energy_ism_fx_e[sf][band] );
    4786       25360 :                     energy_ism_ind[obj] = BASOP_Util_Add_Mant32Exp( energy_ism_ind[obj], energy_ism_ind_e[obj], L_tmp, L_tmp_e, &energy_ism_ind_e[obj] );
    4787       25360 :                     move32();
    4788             :                 }
    4789             :             }
    4790             : 
    4791        5666 :             IF( energy_ism == 0 )
    4792             :             {
    4793           0 :                 hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30; // 1.0f in Q30
    4794           0 :                 move32();
    4795             :             }
    4796             :             ELSE
    4797             :             {
    4798       24246 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4799             :                 {
    4800       18580 :                     hOmasaData->energy_ratio_ism_fx[0][band][obj] = BASOP_Util_Divide3232_Scale_newton( energy_ism_ind[obj], energy_ism, &L_tmp_e );
    4801       18580 :                     move32();
    4802       18580 :                     L_tmp_e = add( L_tmp_e, sub( energy_ism_ind_e[obj], energy_ism_e ) );
    4803             :                     /* Scaling to Q30 */
    4804       18580 :                     hOmasaData->energy_ratio_ism_fx[0][band][obj] = L_shl( hOmasaData->energy_ratio_ism_fx[0][band][obj], sub( L_tmp_e, 1 ) ); // Q30
    4805       18580 :                     move32();
    4806             :                 }
    4807        5666 :                 brange[0] = hMasa->data.band_mapping[band];
    4808        5666 :                 brange[1] = hMasa->data.band_mapping[band + 1];
    4809        5666 :                 move16();
    4810        5666 :                 move16();
    4811             : 
    4812        5666 :                 eneBand = 0;
    4813        5666 :                 move64();
    4814       14722 :                 FOR( sf = 0; sf < omasa_nblocks; sf++ )
    4815             :                 {
    4816       39748 :                     FOR( bin = brange[0]; bin < brange[1]; bin++ )
    4817             :                     {
    4818       30692 :                         eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
    4819             :                     }
    4820             :                 }
    4821        5666 :                 shift = W_norm( eneBand );
    4822        5666 :                 eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
    4823        5666 :                 eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
    4824             : 
    4825        5666 :                 L_tmp = BASOP_Util_Add_Mant32Exp( eneBand32, eneBand_exp, energy_ism, energy_ism_e, &L_tmp_e );
    4826        5666 :                 IF( L_tmp != 0 )
    4827             :                 {
    4828        5666 :                     hOmasaData->masa_to_total_energy_ratio_fx[0][band] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
    4829        5666 :                     move32();
    4830        5666 :                     tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
    4831             :                     /* Scaling to Q30 */
    4832        5666 :                     hOmasaData->masa_to_total_energy_ratio_fx[0][band] = L_shl( hOmasaData->masa_to_total_energy_ratio_fx[0][band], sub( tmp, 1 ) ); // Q30
    4833        5666 :                     move32();
    4834             :                 }
    4835             :                 ELSE
    4836             :                 {
    4837           0 :                     hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30;
    4838           0 :                     move32();
    4839             :                 }
    4840             :             }
    4841             :         }
    4842         604 :         FOR( band = nbands_work; band < numCodingBands; band++ )
    4843             :         {
    4844           0 :             hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30;
    4845           0 :             move32();
    4846             : 
    4847           0 :             FOR( obj = 0; obj < nchan_ism; obj++ )
    4848             :             {
    4849           0 :                 hOmasaData->energy_ratio_ism_fx[0][band][obj] = hOmasaData->energy_ratio_ism_fx[0][nbands_work - 1][obj];
    4850           0 :                 move32();
    4851             :             }
    4852             :         }
    4853             :     }
    4854             :     ELSE
    4855             :     {
    4856        6170 :         FOR( sf = 0; sf < numSf; sf++ )
    4857             :         {
    4858       29616 :             FOR( band = 0; band < nbands_work; band++ )
    4859             :             {
    4860       24680 :                 IF( hOmasaData->energy_ism_fx[sf][band] == 0 )
    4861             :                 {
    4862           0 :                     hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
    4863           0 :                     move32();
    4864             :                 }
    4865             :                 ELSE
    4866             :                 {
    4867       24680 :                     brange[0] = hMasa->data.band_mapping[band];
    4868       24680 :                     brange[1] = hMasa->data.band_mapping[band + 1];
    4869       24680 :                     move16();
    4870       24680 :                     move16();
    4871             : 
    4872       24680 :                     eneBand = 0;
    4873       24680 :                     move64();
    4874      141656 :                     FOR( bin = brange[0]; bin < brange[1]; bin++ )
    4875             :                     {
    4876      116976 :                         eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
    4877             :                     }
    4878       24680 :                     shift = W_norm( eneBand );
    4879       24680 :                     eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
    4880       24680 :                     eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
    4881             : 
    4882       24680 :                     L_tmp = BASOP_Util_Add_Mant32Exp( eneBand32, eneBand_exp, hOmasaData->energy_ism_fx[sf][band], hOmasaData->energy_ism_fx_e[sf][band], &L_tmp_e );
    4883       24680 :                     IF( L_tmp != 0 )
    4884             :                     {
    4885       24680 :                         hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
    4886       24680 :                         move32();
    4887       24680 :                         tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
    4888             :                         /* Scaling to Q30 */
    4889       24680 :                         hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = L_shl( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], sub( tmp, 1 ) ); // Q30
    4890       24680 :                         move32();
    4891             :                     }
    4892             :                     ELSE
    4893             :                     {
    4894           0 :                         hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
    4895           0 :                         move32();
    4896             :                     }
    4897             :                 }
    4898             :             }
    4899        4936 :             FOR( band = nbands_work; band < numCodingBands; band++ )
    4900             :             {
    4901           0 :                 hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
    4902           0 :                 move32();
    4903             : 
    4904           0 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4905             :                 {
    4906           0 :                     hOmasaData->energy_ratio_ism_fx[sf][band][obj] = hOmasaData->energy_ratio_ism_fx[sf][nbands_work - 1][obj];
    4907           0 :                     move32();
    4908             :                 }
    4909             :             }
    4910             :         }
    4911             :     }
    4912             : 
    4913        1862 :     ivas_omasa_encode_masa_to_total_fx( hOmasaData->masa_to_total_energy_ratio_fx, hMetaData, low_bitrate_mode, numCodingBands, numSf );
    4914             : 
    4915             :     /* quantize ism_ratios */
    4916        1862 :     IF( GT_16( nchan_ism, 1 ) )
    4917             :     {
    4918             :         /* inv_step = ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ); *
    4919             :          * step = 1.0f / inv_step;                                */
    4920        1862 :         step = 4681; // 1.f / ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) => 1.f / 7 in Q15
    4921        1862 :         move16();
    4922             : 
    4923        1862 :         rotate = 0;
    4924        1862 :         n_ism_tmp = 0;
    4925        1862 :         move16();
    4926        1862 :         move16();
    4927             : 
    4928        7498 :         FOR( sf = 0; sf < numSf; sf++ )
    4929             :         {
    4930       36078 :             FOR( band = 0; band < numCodingBands; band++ )
    4931             :             {
    4932      137614 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4933             :                 {
    4934      107172 :                     assert( ( hOmasaData->energy_ratio_ism_fx[sf][band][obj] >= 0 ) && ( hOmasaData->energy_ratio_ism_fx[sf][band][obj] <= ONE_IN_Q30 ) );
    4935      107172 :                     ratio_ism_fx[band][obj] = extract_h( hOmasaData->energy_ratio_ism_fx[sf][band][obj] ); // Q14
    4936      107172 :                     move16();
    4937             :                 }
    4938             : 
    4939             :                 /* Quantize ISM ratios */
    4940       30442 :                 quantize_ratio_ism_vector_ivas_fx( ratio_ism_fx[band], 1 /* Q14 */, ratio_ism_idx[band], nchan_ism, hOmasaData->masa_to_total_energy_ratio_fx[sf][band], idx_separated_object );
    4941             : 
    4942       30442 :                 test();
    4943       30442 :                 test();
    4944       30442 :                 IF( EQ_16( n_ism_tmp, numCodingBands ) && ratio_ism_idx[band][idx_separated_object] != 0 && LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
    4945             :                 {
    4946          92 :                     i = 0;
    4947          92 :                     move16();
    4948         697 :                     WHILE( ratio_ism_idx[band][idx_separated_object] > 0 )
    4949             :                     {
    4950         605 :                         IF( NE_16( i, idx_separated_object ) )
    4951             :                         {
    4952         410 :                             ratio_ism_idx[band][i] = add( ratio_ism_idx[band][i], 1 );
    4953         410 :                             ratio_ism_idx[band][idx_separated_object] = sub( ratio_ism_idx[band][idx_separated_object], 1 );
    4954         410 :                             move16();
    4955         410 :                             move16();
    4956             :                         }
    4957         605 :                         i = add( i, 1 );
    4958         605 :                         if ( EQ_16( i, nchan_ism ) )
    4959             :                         {
    4960         138 :                             i = 0;
    4961         138 :                             move16();
    4962             :                         }
    4963             :                     }
    4964             :                 }
    4965             : 
    4966             :                 /* reconstructed values */
    4967       30442 :                 reconstruct_ism_ratios_fx( ratio_ism_idx[band], nchan_ism, step, hMasa->data.hOmasaData->q_energy_ratio_ism_fx[sf][band] );
    4968             :             }
    4969        5636 :             test();
    4970        5636 :             IF( GT_16( nchan_ism, 2 ) && EQ_16( idx_separated_object, sub( nchan_ism, 1 ) ) )
    4971             :             {
    4972             :                 /* rotate components */
    4973         766 :                 rotate = 1;
    4974         766 :                 move16();
    4975        4610 :                 FOR( band = 0; band < numCodingBands; band++ )
    4976             :                 {
    4977        3844 :                     IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
    4978             :                     {
    4979        3352 :                         tmp = ratio_ism_idx[band][nchan_ism - 1];
    4980        3352 :                         ratio_ism_idx[band][nchan_ism - 1] = ratio_ism_idx[band][0];
    4981        3352 :                         ratio_ism_idx[band][0] = tmp;
    4982        3352 :                         move16();
    4983        3352 :                         move16();
    4984        3352 :                         move16();
    4985        3352 :                         test();
    4986        3352 :                         IF( sf == 0 && tmp == 0 )
    4987             :                         {
    4988         799 :                             n_ism_tmp = add( n_ism_tmp, 1 );
    4989             :                         }
    4990             : 
    4991        3352 :                         if ( EQ_16( n_ism_tmp, numCodingBands ) )
    4992             :                         {
    4993        1753 :                             assert( tmp == 0 );
    4994             :                         }
    4995             :                     }
    4996             :                 }
    4997             :             }
    4998             :             ELSE
    4999             :             {
    5000        4870 :                 IF( GT_16( idx_separated_object, -1 ) )
    5001             :                 {
    5002       31468 :                     FOR( band = 0; band < numCodingBands; band++ )
    5003             :                     {
    5004       26598 :                         IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
    5005             :                         {
    5006       23497 :                             test();
    5007       23497 :                             IF( ratio_ism_idx[band][idx_separated_object] == 0 && sf == 0 )
    5008             :                             {
    5009        8636 :                                 n_ism_tmp = add( n_ism_tmp, 1 );
    5010             :                             }
    5011             :                         }
    5012             :                     }
    5013             :                 }
    5014             :             }
    5015             : 
    5016             :             /* encode data for current subframe */
    5017        5636 :             test();
    5018        5636 :             IF( sf > 0 && EQ_16( n_ism_tmp, numCodingBands ) )
    5019             :             {
    5020        2082 :                 encode_ratio_ism_subframe_fx( ratio_ism_idx, nchan_ism, numCodingBands, sf, ratio_ism_idx_prev_sf, hMetaData, hOmasaData->masa_to_total_energy_ratio_fx[sf], 1, idx_separated_object );
    5021             :             }
    5022             :             ELSE
    5023             :             {
    5024        3554 :                 encode_ratio_ism_subframe_fx( ratio_ism_idx, nchan_ism, numCodingBands, sf, ratio_ism_idx_prev_sf, hMetaData, hOmasaData->masa_to_total_energy_ratio_fx[sf], 0, idx_separated_object );
    5025             :             }
    5026             : 
    5027             :             /* calculate quantized ISM ratios */
    5028             :             /* save previous subframe indexes */
    5029       36078 :             FOR( band = 0; band < numCodingBands; band++ )
    5030             :             {
    5031       30442 :                 Copy( ratio_ism_idx[band], ratio_ism_idx_prev_sf[band], nchan_ism );
    5032             :             }
    5033             : 
    5034        5636 :             IF( rotate )
    5035             :             {
    5036        4610 :                 FOR( band = 0; band < numCodingBands; band++ )
    5037             :                 {
    5038        3844 :                     IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
    5039             :                     {
    5040        3352 :                         tmp = ratio_ism_idx[band][nchan_ism - 1];
    5041        3352 :                         ratio_ism_idx[band][nchan_ism - 1] = ratio_ism_idx[band][0];
    5042        3352 :                         ratio_ism_idx[band][0] = tmp;
    5043        3352 :                         move16();
    5044        3352 :                         move16();
    5045        3352 :                         move16();
    5046             :                     }
    5047             :                 }
    5048             :             }
    5049             :         }
    5050             :     }
    5051             : 
    5052        1862 :     calculate_nbits_meta_fx( nchan_ism, hOmasaData->q_energy_ratio_ism_fx, hOmasaData->masa_to_total_energy_ratio_fx, numSf, numCodingBands, bits_ism, idx_separated_object, ism_imp );
    5053             : 
    5054             :     /* quantize directions */
    5055        8142 :     FOR( obj = 0; obj < nchan_ism; obj++ )
    5056             :     {
    5057        6280 :         IF( LT_16( bits_ism[obj], 8 ) )
    5058             :         {
    5059             :             /* check is same as previous */
    5060        2009 :             test();
    5061        2009 :             IF( LT_32( L_abs( L_sub( hIsmMeta[obj]->elevation_fx, hIsmMeta[obj]->q_elevation_old_fx ) ), 41943 /* 0.01f in Q22 */ ) && LT_32( L_abs( L_sub( hIsmMeta[obj]->azimuth_fx, hIsmMeta[obj]->q_azimuth_old_fx ) ), 41943 /* 0.01f in Q22 */ ) )
    5062             :             {
    5063         201 :                 push_next_indice( hMetaData, 1, 1 );
    5064             :                 /* the old stays the same */
    5065             :             }
    5066             :             ELSE
    5067             :             {
    5068        1808 :                 push_next_indice( hMetaData, 0, 1 );
    5069        1808 :                 idx_sph = quantize_direction_fx( hIsmMeta[obj]->elevation_fx, hIsmMeta[obj]->azimuth_fx, bits_ism[obj], &theta_q, &phi_q, &index_theta, &index_phi, MC_LS_SETUP_INVALID );
    5070        1808 :                 push_next_indice( hMetaData, idx_sph, bits_ism[obj] );
    5071        1808 :                 hIsmMeta[obj]->q_elevation_old_fx = hIsmMeta[obj]->elevation_fx;
    5072        1808 :                 hIsmMeta[obj]->q_azimuth_old_fx = hIsmMeta[obj]->azimuth_fx;
    5073        1808 :                 move32();
    5074        1808 :                 move32();
    5075             :             }
    5076             :         }
    5077             :         ELSE
    5078             :         {
    5079        4271 :             idx_sph = quantize_direction_fx( hIsmMeta[obj]->elevation_fx, hIsmMeta[obj]->azimuth_fx, bits_ism[obj], &theta_q, &phi_q, &index_theta, &index_phi, MC_LS_SETUP_INVALID );
    5080        4271 :             push_next_indice( hMetaData, idx_sph, bits_ism[obj] );
    5081        4271 :             hIsmMeta[obj]->q_elevation_old_fx = hIsmMeta[obj]->elevation_fx;
    5082        4271 :             hIsmMeta[obj]->q_azimuth_old_fx = hIsmMeta[obj]->azimuth_fx;
    5083        4271 :             move32();
    5084        4271 :             move32();
    5085             :         }
    5086             :     }
    5087             : 
    5088        1862 :     return;
    5089             : }
    5090             : 
    5091             : /*-------------------------------------------------------------------*
    5092             :  * ivas_merge_masa_transports()
    5093             :  *
    5094             :  * Merge MASA transport channels
    5095             :  *-------------------------------------------------------------------*/
    5096        5858 : void ivas_merge_masa_transports_fx(
    5097             :     Word32 data_in_f1_fx[][L_FRAME48k], // Qx
    5098             :     Word32 *data_in_f2_fx[],            // Qx
    5099             :     Word32 *data_out_f_fx[],            // Qx
    5100             :     const Word16 input_frame,
    5101             :     const Word16 num_transport_channels )
    5102             : {
    5103             :     Word16 i, j;
    5104             : 
    5105       17574 :     FOR( i = 0; i < num_transport_channels; i++ )
    5106             :     {
    5107    10588356 :         FOR( j = 0; j < input_frame; j++ )
    5108             :         {
    5109    10576640 :             data_out_f_fx[i][j] = L_add( data_in_f1_fx[i][j], data_in_f2_fx[i][j] );
    5110    10576640 :             move32();
    5111             :         }
    5112             :     }
    5113             : 
    5114        5858 :     return;
    5115             : }

Generated by: LCOV version 1.14