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 @ 574a190e3c6896c6c4ed10d7f23649709a0c4347 Lines: 2280 2559 89.1 %
Date: 2025-06-27 02:59:36 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       20942 :             push_next_indice( hMetaData, 1, MASA_LOWBITRATE_MODE_BITS );
     607             :         }
     608             :         ELSE
     609             :         {
     610        3969 :             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 = extract_h( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise_32fx ); /*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( extract_h( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise_32fx ), ONE_IN_Q14 ), extract_h( st_ivas->hCPE[0]->hCoreCoder[1]->lp_noise_32fx ), 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       23241 :         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       23164 :             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       23164 :             exp = add( exp, sub( sub( 31, add( hMasa->data.q_energy, tmp2 ) ), 31 ) );
    2444       23164 :             bandRatio = hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[0]; // Q30
    2445       23164 :             move32();
    2446             : 
    2447       23164 :             bandEnergy = 0;
    2448       23164 :             move64();
    2449      115820 :             FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2450             :             {
    2451       92656 :                 bandEnergy = W_mac_32_32( bandEnergy, energy[sf][band], 1 );
    2452             :             }
    2453       23164 :             shift = W_norm( bandEnergy );
    2454       23164 :             bandEnergy32 = W_extract_h( W_shl( bandEnergy, shift ) );
    2455       23164 :             bandEnergy_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
    2456             : 
    2457       23164 :             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 :         W_tmp = 0;
    2467        5619 :         move64();
    2468       28095 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2469             :         {
    2470      134856 :             FOR( band = 0; band < numCodingBands; band++ )
    2471             :             {
    2472      112380 :                 W_tmp = W_mac_32_16( W_tmp, Mpy_32_32( hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[sf], energy[sf][band] ), 1 ); // hMasa->data.q_energy
    2473             :             }
    2474             :         }
    2475        5619 :         shift = W_norm( W_tmp );
    2476        5619 :         meanRatio = W_extract_h( W_shl( W_tmp, shift ) ); // Q:sub( add( hMasa->data.q_energy, shift ), 32 )
    2477        5619 :         shift = sub( 31, sub( add( hMasa->data.q_energy, shift ), 32 ) );
    2478             : 
    2479        5619 :         IF( totalEnergySum != 0 )
    2480             :         {
    2481        5619 :             meanRatio = BASOP_Util_Divide3232_Scale_newton( meanRatio, totalEnergySum, &exp );
    2482        5619 :             exp = add( exp, sub( shift, sub( 31, add( hMasa->data.q_energy, tmp2 ) ) ) ); // exp + (shift - (31 - hMasa->data.q_energy - tmp2)) => 1 + tmp2
    2483             :         }
    2484             :         ELSE
    2485             :         {
    2486           0 :             meanRatio = MAX_32;
    2487           0 :             exp = 31;
    2488           0 :             move32();
    2489           0 :             move16();
    2490             :         }
    2491             : 
    2492             :         /* 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.
    2493             :          * Otherwise, merge over subframes. */
    2494        5619 :         IF( BASOP_Util_Cmp_Mant32Exp( hqmetadata->q_direction[0].band_data[selectedBand].energy_ratio_fx[0], 1, meanRatio, exp ) > 0 )
    2495             :         {
    2496        3969 :             mergeOverFreqBands = 1;
    2497        3969 :             move16();
    2498             :         }
    2499             :         ELSE
    2500             :         {
    2501        1650 :             mergeOverFreqBands = 0;
    2502        1650 :             move16();
    2503             :         }
    2504             :     }
    2505             :     ELSE
    2506             :     {
    2507       19292 :         mergeOverFreqBands = 0;
    2508       19292 :         move16();
    2509             :     }
    2510             : 
    2511             :     /* Merge values over subframes or frequency bands, depending on which one is less important */
    2512       24911 :     IF( !mergeOverFreqBands ) /* Merge values over subframes */
    2513             :     {
    2514             :         Word32 xSum, ySum, zSum;
    2515             :         Word64 W_xSum_sq, W_ySum_sq;
    2516             :         Word32 bandSumEnergy;
    2517             :         Word16 aziRad, eleRad, q_shift, exp_diff;
    2518             :         Word32 x, y, z;
    2519             :         Word32 veclen, L_tmp;
    2520             : 
    2521       20942 :         W_tmp = 0;
    2522       20942 :         move64();
    2523      104180 :         FOR( band = 0; band < numCodingBands; band++ )
    2524             :         {
    2525       83238 :             xSum = 0;
    2526       83238 :             ySum = 0;
    2527       83238 :             zSum = 0;
    2528       83238 :             bandSumEnergy = 0;
    2529       83238 :             move32();
    2530       83238 :             move32();
    2531       83238 :             move32();
    2532       83238 :             move32();
    2533             : 
    2534      416190 :             FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2535             :             {
    2536      332952 :                 aziRad = extract_l( Mpy_32_32( hqmetadata->q_direction[0].band_data[band].azimuth_fx[sf], PI_OVER_180_Q22 ) );
    2537      332952 :                 eleRad = extract_l( Mpy_32_32( hqmetadata->q_direction[0].band_data[band].elevation_fx[sf], PI_OVER_180_Q22 ) );
    2538      332952 :                 veclen = Mpy_32_32( hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[sf], energy[sf][band] ); // hMasa->data.q_energy - 1
    2539             : 
    2540      332952 :                 x = Mpy_32_32( L_mult( getCosWord16( aziRad ), getCosWord16( eleRad ) ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
    2541      332952 :                 move32();
    2542      332952 :                 y = Mpy_32_32( L_mult0( getSinWord16( aziRad ), getCosWord16( eleRad ) ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
    2543      332952 :                 move32();
    2544      332952 :                 z = Mpy_32_32( L_mult0( getSinWord16( eleRad ), ONE_IN_Q14 ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
    2545      332952 :                 move32();
    2546             : 
    2547      332952 :                 xSum = L_add( xSum, x );
    2548      332952 :                 ySum = L_add( ySum, y );
    2549      332952 :                 zSum = L_add( zSum, z );
    2550             : 
    2551      332952 :                 W_tmp = W_add( W_tmp, energy[sf][band] );
    2552             :             }
    2553             : 
    2554       83238 :             tmp2 = W_norm( W_tmp );
    2555       83238 :             tmp2 = s_min( 32, tmp2 );
    2556       83238 :             bandSumEnergy = W_extract_h( W_shl( W_tmp, tmp2 ) );
    2557       83238 :             tmp2 = sub( add( hMasa->data.q_energy, tmp2 ), 32 );
    2558             : 
    2559       83238 :             aziRad = BASOP_util_atan2( ySum, xSum, 0 ); // Q13
    2560       83238 :             W_xSum_sq = W_mult0_32_32( xSum, xSum );    // 2 * hMasa->data.q_energy - Q6
    2561       83238 :             W_ySum_sq = W_mult0_32_32( ySum, ySum );    // 2 * hMasa->data.q_energy - Q6
    2562       83238 :             W_tmp = W_add( W_xSum_sq, W_ySum_sq );      // 2 * hMasa->data.q_energy - Q6
    2563       83238 :             q_shift = W_norm( W_tmp );
    2564       83238 :             L_tmp = W_extract_h( W_shl( W_tmp, q_shift ) ); // 2 * hMasa->data.q_energy - Q6 + (q_shift -32)
    2565       83238 :             exp_diff = sub( Q31, add( sub( imult1616( 2, hMasa->data.q_energy ), Q6 ), sub( q_shift, 32 ) ) );
    2566       83238 :             L_tmp = Sqrt32( L_tmp, &exp_diff );
    2567       83238 :             eleRad = BASOP_util_atan2( zSum, L_tmp, sub( sub( 34, hMasa->data.q_energy ), exp_diff ) ); // Q13
    2568             : 
    2569       83238 :             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
    2570       83238 :             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
    2571             : 
    2572             :             /* Energy ratio is already merged through time */
    2573       83238 :             test();
    2574       83238 :             IF( computeCoherence && hqmetadata->q_direction[0].coherence_band_data != NULL )
    2575             :             {
    2576             :                 Word16 spreadCoh;
    2577        5368 :                 Word32 spreadCohSum = 0;
    2578        5368 :                 move32();
    2579       26840 :                 FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2580             :                 {
    2581       21472 :                     spreadCoh = div_s( (Word16) hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf], 255 ); // Q15
    2582       21472 :                     spreadCohSum = L_add( spreadCohSum, Mpy_32_16_1( energy[sf][band], spreadCoh ) );
    2583             :                 }
    2584             :                 // hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0] = (uint8_t) roundf( spreadCohSum / ( bandSumEnergy + EPSILON ) * 255.0f );
    2585        5368 :                 tmp = BASOP_Util_Divide3232_Scale( spreadCohSum, bandSumEnergy, &exp );
    2586        5368 :                 exp = add( exp, sub( tmp2, hMasa->data.q_energy ) );
    2587        5368 :                 tmp = mult_r( tmp, 32640 /* 255 in Q7 */ );                                                                    // 15 - exp + 7 - 15 => 7 - exp
    2588        5368 :                 hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0] = (UWord8) shr( tmp, sub( 7, exp ) ); // Q0
    2589        5368 :                 move16();
    2590             : 
    2591             :                 /* Copy spread coherence to the rest of subframes for the coherence coding algorithm. */
    2592       21472 :                 FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2593             :                 {
    2594       96624 :                     FOR( band = 0; band < numCodingBands; band++ )
    2595             :                     {
    2596       80520 :                         hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0]; // Q0
    2597       80520 :                         move16();
    2598             :                     }
    2599             :                 }
    2600             : 
    2601             :                 /* Surround coherence is already merged through time */
    2602             :             }
    2603             :         }
    2604             : 
    2605       20942 :         hqmetadata->q_direction->cfg.nblocks = 1;
    2606       20942 :         hMasa->config.joinedSubframes = 1;
    2607       20942 :         move16();
    2608       20942 :         move16();
    2609             :     }
    2610             :     ELSE /* Merge values over frequency bands */
    2611             :     {
    2612             :         /* Use the selected frequency band to represent all data */
    2613       19845 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2614             :         {
    2615       15876 :             hqmetadata->q_direction[0].band_data[0].azimuth_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].azimuth_fx[sf];           // Q22
    2616       15876 :             hqmetadata->q_direction[0].band_data[0].elevation_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].elevation_fx[sf];       // Q22
    2617       15876 :             hqmetadata->q_direction[0].band_data[0].energy_ratio_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].energy_ratio_fx[sf]; // Q30
    2618       15876 :             move32();
    2619       15876 :             move32();
    2620       15876 :             move32();
    2621       15876 :             IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
    2622             :             {
    2623        5280 :                 hqmetadata->q_direction[0].coherence_band_data[0].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[selectedBand].spread_coherence[sf]; // Q0
    2624        5280 :                 move16();
    2625             :             }
    2626       15876 :             IF( hqmetadata->surcoh_band_data != NULL )
    2627             :             {
    2628        5280 :                 hqmetadata->surcoh_band_data[0].surround_coherence[sf] = hqmetadata->surcoh_band_data[selectedBand].surround_coherence[sf];
    2629        5280 :                 move16();
    2630             :             }
    2631             :         }
    2632             : 
    2633             :         /* Copy coherence to rest of bands for the coherence coding algorithm. */
    2634       19845 :         FOR( band = 1; band < numCodingBands; band++ )
    2635             :         {
    2636       15876 :             IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
    2637             :             {
    2638       26400 :                 FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2639             :                 {
    2640       21120 :                     hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[0].spread_coherence[sf]; // Q0
    2641       21120 :                     move16();
    2642             :                 }
    2643             :             }
    2644       15876 :             IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
    2645             :             {
    2646       26400 :                 FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2647             :                 {
    2648       21120 :                     hqmetadata->surcoh_band_data[band].surround_coherence[sf] = hqmetadata->surcoh_band_data[0].surround_coherence[sf];
    2649       21120 :                     move16();
    2650             :                 }
    2651             :             }
    2652             :         }
    2653             : 
    2654        3969 :         hqmetadata->q_direction[0].cfg.nbands = 1;
    2655        3969 :         move16();
    2656             :     }
    2657             : 
    2658       24911 :     return;
    2659             : }
    2660             : 
    2661             : 
    2662       11470 : static Word16 encode_lfe_to_total_energy_ratio_fx(
    2663             :     MASA_ENCODER_HANDLE hMasa,    /* i/o: MASA encoder structure       */
    2664             :     BSTR_ENC_HANDLE hMetaData,    /* i/o: Metadata bitstream handle    */
    2665             :     const Word32 ivas_total_brate /* i  : IVAS total bitrate           */
    2666             : )
    2667             : {
    2668             :     Word16 i;
    2669             :     Word16 xq;
    2670             :     Word16 VQLevels;
    2671             :     Word32 maxLFESubFrameEner;
    2672             :     Word16 maxLFESubFrameEner_e;
    2673             :     Word32 log2LFEaverage;
    2674             :     Word32 log2LFEratio[4];
    2675             :     Word32 xqv[4];
    2676             :     Word32 linearLFEaverage;
    2677             :     Word16 linearLFEaverage_e;
    2678             :     Word16 lfeToTotalEnergyRatioIndices[3];
    2679             :     Word16 lfeAdaptiveVQBits;
    2680             :     Word16 lfeBitsWritten;
    2681             :     Word32 maxVal;
    2682             :     Word16 maxVal_e;
    2683             : 
    2684       11470 :     VQLevels = 0;
    2685       11470 :     move16();
    2686       11470 :     lfeAdaptiveVQBits = 0;
    2687       11470 :     move16();
    2688             : 
    2689             :     /* Determine maximum amount of LFE energy in any subframe */
    2690       11470 :     maxLFESubFrameEner = 0; // maxLFESubFrameEner_e
    2691       11470 :     move32();
    2692       11470 :     maxLFESubFrameEner_e = 0;
    2693       11470 :     move16();
    2694       57350 :     FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    2695             :     {
    2696       45880 :         IF( BASOP_Util_Cmp_Mant32Exp( hMasa->data.lfeToTotalEnergyRatio_fx[i], hMasa->data.lfeToTotalEnergyRatio_e[i], maxLFESubFrameEner, maxLFESubFrameEner_e ) > 0 )
    2697             :         {
    2698        4563 :             maxLFESubFrameEner = hMasa->data.lfeToTotalEnergyRatio_fx[i]; // hMasa->data.lfeToTotalEnergyRatio_e[i]
    2699        4563 :             move32();
    2700        4563 :             maxLFESubFrameEner_e = hMasa->data.lfeToTotalEnergyRatio_e[i];
    2701        4563 :             move16();
    2702             :         }
    2703             :     }
    2704             : 
    2705             :     /* Set default values for the indices */
    2706       45880 :     FOR( i = 0; i < 3; i++ )
    2707             :     {
    2708       34410 :         lfeToTotalEnergyRatioIndices[i] = 0;
    2709       34410 :         move16();
    2710             :     }
    2711             : 
    2712             :     /* Check if there is enough energy in any subframe. If not, send only 1 bit (0) and abort. */
    2713             :     /* If there is enough LFE energy at least in one subframe, quantize it. */
    2714       11470 :     IF( BASOP_Util_Cmp_Mant32Exp( maxLFESubFrameEner, maxLFESubFrameEner_e, 10737418 /* 0.005f in Q31 */, 0 ) > 0 )
    2715             :     {
    2716             :         /* Convert energy to log2 domain, and clamp it to reasonable values */
    2717        1884 :         log2LFEaverage = 0; // Q25
    2718        1884 :         move32();
    2719        9420 :         FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    2720             :         {
    2721             :             // log2LFEratio[i] = log2f( max( 0.001f, hMasa->data.lfeToTotalEnergyRatio[i] ) );
    2722        7536 :             maxVal = 2147484 /* 0.001f in Q31 */;
    2723        7536 :             move32();
    2724        7536 :             maxVal_e = 0;
    2725        7536 :             move16();
    2726        7536 :             IF( BASOP_Util_Cmp_Mant32Exp( hMasa->data.lfeToTotalEnergyRatio_fx[i], hMasa->data.lfeToTotalEnergyRatio_e[i], maxVal, maxVal_e ) > 0 )
    2727             :             {
    2728        7297 :                 maxVal = hMasa->data.lfeToTotalEnergyRatio_fx[i];
    2729        7297 :                 move32();
    2730        7297 :                 maxVal_e = hMasa->data.lfeToTotalEnergyRatio_e[i];
    2731        7297 :                 move16();
    2732             :             }
    2733        7536 :             log2LFEratio[i] = L_add( BASOP_Util_Log2( maxVal ), L_shl( maxVal_e, Q25 ) ); // Q25
    2734        7536 :             move32();
    2735        7536 :             IF( GT_32( log2LFEratio[i], ONE_IN_Q25 ) ) /* Corresponds to linear value 2.0f */
    2736             :             {
    2737           0 :                 log2LFEratio[i] = ONE_IN_Q25; // Q25
    2738           0 :                 move32();
    2739             :             }
    2740        7536 :             ELSE IF( LT_32( log2LFEratio[i], -301989888 /* -9.0f in Q25 */ ) )
    2741             :             {
    2742         286 :                 log2LFEratio[i] = -301989888 /* -9.0f in Q25 */; // Q25
    2743         286 :                 move32();
    2744             :             }
    2745        7536 :             log2LFEaverage = L_add( log2LFEaverage, Mpy_32_32( 536870912 /* 0.25f in Q31 */, log2LFEratio[i] ) ); // Q25
    2746             :         }
    2747             : 
    2748        1884 :         IF( EQ_32( ivas_total_brate, IVAS_13k2 ) )
    2749             :         {
    2750             :             /* Calculate adaptive 1-bit LFE quantizer index */
    2751             :             // linearLFEaverage = exp2f( log2LFEaverage ); /* Convert back to linear domain */
    2752         175 :             linearLFEaverage = BASOP_util_Pow2( log2LFEaverage, Q31 - Q25, &linearLFEaverage_e ); /* Convert back to linear domain */
    2753         175 :             linearLFEaverage = L_shl_sat( linearLFEaverage, sub( linearLFEaverage_e, Q1 ) );      // Q30
    2754         175 :             test();
    2755         175 :             IF( GT_32( linearLFEaverage, MCMASA_LFE_1BIT_THRES_Q30 ) &&
    2756             :                 GT_32( linearLFEaverage, L_add( L_add( MCMASA_LFE_BETA_Q30 >> Q1, L_shr( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q2 ) ),
    2757             :                                                 L_shr( Mpy_32_32( MCMASA_LFE_ALPHA_Q30, hMasa->data.prevq_lfeToTotalEnergyRatio_fx ), Q1 ) ) ) )
    2758             :             {
    2759         128 :                 lfeToTotalEnergyRatioIndices[0] = 1;
    2760         128 :                 move16();
    2761         128 :                 IF( EQ_16( hMasa->data.prevq_lfeIndex, 1 ) )
    2762             :                 {
    2763          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
    2764          86 :                     move32();
    2765             :                 }
    2766             :                 ELSE
    2767             :                 {
    2768          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
    2769          42 :                     move32();
    2770             :                 }
    2771             :             }
    2772             :             ELSE
    2773             :             {
    2774          47 :                 hMasa->data.prevq_lfeToTotalEnergyRatio_fx = Mpy_32_32( MCMASA_LFE_ALPHA_Q30, hMasa->data.prevq_lfeToTotalEnergyRatio_fx ); /* exponential decay */ // Q30
    2775          47 :                 move32();
    2776             :             }
    2777             : 
    2778         175 :             IF( GE_32( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, ONE_IN_Q30 ) )
    2779             :             {
    2780           0 :                 hMasa->data.prevq_lfeToTotalEnergyRatio_fx = ONE_IN_Q31; // Q31
    2781           0 :                 move32();
    2782             :             }
    2783             :             ELSE
    2784             :             {
    2785         175 :                 hMasa->data.prevq_lfeToTotalEnergyRatio_fx = L_shl( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q1 ); // Q31
    2786         175 :                 move32();
    2787             :             }
    2788         175 :             hMasa->data.prevq_lfeIndex = lfeToTotalEnergyRatioIndices[0]; /* Update to previous frame's index memories */
    2789         175 :             move16();
    2790             :         }
    2791             :         ELSE /* Bitrate >= 16.4 kbps */
    2792             :         {
    2793             :             /* Do 1st stage scalar quantization */
    2794        1709 :             lfeToTotalEnergyRatioIndices[0] = 1;
    2795        1709 :             move16();
    2796        1709 :             lfeToTotalEnergyRatioIndices[1] = usquant_fx( extract_l( L_shr( log2LFEaverage, Q14 ) ), &xq, MCMASA_LFE_QLOW_Q11, MCMASA_LFE_DELTA_Q10, 8 );
    2797        1709 :             move16();
    2798             : 
    2799        1709 :             IF( GE_32( ivas_total_brate, IVAS_24k4 ) ) /* Vector quantization is applied if bitrate >= 24.4 kbps */
    2800             :             {
    2801             :                 /* Remove scalar value from the vector*/
    2802        8020 :                 FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    2803             :                 {
    2804        6416 :                     log2LFEratio[i] = L_sub( log2LFEratio[i], L_shl( xq, Q14 ) ); // Q25
    2805        6416 :                     move32();
    2806             :                 }
    2807             : 
    2808             :                 /* Vector quantize residual with energy adaptive bit allocation */
    2809        1604 :                 SWITCH( lfeToTotalEnergyRatioIndices[1] )
    2810             :                 {
    2811         222 :                     case 0:
    2812             :                     case 1:
    2813         222 :                         VQLevels = 0;
    2814         222 :                         move16();
    2815         222 :                         lfeAdaptiveVQBits = 0;
    2816         222 :                         move16();
    2817         222 :                         BREAK;
    2818          97 :                     case 2:
    2819          97 :                         VQLevels = 2;
    2820          97 :                         move16();
    2821          97 :                         lfeAdaptiveVQBits = 1;
    2822          97 :                         move16();
    2823          97 :                         BREAK;
    2824          97 :                     case 3:
    2825          97 :                         VQLevels = 4;
    2826          97 :                         move16();
    2827          97 :                         lfeAdaptiveVQBits = 2;
    2828          97 :                         move16();
    2829          97 :                         BREAK;
    2830         242 :                     case 4:
    2831         242 :                         VQLevels = 8;
    2832         242 :                         move16();
    2833         242 :                         lfeAdaptiveVQBits = 3;
    2834         242 :                         move16();
    2835         242 :                         BREAK;
    2836         946 :                     default:
    2837         946 :                         VQLevels = 16;
    2838         946 :                         move16();
    2839         946 :                         lfeAdaptiveVQBits = 4;
    2840         946 :                         move16();
    2841             :                 }
    2842             : 
    2843        1604 :                 IF( VQLevels > 0 )
    2844             :                 {
    2845        1382 :                     lfeToTotalEnergyRatioIndices[2] = vquant_ivas_fx( log2LFEratio, 0, xqv, McMASA_LFEGain_vectors_fx_q25, 4, VQLevels );
    2846        1382 :                     move16();
    2847             :                 }
    2848             :             }
    2849             :         }
    2850             :     }
    2851             : 
    2852             :     /* Write first LFE bit */
    2853       11470 :     lfeBitsWritten = 0;
    2854       11470 :     move16();
    2855       11470 :     push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[0], 1 );
    2856       11470 :     lfeBitsWritten = add( lfeBitsWritten, 1 );
    2857             : 
    2858       11470 :     test();
    2859       11470 :     IF( EQ_16( lfeToTotalEnergyRatioIndices[0], 1 ) && GE_32( ivas_total_brate, IVAS_16k4 ) )
    2860             :     {
    2861             :         /* If bitrate >= 16.4kbit/s, send 1-bit on/off + 3-bit scalar */
    2862        1709 :         push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[1], 3 );
    2863        1709 :         lfeBitsWritten = add( lfeBitsWritten, 3 );
    2864             : 
    2865             :         /*  If bitrate >= 24.4kbit/s, use adaptive 1 + (3.. 7) bit quantizer */
    2866        1709 :         IF( GE_32( ivas_total_brate, IVAS_24k4 ) )
    2867             :         {
    2868             :             /* Vector quantize residual with energy adaptive bit allocation */
    2869        1604 :             IF( lfeAdaptiveVQBits > 0 )
    2870             :             {
    2871        1382 :                 push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[2], lfeAdaptiveVQBits );
    2872        1382 :                 lfeBitsWritten = add( lfeBitsWritten, lfeAdaptiveVQBits );
    2873             :             }
    2874             :         }
    2875             :     }
    2876             : 
    2877       11470 :     return lfeBitsWritten;
    2878             : }
    2879             : 
    2880             : 
    2881             : /*-------------------------------------------------------------------*
    2882             :  * ivas_masa_enc_reconfigure()
    2883             :  *
    2884             :  * Reconfigure IVAS MASA encoder
    2885             :  *-------------------------------------------------------------------*/
    2886       30626 : void ivas_masa_enc_reconfigure_fx(
    2887             :     Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
    2888             : )
    2889             : {
    2890             :     Word16 n, tmp;
    2891             :     Word16 sce_id, cpe_id;
    2892             :     Word32 ivas_total_brate;
    2893             :     Word32 ism_total_brate;
    2894             :     Word32 tmp_br, tmp_mod;
    2895             : 
    2896       30626 :     ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate;
    2897       30626 :     move32();
    2898             : 
    2899       30626 :     ism_total_brate = 0;
    2900       30626 :     move32();
    2901       30626 :     test();
    2902       30626 :     test();
    2903       30626 :     test();
    2904       30626 :     test();
    2905       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 ) ) )
    2906             :     {
    2907           0 :         FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
    2908             :         {
    2909           0 :             ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[sce_id]->element_brate );
    2910             :         }
    2911             :     }
    2912             : 
    2913       30626 :     IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) )
    2914             :     {
    2915        1269 :         iDiv_and_mod_32( ivas_total_brate, st_ivas->nchan_transport, &tmp_br, &tmp_mod, 0 );
    2916        1934 :         FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
    2917             :         {
    2918         665 :             copy_encoder_config_fx( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 );
    2919         665 :             st_ivas->hSCE[sce_id]->element_brate = tmp_br;
    2920         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() */
    2921         665 :             move32();
    2922         665 :             move32();
    2923             :         }
    2924             : 
    2925        1873 :         FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ )
    2926             :         {
    2927         604 :             st_ivas->hCPE[cpe_id]->element_brate = imult3216( tmp_br, 2 ); //( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS;
    2928         604 :             move32();
    2929             : 
    2930         604 :             IF( GT_16( st_ivas->nCPE, 1 ) )
    2931             :             {
    2932           0 :                 tmp = 1;
    2933             :             }
    2934             :             ELSE
    2935             :             {
    2936         604 :                 tmp = CPE_CHANNELS;
    2937             :             }
    2938         604 :             move16();
    2939             :             /* prepare bitstream buffers */
    2940        1812 :             FOR( n = 0; n < CPE_CHANNELS; n++ )
    2941             :             {
    2942        1208 :                 copy_encoder_config_fx( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 );
    2943             :                 /* st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); */
    2944        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() */
    2945        1208 :                 move32();
    2946             :             }
    2947             : 
    2948         604 :             IF( LT_32( L_sub( ivas_total_brate, ism_total_brate ), MIN_BRATE_MDCT_STEREO ) )
    2949             :             {
    2950         218 :                 st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_DFT;
    2951             :             }
    2952             :             ELSE
    2953             :             {
    2954         386 :                 st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_MDCT;
    2955             :             }
    2956         604 :             move16();
    2957             :         }
    2958             : 
    2959        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 );
    2960             :     }
    2961             : 
    2962       30626 :     return;
    2963             : }
    2964             : 
    2965             : /*-------------------------------------------------------------------*
    2966             :  * average_masa_metadata()
    2967             :  *
    2968             :  * Average MASA metadata frame subframe contents: applies aggregation over time
    2969             :  *-------------------------------------------------------------------*/
    2970           0 : static void average_masa_metadata_fx(
    2971             :     MASA_METADATA_FRAME *hMeta,
    2972             :     Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   /*i Q(31 - energy_e) */
    2973             :     Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*i:stores exponent values for energy_e*/
    2974             :     const SPHERICAL_GRID_DATA *Sph_Grid16,
    2975             :     const UWord8 useSphGrid )
    2976             : {
    2977             :     Word16 i, j, k;
    2978             :     Word16 azi_rad_fx, ele_rad_fx;
    2979             :     UWord8 numDirections;
    2980             : 
    2981             :     /* use the nominal values without data-adaptivity */
    2982           0 :     numDirections = (UWord8) add( hMeta->descriptive_meta.numberOfDirections, 1 );
    2983           0 :     move16();
    2984             : 
    2985             :     /* azi/ele/nrg into vectors for each sub-frame and band */
    2986           0 :     FOR( i = 0; i < numDirections; i++ )
    2987             :     {
    2988           0 :         FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
    2989             :         {
    2990             :             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;
    2991             :             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;
    2992           0 :             x_sum_fx = 0;
    2993           0 :             y_sum_fx = 0;
    2994           0 :             z_sum_fx = 0;
    2995           0 :             energy_sum_fx = 0;
    2996           0 :             spread_coh_sum_fx = 0;
    2997           0 :             surr_coh_sum_fx = 0;
    2998           0 :             x_sum_e = 0;          /*exponent for x_sum_fx*/
    2999           0 :             y_sum_e = 0;          /*exponent for y_sum_fx*/
    3000           0 :             z_sum_e = 0;          /*exponent for z_sum_fx*/
    3001           0 :             energy_sum_e = 0;     /*exponent for energy_sum_fx*/
    3002           0 :             spread_coh_sum_e = 0; /*exponent for spread_coh_sum_fx*/
    3003           0 :             surr_coh_sum_e = 0;   /*exponent for surr_coh_sum_fx*/
    3004           0 :             temp1 = 0;            /* to store temporary computations*/
    3005           0 :             temp2 = 0;            /* to store temporary computations*/
    3006           0 :             temp1_e = 0;          /*to store temporary exponents*/
    3007           0 :             temp2_e = 0;          /*to store temporary exponents*/
    3008           0 :             move32();
    3009           0 :             move32();
    3010           0 :             move32();
    3011           0 :             move32();
    3012           0 :             move32();
    3013           0 :             move32();
    3014           0 :             move32();
    3015           0 :             move32();
    3016           0 :             move16();
    3017           0 :             move16();
    3018           0 :             move16();
    3019           0 :             move16();
    3020           0 :             move16();
    3021           0 :             move16();
    3022           0 :             move16();
    3023           0 :             move16();
    3024             : 
    3025           0 :             FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
    3026             :             {
    3027           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*/
    3028           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*/
    3029           0 :                 vec_len_fx = Mpy_32_32( hMeta->directional_meta[i].energy_ratio_fx[j][k] /*q30*/, energy[j][k] );                                                                                                                                              /*exponent=energy_e+1*/
    3030           0 :                 vec_len_e = add( energy_e[j][k], 1 );
    3031             : 
    3032             :                 /* energy-weighted sum over subframes */
    3033           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*/
    3034           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*/
    3035           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*/
    3036             : 
    3037           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*/
    3038             : 
    3039           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*/
    3040           0 :                 IF( i == 0 )
    3041             :                 {
    3042             :                     /* this is in common metadata and not in each direction */
    3043           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*/
    3044             :                 }
    3045             :             }
    3046             : 
    3047             :             /* the data from the combined sub-frames is written into the first sub-frame band */
    3048           0 :             j = 0;
    3049           0 :             move16();
    3050           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*/
    3051           0 :             move32();
    3052           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*/
    3053           0 :             temp2_e = temp1_e;
    3054           0 :             temp2 = Sqrt32( temp1, &temp2_e );                                                                                                                                              /*temp2_e*/
    3055           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*/
    3056           0 :             move32();
    3057           0 :             IF( EQ_16( useSphGrid, TRUE ) )
    3058             :             {
    3059             : 
    3060           0 :                 hMeta->directional_meta[i].spherical_index[j][k] = index_theta_phi_16_fx( &( hMeta->directional_meta[i].elevation_fx[j][k] ),
    3061           0 :                                                                                           &( hMeta->directional_meta[i].azimuth_fx[j][k] ), Sph_Grid16 );
    3062           0 :                 move16();
    3063             :             }
    3064           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*/
    3065           0 :             vec_len_fx = Sqrt32( vec_len_fx, &vec_len_e );                                                                                              /*vec_len_e*/
    3066           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*/
    3067           0 :             move32();
    3068           0 :             temp2_e = add( temp2_e, sub( vec_len_e, energy_sum_e ) );
    3069           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*/
    3070           0 :             move32();
    3071           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 );
    3072           0 :             move16();
    3073           0 :             temp2_e = add( temp2_e, sub( spread_coh_sum_e, energy_sum_e ) );
    3074           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*/
    3075           0 :             move16();
    3076           0 :             IF( i == 0 )
    3077             :             {
    3078           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 );
    3079           0 :                 move16();
    3080           0 :                 temp2_e = add( temp2_e, sub( surr_coh_sum_e, energy_sum_e ) );
    3081           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*/
    3082           0 :                 move16();
    3083             :             }
    3084             : 
    3085             :             /* copy the same value to all subframes */
    3086           0 :             FOR( j = 1; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
    3087             :             {
    3088           0 :                 hMeta->directional_meta[i].azimuth_fx[j][k] = hMeta->directional_meta[i].azimuth_fx[0][k];                   /*q22*/
    3089           0 :                 hMeta->directional_meta[i].elevation_fx[j][k] = hMeta->directional_meta[i].elevation_fx[0][k];               /*q22*/
    3090           0 :                 hMeta->directional_meta[i].energy_ratio_fx[j][k] = hMeta->directional_meta[i].energy_ratio_fx[0][k];         /*q30*/
    3091           0 :                 hMeta->directional_meta[i].spread_coherence_fx[j][k] = hMeta->directional_meta[i].spread_coherence_fx[0][k]; /*q15*/
    3092           0 :                 move32();
    3093           0 :                 move32();
    3094           0 :                 move32();
    3095           0 :                 move16();
    3096           0 :                 IF( i == 0 )
    3097             :                 {
    3098           0 :                     hMeta->common_meta.surround_coherence_fx[j][k] = hMeta->common_meta.surround_coherence_fx[0][k]; /*q15*/
    3099           0 :                     move16();
    3100             :                 }
    3101             :             }
    3102             :         }
    3103             :     }
    3104             : 
    3105           0 :     FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
    3106             :     {
    3107           0 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
    3108             :         {
    3109           0 :             IF( EQ_16( numDirections, 2 ) )
    3110             :             {
    3111           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*/
    3112             :             }
    3113             :             ELSE
    3114             :             {
    3115           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*/
    3116             :             }
    3117           0 :             move32();
    3118           0 :             hMeta->common_meta.remainder_to_total_ratio_fx[j][k] = 0; /*q30*/
    3119           0 :             move32();
    3120             :         }
    3121             :     }
    3122             : 
    3123           0 :     return;
    3124             : }
    3125             : 
    3126             : 
    3127             : /*-------------------------------------------------------------------*
    3128             :  * copy_masa_metadata_subframe()
    3129             :  *
    3130             :  * Copy MASA metadata frame subframe contents
    3131             :  *-------------------------------------------------------------------*/
    3132      158504 : static void copy_masa_metadata_subframe_fx(
    3133             :     const MASA_METADATA_HANDLE hMetaFrom, /* i  : MASA frame metdata to be copied      */
    3134             :     const UWord8 sfFrom,                  /* i  : subframe index of the copy source    */
    3135             :     MASA_METADATA_HANDLE hMetaTo,         /* o  : MASA frame metadata copy destination */
    3136             :     const UWord8 sfTo                     /* i  : subframe index of the copy target    */
    3137             : )
    3138             : {
    3139             :     UWord8 dir;
    3140             : 
    3141             :     /* directional metadata */
    3142      475512 :     FOR( dir = 0; dir < MASA_MAXIMUM_DIRECTIONS; dir++ )
    3143             :     {
    3144      317008 :         Copy32( hMetaFrom->directional_meta[dir].azimuth_fx[sfFrom], hMetaTo->directional_meta[dir].azimuth_fx[sfTo], MASA_FREQUENCY_BANDS );                 // Q22
    3145      317008 :         Copy32( hMetaFrom->directional_meta[dir].elevation_fx[sfFrom], hMetaTo->directional_meta[dir].elevation_fx[sfTo], MASA_FREQUENCY_BANDS );             // Q22
    3146      317008 :         Copy32( hMetaFrom->directional_meta[dir].energy_ratio_fx[sfFrom], hMetaTo->directional_meta[dir].energy_ratio_fx[sfTo], MASA_FREQUENCY_BANDS );       // Q30
    3147      317008 :         Copy( hMetaFrom->directional_meta[dir].spread_coherence_fx[sfFrom], hMetaTo->directional_meta[dir].spread_coherence_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q15
    3148             :     }
    3149             : 
    3150             :     /* common metadata */
    3151      158504 :     Copy32( hMetaFrom->common_meta.diffuse_to_total_ratio_fx[sfFrom], hMetaTo->common_meta.diffuse_to_total_ratio_fx[sfTo], MASA_FREQUENCY_BANDS );     // Q30
    3152      158504 :     Copy( hMetaFrom->common_meta.surround_coherence_fx[sfFrom], hMetaTo->common_meta.surround_coherence_fx[sfTo], MASA_FREQUENCY_BANDS );               // Q15
    3153      158504 :     Copy32( hMetaFrom->common_meta.remainder_to_total_ratio_fx[sfFrom], hMetaTo->common_meta.remainder_to_total_ratio_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q30
    3154             : 
    3155      158504 :     return;
    3156             : }
    3157             : 
    3158             : /*-------------------------------------------------------------------*
    3159             :  * copy_masa_metadata()
    3160             :  *
    3161             :  * Copy MASA metada frame contents
    3162             :  *-------------------------------------------------------------------*/
    3163       39626 : static void copy_masa_metadata_fx(
    3164             :     const MASA_METADATA_HANDLE hMetaFrom, /* i  : MASA frame metadata to be copied     */
    3165             :     MASA_METADATA_HANDLE hMetaTo          /* o  : MASA frame metadata copy destination */
    3166             : )
    3167             : {
    3168             :     UWord8 sf, byte_idx;
    3169             : 
    3170             :     /* descriptive metadata */
    3171      356634 :     FOR( byte_idx = 0; byte_idx < 8; byte_idx++ )
    3172             :     {
    3173      317008 :         hMetaTo->descriptive_meta.formatDescriptor[byte_idx] = hMetaFrom->descriptive_meta.formatDescriptor[byte_idx];
    3174      317008 :         move16();
    3175             :     }
    3176             : 
    3177       39626 :     hMetaTo->descriptive_meta.numberOfDirections = hMetaFrom->descriptive_meta.numberOfDirections;
    3178       39626 :     hMetaTo->descriptive_meta.numberOfChannels = hMetaFrom->descriptive_meta.numberOfChannels;
    3179       39626 :     hMetaTo->descriptive_meta.sourceFormat = hMetaFrom->descriptive_meta.sourceFormat;
    3180       39626 :     hMetaTo->descriptive_meta.transportDefinition = hMetaFrom->descriptive_meta.transportDefinition;
    3181       39626 :     hMetaTo->descriptive_meta.channelAngle = hMetaFrom->descriptive_meta.channelAngle;
    3182       39626 :     hMetaTo->descriptive_meta.channelDistance = hMetaFrom->descriptive_meta.channelDistance;
    3183       39626 :     hMetaTo->descriptive_meta.channelLayout = hMetaFrom->descriptive_meta.channelLayout;
    3184       39626 :     move16();
    3185       39626 :     move16();
    3186       39626 :     move16();
    3187       39626 :     move16();
    3188       39626 :     move16();
    3189       39626 :     move16();
    3190       39626 :     move16();
    3191             : 
    3192             :     /* directional and common metadata */
    3193      198130 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    3194             :     {
    3195      158504 :         copy_masa_metadata_subframe_fx( hMetaFrom, sf, hMetaTo, sf );
    3196             :     }
    3197             : 
    3198       39626 :     return;
    3199             : }
    3200             : 
    3201             : /*-------------------------------------------------------------------*
    3202             :  * are_masa_subframes_similar()
    3203             :  *
    3204             :  * Compare the similarity of MASA metadata in two sub-frames
    3205             :  *-------------------------------------------------------------------*/
    3206             : 
    3207             : /* r: similarity decision */
    3208      175035 : static UWord8 are_masa_subframes_similar_fx(
    3209             :     const MASA_METADATA_HANDLE frame1, /* i  : MASA metadata frame 1                      */
    3210             :     const UWord8 sf1_idx,              /* i  : index of the subframe of frame1 to inspect */
    3211             :     const MASA_METADATA_HANDLE frame2, /* i  : MASA metadata frame 2                      */
    3212             :     const UWord8 sf2_idx               /* i  : index of the subframe of frame2 to inspect */
    3213             : )
    3214             : {
    3215             :     UWord8 num_dir;
    3216             :     UWord8 dir;
    3217             :     UWord8 band_idx;
    3218             :     UWord8 sf_differ;
    3219             : 
    3220      175035 :     num_dir = frame1->descriptive_meta.numberOfDirections;
    3221      175035 :     dir = 0;
    3222      175035 :     band_idx = 0;
    3223      175035 :     sf_differ = FALSE;
    3224      175035 :     move16();
    3225      175035 :     move16();
    3226      175035 :     move16();
    3227      175035 :     move16();
    3228             : 
    3229      175035 :     IF( NE_16( num_dir, frame2->descriptive_meta.numberOfDirections ) )
    3230             :     {
    3231           0 :         sf_differ = TRUE;
    3232           0 :         move16();
    3233             :     }
    3234             :     ELSE
    3235             :     {
    3236             :         /* check per-direction metadata */
    3237      175035 :         dir = 0;
    3238      175035 :         band_idx = 0;
    3239      175035 :         move16();
    3240      175035 :         move16();
    3241             : 
    3242      360870 :         WHILE( ( sf_differ == FALSE ) && ( dir <= num_dir ) )
    3243             :         {
    3244      185835 :             test();
    3245      185835 :             band_idx = 0;
    3246      185835 :             move16();
    3247     1244235 :             WHILE( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) )
    3248             :             {
    3249     1200135 :                 test();
    3250             :                 Word32 azi_dif_fx;
    3251     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
    3252     1200135 :                 IF( GT_32( azi_dif_fx, 180 << Q22 ) )
    3253       16892 :                 azi_dif_fx = L_sub( 360 << Q22, azi_dif_fx ); // Q22
    3254             : 
    3255     1200135 :                 IF( GT_32( azi_dif_fx, ONE_IN_Q21 /*0.5 in Q22*/ ) )
    3256             :                 {
    3257      139100 :                     sf_differ = TRUE;
    3258      139100 :                     move16();
    3259      139100 :                     BREAK;
    3260             :                 }
    3261             : 
    3262     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 ) )
    3263             :                 {
    3264        2616 :                     sf_differ = TRUE;
    3265        2616 :                     move16();
    3266        2616 :                     BREAK;
    3267             :                 }
    3268             : 
    3269     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 ) )
    3270             :                 {
    3271          19 :                     sf_differ = TRUE;
    3272          19 :                     move16();
    3273          19 :                     BREAK;
    3274             :                 }
    3275             : 
    3276     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 ) )
    3277             :                 {
    3278           0 :                     sf_differ = TRUE;
    3279           0 :                     move16();
    3280           0 :                     BREAK;
    3281             :                 }
    3282             : 
    3283     1058400 :                 band_idx = (UWord8) add( band_idx, 1 );
    3284     1058400 :                 move16();
    3285             :             }
    3286      185835 :             dir = (UWord8) add( dir, 1 );
    3287      185835 :             move16();
    3288             :         }
    3289             : 
    3290             :         /* check the common metadata */
    3291      175035 :         WHILE( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) )
    3292             :         {
    3293           0 :             test();
    3294           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 ) )
    3295             :             {
    3296           0 :                 sf_differ = TRUE;
    3297           0 :                 move16();
    3298           0 :                 BREAK;
    3299             :             }
    3300             : 
    3301           0 :             band_idx = (UWord8) add( band_idx, 1 );
    3302           0 :             move16();
    3303             :         }
    3304             :     }
    3305             : 
    3306      175035 :     IF( sf_differ )
    3307             :     {
    3308      141735 :         return FALSE;
    3309             :     }
    3310             :     ELSE
    3311             :     {
    3312       33300 :         return TRUE;
    3313             :     }
    3314             : }
    3315             : 
    3316             : /*-------------------------------------------------------------------*
    3317             :  * detect_framing_async()
    3318             :  *
    3319             :  * Compare the similarity of MASA metadata in two sub-frames
    3320             :  * Analysis result is stored in hMasa->data.sync_state, and
    3321             :  * potentially hMasa->masaMetadata is modified
    3322             :  *-------------------------------------------------------------------*/
    3323       39626 : static void detect_framing_async_fx(
    3324             :     MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder structure */
    3325             : )
    3326             : {
    3327             :     MASA_METADATA_HANDLE current_meta;
    3328             :     MASA_METADATA_HANDLE previous_meta;
    3329             :     MASA_SYNC_HANDLE sync_state;
    3330             :     MASA_FRAME_MODE frame_mode;
    3331             :     UWord8 n_sim_start, n_sim_stop, sf_idx;
    3332             :     UWord8 found_offset;
    3333             : 
    3334       39626 :     current_meta = &( hMasa->masaMetadata );  /* metadata from current frame */
    3335       39626 :     sync_state = &( hMasa->data.sync_state ); /* synchronization structure */
    3336       39626 :     previous_meta = &( sync_state->previous_metadata );
    3337             : 
    3338             :     /* check current frame, how many are similar from the start and from the end */
    3339       39626 :     n_sim_start = 1;
    3340       39626 :     move16();
    3341       56276 :     FOR( sf_idx = n_sim_start; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
    3342             :     {
    3343       50726 :         IF( EQ_16( are_masa_subframes_similar_fx( current_meta, 0, current_meta, sf_idx ), TRUE ) )
    3344             :         {
    3345       16650 :             n_sim_start = (UWord8) add( sf_idx, 1 );
    3346       16650 :             move16();
    3347             :         }
    3348             :         ELSE
    3349             :         {
    3350       34076 :             BREAK;
    3351             :         }
    3352             :     }
    3353             : 
    3354             :     /* number of similar sub-frames starting from the end of the frame */
    3355       39626 :     IF( EQ_16( n_sim_start, MAX_PARAM_SPATIAL_SUBFRAMES ) ) /* shortcut */
    3356             :     {
    3357        5550 :         n_sim_stop = n_sim_start;
    3358        5550 :         move16();
    3359             :     }
    3360             :     ELSE
    3361             :     {
    3362       34076 :         n_sim_stop = 1;
    3363       34076 :         move16();
    3364       34076 :         FOR( sf_idx = 2; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
    3365             :         {
    3366             :             /* we need to check only the two middle sub-frames, as all being the same would have taken the shortcut above */
    3367       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 ) )
    3368             :             {
    3369           0 :                 n_sim_stop = sf_idx;
    3370           0 :                 move16();
    3371             :             }
    3372             :             ELSE
    3373             :             {
    3374       34076 :                 BREAK;
    3375             :             }
    3376             :         }
    3377             :     }
    3378             : 
    3379       39626 :     frame_mode = MASA_FRAME_4SF; /* default mode: 4sf */
    3380       39626 :     move16();
    3381       39626 :     IF( GT_16( sync_state->prev_offset, MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) )
    3382             :     {
    3383             :         /* earlier offset was large => reset the offset */
    3384           0 :         found_offset = 0;
    3385             :     }
    3386             :     ELSE
    3387             :     {
    3388             :         /* keep previous offset unless something else is found. alternatively, we could reset always */
    3389       39626 :         found_offset = sync_state->prev_offset;
    3390             :     }
    3391       39626 :     move16();
    3392             : 
    3393       39626 :     test();
    3394       39626 :     test();
    3395       39626 :     IF( EQ_16( n_sim_start, MAX_PARAM_SPATIAL_SUBFRAMES ) && EQ_16( n_sim_stop, MAX_PARAM_SPATIAL_SUBFRAMES ) )
    3396             :     {
    3397             :         /* full frame consists of similar sub-frames */
    3398        5550 :         frame_mode = MASA_FRAME_1SF;
    3399        5550 :         move16();
    3400        5550 :         test();
    3401        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 ) )
    3402             :         {
    3403             :             /* > 4 sub-frames of similar data */
    3404           0 :             IF( LT_16( sync_state->prev_sim_stop, 3 ) )
    3405             :             {
    3406             :                 /* can nicely align the framing with the earlier data and a small offset */
    3407           0 :                 found_offset = sync_state->prev_sim_stop;
    3408             :             }
    3409             :             ELSE
    3410             :             {
    3411             :                 /* too many similar sub-frames to determine the offset accurately => keep earlier value */
    3412           0 :                 found_offset = sync_state->prev_offset;
    3413             :             }
    3414           0 :             move16();
    3415             :         }
    3416             :         ELSE
    3417             :         {
    3418             :             /* earlier window was different => reset the offset */
    3419        5550 :             found_offset = 0;
    3420        5550 :             move16();
    3421             :         }
    3422             :     }
    3423       34076 :     ELSE IF( EQ_16( n_sim_stop, 3 ) )
    3424             :     {
    3425             :         /* first sub-frame different that the rest 3
    3426             :                        => make a risky guess that the future sf would be the same too and we're in an offset case */
    3427           0 :         frame_mode = MASA_FRAME_1SF;
    3428           0 :         found_offset = 3;
    3429           0 :         move16();
    3430           0 :         move16();
    3431             :     }
    3432       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 ) )
    3433             :     {
    3434             :         /* seeing data similar to past */
    3435           0 :         test();
    3436           0 :         IF( GT_16( n_sim_start, 1 ) && ( GE_16( add( n_sim_start, sync_state->prev_sim_stop ), MAX_PARAM_SPATIAL_SUBFRAMES ) ) )
    3437             :         {
    3438             :             /* with the past, would have at least one long frame similar subframes */
    3439           0 :             frame_mode = MASA_FRAME_1SF;
    3440           0 :             move16();
    3441             : 
    3442           0 :             IF( sync_state->prev_offset == 0 )
    3443             :             {
    3444           0 :                 found_offset = (UWord8) s_min( 2, sync_state->prev_sim_stop );
    3445             :             }
    3446             :             ELSE
    3447             :             {
    3448           0 :                 found_offset = sync_state->prev_offset;
    3449           0 :                 move16();
    3450             :             }
    3451             :         }
    3452             :     }
    3453             : 
    3454             :     /* keep the original contents of the frame, but then perform interpolation later */
    3455             :     /* just copy current frame to storage */
    3456       39626 :     copy_masa_metadata_fx( current_meta, previous_meta );
    3457             : 
    3458       39626 :     sync_state->prev_sim_stop = n_sim_stop;
    3459       39626 :     sync_state->prev_offset = found_offset;
    3460       39626 :     sync_state->frame_mode = frame_mode;
    3461       39626 :     move16();
    3462       39626 :     move16();
    3463       39626 :     move16();
    3464             : 
    3465       39626 :     return;
    3466             : }
    3467             : 
    3468             : /*-------------------------------------------------------------------*
    3469             :  * masa_metadata_direction_alignment()
    3470             :  *
    3471             :  * In 2dir MASA metadata, determine the ordering of the directional
    3472             :  * fields such that the azi/ele change across time is minimized.
    3473             :  *-------------------------------------------------------------------*/
    3474       39626 : static void masa_metadata_direction_alignment_fx(
    3475             :     MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder handle */
    3476             : )
    3477             : {
    3478             :     UWord8 band, n_dirs;
    3479             :     MASA_DIR_ALIGN_HANDLE hAlignState;
    3480             :     MASA_METADATA_HANDLE hMeta;
    3481       39626 :     hAlignState = &( hMasa->data.dir_align_state );
    3482       39626 :     hMeta = &( hMasa->masaMetadata );
    3483             : 
    3484       39626 :     n_dirs = (UWord8) add( hMeta->descriptive_meta.numberOfDirections, 1 ); /* 1-based */
    3485       39626 :     move16();
    3486      990650 :     FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
    3487             :     {
    3488             :         UWord8 sf;
    3489             :         Word32 diff_swap_fx;
    3490             :         Word32 diff_no_swap_fx;
    3491             : 
    3492             :         /* trade 2*(cos+sin) against storing the values between frames */
    3493             :         Word16 prev_ele_dir1_sin_fx, prev_ele_dir2_sin_fx;
    3494             :         Word16 prev_ele_dir1_cos_fx, prev_ele_dir2_cos_fx;
    3495             : 
    3496      951024 :         prev_ele_dir1_sin_fx = getSineWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir1_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3497      951024 :         prev_ele_dir2_sin_fx = getSineWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir2_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3498             : 
    3499      951024 :         prev_ele_dir1_cos_fx = getCosWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir1_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3500      951024 :         prev_ele_dir2_cos_fx = getCosWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir2_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3501             : 
    3502     4755120 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    3503             :         {
    3504             :             Word32 azi_rad1_fx, ele_rad1_fx;
    3505             :             Word32 azi_rad2_fx, ele_rad2_fx;
    3506             :             Word16 cos_ele1_fx, cos_ele2_fx;
    3507             :             Word16 sin_ele1_fx, sin_ele2_fx;
    3508             :             Word16 temp1;
    3509             :             Word32 temp2;
    3510             :             Word16 temp1_e;
    3511             : 
    3512             : 
    3513     3804096 :             azi_rad1_fx = Mpy_32_16_1( hMeta->directional_meta[0].azimuth_fx[sf][band], 572 /*PI_OVER_180 q15*/ );   /*q22*/
    3514     3804096 :             ele_rad1_fx = Mpy_32_16_1( hMeta->directional_meta[0].elevation_fx[sf][band], 572 /*PI_OVER_180 q15*/ ); /*q22*/
    3515             : 
    3516     3804096 :             IF( GT_16( n_dirs, 1 ) )
    3517             :             {
    3518      950400 :                 azi_rad2_fx = Mpy_32_16_1( hMeta->directional_meta[1].azimuth_fx[sf][band], 572 /*PI_OVER_180 q15*/ );   /*q22*/
    3519      950400 :                 ele_rad2_fx = Mpy_32_16_1( hMeta->directional_meta[1].elevation_fx[sf][band], 572 /*PI_OVER_180 q15*/ ); /*q22*/
    3520             : 
    3521      950400 :                 test();
    3522      950400 :                 test();
    3523      950400 :                 test();
    3524      950400 :                 test();
    3525      950400 :                 test();
    3526      950400 :                 test();
    3527             :                 /* quick checks to detect constant data and earlier flip */
    3528      950400 :                 IF( LT_32( L_abs( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir1_fx[band] ) ), EPSILON_FX ) &&
    3529             :                     LT_32( L_abs( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir2_fx[band] ) ), EPSILON_FX ) &&
    3530             :                     LT_32( L_abs( L_sub( ele_rad1_fx, hAlignState->previous_ele_dir1_fx[band] ) ), EPSILON_FX ) &&
    3531             :                     LT_32( L_abs( L_sub( ele_rad2_fx, hAlignState->previous_ele_dir2_fx[band] ) ), EPSILON_FX ) )
    3532             :                 {
    3533       91800 :                     diff_swap_fx = ONE_IN_Q13; /*1 q13*/
    3534       91800 :                     move32();
    3535       91800 :                     diff_no_swap_fx = 0;
    3536       91800 :                     move32();
    3537             :                     /* cached values that will be used for the short-cuts and over-written by the real computations, if done */
    3538       91800 :                     sin_ele1_fx = prev_ele_dir1_sin_fx; /*q15*/
    3539       91800 :                     sin_ele2_fx = prev_ele_dir2_sin_fx; /*q15*/
    3540       91800 :                     cos_ele1_fx = prev_ele_dir1_cos_fx; /*q15*/
    3541       91800 :                     cos_ele2_fx = prev_ele_dir2_cos_fx; /*q15*/
    3542       91800 :                     move16();
    3543       91800 :                     move16();
    3544       91800 :                     move16();
    3545       91800 :                     move16();
    3546             :                 }
    3547      858600 :                 ELSE IF( LT_32( L_abs( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir2_fx[band] ) ), EPSILON_FX ) &&
    3548             :                          LT_32( L_abs( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir1_fx[band] ) ), EPSILON_FX ) &&
    3549             :                          LT_32( L_abs( L_sub( ele_rad1_fx, hAlignState->previous_ele_dir2_fx[band] ) ), EPSILON_FX ) &&
    3550             :                          LT_32( L_abs( L_sub( ele_rad2_fx, hAlignState->previous_ele_dir1_fx[band] ) ), EPSILON_FX ) )
    3551             :                 {
    3552       37800 :                     diff_swap_fx = 0;
    3553       37800 :                     move32();
    3554       37800 :                     diff_no_swap_fx = ONE_IN_Q13; /*1.0 q13*/
    3555       37800 :                     move32();
    3556             :                     /* cached values that will be used for the short-cuts and over-written by the real computations, if done */
    3557       37800 :                     sin_ele1_fx = prev_ele_dir2_sin_fx; /*q15*/
    3558       37800 :                     sin_ele2_fx = prev_ele_dir1_sin_fx; /*q15*/
    3559       37800 :                     cos_ele1_fx = prev_ele_dir2_cos_fx; /*q15*/
    3560       37800 :                     cos_ele2_fx = prev_ele_dir1_cos_fx; /*q15*/
    3561       37800 :                     move16();
    3562       37800 :                     move16();
    3563       37800 :                     move16();
    3564       37800 :                     move16();
    3565             :                 }
    3566             :                 ELSE
    3567             :                 {
    3568             :                     /* angular distance of the two vectors */
    3569             :                     /* pre-compute values for re-use */
    3570      820800 :                     sin_ele1_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3571      820800 :                     sin_ele2_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad2_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3572             : 
    3573      820800 :                     cos_ele1_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3574      820800 :                     cos_ele2_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad2_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3575             : 
    3576      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*/
    3577      820800 :                     temp1 = mult( mult( temp1, cos_ele1_fx ) /*q31*/, prev_ele_dir1_cos_fx /*q15*/ );                                                           /*q15*/
    3578      820800 :                     temp1 = add_sat( mult( sin_ele1_fx, prev_ele_dir1_sin_fx ), temp1 );                                                                        /*q15*/
    3579      820800 :                     temp1_e = 1;                                                                                                                                /*stores expoenent for square root operation*/
    3580      820800 :                     move16();
    3581      820800 :                     temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
    3582      820800 :                     temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) );             /*q13*/
    3583      820800 :                     diff_no_swap_fx = L_deposit_l( temp1 );                                   /*q13*/
    3584             : 
    3585      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*/
    3586      820800 :                     temp1 = mult( mult( temp1, cos_ele2_fx ) /*q31*/, prev_ele_dir2_cos_fx /*q15*/ );                                                           /*q15*/
    3587      820800 :                     temp1 = add_sat( mult( sin_ele2_fx, prev_ele_dir2_sin_fx ), temp1 );                                                                        /*q15*/
    3588      820800 :                     temp1_e = 1;                                                                                                                                /*stores expoenent for square root operation*/
    3589      820800 :                     move16();
    3590      820800 :                     temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
    3591      820800 :                     temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) );             /*q13*/
    3592      820800 :                     diff_no_swap_fx = L_add( diff_no_swap_fx, temp1 );                        /*q13*/
    3593             : 
    3594      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*/
    3595      820800 :                     temp1 = mult( mult( temp1, cos_ele1_fx ) /*q31*/, prev_ele_dir2_cos_fx /*q15*/ );                                                           /*q15*/
    3596      820800 :                     temp1 = add_sat( mult( sin_ele1_fx, prev_ele_dir2_sin_fx ), temp1 );                                                                        /*q15*/
    3597      820800 :                     temp1_e = 1;                                                                                                                                /*stores expoenent for square root operation*/
    3598      820800 :                     move16();
    3599      820800 :                     temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
    3600      820800 :                     temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) );             /*q13*/
    3601      820800 :                     diff_swap_fx = L_deposit_l( temp1 );                                      /*q13*/
    3602             : 
    3603      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*/
    3604      820800 :                     temp1 = mult( mult( temp1, cos_ele2_fx ) /*q31*/, prev_ele_dir1_cos_fx /*q15*/ );                                                           /*q15*/
    3605      820800 :                     temp1 = add_sat( mult( sin_ele2_fx, prev_ele_dir1_sin_fx ), temp1 );                                                                        /*q15*/
    3606      820800 :                     temp1_e = 1;                                                                                                                                /*stores expoenent for square root operation*/
    3607      820800 :                     move16();
    3608      820800 :                     temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
    3609      820800 :                     temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) );             /*q13*/
    3610      820800 :                     diff_swap_fx = L_add( diff_swap_fx, temp1 );                              /*q13*/
    3611             :                 }
    3612             :             }
    3613             :             ELSE
    3614             :             {
    3615             :                 /* 1dir */
    3616     2853696 :                 sin_ele1_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
    3617     2853696 :                 cos_ele1_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) );  /*q15*/
    3618             : 
    3619     2853696 :                 azi_rad2_fx = 0;
    3620     2853696 :                 ele_rad2_fx = 0;
    3621     2853696 :                 move32();
    3622     2853696 :                 move32();
    3623             : 
    3624     2853696 :                 sin_ele2_fx = 0;      /* sin(0) */
    3625     2853696 :                 cos_ele2_fx = MAX_16; /* cos(0) in Q15*/
    3626     2853696 :                 move16();
    3627     2853696 :                 move16();
    3628             : 
    3629     2853696 :                 diff_swap_fx = ONE_IN_Q13; /*1.0 in Q13*/
    3630     2853696 :                 diff_no_swap_fx = 0;
    3631     2853696 :                 move32();
    3632     2853696 :                 move32();
    3633             :             }
    3634             : 
    3635     3804096 :             test();
    3636     3804096 :             IF( GT_16( n_dirs, 1 ) && GT_32( diff_no_swap_fx, diff_swap_fx ) )
    3637      121788 :             {
    3638             :                 /* swap the metadata of the two directions in this TF-tile */
    3639             :                 Word32 tmp_val;
    3640             :                 Word16 tmp_val_16;
    3641             :                 UWord16 tmp_int_val;
    3642      121788 :                 tmp_val = hMeta->directional_meta[0].azimuth_fx[sf][band];                                         /*q22*/
    3643      121788 :                 hMeta->directional_meta[0].azimuth_fx[sf][band] = hMeta->directional_meta[1].azimuth_fx[sf][band]; /*q22*/
    3644      121788 :                 hMeta->directional_meta[1].azimuth_fx[sf][band] = tmp_val;                                         /*q22*/
    3645      121788 :                 move32();
    3646      121788 :                 move32();
    3647      121788 :                 move32();
    3648             : 
    3649      121788 :                 tmp_val = hMeta->directional_meta[0].elevation_fx[sf][band];                                           /*q22*/
    3650      121788 :                 hMeta->directional_meta[0].elevation_fx[sf][band] = hMeta->directional_meta[1].elevation_fx[sf][band]; /*q22*/
    3651      121788 :                 hMeta->directional_meta[1].elevation_fx[sf][band] = tmp_val;                                           /*q22*/
    3652      121788 :                 move32();
    3653      121788 :                 move32();
    3654      121788 :                 move32();
    3655             : 
    3656      121788 :                 tmp_int_val = hMeta->directional_meta[0].spherical_index[sf][band];                                          /*q0*/
    3657      121788 :                 hMeta->directional_meta[0].spherical_index[sf][band] = hMeta->directional_meta[1].spherical_index[sf][band]; /*q0*/
    3658      121788 :                 hMeta->directional_meta[1].spherical_index[sf][band] = tmp_int_val;                                          /*q0*/
    3659      121788 :                 move32();
    3660      121788 :                 move32();
    3661      121788 :                 move32();
    3662             : 
    3663      121788 :                 tmp_val = hMeta->directional_meta[0].energy_ratio_fx[sf][band];                                              /*q30*/
    3664      121788 :                 hMeta->directional_meta[0].energy_ratio_fx[sf][band] = hMeta->directional_meta[1].energy_ratio_fx[sf][band]; /*q30*/
    3665      121788 :                 hMeta->directional_meta[1].energy_ratio_fx[sf][band] = tmp_val;                                              /*q30*/
    3666      121788 :                 move32();
    3667      121788 :                 move32();
    3668      121788 :                 move32();
    3669             : 
    3670      121788 :                 tmp_val_16 = hMeta->directional_meta[0].spread_coherence_fx[sf][band];                                               /*q15*/
    3671      121788 :                 hMeta->directional_meta[0].spread_coherence_fx[sf][band] = hMeta->directional_meta[1].spread_coherence_fx[sf][band]; /*q15*/
    3672      121788 :                 hMeta->directional_meta[1].spread_coherence_fx[sf][band] = tmp_val_16;                                               /*q15*/
    3673      121788 :                 move16();
    3674      121788 :                 move16();
    3675      121788 :                 move16();
    3676             : 
    3677      121788 :                 hAlignState->previous_azi_dir1_fx[band] = azi_rad2_fx; /*q22*/
    3678      121788 :                 hAlignState->previous_ele_dir1_fx[band] = ele_rad2_fx; /*q22*/
    3679      121788 :                 move32();
    3680      121788 :                 move32();
    3681             : 
    3682      121788 :                 hAlignState->previous_azi_dir2_fx[band] = azi_rad1_fx; /*q22*/
    3683      121788 :                 hAlignState->previous_ele_dir2_fx[band] = ele_rad1_fx; /*q22*/
    3684      121788 :                 move32();
    3685      121788 :                 move32();
    3686             : 
    3687      121788 :                 prev_ele_dir1_cos_fx = cos_ele2_fx; /*q15*/
    3688      121788 :                 prev_ele_dir1_sin_fx = sin_ele2_fx; /*q15*/
    3689      121788 :                 move16();
    3690      121788 :                 move16();
    3691             : 
    3692      121788 :                 prev_ele_dir2_cos_fx = cos_ele1_fx; /*q15*/
    3693      121788 :                 prev_ele_dir2_sin_fx = sin_ele1_fx; /*q15*/
    3694      121788 :                 move16();
    3695      121788 :                 move16();
    3696             :             }
    3697             :             ELSE
    3698             :             {
    3699     3682308 :                 hAlignState->previous_azi_dir1_fx[band] = azi_rad1_fx; /*q22*/
    3700     3682308 :                 hAlignState->previous_ele_dir1_fx[band] = ele_rad1_fx; /*q22*/
    3701     3682308 :                 move32();
    3702     3682308 :                 move32();
    3703             : 
    3704     3682308 :                 hAlignState->previous_azi_dir2_fx[band] = azi_rad2_fx; /*q22*/
    3705     3682308 :                 hAlignState->previous_ele_dir2_fx[band] = ele_rad2_fx; /*q22*/
    3706     3682308 :                 move32();
    3707     3682308 :                 move32();
    3708             : 
    3709     3682308 :                 prev_ele_dir1_cos_fx = cos_ele1_fx; /*q15*/
    3710     3682308 :                 prev_ele_dir1_sin_fx = sin_ele1_fx; /*q15*/
    3711     3682308 :                 move16();
    3712     3682308 :                 move16();
    3713             : 
    3714     3682308 :                 prev_ele_dir2_cos_fx = cos_ele2_fx; /*q15*/
    3715     3682308 :                 prev_ele_dir2_sin_fx = sin_ele2_fx; /*q15*/
    3716     3682308 :                 move16();
    3717     3682308 :                 move16();
    3718             :             }
    3719             :         } /* sf */
    3720             :     }     /* band */
    3721             : 
    3722       39626 :     return;
    3723             : }
    3724             : 
    3725             : /*-------------------------------------------------------------------*
    3726             :  * ivas_merge_masa_metadata()
    3727             :  *
    3728             :  *
    3729             :  *-------------------------------------------------------------------*/
    3730        3996 : void ivas_merge_masa_metadata_fx(
    3731             :     MASA_ENCODER_HANDLE hMasa,           /* i/o: MASA enc handle. source for MASA metadata and combined metadata will be here */
    3732             :     OMASA_SPATIAL_META_HANDLE hOMasaMeta /* i  : ISM-object metadata to be merged with the MASA metadata                      */
    3733             : )
    3734             : {
    3735             :     Word16 sf, band;
    3736             :     UWord8 numCodingBands;
    3737             :     UWord8 numDirections;
    3738             :     UWord8 numSf;
    3739             :     MASA_METADATA_HANDLE hMeta;
    3740             :     Word16 energyTimesRatioMASA_e[2];
    3741             :     Word16 total_diff_nrg_e;
    3742             :     Word16 energyMerged_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    3743             :     Word32 energyTimesRatioISM_fx; /*energyTimesRatioISM_e*/
    3744             :     Word16 energyTimesRatioISM_e;
    3745             :     Word32 energyTimesRatioMASA_fx[2]; /*energyTimesRatioMASA_e*/
    3746             :     Word32 total_diff_nrg_fx;
    3747             :     Word32 eneBand_fx; /*eneBand_e*/
    3748             :     Word16 eneBand_e;
    3749             :     Word32 energyMerged_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; /*energyMerged_e*/
    3750             :     Word32 temp1 /*temp1_e*/, temp2 /*temp2_e*/;
    3751             :     Word16 temp1_e, temp2_e;
    3752             : 
    3753        3996 :     numCodingBands = hMasa->config.numCodingBands;
    3754        3996 :     numDirections = hMasa->config.numberOfDirections;
    3755        3996 :     IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
    3756             :     {
    3757           0 :         numSf = 1;
    3758             :     }
    3759             :     ELSE
    3760             :     {
    3761        3996 :         numSf = 4;
    3762             :     }
    3763        3996 :     move16();
    3764        3996 :     move16();
    3765        3996 :     move16();
    3766        3996 :     hMeta = &( hMasa->masaMetadata );
    3767             : 
    3768       19980 :     FOR( sf = 0; sf < numSf; sf++ )
    3769             :     {
    3770      396000 :         FOR( band = 0; band < numCodingBands; band++ )
    3771             :         {
    3772             :             Word16 merge_dest;
    3773             :             Word32 dir_sum_fx; /*dir_sum_e*/
    3774             :             Word16 dir_sum_e;
    3775             :             UWord8 band_n_dirs;
    3776      380016 :             test();
    3777      380016 :             test();
    3778      380016 :             IF( EQ_16( numDirections, 1 ) || ( EQ_16( numDirections, 2 ) && hMasa->data.twoDirBands[band] == 0 ) )
    3779             :             {
    3780      380016 :                 band_n_dirs = 1;
    3781             :             }
    3782             :             ELSE
    3783             :             {
    3784           0 :                 band_n_dirs = 2;
    3785             :             }
    3786      380016 :             move16();
    3787             : 
    3788             :             /* Compute energies */
    3789      380016 :             eneBand_fx = hMasa->data.energy_fx[sf][band];
    3790      380016 :             eneBand_e = hMasa->data.energy_e[sf][band];
    3791      380016 :             move32();
    3792      380016 :             move16();
    3793      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] );
    3794      380016 :             move32();
    3795             : 
    3796             :             /* Compute weights */
    3797      380016 :             energyTimesRatioMASA_fx[0] = Mpy_32_32( eneBand_fx, hMeta->directional_meta[0].energy_ratio_fx[sf][band] );
    3798      380016 :             energyTimesRatioMASA_e[0] = add( eneBand_e, 1 );
    3799      380016 :             move32();
    3800      380016 :             move16();
    3801      380016 :             IF( EQ_16( band_n_dirs, 2 ) )
    3802             :             {
    3803           0 :                 energyTimesRatioMASA_fx[1] = Mpy_32_32( eneBand_fx, hMeta->directional_meta[1].energy_ratio_fx[sf][band] ); // energyTimesRatioMASA_e
    3804           0 :                 energyTimesRatioMASA_e[1] = add( eneBand_e, 1 );
    3805             :             }
    3806             :             ELSE
    3807             :             {
    3808      380016 :                 energyTimesRatioMASA_fx[1] = 0; // energyTimesRatioMASA_e
    3809      380016 :                 energyTimesRatioMASA_e[1] = 0;
    3810             :             }
    3811      380016 :             move32();
    3812      380016 :             move16();
    3813             : 
    3814             :             /* target is original MASA diffuseness */
    3815      380016 :             total_diff_nrg_fx = Mpy_32_32( eneBand_fx, hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] ); // total_diff_nrg_e
    3816      380016 :             total_diff_nrg_e = add( eneBand_e, 1 );
    3817             : 
    3818             :             /* criterion is mean of ISM ratio and new ratio */
    3819      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]*/
    3820      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] )*/
    3821      380016 :             temp2_e = add( temp2_e, sub( total_diff_nrg_e, temp1_e ) );
    3822      380016 :             IF( temp2_e < 0 )
    3823             :             {
    3824      305014 :                 temp2 = L_shl( temp2, temp2_e );
    3825      305014 :                 temp2_e = 0;
    3826      305014 :                 move16();
    3827             :             }
    3828      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] ) )*/
    3829      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] ) )*/
    3830      380016 :             energyTimesRatioISM_fx = Mpy_32_32( L_shr( temp2, 1 ), hMasa->data.hOmasaData->energy_ism_fx[sf][band] );                   /*energyTimesRatioISM_e*/
    3831      380016 :             energyTimesRatioISM_e = add( temp2_e, hMasa->data.hOmasaData->energy_ism_fx_e[sf][band] );
    3832             :             /*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];*/
    3833             : 
    3834             :             /* Determine combined metadata based on the weights */
    3835      380016 :             merge_dest = -1;
    3836      380016 :             move16();
    3837      380016 :             test();
    3838      380016 :             test();
    3839      380016 :             test();
    3840      380016 :             test();
    3841      380016 :             test();
    3842      380016 :             test();
    3843      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 ) ) ||
    3844             :                 ( 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 ) ) )
    3845             :             {
    3846             :                 /* 1dir and ISM the most energetic, or 2dir and ISM the more energetic than MASA1 */
    3847      144457 :                 merge_dest = 0;
    3848             :             }
    3849      235559 :             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 ) )
    3850             :             {
    3851             :                 /* 2dir and ISM the most energetic and MASA2 the least energetic */
    3852           0 :                 merge_dest = 1;
    3853             :             }
    3854      380016 :             move16();
    3855             : 
    3856      380016 :             IF( merge_dest >= 0 ) /* replace one MASA with ISM */
    3857             :             {
    3858      144457 :                 hMeta->directional_meta[merge_dest].azimuth_fx[sf][band] = hOMasaMeta->directional_meta[0].azimuth_fx[sf][band];     /*q22*/
    3859      144457 :                 hMeta->directional_meta[merge_dest].elevation_fx[sf][band] = hOMasaMeta->directional_meta[0].elevation_fx[sf][band]; /*q22*/
    3860      144457 :                 move32();
    3861      144457 :                 move32();
    3862             :                 /* limit with the earlier direct-energy ratio */
    3863      144457 :                 dir_sum_fx = temp2; /* new dir ratio */
    3864      144457 :                 dir_sum_e = temp2_e;
    3865      144457 :                 move32();
    3866      144457 :                 move16();
    3867             :                 /*dir_sum = 1.0f - total_diff_nrg / ( EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band] )*/
    3868      144457 :                 IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( dir_sum_fx, dir_sum_e, hOMasaMeta->directional_meta[0].energy_ratio_fx[sf][band], 1 ), -1 ) )
    3869             :                 {
    3870           0 :                     hMeta->directional_meta[merge_dest].energy_ratio_fx[sf][band] = L_shl( dir_sum_fx, sub( dir_sum_e, 1 ) ); /*scaling to Q30*/
    3871             :                 }
    3872             :                 ELSE
    3873             :                 {
    3874      144457 :                     hMeta->directional_meta[merge_dest].energy_ratio_fx[sf][band] = hOMasaMeta->directional_meta[0].energy_ratio_fx[sf][band]; /*q30*/
    3875      144457 :                     move32();
    3876             :                 }
    3877             :                 /* clip with original ISM dir */
    3878      144457 :                 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*/
    3879      144457 :                 move32();
    3880      144457 :                 move32(); /*hMeta->directional_meta[merge_dest].energy_ratio_fx*/
    3881             : 
    3882      144457 :                 IF( hMasa->config.useCoherence )
    3883             :                 {
    3884           0 :                     hMeta->directional_meta[merge_dest].spread_coherence_fx[sf][band] = hOMasaMeta->directional_meta[0].spread_coherence_fx[sf][band]; /*q15*/
    3885           0 :                     hMeta->common_meta.surround_coherence_fx[sf][band] = hOMasaMeta->common_meta.surround_coherence_fx[sf][band];                      /*q15*/
    3886           0 :                     move16();
    3887           0 :                     move16();
    3888             :                 }
    3889             : 
    3890             :                 /* recompute direct energy ratios to match the diffuse ratio */
    3891             :                 Word32 direct_quota_fx, direct_scaler_fx;
    3892             :                 Word16 direct_scaler_e;
    3893      144457 :                 direct_quota_fx = L_sub( ONE_IN_Q30, hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] );
    3894      144457 :                 IF( EQ_16( band_n_dirs, 1 ) )
    3895             :                 {
    3896      144457 :                     hMeta->directional_meta[0].energy_ratio_fx[sf][band] = direct_quota_fx; /*q30*/
    3897      144457 :                     move32();
    3898             :                 }
    3899             :                 ELSE
    3900             :                 {
    3901           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*/
    3902           0 :                     direct_scaler_fx = BASOP_Util_Divide3232_Scale( direct_quota_fx, L_add( EPSILON_FX, dir_sum_fx ), &direct_scaler_e );
    3903           0 :                     direct_scaler_fx = L_shl( direct_scaler_fx, direct_scaler_e ); /*q31*/
    3904           0 :                     direct_scaler_e = 0;
    3905           0 :                     move16();
    3906           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*/
    3907           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*/
    3908           0 :                     move32();
    3909           0 :                     move32();
    3910             :                 }
    3911             :             }
    3912             :         }
    3913             :     }
    3914             : 
    3915       19980 :     FOR( sf = 0; sf < numSf; sf++ )
    3916             :     {
    3917      396000 :         FOR( band = 0; band < numCodingBands; band++ )
    3918             :         {
    3919      380016 :             hMasa->data.energy_fx[sf][band] = energyMerged_fx[sf][band];
    3920      380016 :             hMasa->data.energy_e[sf][band] = energyMerged_e[sf][band];
    3921      380016 :             move32();
    3922      380016 :             move16();
    3923             :         }
    3924             :     }
    3925             : 
    3926        3996 :     return;
    3927             : }
    3928       30442 : static void quantize_ratio_ism_vector_ivas_fx(
    3929             :     const Word16 *ratio_ism, /* ratio_ism_e */
    3930             :     Word16 ratio_ism_e,
    3931             :     Word16 *idx, /* Q0 */
    3932             :     const Word16 nchan_ism,
    3933             :     const Word32 masa_to_total_energy_ratio,
    3934             :     const Word16 idx_sep_object )
    3935             : {
    3936             :     Word16 i, j, best_i, best_i2;
    3937             :     Word16 dist, div, tmp, dist2, best_dist, temp, temp_e, tmp_e, idx_e, best_dist_e, dist_e, dist2_e;
    3938             :     Word16 part_idx_sum, max_sum_idx;
    3939             :     Word16 ratio_ism_loc[MAX_NUM_OBJECTS];
    3940             :     Word16 no_ism_loc;
    3941             : 
    3942       30442 :     max_sum_idx = sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 );
    3943             : 
    3944       30442 :     test();
    3945       30442 :     IF( GT_16( idx_sep_object, -1 ) )
    3946             :     {
    3947       30442 :         temp = BASOP_Util_Divide1616_Scale( 1, max_sum_idx, &temp_e );
    3948       30442 :         BASOP_Util_Add_MantExp( ratio_ism[idx_sep_object], ratio_ism_e, negate( temp ), temp_e, &tmp );
    3949             : 
    3950       30442 :         test();
    3951       30442 :         IF( tmp < 0 )
    3952             :         {
    3953             :             /* take it out from quantize function  */
    3954       28839 :             Copy( ratio_ism, ratio_ism_loc, idx_sep_object ); // Q(15 - ratio_ism_e)
    3955       28839 :             Copy( &ratio_ism[idx_sep_object + 1], &ratio_ism_loc[idx_sep_object], nchan_ism - idx_sep_object - 1 );
    3956       28839 :             no_ism_loc = sub( nchan_ism, 1 );
    3957             :         }
    3958             :         ELSE
    3959             :         {
    3960        1603 :             no_ism_loc = nchan_ism;
    3961        1603 :             move16();
    3962        1603 :             Copy( ratio_ism, ratio_ism_loc, nchan_ism );
    3963             :         }
    3964             :     }
    3965             :     ELSE
    3966             :     {
    3967           0 :         no_ism_loc = nchan_ism;
    3968           0 :         move16();
    3969           0 :         Copy( ratio_ism, ratio_ism_loc, nchan_ism );
    3970             :     }
    3971             : 
    3972       30442 :     test();
    3973       30442 :     IF( GT_16( nchan_ism, 1 ) )
    3974             :     {
    3975       30442 :         test();
    3976       30442 :         IF( GE_32( masa_to_total_energy_ratio, MASA2TOTAL_THR_Q30 ) )
    3977             :         {
    3978        3593 :             distribute_evenly_ism_fx( idx, max_sum_idx, nchan_ism );
    3979             :         }
    3980             :         ELSE
    3981             :         {
    3982       26849 :             test();
    3983       26849 :             IF( GT_16( no_ism_loc, 1 ) )
    3984             :             {
    3985             : 
    3986       26135 :                 dist = 0;
    3987       26135 :                 dist_e = 0;
    3988       26135 :                 div = div_s( 1, max_sum_idx ); // Q15
    3989       26135 :                 move16();
    3990       26135 :                 move16();
    3991             : 
    3992       26135 :                 part_idx_sum = 0;
    3993       26135 :                 move16();
    3994             : 
    3995       95154 :                 FOR( i = 0; i < no_ism_loc; i++ )
    3996             :                 {
    3997       69019 :                     idx[i] = extract_l( L_shr( L_mult0( ratio_ism_loc[i], max_sum_idx ), sub( 15, ratio_ism_e ) ) ); // Q0
    3998       69019 :                     move16();
    3999       69019 :                     part_idx_sum = add( part_idx_sum, idx[i] );
    4000             : 
    4001       69019 :                     tmp_e = BASOP_Util_Add_MantExp( ratio_ism_loc[i], ratio_ism_e, negate( imult1616( idx[i], div ) ), 0, &tmp ); // tmp_e
    4002       69019 :                     dist_e = BASOP_Util_Add_MantExp( dist, dist_e, mult( tmp, tmp ), add( tmp_e, tmp_e ), &dist );                // dist_e
    4003             :                 }
    4004             : 
    4005       26135 :                 best_dist = dist;
    4006       26135 :                 best_dist_e = dist_e;
    4007       26135 :                 best_i2 = -1;
    4008       26135 :                 move16();
    4009       26135 :                 move16();
    4010       26135 :                 move16();
    4011             : 
    4012       54125 :                 WHILE( ( part_idx_sum < max_sum_idx ) )
    4013             :                 {
    4014       27990 :                     best_i = -1;
    4015       27990 :                     move16();
    4016             :                     /* check which index to increase by 1 for a possible improvement */
    4017             : 
    4018      102694 :                     FOR( i = 0; i < no_ism_loc; i++ )
    4019             :                     {
    4020       74704 :                         idx[i] = add( idx[i], 1 );
    4021       74704 :                         move16();
    4022       74704 :                         dist2 = 0;
    4023       74704 :                         dist2_e = 0;
    4024       74704 :                         move16();
    4025       74704 :                         move16();
    4026             : 
    4027      282160 :                         FOR( j = 0; j < no_ism_loc; j++ )
    4028             :                         {
    4029      207456 :                             Word32 temp1 = L_mult( idx[i], div ); // Q : 15 + 0 + 1
    4030      207456 :                             Word16 temp1_n = norm_l( temp1 );
    4031      207456 :                             Word16 temp1_16 = extract_h( L_shl( temp1, temp1_n ) );                                                        // Q : Q + temp1_n - 16
    4032      207456 :                             tmp_e = BASOP_Util_Add_MantExp( ratio_ism_loc[i], ratio_ism_e, negate( temp1_16 ), sub( 15, temp1_n ), &tmp ); // tmp_e
    4033      207456 :                             dist2_e = BASOP_Util_Add_MantExp( dist2, dist2_e, mult_sat( tmp, tmp ), add( tmp_e, tmp_e ), &dist2 );         // dist_e
    4034             :                         }
    4035             : 
    4036       74704 :                         BASOP_Util_Add_MantExp( dist2, dist2_e, negate( best_dist ), best_dist_e, &tmp );
    4037       74704 :                         test();
    4038       74704 :                         IF( tmp < 0 )
    4039             :                         {
    4040       22940 :                             best_i2 = best_i;
    4041       22940 :                             best_i = i;
    4042       22940 :                             best_dist = dist2;
    4043       22940 :                             best_dist_e = dist2_e;
    4044       22940 :                             move16();
    4045       22940 :                             move16();
    4046       22940 :                             move16();
    4047       22940 :                             move16();
    4048             :                         }
    4049       74704 :                         idx[i] = sub( idx[i], 1 );
    4050       74704 :                         move16();
    4051             :                     }
    4052             : 
    4053       27990 :                     test();
    4054       27990 :                     IF( GT_16( best_i, -1 ) )
    4055             :                     {
    4056       21734 :                         idx[best_i] = add( idx[best_i], 1 );
    4057       21734 :                         move16();
    4058       21734 :                         part_idx_sum = add( part_idx_sum, 1 );
    4059             :                     }
    4060             :                     ELSE
    4061             :                     {
    4062        6256 :                         test();
    4063        6256 :                         IF( GT_16( best_i2, -1 ) )
    4064             :                         {
    4065        1043 :                             idx[best_i2] = add( idx[best_i2], 1 );
    4066        1043 :                             move16();
    4067        1043 :                             part_idx_sum = add( part_idx_sum, 1 );
    4068             :                         }
    4069             :                         ELSE
    4070             :                         {
    4071        5213 :                             idx[no_ism_loc - 1] = add( idx[no_ism_loc - 1], sub( max_sum_idx, part_idx_sum ) );
    4072        5213 :                             move16();
    4073        5213 :                             part_idx_sum = max_sum_idx;
    4074        5213 :                             move16();
    4075             :                         }
    4076             :                     }
    4077             :                 }
    4078       26135 :                 assert( sum_s( idx, no_ism_loc ) == max_sum_idx );
    4079             :             }
    4080             :             ELSE
    4081             :             {
    4082         714 :                 idx[0] = max_sum_idx;
    4083         714 :                 move16();
    4084             :             }
    4085             : 
    4086       26849 :             test();
    4087       26849 :             IF( LT_16( no_ism_loc, nchan_ism ) )
    4088             :             {
    4089             :                 /*  insert back the ratio of the separated object  */
    4090       70971 :                 FOR( i = nchan_ism - 1; i > idx_sep_object; i-- )
    4091             :                 {
    4092       45655 :                     idx[i] = idx[i - 1];
    4093       45655 :                     move16();
    4094             :                 }
    4095       25316 :                 idx[idx_sep_object] = 0;
    4096       25316 :                 move16();
    4097             :             }
    4098             :         }
    4099             :     }
    4100             :     ELSE
    4101             :     {
    4102             :         // idx[0] = (int16_t) ( ( ratio_ism[0] ) * ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) + 0.5f );
    4103           0 :         tmp = imult1616( ratio_ism[0], sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 ) ); // tmp_e
    4104           0 :         tmp_e = ratio_ism_e;
    4105           0 :         move16();
    4106           0 :         idx_e = BASOP_Util_Add_MantExp( tmp, tmp_e, 16384 /* 0.5 in Q15 */, 0, &idx[0] ); // idx_e
    4107           0 :         idx[0] = shl( idx[0], sub( idx_e, 15 ) );                                         // Q0
    4108           0 :         move16();
    4109             :     }
    4110             : 
    4111       30442 :     return;
    4112             : }
    4113        6665 : static Word16 index_slice_enum_fx(
    4114             :     const Word16 *ratio_ism_idx,
    4115             :     const Word16 nchan_ism )
    4116             : {
    4117             :     Word16 i;
    4118             :     Word16 x, index;
    4119             :     Word16 base;
    4120             : 
    4121        6665 :     IF( EQ_16( nchan_ism, 2 ) )
    4122             :     {
    4123         308 :         index = ratio_ism_idx[0];
    4124         308 :         move16();
    4125             :     }
    4126             :     ELSE
    4127             :     {
    4128        6357 :         x = ratio_ism_idx[nchan_ism - 2];
    4129        6357 :         base = 10;
    4130        6357 :         move16();
    4131        6357 :         move16();
    4132       17248 :         FOR( i = nchan_ism - 3; i >= 0; i-- )
    4133             :         {
    4134       10891 :             x = add( x, imult1616( ratio_ism_idx[i], base ) );
    4135       10891 :             base = imult1616( base, 10 );
    4136             :         }
    4137             : 
    4138        6357 :         index = 0;
    4139        6357 :         i = 0;
    4140        6357 :         move16();
    4141        6357 :         move16();
    4142      928866 :         WHILE( LE_16( i, x ) )
    4143             :         {
    4144      922509 :             IF( valid_ratio_index_fx( i, 7, nchan_ism - 1 ) )
    4145             :             {
    4146      252718 :                 index = add( index, 1 );
    4147             :             }
    4148      922509 :             i = add( i, 1 );
    4149             :         }
    4150        6357 :         index = sub( index, 1 );
    4151             :     }
    4152             : 
    4153        6665 :     return index;
    4154             : }
    4155             : 
    4156       61502 : static void transform_difference_index_ivas_fx(
    4157             :     const Word16 *diff_idx,
    4158             :     Word16 *idx,
    4159             :     const Word16 len )
    4160             : {
    4161             :     Word16 i;
    4162      189070 :     FOR( i = 0; i < len; i++ )
    4163             :     {
    4164      127568 :         IF( diff_idx[i] <= 0 )
    4165             :         {
    4166       99618 :             idx[i] = negate( shl( diff_idx[i], 1 ) );
    4167       99618 :             move16();
    4168             :         }
    4169             :         ELSE
    4170             :         {
    4171       27950 :             idx[i] = sub( shl( diff_idx[i], 1 ), 1 );
    4172       27950 :             move16();
    4173             :         }
    4174             :     }
    4175             : 
    4176       61502 :     return;
    4177             : }
    4178       20139 : static void transform_index_and_GR_encode_ivas_fx(
    4179             :     Word16 *diff_idx,         /* i  : differenc eindex to encode    */
    4180             :     const Word16 len,         /* i  : input length                  */
    4181             :     const Word16 GR_order,    /* i  : GR order                      */
    4182             :     BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle     */
    4183             : )
    4184             : {
    4185             :     Word16 i;
    4186             :     Word16 idx[IVAS_MAX_NUM_OBJECTS];
    4187             : 
    4188             :     /* transform difference index into positive */
    4189       20139 :     transform_difference_index_ivas_fx( diff_idx, idx, len );
    4190             : 
    4191             :     /* GR encoding */
    4192       61030 :     FOR( i = 0; i < len; i++ )
    4193             :     {
    4194       40891 :         ivas_qmetadata_encode_extended_gr_fx( hMetaData, idx[i], 100, GR_order );
    4195             :     }
    4196             : 
    4197       20139 :     return;
    4198             : }
    4199        1862 : static Word16 try_differential_fx(
    4200             :     const Word16 numCodingBands,
    4201             :     const Word32 *masa_to_total_energy_ratio, /* Q30 */
    4202             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
    4203             :     const Word16 nchan_ism,
    4204             :     const Word16 bits_index,
    4205             :     Word16 *p_b_signif )
    4206             : {
    4207             :     Word16 b, i;
    4208             :     Word16 nbits0;
    4209             :     Word16 b_signif;
    4210             :     Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
    4211             :     Word16 diff_idx[MAX_NUM_OBJECTS];
    4212             : 
    4213        1862 :     b_signif = 0;
    4214        1862 :     move16();
    4215        2162 :     WHILE( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR_Q30 ) )
    4216             :     {
    4217         300 :         test();
    4218         300 :         b_signif = add( b_signif, 1 );
    4219             :     }
    4220             : 
    4221        1862 :     nbits0 = 0;
    4222        1862 :     move16();
    4223             : 
    4224        1862 :     IF( LT_16( b_signif, numCodingBands ) )
    4225             :     {
    4226        1806 :         nbits0 = bits_index;
    4227        1806 :         move16();
    4228        1806 :         Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
    4229             : 
    4230       11560 :         FOR( b = b_signif + 1; b < numCodingBands; b++ )
    4231             :         {
    4232        9754 :             IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4233             :             {
    4234        8627 :                 v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
    4235        8627 :                 Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
    4236             : 
    4237             :                 /* transform difference index into positive */
    4238        8627 :                 transform_difference_index_ivas_fx( diff_idx, diff_idx, sub( nchan_ism, 1 ) );
    4239             : 
    4240             :                 /* GR encoding */
    4241       30122 :                 FOR( i = 0; i < nchan_ism - 1; i++ )
    4242             :                 {
    4243       21495 :                     nbits0 = add( nbits0, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 0 ) );
    4244             :                 }
    4245             :             }
    4246             :         }
    4247             :     }
    4248        1862 :     *p_b_signif = b_signif;
    4249        1862 :     move16();
    4250             : 
    4251        1862 :     return nbits0;
    4252             : }
    4253             : 
    4254         666 : static void differential_coding_first_subframe_ivas_fx(
    4255             :     BSTR_ENC_HANDLE hMetaData,
    4256             :     const Word32 *masa_to_total_energy_ratio, // Q30
    4257             :     const Word16 b_signif,
    4258             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
    4259             :     const Word16 nchan_ism,
    4260             :     const Word16 numCodingBands,
    4261             :     const Word16 bits_index )
    4262             : {
    4263             :     Word16 index, b;
    4264             :     Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
    4265             :     Word16 diff_idx[MAX_NUM_OBJECTS];
    4266             : 
    4267             :     /* differential encoding*/
    4268         666 :     push_next_indice( hMetaData, 0, 1 );
    4269             : 
    4270         666 :     IF( LT_16( b_signif, numCodingBands ) )
    4271             :     {
    4272         666 :         index = index_slice_enum_fx( ratio_ism_idx[b_signif], nchan_ism );
    4273         666 :         push_next_indice( hMetaData, index, bits_index );
    4274             : 
    4275         666 :         Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
    4276             : 
    4277        4892 :         FOR( b = b_signif + 1; b < numCodingBands; b++ )
    4278             :         {
    4279        4226 :             IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4280             :             {
    4281        3768 :                 v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
    4282        3768 :                 Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
    4283             : 
    4284             :                 /* transform difference index into positive */
    4285        3768 :                 transform_index_and_GR_encode_ivas_fx( diff_idx, sub( nchan_ism, 1 ), 0, hMetaData );
    4286             :             }
    4287             :         }
    4288             :     }
    4289             : 
    4290         666 :     return;
    4291             : }
    4292        1140 : static void independent_coding_ratio_ism_idx_fx(
    4293             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* i  : ISM ratios                */
    4294             :     const Word32 *masa_to_total_energy_ratio,                    /* i  : MASA to total ratios, Q30 */
    4295             :     const Word16 nchan_ism,                                      /* i  : number of objects         */
    4296             :     const Word16 numCodingBands,                                 /* i  : number of subbands        */
    4297             :     const Word16 bits_index,                                     /* i  : number of bits per index  */
    4298             :     BSTR_ENC_HANDLE hMetaData                                    /* i/o: metadata bitstream handle */
    4299             : )
    4300             : {
    4301             :     Word16 b, index;
    4302             : 
    4303        7844 :     FOR( b = 0; b < numCodingBands; b++ )
    4304             :     {
    4305        6704 :         IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4306             :         {
    4307        5999 :             index = index_slice_enum_fx( ratio_ism_idx[b], nchan_ism );
    4308        5999 :             push_next_indice( hMetaData, index, bits_index );
    4309             :         }
    4310             :     }
    4311             : 
    4312        1140 :     return;
    4313             : }
    4314             : 
    4315       29124 : static void remove_sep_obj_fx(
    4316             :     Word16 *diff_idx,        /* i/o: array of difference of indexes                        */
    4317             :     const Word16 nchan_ism,  /* i  : number of objects                                     */
    4318             :     const Word16 idx_sep_obj /* i  : index of separated object, to be taken out of array   */
    4319             : )
    4320             : {
    4321             :     Word16 i;
    4322             : 
    4323       88197 :     FOR( i = idx_sep_obj; i < nchan_ism - 1; i++ )
    4324             :     {
    4325       59073 :         diff_idx[i] = diff_idx[i + 1];
    4326       59073 :         move16();
    4327             :     }
    4328             : 
    4329       29124 :     return;
    4330             : }
    4331             : 
    4332       32736 : static void estimate_bits_subband_ism_ratio_fx(
    4333             :     const Word16 *ratio_ism_idx,
    4334             :     const Word16 *ratio_ism_idx_ref, /* ( i/o ) */
    4335             :     const Word16 nchan_ism,
    4336             :     const Word16 shift_one,
    4337             :     const Word16 idx_sep_obj,
    4338             :     Word16 *p_nbits0,
    4339             :     Word16 *p_nbits1 )
    4340             : {
    4341             :     Word16 diff_idx[MAX_NUM_OBJECTS];
    4342             :     Word16 nbits0, nbits1;
    4343             :     Word16 i;
    4344             : 
    4345       32736 :     nbits0 = 0;
    4346       32736 :     nbits1 = 0;
    4347       32736 :     move16();
    4348       32736 :     move16();
    4349             : 
    4350             :     /* take difference with respect to previous subframe */
    4351       32736 :     v_sub_s16_fx( ratio_ism_idx, ratio_ism_idx_ref, diff_idx, nchan_ism );
    4352             : 
    4353       32736 :     IF( shift_one )
    4354             :     {
    4355       19416 :         remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj );
    4356             :     }
    4357             : 
    4358             :     /* transform difference index into positive */
    4359       32736 :     transform_difference_index_ivas_fx( diff_idx, diff_idx, sub( sub( nchan_ism, 1 ), shift_one ) );
    4360             : 
    4361             :     /* GR encoding */
    4362       97918 :     FOR( i = 0; i < nchan_ism - 1 - shift_one; i++ )
    4363             :     {
    4364       65182 :         nbits0 = add( nbits0, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 0 ) );
    4365       65182 :         nbits1 = add( nbits1, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 1 ) );
    4366             :     }
    4367             : 
    4368       32736 :     *p_nbits0 = nbits0;
    4369       32736 :     *p_nbits1 = nbits1;
    4370       32736 :     move16();
    4371       32736 :     move16();
    4372             : 
    4373       32736 :     return;
    4374             : }
    4375             : 
    4376        5636 : static Word16 encode_ratio_ism_subframe_fx(
    4377             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
    4378             :     const Word16 nchan_ism,
    4379             :     const UWord8 numCodingBands,
    4380             :     const Word16 sf,
    4381             :     Word16 ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
    4382             :     BSTR_ENC_HANDLE hMetaData,
    4383             :     const Word32 *masa_to_total_energy_ratio, /* Q30 */
    4384             :     const Word16 shift_one,
    4385             :     const Word16 idx_separated_obj )
    4386             : {
    4387             :     Word16 b, b_signif;
    4388             :     Word16 diff_idx[MAX_NUM_OBJECTS];
    4389             :     Word16 nbits, nbits0, nbits1, GR_order, GR_order_sb;
    4390             :     Word16 differential_subframe;
    4391             :     Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
    4392             :     Word16 bits_index;
    4393             :     Word16 nbits00, nbits11;
    4394             :     Word16 idx_sep_obj_local;
    4395             : 
    4396        5636 :     idx_sep_obj_local = idx_separated_obj;
    4397        5636 :     move16();
    4398        5636 :     IF( GT_16( idx_separated_obj, -1 ) )
    4399             :     {
    4400        5636 :         if ( EQ_16( idx_separated_obj, sub( nchan_ism, 1 ) ) )
    4401             :         {
    4402         803 :             idx_sep_obj_local = 0;
    4403         803 :             move16();
    4404             :         }
    4405             :     }
    4406        5636 :     nbits = 0;
    4407        5636 :     nbits0 = 0;
    4408        5636 :     nbits1 = 0;
    4409        5636 :     move16();
    4410        5636 :     move16();
    4411        5636 :     move16();
    4412             : 
    4413        5636 :     differential_subframe = 1; /* the differences are taken with respect to previous subframe */
    4414        5636 :     move16();
    4415             : 
    4416             :     /* first subframe */
    4417        5636 :     bits_index = 0;
    4418        5636 :     move16();
    4419        5636 :     IF( sf == 0 )
    4420             :     {
    4421        1862 :         bits_index = bits_index_ism_ratio_fx( nchan_ism );
    4422             : 
    4423        1862 :         nbits = 0;
    4424        1862 :         move16();
    4425       13722 :         FOR( b = 0; b < numCodingBands; b++ )
    4426             :         {
    4427       11860 :             IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4428             :             {
    4429       10433 :                 nbits = add( nbits, bits_index );
    4430             :             }
    4431             :         }
    4432             : 
    4433        1862 :         nbits0 = try_differential_fx( numCodingBands, masa_to_total_energy_ratio, ratio_ism_idx, nchan_ism, bits_index, &b_signif );
    4434             : 
    4435        1862 :         test();
    4436        1862 :         IF( LE_16( nbits, nbits0 ) && nbits > 0 )
    4437             :         {
    4438             :             /* independent encoding */
    4439        1140 :             push_next_indice( hMetaData, 1, 1 );
    4440        1140 :             independent_coding_ratio_ism_idx_fx( ratio_ism_idx, masa_to_total_energy_ratio, nchan_ism, numCodingBands, bits_index, hMetaData );
    4441        1140 :             nbits = add( nbits, 1 );
    4442             :         }
    4443             :         ELSE
    4444             :         {
    4445         722 :             IF( nbits > 0 )
    4446             :             {
    4447         666 :                 differential_coding_first_subframe_ivas_fx( hMetaData, masa_to_total_energy_ratio, b_signif, ratio_ism_idx, nchan_ism, numCodingBands, bits_index );
    4448             : 
    4449         666 :                 nbits = add( nbits0, 1 );
    4450             :             }
    4451             :         }
    4452             :     }
    4453             :     ELSE
    4454             :     {
    4455             :         /* not first subframe */
    4456        3774 :         test();
    4457        3774 :         IF( EQ_16( shift_one, 1 ) && EQ_16( nchan_ism, 2 ) )
    4458             :         {
    4459          45 :             nbits = 0;
    4460          45 :             move16();
    4461             :         }
    4462             :         ELSE
    4463             :         {
    4464        3729 :             nbits0 = 0;
    4465        3729 :             nbits1 = 0;
    4466        3729 :             move16();
    4467        3729 :             move16();
    4468             : 
    4469       22266 :             FOR( b = 0; b < numCodingBands; b++ )
    4470             :             {
    4471       18537 :                 IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4472             :                 {
    4473       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 );
    4474       16371 :                     nbits0 = add( nbits0, nbits00 );
    4475       16371 :                     nbits1 = add( nbits1, nbits11 );
    4476             :                 }
    4477             :             }
    4478        3729 :             IF( LT_16( nbits0, nbits1 ) )
    4479             :             {
    4480        2691 :                 GR_order = 0;
    4481        2691 :                 nbits = nbits0;
    4482        2691 :                 move16();
    4483        2691 :                 move16();
    4484             :             }
    4485             :             ELSE
    4486             :             {
    4487        1038 :                 GR_order = 1;
    4488        1038 :                 nbits = nbits1;
    4489        1038 :                 move16();
    4490        1038 :                 move16();
    4491             :             }
    4492             : 
    4493        3729 :             IF( GT_16( numCodingBands, 1 ) )
    4494             :             {
    4495             :                 /* try the difference from subband to subband; first subband is compared to previous subframe first subband*/
    4496             :                 /* take difference with respect to previous subframe only for first subband */
    4497        3702 :                 nbits0 = 0;
    4498        3702 :                 nbits1 = 0;
    4499        3702 :                 b_signif = 0;
    4500        3702 :                 move16();
    4501        3702 :                 move16();
    4502        3702 :                 move16();
    4503        3963 :                 WHILE( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR_Q30 ) )
    4504             :                 {
    4505         261 :                     test();
    4506         261 :                     b_signif = add( b_signif, 1 );
    4507             :                 }
    4508             : 
    4509        3702 :                 IF( LT_16( b_signif, numCodingBands ) )
    4510             :                 {
    4511        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 );
    4512             : 
    4513        3690 :                     Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
    4514             : 
    4515       18249 :                     FOR( b = b_signif + 1; b < numCodingBands; b++ )
    4516             :                     {
    4517       14559 :                         IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4518             :                         {
    4519       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 );
    4520       12675 :                             nbits0 = add( nbits0, nbits00 );
    4521       12675 :                             nbits1 = add( nbits1, nbits11 );
    4522       12675 :                             Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
    4523             :                         }
    4524             :                     }
    4525             : 
    4526        3690 :                     IF( LT_16( nbits0, nbits1 ) )
    4527             :                     {
    4528         529 :                         GR_order_sb = 0;
    4529         529 :                         move16();
    4530             :                     }
    4531             :                     ELSE
    4532             :                     {
    4533        3161 :                         GR_order_sb = 1;
    4534        3161 :                         nbits0 = nbits1;
    4535        3161 :                         move16();
    4536        3161 :                         move16();
    4537             :                     }
    4538             : 
    4539        3690 :                     IF( LT_16( nbits0, nbits ) )
    4540             :                     {
    4541         343 :                         differential_subframe = 0;
    4542         343 :                         nbits = nbits0;
    4543         343 :                         GR_order = GR_order_sb;
    4544         343 :                         move16();
    4545         343 :                         move16();
    4546         343 :                         move16();
    4547             :                     }
    4548             : 
    4549        3690 :                     IF( nbits > 0 )
    4550             :                     {
    4551             :                         /* write prediction type */
    4552        3690 :                         push_next_indice( hMetaData, differential_subframe, 1 );
    4553             :                         /* write GR order */
    4554        3690 :                         push_next_indice( hMetaData, GR_order, 1 );
    4555        3690 :                         nbits = add( nbits, 1 ); /* for the prediction type */
    4556        3690 :                         nbits = add( nbits, 1 ); /* for GR_order */
    4557             : 
    4558             :                         /* write data */
    4559        3690 :                         IF( differential_subframe )
    4560             :                         {
    4561       20082 :                             FOR( b = 0; b < numCodingBands; b++ )
    4562             :                             {
    4563       16735 :                                 IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4564             :                                 {
    4565             :                                     /* take difference with respect to previous subframe */
    4566       14850 :                                     v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], diff_idx, nchan_ism );
    4567             : 
    4568       14850 :                                     IF( shift_one )
    4569             :                                     {
    4570        9289 :                                         remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
    4571             :                                     }
    4572             : 
    4573       14850 :                                     transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
    4574             :                                 }
    4575             :                             }
    4576             :                         }
    4577             :                         ELSE
    4578             :                         {
    4579         343 :                             v_sub_s16_fx( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], diff_idx, nchan_ism );
    4580             : 
    4581         343 :                             IF( shift_one )
    4582             :                             {
    4583          87 :                                 remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
    4584             :                             }
    4585             : 
    4586         343 :                             transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
    4587             : 
    4588         343 :                             Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, sub( nchan_ism, shift_one ) );
    4589             : 
    4590        1709 :                             FOR( b = b_signif + 1; b < numCodingBands; b++ )
    4591             :                             {
    4592             :                                 /* take difference with respect to previous subband */
    4593        1366 :                                 IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
    4594             :                                 {
    4595        1172 :                                     v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
    4596             : 
    4597        1172 :                                     IF( shift_one )
    4598             :                                     {
    4599         332 :                                         remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
    4600             :                                     }
    4601             : 
    4602        1172 :                                     transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
    4603             : 
    4604        1172 :                                     Copy( ratio_ism_idx[b], ratio_ism_idx_ref, sub( nchan_ism, shift_one ) );
    4605             :                                 }
    4606             :                             }
    4607             :                         }
    4608             :                     }
    4609             :                 }
    4610             :             }
    4611             :             ELSE
    4612             :             {
    4613             :                 /* only differential wrt previous subframe is possible  */
    4614             :                 /* write the differential to subframe case and no bit to signal the difference type */
    4615             : 
    4616          27 :                 IF( nbits > 0 )
    4617             :                 {
    4618             :                     /* write GR order */
    4619           6 :                     push_next_indice( hMetaData, GR_order, 1 );
    4620           6 :                     nbits = add( nbits, 1 ); /* for GR_order */
    4621             :                     /* write data */
    4622             :                     /* only one subband */
    4623           6 :                     IF( LT_32( masa_to_total_energy_ratio[0], MASA2TOTAL_THR_Q30 ) )
    4624             :                     {
    4625             :                         /* take difference with respect to previous subframe */
    4626           6 :                         v_sub_s16_fx( ratio_ism_idx[0], ratio_ism_idx_prev_sf[0], diff_idx, nchan_ism );
    4627             : 
    4628           6 :                         IF( shift_one )
    4629             :                         {
    4630           0 :                             remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
    4631             :                         }
    4632             : 
    4633           6 :                         transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
    4634             :                     }
    4635             :                 }
    4636             :             }
    4637             :         }
    4638             :     }
    4639             : 
    4640        5636 :     return nbits;
    4641             : }
    4642        1862 : static void ivas_encode_masaism_metadata_fx(
    4643             :     MASA_ENCODER_HANDLE hMasa,
    4644             :     IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle             */
    4645             :     BSTR_ENC_HANDLE hMetaData,        /* i/o: metadata bitstream handle     */
    4646             :     ISM_METADATA_HANDLE hIsmMeta[],   /* i/o: ISM metadata handles          */
    4647             :     const Word16 nchan_ism,           /* i  : number of ISM channels        */
    4648             :     const Word16 low_bitrate_mode,    /* i  : is low bitrate more? 1/0      */
    4649             :     const Word16 omasa_nbands,
    4650             :     const Word16 omasa_nblocks,
    4651             :     const Word16 idx_separated_object,
    4652             :     const Word16 ism_imp )
    4653             : {
    4654             :     Word16 sf, band;
    4655             :     UWord8 numCodingBands;
    4656             :     UWord8 numSf;
    4657             :     Word16 brange[2];
    4658             :     Word64 eneBand;
    4659             :     Word32 eneBand32;
    4660             :     Word16 eneBand_exp, shift;
    4661             :     Word16 bin;
    4662             :     Word16 obj;
    4663             :     Word16 bits_ism[MAX_NUM_OBJECTS];
    4664             :     UWord16 idx_sph;
    4665             :     Word32 theta_q, phi_q;
    4666             :     UWord16 index_theta, index_phi;
    4667             :     Word16 ratio_ism_fx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
    4668             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
    4669             :     Word32 energy_ism, energy_ism_ind[MAX_NUM_OBJECTS];
    4670             :     Word16 tmp, rotate, energy_ism_e, energy_ism_ind_e[MAX_NUM_OBJECTS];
    4671             :     Word16 n_ism_tmp, i;
    4672        1862 :     OMASA_ENCODER_DATA_HANDLE hOmasaData = hMasa->data.hOmasaData;
    4673             :     Word16 nbands_work;
    4674             :     Word32 L_tmp;
    4675             :     Word16 L_tmp_e;
    4676             : 
    4677             :     /* use the values from hQMetaData */
    4678        1862 :     numCodingBands = (UWord8) hQMetaData->q_direction->cfg.nbands;
    4679        1862 :     numSf = (Word8) hQMetaData->q_direction->cfg.nblocks;
    4680        1862 :     nbands_work = s_min( numCodingBands, omasa_nbands );
    4681        1862 :     move16();
    4682        1862 :     move16();
    4683        1862 :     IF( EQ_16( numCodingBands, 1 ) )
    4684             :     {
    4685         120 :         FOR( sf = 0; sf < numSf; sf++ )
    4686             :         {
    4687          96 :             L_tmp = 0;
    4688          96 :             L_tmp_e = 0;
    4689          96 :             move32();
    4690          96 :             move16();
    4691         576 :             FOR( i = 0; i < omasa_nbands; i++ )
    4692             :             {
    4693         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 );
    4694             :             }
    4695             :             /* if ( sum_f( hOmasaData->energy_ism[sf], omasa_nbands ) == 0.0f ) */
    4696          96 :             IF( L_tmp == 0 )
    4697             :             {
    4698           0 :                 hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30; // 1.0f in Q30
    4699           0 :                 move32();
    4700             :             }
    4701             :             ELSE
    4702             :             {
    4703          96 :                 brange[0] = hMasa->data.band_mapping[0];
    4704          96 :                 brange[1] = hMasa->data.band_mapping[omasa_nbands];
    4705          96 :                 eneBand = 0;
    4706          96 :                 move16();
    4707          96 :                 move16();
    4708          96 :                 move64();
    4709        2400 :                 FOR( bin = brange[0]; bin < brange[1]; bin++ )
    4710             :                 {
    4711        2304 :                     eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
    4712             :                 }
    4713          96 :                 shift = W_norm( eneBand );
    4714          96 :                 eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
    4715          96 :                 eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
    4716             : 
    4717          96 :                 energy_ism = 0;
    4718          96 :                 energy_ism_e = 0;
    4719          96 :                 move32();
    4720          96 :                 move16();
    4721         288 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4722             :                 {
    4723         192 :                     energy_ism_ind[obj] = 0;
    4724         192 :                     energy_ism_ind_e[obj] = 0;
    4725         192 :                     move32();
    4726         192 :                     move16();
    4727             :                 }
    4728             : 
    4729         576 :                 FOR( band = 0; band < omasa_nbands; band++ )
    4730             :                 {
    4731         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 );
    4732        1440 :                     FOR( obj = 0; obj < nchan_ism; obj++ )
    4733             :                     {
    4734             : 
    4735         960 :                         hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30; // 1.0f in Q30
    4736         960 :                         move32();
    4737             :                     }
    4738             :                 }
    4739             : 
    4740         288 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4741             :                 {
    4742         192 :                     hOmasaData->energy_ratio_ism_fx[sf][0][obj] = BASOP_Util_Divide3232_Scale_newton( energy_ism_ind[obj], energy_ism, &L_tmp_e );
    4743         192 :                     move32();
    4744         192 :                     L_tmp_e = add( L_tmp_e, sub( energy_ism_ind_e[obj], energy_ism_e ) );
    4745             :                     /* Scaling to Q30 */
    4746         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
    4747         192 :                     move32();
    4748             :                 }
    4749          96 :                 L_tmp = BASOP_Util_Add_Mant32Exp( eneBand32, eneBand_exp, energy_ism, energy_ism_e, &L_tmp_e );
    4750          96 :                 IF( L_tmp != 0 )
    4751             :                 {
    4752          96 :                     hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
    4753          96 :                     move32();
    4754          96 :                     tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
    4755             :                     /* Scaling to Q30 */
    4756          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
    4757          96 :                     move32();
    4758             :                 }
    4759             :                 ELSE
    4760             :                 {
    4761           0 :                     hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30;
    4762           0 :                     move32();
    4763             :                 }
    4764             :             }
    4765             :         }
    4766             :     }
    4767        1838 :     ELSE IF( EQ_16( numSf, 1 ) )
    4768             :     {
    4769        6270 :         FOR( band = 0; band < nbands_work; band++ )
    4770             :         {
    4771        5666 :             energy_ism = 0; /* ISM energy for current subband */ // energy_ism_e
    4772        5666 :             energy_ism_e = 0;                                    /* ISM energy for current subband */
    4773        5666 :             move32();
    4774        5666 :             move16();
    4775       24246 :             FOR( obj = 0; obj < nchan_ism; obj++ )
    4776             :             {
    4777       18580 :                 energy_ism_ind[obj] = 0;
    4778       18580 :                 energy_ism_ind_e[obj] = 0;
    4779       18580 :                 move32();
    4780       18580 :                 move16();
    4781             :             }
    4782       14722 :             FOR( sf = 0; sf < omasa_nblocks; sf++ )
    4783             :             {
    4784        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 );
    4785       34416 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4786             :                 {
    4787       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
    4788       25360 :                     L_tmp_e = add( 1, hOmasaData->energy_ism_fx_e[sf][band] );
    4789       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] );
    4790       25360 :                     move32();
    4791             :                 }
    4792             :             }
    4793             : 
    4794        5666 :             IF( energy_ism == 0 )
    4795             :             {
    4796           0 :                 hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30; // 1.0f in Q30
    4797           0 :                 move32();
    4798             :             }
    4799             :             ELSE
    4800             :             {
    4801       24246 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4802             :                 {
    4803       18580 :                     hOmasaData->energy_ratio_ism_fx[0][band][obj] = BASOP_Util_Divide3232_Scale_newton( energy_ism_ind[obj], energy_ism, &L_tmp_e );
    4804       18580 :                     move32();
    4805       18580 :                     L_tmp_e = add( L_tmp_e, sub( energy_ism_ind_e[obj], energy_ism_e ) );
    4806             :                     /* Scaling to Q30 */
    4807       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
    4808       18580 :                     move32();
    4809             :                 }
    4810        5666 :                 brange[0] = hMasa->data.band_mapping[band];
    4811        5666 :                 brange[1] = hMasa->data.band_mapping[band + 1];
    4812        5666 :                 move16();
    4813        5666 :                 move16();
    4814             : 
    4815        5666 :                 eneBand = 0;
    4816        5666 :                 move64();
    4817       14722 :                 FOR( sf = 0; sf < omasa_nblocks; sf++ )
    4818             :                 {
    4819       39748 :                     FOR( bin = brange[0]; bin < brange[1]; bin++ )
    4820             :                     {
    4821       30692 :                         eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
    4822             :                     }
    4823             :                 }
    4824        5666 :                 shift = W_norm( eneBand );
    4825        5666 :                 eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
    4826        5666 :                 eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
    4827             : 
    4828        5666 :                 L_tmp = BASOP_Util_Add_Mant32Exp( eneBand32, eneBand_exp, energy_ism, energy_ism_e, &L_tmp_e );
    4829        5666 :                 IF( L_tmp != 0 )
    4830             :                 {
    4831        5666 :                     hOmasaData->masa_to_total_energy_ratio_fx[0][band] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
    4832        5666 :                     move32();
    4833        5666 :                     tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
    4834             :                     /* Scaling to Q30 */
    4835        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
    4836        5666 :                     move32();
    4837             :                 }
    4838             :                 ELSE
    4839             :                 {
    4840           0 :                     hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30;
    4841           0 :                     move32();
    4842             :                 }
    4843             :             }
    4844             :         }
    4845         604 :         FOR( band = nbands_work; band < numCodingBands; band++ )
    4846             :         {
    4847           0 :             hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30;
    4848           0 :             move32();
    4849             : 
    4850           0 :             FOR( obj = 0; obj < nchan_ism; obj++ )
    4851             :             {
    4852           0 :                 hOmasaData->energy_ratio_ism_fx[0][band][obj] = hOmasaData->energy_ratio_ism_fx[0][nbands_work - 1][obj];
    4853           0 :                 move32();
    4854             :             }
    4855             :         }
    4856             :     }
    4857             :     ELSE
    4858             :     {
    4859        6170 :         FOR( sf = 0; sf < numSf; sf++ )
    4860             :         {
    4861       29616 :             FOR( band = 0; band < nbands_work; band++ )
    4862             :             {
    4863       24680 :                 IF( hOmasaData->energy_ism_fx[sf][band] == 0 )
    4864             :                 {
    4865           0 :                     hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
    4866           0 :                     move32();
    4867             :                 }
    4868             :                 ELSE
    4869             :                 {
    4870       24680 :                     brange[0] = hMasa->data.band_mapping[band];
    4871       24680 :                     brange[1] = hMasa->data.band_mapping[band + 1];
    4872       24680 :                     move16();
    4873       24680 :                     move16();
    4874             : 
    4875       24680 :                     eneBand = 0;
    4876       24680 :                     move64();
    4877      141656 :                     FOR( bin = brange[0]; bin < brange[1]; bin++ )
    4878             :                     {
    4879      116976 :                         eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
    4880             :                     }
    4881       24680 :                     shift = W_norm( eneBand );
    4882       24680 :                     eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
    4883       24680 :                     eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
    4884             : 
    4885       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 );
    4886       24680 :                     IF( L_tmp != 0 )
    4887             :                     {
    4888       24680 :                         hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
    4889       24680 :                         move32();
    4890       24680 :                         tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
    4891             :                         /* Scaling to Q30 */
    4892       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
    4893       24680 :                         move32();
    4894             :                     }
    4895             :                     ELSE
    4896             :                     {
    4897           0 :                         hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
    4898           0 :                         move32();
    4899             :                     }
    4900             :                 }
    4901             :             }
    4902        4936 :             FOR( band = nbands_work; band < numCodingBands; band++ )
    4903             :             {
    4904           0 :                 hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
    4905           0 :                 move32();
    4906             : 
    4907           0 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4908             :                 {
    4909           0 :                     hOmasaData->energy_ratio_ism_fx[sf][band][obj] = hOmasaData->energy_ratio_ism_fx[sf][nbands_work - 1][obj];
    4910           0 :                     move32();
    4911             :                 }
    4912             :             }
    4913             :         }
    4914             :     }
    4915             : 
    4916        1862 :     ivas_omasa_encode_masa_to_total_fx( hOmasaData->masa_to_total_energy_ratio_fx, hMetaData, low_bitrate_mode, numCodingBands, numSf );
    4917             : 
    4918             :     /* quantize ism_ratios */
    4919        1862 :     IF( GT_16( nchan_ism, 1 ) )
    4920             :     {
    4921        1862 :         rotate = 0;
    4922        1862 :         n_ism_tmp = 0;
    4923        1862 :         move16();
    4924        1862 :         move16();
    4925             : 
    4926        7498 :         FOR( sf = 0; sf < numSf; sf++ )
    4927             :         {
    4928       36078 :             FOR( band = 0; band < numCodingBands; band++ )
    4929             :             {
    4930      137614 :                 FOR( obj = 0; obj < nchan_ism; obj++ )
    4931             :                 {
    4932      107172 :                     assert( ( hOmasaData->energy_ratio_ism_fx[sf][band][obj] >= 0 ) && ( hOmasaData->energy_ratio_ism_fx[sf][band][obj] <= ONE_IN_Q30 ) );
    4933      107172 :                     ratio_ism_fx[band][obj] = extract_h( hOmasaData->energy_ratio_ism_fx[sf][band][obj] ); // Q14
    4934      107172 :                     move16();
    4935             :                 }
    4936             : 
    4937             :                 /* Quantize ISM ratios */
    4938       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 );
    4939             : 
    4940       30442 :                 test();
    4941       30442 :                 test();
    4942       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 ) )
    4943             :                 {
    4944          92 :                     i = 0;
    4945          92 :                     move16();
    4946         697 :                     WHILE( ratio_ism_idx[band][idx_separated_object] > 0 )
    4947             :                     {
    4948         605 :                         IF( NE_16( i, idx_separated_object ) )
    4949             :                         {
    4950         410 :                             ratio_ism_idx[band][i] = add( ratio_ism_idx[band][i], 1 );
    4951         410 :                             ratio_ism_idx[band][idx_separated_object] = sub( ratio_ism_idx[band][idx_separated_object], 1 );
    4952         410 :                             move16();
    4953         410 :                             move16();
    4954             :                         }
    4955         605 :                         i = add( i, 1 );
    4956         605 :                         if ( EQ_16( i, nchan_ism ) )
    4957             :                         {
    4958         138 :                             i = 0;
    4959         138 :                             move16();
    4960             :                         }
    4961             :                     }
    4962             :                 }
    4963             : 
    4964             :                 /* reconstructed values */
    4965       30442 :                 reconstruct_ism_ratios_fx( ratio_ism_idx[band], nchan_ism, STEP_PARAM_ISM_POW_RATIO_NBITS_Q31, hMasa->data.hOmasaData->q_energy_ratio_ism_fx[sf][band] );
    4966             :             }
    4967        5636 :             test();
    4968        5636 :             IF( GT_16( nchan_ism, 2 ) && EQ_16( idx_separated_object, sub( nchan_ism, 1 ) ) )
    4969             :             {
    4970             :                 /* rotate components */
    4971         766 :                 rotate = 1;
    4972         766 :                 move16();
    4973        4610 :                 FOR( band = 0; band < numCodingBands; band++ )
    4974             :                 {
    4975        3844 :                     IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
    4976             :                     {
    4977        3352 :                         tmp = ratio_ism_idx[band][nchan_ism - 1];
    4978        3352 :                         ratio_ism_idx[band][nchan_ism - 1] = ratio_ism_idx[band][0];
    4979        3352 :                         ratio_ism_idx[band][0] = tmp;
    4980        3352 :                         move16();
    4981        3352 :                         move16();
    4982        3352 :                         move16();
    4983        3352 :                         test();
    4984        3352 :                         IF( sf == 0 && tmp == 0 )
    4985             :                         {
    4986         799 :                             n_ism_tmp = add( n_ism_tmp, 1 );
    4987             :                         }
    4988             : 
    4989        3352 :                         if ( EQ_16( n_ism_tmp, numCodingBands ) )
    4990             :                         {
    4991        1753 :                             assert( tmp == 0 );
    4992             :                         }
    4993             :                     }
    4994             :                 }
    4995             :             }
    4996             :             ELSE
    4997             :             {
    4998        4870 :                 IF( GT_16( idx_separated_object, -1 ) )
    4999             :                 {
    5000       31468 :                     FOR( band = 0; band < numCodingBands; band++ )
    5001             :                     {
    5002       26598 :                         IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
    5003             :                         {
    5004       23497 :                             test();
    5005       23497 :                             IF( ratio_ism_idx[band][idx_separated_object] == 0 && sf == 0 )
    5006             :                             {
    5007        8636 :                                 n_ism_tmp = add( n_ism_tmp, 1 );
    5008             :                             }
    5009             :                         }
    5010             :                     }
    5011             :                 }
    5012             :             }
    5013             : 
    5014             :             /* encode data for current subframe */
    5015        5636 :             test();
    5016        5636 :             IF( sf > 0 && EQ_16( n_ism_tmp, numCodingBands ) )
    5017             :             {
    5018        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 );
    5019             :             }
    5020             :             ELSE
    5021             :             {
    5022        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 );
    5023             :             }
    5024             : 
    5025             :             /* calculate quantized ISM ratios */
    5026             :             /* save previous subframe indexes */
    5027       36078 :             FOR( band = 0; band < numCodingBands; band++ )
    5028             :             {
    5029       30442 :                 Copy( ratio_ism_idx[band], ratio_ism_idx_prev_sf[band], nchan_ism );
    5030             :             }
    5031             : 
    5032        5636 :             IF( rotate )
    5033             :             {
    5034        4610 :                 FOR( band = 0; band < numCodingBands; band++ )
    5035             :                 {
    5036        3844 :                     IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
    5037             :                     {
    5038        3352 :                         tmp = ratio_ism_idx[band][nchan_ism - 1];
    5039        3352 :                         ratio_ism_idx[band][nchan_ism - 1] = ratio_ism_idx[band][0];
    5040        3352 :                         ratio_ism_idx[band][0] = tmp;
    5041        3352 :                         move16();
    5042        3352 :                         move16();
    5043        3352 :                         move16();
    5044             :                     }
    5045             :                 }
    5046             :             }
    5047             :         }
    5048             :     }
    5049             : 
    5050        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 );
    5051             : 
    5052             :     /* quantize directions */
    5053        8142 :     FOR( obj = 0; obj < nchan_ism; obj++ )
    5054             :     {
    5055        6280 :         IF( LT_16( bits_ism[obj], 8 ) )
    5056             :         {
    5057             :             /* check is same as previous */
    5058        2009 :             test();
    5059        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 */ ) )
    5060             :             {
    5061         201 :                 push_next_indice( hMetaData, 1, 1 );
    5062             :                 /* the old stays the same */
    5063             :             }
    5064             :             ELSE
    5065             :             {
    5066        1808 :                 push_next_indice( hMetaData, 0, 1 );
    5067        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 );
    5068        1808 :                 push_next_indice( hMetaData, idx_sph, bits_ism[obj] );
    5069        1808 :                 hIsmMeta[obj]->q_elevation_old_fx = hIsmMeta[obj]->elevation_fx;
    5070        1808 :                 hIsmMeta[obj]->q_azimuth_old_fx = hIsmMeta[obj]->azimuth_fx;
    5071        1808 :                 move32();
    5072        1808 :                 move32();
    5073             :             }
    5074             :         }
    5075             :         ELSE
    5076             :         {
    5077        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 );
    5078        4271 :             push_next_indice( hMetaData, idx_sph, bits_ism[obj] );
    5079        4271 :             hIsmMeta[obj]->q_elevation_old_fx = hIsmMeta[obj]->elevation_fx;
    5080        4271 :             hIsmMeta[obj]->q_azimuth_old_fx = hIsmMeta[obj]->azimuth_fx;
    5081        4271 :             move32();
    5082        4271 :             move32();
    5083             :         }
    5084             :     }
    5085             : 
    5086        1862 :     return;
    5087             : }
    5088             : 
    5089             : /*-------------------------------------------------------------------*
    5090             :  * ivas_merge_masa_transports()
    5091             :  *
    5092             :  * Merge MASA transport channels
    5093             :  *-------------------------------------------------------------------*/
    5094        5858 : void ivas_merge_masa_transports_fx(
    5095             :     Word32 data_in_f1_fx[][L_FRAME48k], // Qx
    5096             :     Word32 *data_in_f2_fx[],            // Qx
    5097             :     Word32 *data_out_f_fx[],            // Qx
    5098             :     const Word16 input_frame,
    5099             :     const Word16 num_transport_channels )
    5100             : {
    5101             :     Word16 i, j;
    5102             : 
    5103       17574 :     FOR( i = 0; i < num_transport_channels; i++ )
    5104             :     {
    5105    10588356 :         FOR( j = 0; j < input_frame; j++ )
    5106             :         {
    5107    10576640 :             data_out_f_fx[i][j] = L_add( data_in_f1_fx[i][j], data_in_f2_fx[i][j] );
    5108    10576640 :             move32();
    5109             :         }
    5110             :     }
    5111             : 
    5112        5858 :     return;
    5113             : }

Generated by: LCOV version 1.14