LCOV - code coverage report
Current view: top level - lib_dec - ivas_masa_dec_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 22b74eaeaa63d28e0fcc8ed21c8f7c451f461847 Lines: 1588 1679 94.6 %
Date: 2025-10-19 02:52:40 Functions: 19 19 100.0 %

          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 <assert.h>
      36             : #include "options.h"
      37             : #include "ivas_cnst.h"
      38             : #include "ivas_prot_rend_fx.h"
      39             : #include "rom_com.h"
      40             : #include "ivas_rom_com.h"
      41             : #include "ivas_stat_dec.h"
      42             : #include "prot_fx.h"
      43             : #include "wmc_auto.h"
      44             : #include "ivas_prot_fx.h"
      45             : 
      46             : 
      47             : /*-----------------------------------------------------------------------*
      48             :  * Local constants
      49             :  *-----------------------------------------------------------------------*/
      50             : 
      51             : #define SPAR_META_DELAY_SUBFRAMES 2                              /* Number of subframes to delay the SPAR metadata */
      52             : #define SPH_IDX_FRONT             ( MASA_NO_POINTS_EQUATOR / 2 ) /* Spherical index corresponding to front direction for setting as default value */
      53             : 
      54             : 
      55             : /*-----------------------------------------------------------------------*
      56             :  * Local function prototypes
      57             :  *-----------------------------------------------------------------------*/
      58             : 
      59             : static Word16 rint_fx( const Word32 num );
      60             : 
      61             : static void index_16bits_fx( IVAS_QMETADATA_HANDLE hQMetaData, SPHERICAL_GRID_DATA *Sph_Grid16 );
      62             : 
      63             : static void create_masa_ext_out_meta_fx( MASA_DECODER *hMasa, IVAS_QMETADATA_HANDLE hQMetaData, const Word16 nchan_transport );
      64             : 
      65             : static void replicate_subframes_fx( IVAS_QMETADATA_HANDLE hQMetaData );
      66             : 
      67             : static void restore_lowbitrate_masa_fx( IVAS_QMETADATA_HANDLE hQMetaData, const Word16 low_bitrate_mode, const Word16 numCodingBands );
      68             : 
      69             : static ivas_error init_lfe_synth_data_fx( Decoder_Struct *st_ivas, MASA_DECODER_HANDLE hMasa );
      70             : 
      71             : static void compute_foa_cov_matrix_fx( Word32 foaCov_fx[FOA_CHANNELS][FOA_CHANNELS], Word32 inCov_fx[FOA_CHANNELS][FOA_CHANNELS], Word32 mixMtx_fx[FOA_CHANNELS][FOA_CHANNELS] );
      72             : 
      73             : static Word16 decode_lfe_to_total_energy_ratio_fx( MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, UWord16 *bitstream, Word16 *index, const Word32 ivas_total_brate );
      74             : 
      75             : static ivas_error ivas_masa_dec_config_fx( Decoder_Struct *st_ivas );
      76             : 
      77             : static Word16 ivas_decode_masaism_metadata_fx( IVAS_QMETADATA_HANDLE hQMetaData, MASA_DECODER_HANDLE hMasa, MASA_ISM_DATA_HANDLE hMasaIsmData, const Word16 nchan_ism, UWord16 *bit_stream, Word16 *next_bit_pos, const Word16 idx_separated_object, const Word16 ism_imp, const Word16 dirac_bs_md_write_idx, const Word16 dirac_md_buffer_length );
      78             : 
      79             : static void decode_index_slice_fx( Word16 index, Word16 *ratio_idx_ism, const Word16 nchan_ism, const Word16 K );
      80             : 
      81             : static void decode_ism_ratios_fx( UWord16 *bit_stream, Word16 *next_bit_pos, Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], const Word16 nchan_ism, const Word16 nbands, const Word16 nblocks, const Word16 idx_separated_object );
      82             : 
      83             : static void read_ism_ratio_index_fx( Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], const Word16 nchan_ism, const Word16 numCodingBands, const Word16 sf, Word16 ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], UWord16 *bit_stream, Word16 *next_bit_pos, const Word32 *masa_to_total_energy_ratio_fx, const Word16 idx_sep_obj, Word16 *num_zeros );
      84             : 
      85             : 
      86             : /*-----------------------------------------------------------------------*
      87             :  * ivas_masa_decode_fx()
      88             :  *
      89             :  * MASA metadata decoder
      90             :  *-----------------------------------------------------------------------*/
      91             : 
      92       50645 : ivas_error ivas_masa_decode_fx(
      93             :     Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct                    */
      94             :     Decoder_State *st,       /* i/o: decoder state structure with bitstream */
      95             :     Word16 *nb_bits_read     /* o  : number of bits read                    Q0*/
      96             : )
      97             : {
      98             :     UWord16 byteBuffer;
      99             :     Word16 next_bit_pos_orig;
     100             :     Word32 masa_brate, ivas_total_brate;
     101             :     MASA_DECODER_HANDLE hMasa;
     102             :     IVAS_QMETADATA_HANDLE hQMetaData;
     103             :     IVAS_FORMAT ivas_format;
     104             :     Word16 low_bitrate_mode, tmp_elem_mode;
     105             :     ivas_error error;
     106             :     Word16 obj;
     107             :     Word16 i, ch, ism_imp;
     108             :     Word16 dirac_bs_md_write_idx, tmp;
     109             :     Word32 masa_total_brate;
     110             : 
     111       50645 :     dirac_bs_md_write_idx = 0;
     112       50645 :     move16();
     113       50645 :     ism_imp = 0;
     114       50645 :     move16();
     115             : 
     116       50645 :     error = IVAS_ERR_OK;
     117       50645 :     move16();
     118       50645 :     ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
     119       50645 :     move32();
     120             : 
     121       50645 :     low_bitrate_mode = -1; /* This means that LBR mode is not used. */
     122       50645 :     move16();
     123             : 
     124       50645 :     test();
     125       50645 :     test();
     126       50645 :     test();
     127       50645 :     IF( st_ivas->hOutSetup.separateChannelEnabled || 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 ) )
     128             :     {
     129        7121 :         masa_brate = st_ivas->hCPE[0]->element_brate;
     130        7121 :         move32();
     131             :     }
     132             :     ELSE
     133             :     {
     134       43524 :         masa_brate = ivas_total_brate;
     135       43524 :         move32();
     136             :     }
     137             : 
     138       50645 :     hMasa = st_ivas->hMasa;
     139       50645 :     hQMetaData = st_ivas->hQMetaData;
     140       50645 :     ivas_format = st_ivas->ivas_format;
     141       50645 :     move32();
     142             : 
     143       50645 :     hMasa->data.dir_decode_quality_fx = MAX16B; /* Set to default of max quality */ /* 1.0f in Q15 */
     144       50645 :     move16();
     145             : 
     146       50645 :     hQMetaData->is_masa_ivas_format = 1;
     147       50645 :     move16();
     148             : 
     149       50645 :     *nb_bits_read = 0;
     150       50645 :     move16();
     151             : 
     152       50645 :     next_bit_pos_orig = st->next_bit_pos;
     153       50645 :     move16();
     154             : 
     155             :     /* masa_brate / FRAMES_PER_SEC */
     156       50645 :     tmp = extract_l( Mpy_32_32( masa_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) ); // Q0
     157             : 
     158       50645 :     IF( EQ_32( masa_brate, IVAS_SID_5k2 ) )
     159             :     {
     160         191 :         st->next_bit_pos = sub( sub( tmp, 1 ), SID_FORMAT_NBITS );
     161             :     }
     162             :     ELSE
     163             :     {
     164       50454 :         st->next_bit_pos = sub( tmp, 1 );
     165             :     }
     166       50645 :     move16();
     167             : 
     168       50645 :     test();
     169       50645 :     test();
     170       50645 :     IF( EQ_32( ivas_format, MASA_FORMAT ) && ( EQ_32( masa_brate, IVAS_SID_5k2 ) || EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) )
     171             :     {
     172        1397 :         hMasa->config.numberOfDirections = 1;
     173        1397 :         move16();
     174             :     }
     175             : 
     176       50645 :     test();
     177       50645 :     test();
     178       50645 :     test();
     179       50645 :     test();
     180       50645 :     test();
     181       50645 :     IF( st->bfi == 0 && GT_32( ivas_total_brate, IVAS_SID_5k2 ) )
     182             :     {
     183       48523 :         test();
     184       48523 :         IF( NE_32( ivas_format, MC_FORMAT ) || NE_16( st_ivas->mc_mode, MC_MODE_MCMASA ) )
     185       37030 :         {
     186       37030 :             Word16 bits_per_frame = extract_l( Mpy_32_32( ivas_total_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) );
     187             : 
     188       37030 :             IF( EQ_32( ivas_format, MASA_FORMAT ) )
     189             :             {
     190             :                 /* re-read the number of objects, needed in case of bad frame  */
     191       30630 :                 ch = sub( 5, add( st_ivas->bit_stream[sub( bits_per_frame, 3 )], shl( st_ivas->bit_stream[sub( bits_per_frame, 2 )], 1 ) ) );
     192             : 
     193       30630 :                 if ( EQ_16( ch, 5 ) )
     194             :                 {
     195       28792 :                     ch = 0;
     196       28792 :                     move16();
     197             :                 }
     198       30630 :                 st_ivas->nchan_ism = ch;
     199       30630 :                 move16();
     200             :             }
     201             : 
     202       37030 :             test();
     203       37030 :             IF( EQ_32( ivas_format, MASA_FORMAT ) && GT_16( st_ivas->nchan_ism, 0 ) )
     204             :             {
     205             :                 /* there was OMASA in the input */
     206        1838 :                 hMasa->config.input_ivas_format = MASA_ISM_FORMAT;
     207        1838 :                 move32();
     208        1838 :                 IF( LT_16( st_ivas->nchan_ism, 3 ) )
     209             :                 {
     210             :                     /* was read in ivas_init_dec() to distinguish between 1 and 2 objects */
     211         418 :                     IF( EQ_16( st_ivas->bit_stream[bits_per_frame - 1], 0 ) )
     212             :                     {
     213         221 :                         st_ivas->nchan_ism = 1;
     214         221 :                         move16();
     215             :                     }
     216         418 :                     st->next_bit_pos = sub( st->next_bit_pos, MASA_TRANSP_BITS );
     217         418 :                     *nb_bits_read = add( *nb_bits_read, MASA_TRANSP_BITS );
     218             : 
     219             :                     /* the two reserved bits were already read in ivas_init_dec()*/
     220         418 :                     byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     221         418 :                     byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     222         418 :                     move16();
     223         418 :                     move16();
     224         418 :                     *nb_bits_read = add( *nb_bits_read, MASA_HEADER_BITS );
     225             : 
     226             :                     /* read number of directions */
     227         418 :                     byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     228         418 :                     move16();
     229         418 :                     *nb_bits_read = add( *nb_bits_read, 1 );
     230         418 :                     hMasa->config.numberOfDirections = (UWord8) L_add( byteBuffer, 1 );
     231             :                 }
     232             :                 ELSE
     233             :                 {
     234             :                     /* if there are 3 or 4 objects the number of transport channels bit is given to MASA format
     235             :                     and used to read number of directions*/
     236        1420 :                     byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     237        1420 :                     move16();
     238        1420 :                     *nb_bits_read = add( *nb_bits_read, 1 );
     239        1420 :                     hMasa->config.numberOfDirections = (UWord8) L_add( byteBuffer, 1 );
     240             : 
     241             :                     /* the two reserved bits were already read in ivas_init_dec()*/
     242        1420 :                     byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     243        1420 :                     byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     244        1420 :                     move16();
     245        1420 :                     move16();
     246        1420 :                     *nb_bits_read = add( *nb_bits_read, MASA_HEADER_BITS );
     247             :                 }
     248             :             }
     249             :             ELSE
     250             :             {
     251       35192 :                 IF( NE_32( ivas_format, MASA_ISM_FORMAT ) )
     252             :                 {
     253             :                     /* number of transport channels is always 2 for MASA_ISM format */
     254             :                     /* the number of MASA transport channels was read in ivas_dec_setup() */
     255       28792 :                     st->next_bit_pos = sub( st->next_bit_pos, MASA_TRANSP_BITS );
     256       28792 :                     *nb_bits_read = add( *nb_bits_read, MASA_TRANSP_BITS );
     257       28792 :                     move16();
     258             :                 }
     259             : 
     260       35192 :                 test();
     261       35192 :                 IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && NE_32( st_ivas->ism_mode, ISM_MODE_NONE ) )
     262             :                 {
     263             :                     /* the number of objects  was read */
     264        6400 :                     st->next_bit_pos = sub( st->next_bit_pos, NO_BITS_MASA_ISM_NO_OBJ );
     265        6400 :                     *nb_bits_read = add( *nb_bits_read, NO_BITS_MASA_ISM_NO_OBJ );
     266        6400 :                     move16();
     267        6400 :                     move16();
     268             : 
     269        6400 :                     IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     270             :                     {
     271             :                         /* read index of separated object */
     272             :                         /* nchan_ism should be > 1*/
     273        1634 :                         byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     274        1634 :                         move16();
     275        1634 :                         *nb_bits_read = add( *nb_bits_read, 1 );
     276        1634 :                         move16();
     277        1634 :                         st_ivas->hMasaIsmData->idx_separated_ism = extract_l( L_add( L_shl( byteBuffer, 1 ), st->bit_stream[( st->next_bit_pos )--] ) );
     278        1634 :                         move16();
     279        1634 :                         *nb_bits_read = add( *nb_bits_read, 1 );
     280        1634 :                         move16();
     281             :                     }
     282             :                     ELSE
     283             :                     {
     284        4766 :                         st_ivas->hMasaIsmData->idx_separated_ism = -1;
     285        4766 :                         move16();
     286             :                     }
     287             : 
     288             :                     /* read ISM importance flag (one per object) */
     289        6400 :                     IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     290             :                     {
     291        1634 :                         ism_imp = 0;
     292        1634 :                         move16();
     293             : 
     294        4902 :                         FOR( i = 0; i < ISM_METADATA_FLAG_BITS; i++ )
     295             :                         {
     296        3268 :                             byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     297        3268 :                             move16();
     298        3268 :                             *nb_bits_read = add( *nb_bits_read, 1 );
     299        3268 :                             move16();
     300        3268 :                             ism_imp = add( shl( ism_imp, 1 ), (Word16) byteBuffer );
     301             :                         }
     302        1634 :                         st_ivas->hIsmMetaData[0]->ism_imp = ism_imp;
     303        1634 :                         move16();
     304             :                     }
     305             : 
     306        6400 :                     IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     307             :                     {
     308        2017 :                         ism_imp = 0;
     309        2017 :                         move16();
     310        6051 :                         FOR( i = 0; i < ISM_METADATA_FLAG_BITS; i++ )
     311             :                         {
     312        4034 :                             byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     313        4034 :                             move16();
     314        4034 :                             *nb_bits_read = add( *nb_bits_read, 1 );
     315        4034 :                             move16();
     316        4034 :                             ism_imp = add( shl( ism_imp, 1 ), (Word16) byteBuffer );
     317        4034 :                             move16();
     318             :                         }
     319        2017 :                         st_ivas->hIsmMetaData[0]->ism_imp = ism_imp;
     320        2017 :                         move16();
     321             : 
     322             :                         /* reset */
     323        2017 :                         st_ivas->hIsmMetaData[0]->ism_md_null_flag = 0;
     324        2017 :                         move16();
     325        2017 :                         st_ivas->hIsmMetaData[0]->ism_md_lowrate_flag = 0;
     326        2017 :                         move16();
     327             : 
     328        2017 :                         IF( EQ_16( st_ivas->hIsmMetaData[0]->ism_imp, ISM_NO_META ) )
     329             :                         {
     330             :                             /* read flags */
     331           0 :                             st_ivas->hIsmMetaData[0]->ism_md_null_flag = st->bit_stream[( st->next_bit_pos )--];
     332           0 :                             move16();
     333           0 :                             *nb_bits_read = add( *nb_bits_read, ISM_METADATA_MD_FLAG_BITS );
     334           0 :                             move16();
     335           0 :                             st_ivas->hIsmMetaData[0]->ism_md_lowrate_flag = st->bit_stream[( st->next_bit_pos )--];
     336           0 :                             move16();
     337           0 :                             *nb_bits_read = add( *nb_bits_read, ISM_METADATA_INACTIVE_FLAG_BITS );
     338           0 :                             move16();
     339             :                         }
     340             :                     }
     341        4383 :                     ELSE IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
     342             :                     {
     343       10100 :                         FOR( ch = 0; ch < st_ivas->nchan_ism; ch++ )
     344             :                         {
     345        7351 :                             ism_imp = 0;
     346        7351 :                             move16();
     347       22053 :                             FOR( i = 0; i < ISM_METADATA_FLAG_BITS; i++ )
     348             :                             {
     349       14702 :                                 byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     350       14702 :                                 move16();
     351       14702 :                                 *nb_bits_read = add( *nb_bits_read, 1 );
     352       14702 :                                 move16();
     353       14702 :                                 ism_imp = add( shl( ism_imp, 1 ), (Word16) byteBuffer );
     354             :                             }
     355        7351 :                             st_ivas->hIsmMetaData[ch]->ism_imp = ism_imp;
     356        7351 :                             move16();
     357             : 
     358             :                             /* reset */
     359        7351 :                             st_ivas->hIsmMetaData[ch]->ism_md_null_flag = 0;
     360        7351 :                             move16();
     361        7351 :                             st_ivas->hIsmMetaData[ch]->ism_md_lowrate_flag = 0;
     362        7351 :                             move16();
     363             : 
     364        7351 :                             IF( EQ_16( st_ivas->hIsmMetaData[ch]->ism_imp, ISM_NO_META ) )
     365             :                             {
     366             :                                 /* read flags */
     367           0 :                                 st_ivas->hIsmMetaData[ch]->ism_md_null_flag = st->bit_stream[( st->next_bit_pos )--];
     368           0 :                                 move16();
     369           0 :                                 *nb_bits_read = add( *nb_bits_read, ISM_METADATA_MD_FLAG_BITS );
     370           0 :                                 move16();
     371           0 :                                 st_ivas->hIsmMetaData[ch]->ism_md_lowrate_flag = st->bit_stream[( st->next_bit_pos )--];
     372           0 :                                 move16();
     373           0 :                                 *nb_bits_read = add( *nb_bits_read, ISM_METADATA_INACTIVE_FLAG_BITS );
     374           0 :                                 move16();
     375             :                             }
     376             :                         }
     377             : 
     378        2749 :                         st_ivas->flag_omasa_brate = 0;
     379        2749 :                         move16();
     380             : 
     381        2749 :                         test();
     382        2749 :                         IF( GE_16( st_ivas->nchan_ism, 3 ) && EQ_32( ivas_total_brate, IVAS_128k ) )
     383             :                         {
     384         122 :                             st_ivas->flag_omasa_brate = st->bit_stream[( st->next_bit_pos )--];
     385         122 :                             move16();
     386         122 :                             *nb_bits_read = add( *nb_bits_read, 1 );
     387         122 :                             move16();
     388             :                         }
     389             :                     }
     390             :                 }
     391       35192 :                 byteBuffer = st->bit_stream[st->next_bit_pos];
     392       35192 :                 move16();
     393       35192 :                 st->next_bit_pos = sub( st->next_bit_pos, 1 );
     394       35192 :                 byteBuffer = add( byteBuffer, shl( st->bit_stream[st->next_bit_pos], 1 ) );
     395       35192 :                 st->next_bit_pos = sub( st->next_bit_pos, 1 );
     396             : 
     397       35192 :                 test();
     398       35192 :                 IF( EQ_16( byteBuffer, 0 ) && EQ_32( ivas_format, MASA_FORMAT ) )
     399             :                 {
     400       28792 :                     hMasa->config.input_ivas_format = MASA_FORMAT;
     401       28792 :                     move32();
     402             :                 }
     403             :                 ELSE
     404             :                 {
     405        6400 :                     hMasa->config.input_ivas_format = MASA_ISM_FORMAT;
     406        6400 :                     move32();
     407             :                 }
     408       35192 :                 *nb_bits_read = add( *nb_bits_read, MASA_HEADER_BITS );
     409             : 
     410             :                 /* read number of directions */
     411       35192 :                 byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     412       35192 :                 move16();
     413       35192 :                 *nb_bits_read = add( *nb_bits_read, 1 );
     414       35192 :                 move16();
     415       35192 :                 hMasa->config.numberOfDirections = (UWord8) L_add( byteBuffer, 1 );
     416       35192 :                 move16();
     417             :             }
     418             :         }
     419             :         ELSE
     420             :         {
     421       11493 :             hMasa->config.numberOfDirections = 1;
     422       11493 :             move16();
     423             :         }
     424             : 
     425       48523 :         test();
     426       48523 :         IF( NE_32( ivas_format, MC_FORMAT ) || NE_32( st_ivas->mc_mode, MC_MODE_MCMASA ) )
     427             :         {
     428             :             /* read subframe mode */
     429       37030 :             byteBuffer = st->bit_stream[( st->next_bit_pos )--];
     430       37030 :             move16();
     431       37030 :             *nb_bits_read = add( *nb_bits_read, 1 );
     432       37030 :             move16();
     433       37030 :             hMasa->config.joinedSubframes = (UWord8) byteBuffer;
     434       37030 :             move16();
     435             :         }
     436             :         ELSE
     437             :         {
     438       11493 :             hMasa->config.joinedSubframes = FALSE;
     439       11493 :             move16();
     440             :         }
     441             : 
     442       48523 :         IF( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) )
     443             :         {
     444       11493 :             *nb_bits_read = add( *nb_bits_read, decode_lfe_to_total_energy_ratio_fx( hMasa->hMasaLfeSynth, st->bit_stream, &st->next_bit_pos, ivas_total_brate ) );
     445       11493 :             move16();
     446             :         }
     447             : 
     448             :         /* Once we know incoming configuration, we can config decoder further based on bitrate etc. */
     449       48523 :         if ( NE_32( ( error = ivas_masa_dec_config_fx( st_ivas ) ), IVAS_ERR_OK ) )
     450             :         {
     451           0 :             return error;
     452             :         }
     453             : 
     454             :         /* If we are under metadata bit budget limit and joined subframes is not signalled, then read LBR mode. */
     455       48523 :         test();
     456       48523 :         IF( LT_32( hMasa->config.max_metadata_bits, MINIMUM_BIT_BUDGET_NORMAL_META ) && EQ_16( hMasa->config.joinedSubframes, FALSE ) )
     457             :         {
     458             :             /* read low bitrate mode */
     459       23203 :             byteBuffer = st->bit_stream[st->next_bit_pos];
     460       23203 :             move16();
     461       23203 :             st->next_bit_pos = sub( st->next_bit_pos, 1 );
     462       23203 :             move16();
     463       23203 :             *nb_bits_read = add( *nb_bits_read, 1 );
     464       23203 :             move16();
     465       23203 :             low_bitrate_mode = byteBuffer;
     466       23203 :             move16();
     467             : 
     468       23203 :             IF( EQ_16( low_bitrate_mode, 1 ) )
     469             :             {
     470       19320 :                 hQMetaData->q_direction[0].cfg.nblocks = 1;
     471       19320 :                 move16();
     472             :             }
     473             :             ELSE
     474             :             {
     475        3883 :                 hQMetaData->q_direction[0].cfg.nbands = 1;
     476        3883 :                 move16();
     477             :             }
     478             :         }
     479             : 
     480             :         /* Remove already read bits from the bit budget */
     481       48523 :         hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, *nb_bits_read );
     482       48523 :         move16();
     483             : 
     484       48523 :         IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     485             :         {
     486        6400 :             IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     487             :             {
     488        1634 :                 IF( st_ivas->hDirAC != NULL )
     489             :                 {
     490        1222 :                     *nb_bits_read = add( *nb_bits_read,
     491        1222 :                                          ivas_decode_masaism_metadata_fx( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData, st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos,
     492        1222 :                                                                           st_ivas->hMasaIsmData->idx_separated_ism, ism_imp, st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx, st_ivas->hSpatParamRendCom->dirac_md_buffer_length ) );
     493        1222 :                     move16();
     494        6366 :                     FOR( obj = 0; obj <= st_ivas->nchan_ism; obj++ )
     495             :                     {
     496        5144 :                         IF( EQ_16( st_ivas->hMasaIsmData->idx_separated_ism, obj ) )
     497             :                         {
     498             :                             Word16 sf;
     499             :                             Word16 meta_write_index;
     500             : 
     501        6110 :                             FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
     502             :                             {
     503        4888 :                                 meta_write_index = add( st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx, sf ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length;
     504        4888 :                                 st_ivas->hMasaIsmData->azimuth_separated_ism_fx[meta_write_index] = st_ivas->hMasaIsmData->azimuth_ism_fx[obj][meta_write_index];
     505        4888 :                                 move16();
     506        4888 :                                 st_ivas->hMasaIsmData->elevation_separated_ism_fx[meta_write_index] = st_ivas->hMasaIsmData->elevation_ism_fx[obj][meta_write_index];
     507        4888 :                                 move16();
     508             :                             }
     509             :                         }
     510             :                     }
     511             :                 }
     512         412 :                 ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
     513             :                 {
     514          40 :                     *nb_bits_read = add( *nb_bits_read, ivas_decode_masaism_metadata_fx( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData,
     515          40 :                                                                                          st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos,
     516          40 :                                                                                          st_ivas->hMasaIsmData->idx_separated_ism, ism_imp, st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx, st_ivas->hSpatParamRendCom->dirac_md_buffer_length ) );
     517             :                 }
     518             :                 ELSE
     519             :                 {
     520         372 :                     *nb_bits_read = add( *nb_bits_read, ivas_decode_masaism_metadata_fx( hQMetaData, st_ivas->hMasa, st_ivas->hMasaIsmData, st_ivas->nchan_ism, st->bit_stream, &st->next_bit_pos,
     521         372 :                                                                                          st_ivas->hMasaIsmData->idx_separated_ism, ism_imp, 0, MAX_PARAM_SPATIAL_SUBFRAMES ) );
     522         372 :                     move16();
     523             :                 }
     524             :             }
     525             :         }
     526             : 
     527       48523 :         masa_total_brate = ivas_total_brate;
     528       48523 :         move32();
     529       48523 :         test();
     530       48523 :         IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
     531             :         {
     532        2749 :             masa_total_brate = calculate_cpe_brate_MASA_ISM_fx( st_ivas->ism_mode, ivas_total_brate, st_ivas->nchan_ism );
     533             :         }
     534             : 
     535       48523 :         IF( GE_32( masa_total_brate, IVAS_384k ) )
     536             :         {
     537        2239 :             IF( GE_32( masa_total_brate, IVAS_512k ) )
     538             :             {
     539         790 :                 *nb_bits_read = add( *nb_bits_read,
     540         790 :                                      ivas_qmetadata_dec_decode_hr_384_512( hQMetaData, st->bit_stream, &st->next_bit_pos, hMasa->data.sph_grid16, 16, 4, hMasa->config.numCodingBands ) );
     541         790 :                 move16();
     542             :             }
     543             :             ELSE
     544             :             {
     545        1449 :                 *nb_bits_read = add( *nb_bits_read,
     546        1449 :                                      ivas_qmetadata_dec_decode_hr_384_512( hQMetaData, st->bit_stream, &st->next_bit_pos, hMasa->data.sph_grid16, 11, 3, hMasa->config.numCodingBands ) );
     547        1449 :                 move16();
     548             :             }
     549             :         }
     550             :         ELSE
     551             :         {
     552       46284 :             *nb_bits_read = add( *nb_bits_read,
     553       46284 :                                  ivas_qmetadata_dec_decode( hQMetaData, st->bit_stream, &st->next_bit_pos, 0 ) );
     554       46284 :             move16();
     555             :         }
     556             : 
     557       48523 :         test();
     558       48523 :         test();
     559       48523 :         IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     560             :         {
     561             :             /* Modify spatial metadata based on the MASA-to-total energy ratios */
     562        1634 :             ivas_omasa_modify_masa_energy_ratios_fx( hQMetaData, st_ivas->hMasaIsmData->masa_to_total_energy_ratio_fx );
     563             :         }
     564             : 
     565             :         /* Get direction decoding quality. EC 1 and 2 are handled by the default value. */
     566       48523 :         if ( EQ_16( hQMetaData->ec_flag, 2 ) )
     567             :         {
     568        4648 :             hMasa->data.dir_decode_quality_fx = hQMetaData->dir_comp_ratio_fx; /* Q15 */
     569        4648 :             move16();
     570             :         }
     571             : 
     572       48523 :         hMasa->config.coherencePresent = !hQMetaData->all_coherence_zero;
     573       48523 :         move16();
     574             : 
     575       48523 :         test();
     576       48523 :         test();
     577       48523 :         IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) && ( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) ) )
     578             :         {
     579        5305 :             index_16bits_fx( hQMetaData, hMasa->data.sph_grid16 );
     580             :         }
     581             : 
     582             :         /* If LBR mode is not disabled, then we restore metadata to 5 bands and 4 subframes based on the LBR mode. */
     583       48523 :         IF( NE_16( low_bitrate_mode, -1 ) )
     584             :         {
     585       23203 :             restore_lowbitrate_masa_fx( hQMetaData, low_bitrate_mode, hMasa->config.numCodingBands );
     586             :         }
     587       25320 :         ELSE IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
     588             :         {
     589        5430 :             replicate_subframes_fx( hQMetaData );
     590             :         }
     591             :     }
     592        2122 :     ELSE IF( st->bfi == 0 && EQ_32( ivas_format, MASA_FORMAT ) && EQ_32( ivas_total_brate, IVAS_SID_5k2 ) )
     593             :     {
     594         191 :         IF( hQMetaData->q_direction == NULL )
     595             :         {
     596             :             /* replicate ivas_masa_dec_config() in case that first good received frame is SID frame */
     597           0 :             if ( NE_32( ( error = ivas_masa_dec_config_fx( st_ivas ) ), IVAS_ERR_OK ) )
     598             :             {
     599           0 :                 return error;
     600             :             }
     601             : 
     602           0 :             ivas_masa_set_elements_fx( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, st_ivas->ivas_format, st_ivas->ism_mode, 0 );
     603             : 
     604           0 :             hQMetaData->metadata_max_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC;
     605           0 :             move16();
     606             : 
     607           0 :             if ( NE_32( ( error = ivas_qmetadata_allocate_memory_fx( hQMetaData, 5, 1, 0 ) ), IVAS_ERR_OK ) )
     608             :             {
     609           0 :                 return error;
     610             :             }
     611             : 
     612           0 :             hQMetaData->numTwoDirBands = hMasa->config.numTwoDirBands;
     613           0 :             move16();
     614           0 :             hQMetaData->useLowerRes = 0;
     615           0 :             move16();
     616             : 
     617           0 :             hQMetaData->q_direction->cfg.nbands = 5;
     618           0 :             move16();
     619           0 :             hQMetaData->q_direction->cfg.nblocks = 4;
     620           0 :             move16();
     621             : 
     622           0 :             test();
     623           0 :             IF( EQ_32( ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_MCMASA ) )
     624             :             {
     625           0 :                 hQMetaData->q_direction->cfg.mc_ls_setup = ivas_mc_map_output_config_to_mc_ls_setup_fx( st_ivas->transport_config );
     626             :             }
     627             :             ELSE
     628             :             {
     629           0 :                 hQMetaData->q_direction->cfg.mc_ls_setup = MC_LS_SETUP_INVALID;
     630             :             }
     631           0 :             move16();
     632             :         }
     633             : 
     634         191 :         tmp_elem_mode = -1;
     635         191 :         move16();
     636             : 
     637         191 :         *nb_bits_read = add( *nb_bits_read,
     638         191 :                              ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), st_ivas->nchan_transport, &tmp_elem_mode, ivas_format ) );
     639         191 :         move16();
     640             : 
     641         191 :         IF( EQ_16( st_ivas->nchan_transport, 2 ) )
     642             :         {
     643          74 :             assert( st_ivas->nCPE > 0 );
     644          74 :             st_ivas->hCPE[0]->element_mode = tmp_elem_mode;
     645          74 :             move16();
     646             :         }
     647         191 :         *nb_bits_read = add( *nb_bits_read, SID_FORMAT_NBITS );
     648         191 :         move16();
     649             :     }
     650        1931 :     ELSE IF( st->bfi == 0 && EQ_32( ivas_format, MASA_FORMAT ) && EQ_32( ivas_total_brate, FRAME_NO_DATA ) )
     651             :     {
     652        1206 :         IF( hQMetaData->q_direction == NULL )
     653             :         {
     654           0 :             IF( ( error = ivas_masa_dec_config_fx( st_ivas ) ) != IVAS_ERR_OK )
     655             :             {
     656           0 :                 return error;
     657             :             }
     658             :         }
     659             :     }
     660             : 
     661       50645 :     IF( st_ivas->hDirAC != NULL )
     662             :     {
     663       40558 :         dirac_bs_md_write_idx = st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx; /* Store the write-index for this frame */
     664       40558 :         move16();
     665             : 
     666       40558 :         ivas_qmetadata_to_dirac_fx( hQMetaData, st_ivas->hDirAC, hMasa, st_ivas->hSpatParamRendCom, ivas_total_brate, ivas_format, 0, 0 );
     667             :     }
     668       10087 :     ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
     669             :     {
     670          40 :         Word16 index = add( st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx, MAX_PARAM_SPATIAL_SUBFRAMES );
     671          40 :         IF( GE_16( index, st_ivas->hSpatParamRendCom->dirac_md_buffer_length ) )
     672             :         {
     673          20 :             index = sub( index, st_ivas->hSpatParamRendCom->dirac_md_buffer_length );
     674             :         }
     675             : 
     676          40 :         st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx = index;
     677          40 :         move16();
     678             :     }
     679             : 
     680       50645 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     681             :     {
     682        6528 :         IF( hQMetaData->q_direction == NULL )
     683             :         {
     684           0 :             IF( NE_32( ( error = ivas_masa_dec_config_fx( st_ivas ) ), IVAS_ERR_OK ) )
     685             :             {
     686           0 :                 return error;
     687             :             }
     688             :         }
     689             : 
     690        6528 :         IF( st_ivas->hDirAC != NULL )
     691             :         {
     692             :             Word16 b;
     693             :             Word16 block;
     694             :             Word16 meta_write_index;
     695             : 
     696        8845 :             FOR( i = 0; i < st_ivas->hSpatParamRendCom->numIsmDirections; i++ )
     697             :             {
     698       20035 :                 FOR( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ )
     699             :                 {
     700       16028 :                     meta_write_index = add( dirac_bs_md_write_idx, block ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length;
     701             : 
     702      810908 :                     FOR( b = 0; b < st_ivas->hSpatParamRendCom->num_freq_bands; b++ )
     703             :                     {
     704     1589760 :                         st_ivas->hSpatParamRendCom->diffuseness_vector_fx[meta_write_index][b] = L_sub( st_ivas->hSpatParamRendCom->diffuseness_vector_fx[meta_write_index][b],
     705      794880 :                                                                                                         st_ivas->hMasaIsmData->energy_ratio_ism_fx[i][meta_write_index][b] ); // Q30
     706      794880 :                         move32();
     707             :                     }
     708             :                 }
     709             :             }
     710             : 
     711       24190 :             FOR( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ )
     712             :             {
     713       19352 :                 meta_write_index = add( dirac_bs_md_write_idx, block ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length;
     714             : 
     715      994392 :                 FOR( b = 0; b < st_ivas->hSpatParamRendCom->num_freq_bands; b++ )
     716             :                 {
     717      975040 :                     st_ivas->hSpatParamRendCom->diffuseness_vector_fx[meta_write_index][b] = L_max( 0, st_ivas->hSpatParamRendCom->diffuseness_vector_fx[meta_write_index][b] ); // Q30
     718      975040 :                     move32();
     719             :                 }
     720             :             }
     721             :         }
     722             :     }
     723             : 
     724       50645 :     st->next_bit_pos = next_bit_pos_orig;
     725       50645 :     move16();
     726             : 
     727       50645 :     IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) )
     728             :     {
     729             :         Word32 cpe_brate;
     730        6528 :         cpe_brate = calculate_cpe_brate_MASA_ISM_fx( st_ivas->ism_mode, ivas_total_brate, st_ivas->nchan_ism );
     731             : 
     732        6528 :         test();
     733        6528 :         test();
     734        6528 :         IF( EQ_16( st_ivas->nCPE, 1 ) && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL )
     735             :         {
     736        2989 :             IF( LT_32( cpe_brate, MASA_STEREO_MIN_BITRATE ) )
     737             :             {
     738        1224 :                 st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 1;
     739        1224 :                 move16();
     740             :             }
     741             :             ELSE
     742             :             {
     743        1765 :                 st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0;
     744        1765 :                 move16();
     745             :             }
     746             : 
     747        2989 :             if ( LE_32( ivas_total_brate, IVAS_SID_5k2 ) )
     748             :             {
     749           0 :                 st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0;
     750           0 :                 move32();
     751             :             }
     752             :         }
     753             :     }
     754             :     ELSE
     755             :     {
     756       44117 :         test();
     757       44117 :         test();
     758       44117 :         test();
     759       44117 :         IF( EQ_32( ivas_format, MASA_FORMAT ) && EQ_16( st_ivas->nCPE, 1 ) && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL )
     760             :         {
     761        8860 :             IF( LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) )
     762             :             {
     763        4476 :                 st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 1;
     764        4476 :                 move16();
     765             :             }
     766             :             ELSE
     767             :             {
     768        4384 :                 st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0;
     769        4384 :                 move16();
     770             :             }
     771             : 
     772        8860 :             if ( LE_32( ivas_total_brate, IVAS_SID_5k2 ) )
     773             :             {
     774         528 :                 st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0;
     775         528 :                 move16();
     776             :             }
     777             :         }
     778             :     }
     779             : 
     780       50645 :     test();
     781       50645 :     IF( EQ_32( ivas_format, MASA_FORMAT ) && EQ_16( st_ivas->nCPE, 1 ) )
     782             :     {
     783       18439 :         st_ivas->hCPE[0]->hCoreCoder[0]->masa_sid_format = 0;
     784       18439 :         move16();
     785             : 
     786       18439 :         IF( LE_32( st_ivas->hDecoderConfig->last_ivas_total_brate, IVAS_SID_5k2 ) )
     787             :         {
     788         528 :             st_ivas->hCPE[0]->hCoreCoder[0]->masa_sid_format = 1;
     789         528 :             move16();
     790             : 
     791         528 :             if ( GE_32( ivas_total_brate, IVAS_SID_5k2 ) )
     792             :             {
     793          74 :                 st_ivas->hCPE[0]->element_brate = ivas_total_brate;
     794          74 :                 move32();
     795             :             }
     796             :         }
     797             :     }
     798             : 
     799       50645 :     test();
     800       50645 :     test();
     801       50645 :     IF( ( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) || EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) && EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
     802             :     {
     803        5608 :         create_masa_ext_out_meta_fx( hMasa, hQMetaData, st_ivas->nchan_transport );
     804             :     }
     805             : 
     806       50645 :     return error /* *nb_bits_read*/;
     807             : }
     808             : 
     809             : 
     810             : /*-------------------------------------------------------------------*
     811             :  * ivas_masa_dec_open()
     812             :  *
     813             :  *
     814             :  *-------------------------------------------------------------------*/
     815             : 
     816         404 : ivas_error ivas_masa_dec_open_fx(
     817             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder handle  */
     818             : )
     819             : {
     820             :     MASA_DECODER_HANDLE hMasa;
     821             :     ivas_error error;
     822             :     Word16 i;
     823             :     Word32 ism_total_brate;
     824             : 
     825         404 :     error = IVAS_ERR_OK;
     826         404 :     move16();
     827             : 
     828         404 :     IF( ( hMasa = (MASA_DECODER_HANDLE) malloc( sizeof( MASA_DECODER ) ) ) == NULL )
     829             :     {
     830           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     831             :     }
     832             : 
     833         404 :     ism_total_brate = 0;
     834         404 :     move32();
     835             : 
     836             :     /* ISM metadata */
     837             : 
     838             : #ifdef OMASA_OBJECT_EDITING
     839         404 :     test();
     840         404 :     IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && st_ivas->hIsmMetaData[0] != NULL )
     841             : #else
     842             :     test();
     843             :     test();
     844             :     IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && st_ivas->hIsmMetaData[0] != NULL && EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
     845             : #endif
     846             :     {
     847             :         /* these are not needed -> clean. EXT metafile writer in OMASA needs only the number of ISMs and writes default null-data */
     848           0 :         ivas_ism_metadata_close( st_ivas->hIsmMetaData, 0 );
     849             :     }
     850             : 
     851         404 :     test();
     852         404 :     test();
     853         404 :     test();
     854         404 :     test();
     855         404 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && GT_16( 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 ) ) )
     856             :     {
     857          91 :         FOR( i = 0; i < st_ivas->nSCE; i++ )
     858             :         {
     859          58 :             ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[i]->element_brate );
     860             :         }
     861             :     }
     862             : 
     863         404 :     ivas_masa_set_elements_fx( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate );
     864             : 
     865         404 :     Copy( DirAC_block_grouping, hMasa->config.block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
     866         404 :     Copy( MASA_band_grouping_24, hMasa->config.band_grouping, MASA_FREQUENCY_BANDS + 1 );
     867         404 :     hMasa->config.numberOfDirections = 1;
     868         404 :     move16();
     869         404 :     hMasa->config.joinedSubframes = FALSE;
     870         404 :     move16();
     871             : 
     872             :     /* Create spherical grid only for external output */
     873         404 :     test();
     874         404 :     test();
     875         404 :     IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) && ( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) || EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) )
     876             :     {
     877          21 :         IF( ( hMasa->data.sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL )
     878             :         {
     879           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     880             :         }
     881             : 
     882          21 :         generate_gridEq_fx( hMasa->data.sph_grid16 );
     883             : 
     884          21 :         IF( ( hMasa->data.extOutMeta = (MASA_DECODER_EXT_OUT_META *) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL )
     885             :         {
     886           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     887             :         }
     888             :     }
     889             :     ELSE
     890             :     {
     891         383 :         hMasa->data.sph_grid16 = NULL;
     892         383 :         hMasa->data.extOutMeta = NULL;
     893             :     }
     894             : 
     895         404 :     IF( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) )
     896             :     {
     897         289 :         error = init_lfe_synth_data_fx( st_ivas, hMasa );
     898             :     }
     899             :     ELSE
     900             :     {
     901         115 :         hMasa->hMasaLfeSynth = NULL;
     902             :     }
     903             : 
     904         404 :     st_ivas->hMasa = hMasa;
     905             : 
     906             :     /* allocate transport channels*/
     907         404 :     test();
     908         404 :     test();
     909         404 :     test();
     910         404 :     test();
     911         404 :     IF( st_ivas->hTcBuffer == NULL && NE_16( st_ivas->renderer_type, RENDERER_DISABLE ) && NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) && NE_16( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) )
     912             :     {
     913             :         Word16 nchan_to_allocate, nchan_transport;
     914             : #ifdef NONBE_1303_REND_GRANULARITY
     915             :         Word16 granularity;
     916             : #endif
     917             :         TC_BUFFER_MODE buffer_mode;
     918             : 
     919          52 :         buffer_mode = TC_BUFFER_MODE_RENDERER;
     920          52 :         move16();
     921          52 :         test();
     922          52 :         test();
     923          52 :         test();
     924          52 :         IF( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) && ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_MONO ) ) )
     925             :         {
     926           3 :             buffer_mode = TC_BUFFER_MODE_BUFFER;
     927           3 :             move16();
     928             :         }
     929          49 :         ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) )
     930             :         {
     931           5 :             buffer_mode = TC_BUFFER_MODE_BUFFER;
     932           5 :             move16();
     933             :         }
     934             : 
     935          52 :         nchan_transport = ivas_jbm_dec_get_num_tc_channels_fx( st_ivas );
     936          52 :         nchan_to_allocate = nchan_transport;
     937          52 :         move16();
     938             : 
     939          52 :         test();
     940          52 :         test();
     941          52 :         test();
     942          52 :         test();
     943          52 :         IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) )
     944             :         {
     945           5 :             nchan_transport = 1;
     946           5 :             move16();
     947           5 :             nchan_to_allocate = 1;
     948           5 :             move16();
     949             :         }
     950          47 :         ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) || EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) ) )
     951             :         {
     952           1 :             nchan_transport = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
     953           1 :             nchan_to_allocate = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
     954             :         }
     955          46 :         ELSE IF( EQ_16( st_ivas->nchan_transport, 1 ) && EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) )
     956             :         {
     957             :             /* addtl channel for CNG */
     958          13 :             nchan_to_allocate = add( nchan_to_allocate, 1 );
     959             :         }
     960             : 
     961             : #ifdef NONBE_1303_REND_GRANULARITY
     962          52 :         granularity = ivas_jbm_dec_get_render_granularity_fx( st_ivas->renderer_type, RENDERER_DISABLE, st_ivas->hDecoderConfig->output_Fs );
     963             : 
     964          52 :         IF( ( error = ivas_jbm_dec_tc_buffer_open_fx( st_ivas, buffer_mode, nchan_transport, nchan_to_allocate, nchan_to_allocate, granularity ) ) != IVAS_ERR_OK )
     965             : #else
     966             :         IF( ( error = ivas_jbm_dec_tc_buffer_open_fx( st_ivas, buffer_mode, nchan_transport, nchan_to_allocate, nchan_to_allocate, NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK )
     967             : #endif
     968             :         {
     969           0 :             return error;
     970             :         }
     971             :     }
     972             : 
     973         404 :     return error;
     974             : }
     975             : 
     976             : 
     977             : /*-----------------------------------------------------------------------*
     978             :  * ivas_masa_dec_close()
     979             :  *
     980             :  * close MASA decoder
     981             :  *-----------------------------------------------------------------------*/
     982             : 
     983        1520 : void ivas_masa_dec_close_fx(
     984             :     MASA_DECODER_HANDLE *hMasa_out /* i/o: MASA metadata structure      */
     985             : )
     986             : {
     987             :     MASA_DECODER_HANDLE hMasa;
     988             : 
     989        1520 :     test();
     990        1520 :     IF( hMasa_out == NULL || *hMasa_out == NULL )
     991             :     {
     992        1116 :         return;
     993             :     }
     994             : 
     995         404 :     hMasa = *hMasa_out;
     996             : 
     997             :     /* Free spherical grid memory if in use */
     998         404 :     IF( hMasa->data.sph_grid16 != NULL )
     999             :     {
    1000          46 :         free( hMasa->data.sph_grid16 );
    1001          46 :         hMasa->data.sph_grid16 = NULL;
    1002             :     }
    1003             : 
    1004         404 :     IF( hMasa->data.extOutMeta != NULL )
    1005             :     {
    1006          21 :         free( hMasa->data.extOutMeta );
    1007          21 :         hMasa->data.extOutMeta = NULL;
    1008             :     }
    1009             : 
    1010         404 :     IF( hMasa->hMasaLfeSynth != NULL )
    1011             :     {
    1012         289 :         IF( hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx != NULL )
    1013             :         {
    1014          13 :             free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx );
    1015          13 :             hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx = NULL;
    1016             :         }
    1017         289 :         IF( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx != NULL )
    1018             :         {
    1019          13 :             free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx );
    1020          13 :             hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx = NULL;
    1021             :         }
    1022         289 :         IF( hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx != NULL )
    1023             :         {
    1024          13 :             free( hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx );
    1025          13 :             hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx = NULL;
    1026             :         }
    1027         289 :         IF( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx != NULL )
    1028             :         {
    1029          13 :             free( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx );
    1030          13 :             hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx = NULL;
    1031             :         }
    1032         289 :         free( hMasa->hMasaLfeSynth );
    1033         289 :         hMasa->hMasaLfeSynth = NULL;
    1034             :     }
    1035             : 
    1036         404 :     free( *hMasa_out );
    1037         404 :     *hMasa_out = NULL;
    1038             : 
    1039         404 :     return;
    1040             : }
    1041             : 
    1042             : 
    1043             : /*-------------------------------------------------------------------*
    1044             :  * ivas_masa_dec_config()
    1045             :  *
    1046             :  * Frame-by-frame configuration of MASA decoder
    1047             :  *-------------------------------------------------------------------*/
    1048             : 
    1049       48523 : static ivas_error ivas_masa_dec_config_fx(
    1050             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder handle  */
    1051             : )
    1052             : {
    1053             :     Word16 i;
    1054             :     MASA_DECODER_HANDLE hMasa;
    1055             :     UWord8 maxBand;
    1056             :     Word16 maxBin;
    1057             :     ivas_error error;
    1058             :     Word32 ivas_total_brate;
    1059             :     Word32 ism_total_brate;
    1060       48523 :     error = IVAS_ERR_OK;
    1061       48523 :     move32();
    1062       48523 :     hMasa = st_ivas->hMasa;
    1063             : 
    1064       48523 :     ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
    1065       48523 :     move32();
    1066       48523 :     ism_total_brate = 0;
    1067       48523 :     move32();
    1068             : 
    1069       48523 :     test();
    1070       48523 :     test();
    1071       48523 :     test();
    1072       48523 :     test();
    1073       48523 :     IF( EQ_32( st_ivas->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 ) ) )
    1074             :     {
    1075       17402 :         FOR( i = 0; i < st_ivas->nSCE; i++ )
    1076             :         {
    1077       11002 :             ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[i]->element_brate );
    1078             :         }
    1079             :     }
    1080             : 
    1081       48523 :     ivas_masa_set_elements_fx( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate );
    1082             : 
    1083       48523 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
    1084             :     {
    1085        6400 :         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 );
    1086             :     }
    1087             :     ELSE
    1088             :     {
    1089       42123 :         ivas_masa_set_coding_config_fx( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, ( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_MCMASA ) ) );
    1090             :     }
    1091             : 
    1092       48523 :     test();
    1093       48523 :     test();
    1094       48523 :     IF( ( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) || EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) && EQ_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_512k ) )
    1095             :     {
    1096        1170 :         hMasa->config.mergeRatiosOverSubframes = 0;
    1097        1170 :         move16();
    1098             : 
    1099             :         /* initialize spherical grid */
    1100        1170 :         IF( hMasa->data.sph_grid16 == NULL )
    1101             :         {
    1102          25 :             IF( ( hMasa->data.sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL )
    1103             :             {
    1104           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA data handle\n" ) );
    1105             :             }
    1106          25 :             generate_gridEq_fx( hMasa->data.sph_grid16 );
    1107             :         }
    1108             :     }
    1109       48523 :     st_ivas->hQMetaData->metadata_max_bits = hMasa->config.max_metadata_bits;
    1110       48523 :     move16();
    1111       48523 :     st_ivas->hQMetaData->bandMap = hMasa->data.band_mapping;
    1112       48523 :     move16();
    1113       48523 :     st_ivas->hQMetaData->nchan_transport = st_ivas->nchan_transport;
    1114       48523 :     move16();
    1115             : 
    1116       48523 :     IF( NE_32( ( error = ivas_qmetadata_allocate_memory_fx( st_ivas->hQMetaData, hMasa->config.numCodingBands, hMasa->config.numberOfDirections, hMasa->config.useCoherence ) ), IVAS_ERR_OK ) )
    1117             :     {
    1118           0 :         return error;
    1119             :     }
    1120             : 
    1121       48523 :     st_ivas->hQMetaData->numTwoDirBands = st_ivas->hMasa->config.numTwoDirBands;
    1122       48523 :     move16();
    1123       48523 :     st_ivas->hQMetaData->useLowerRes = 0;
    1124       48523 :     move16();
    1125             : 
    1126      102338 :     FOR( i = 0; i < st_ivas->hQMetaData->no_directions; i++ )
    1127             :     {
    1128       53815 :         st_ivas->hQMetaData->q_direction[i].cfg.nbands = hMasa->config.numCodingBands;
    1129       53815 :         move16();
    1130       53815 :         IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
    1131             :         {
    1132        6394 :             st_ivas->hQMetaData->q_direction[i].cfg.nblocks = 1;
    1133             :         }
    1134             :         ELSE
    1135             :         {
    1136       47421 :             st_ivas->hQMetaData->q_direction[i].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES;
    1137             :         }
    1138       53815 :         move16();
    1139             : 
    1140       53815 :         test();
    1141       53815 :         IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) )
    1142             :         {
    1143       11493 :             st_ivas->hQMetaData->q_direction[i].cfg.mc_ls_setup = ivas_mc_map_output_config_to_mc_ls_setup_fx( st_ivas->transport_config );
    1144       11493 :             move32();
    1145             :         }
    1146             :         ELSE
    1147             :         {
    1148       42322 :             st_ivas->hQMetaData->q_direction[i].cfg.mc_ls_setup = MC_LS_SETUP_INVALID;
    1149       42322 :             move32();
    1150             :         }
    1151             :     }
    1152             : 
    1153       48523 :     ivas_set_qmetadata_maxbit_req_fx( st_ivas->hQMetaData, st_ivas->ivas_format );
    1154             : 
    1155             :     /* Find maximum band usable */
    1156       48523 :     maxBin = extract_l( Mpy_32_32( st_ivas->hDecoderConfig->output_Fs, INV_CLDFB_BANDWIDTH_Q31 ) );
    1157       48523 :     maxBand = 0;
    1158       48523 :     move16();
    1159     1246947 :     WHILE( LE_16( maxBand, MASA_FREQUENCY_BANDS ) && LE_16( MASA_band_grouping_24[maxBand], maxBin ) )
    1160             :     {
    1161     1198424 :         maxBand = (UWord8) add( maxBand, 1 );
    1162             :     }
    1163       48523 :     maxBand = (UWord8) sub( maxBand, 1 );
    1164             : 
    1165       48523 :     IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
    1166             :     {
    1167             :         /* need to apply the sampling rate correction also for the EXT output MASA meta buffer */
    1168        5545 :         masa_sample_rate_band_correction_fx( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hQMetaData, maxBand, 0, hMasa->data.extOutMeta );
    1169             :     }
    1170             :     ELSE
    1171             :     {
    1172       42978 :         masa_sample_rate_band_correction_fx( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hQMetaData, maxBand, 0, NULL );
    1173             :     }
    1174             : 
    1175       48523 :     return error;
    1176             : }
    1177             : 
    1178             : 
    1179             : /*-------------------------------------------------------------------*
    1180             :  * ivas_masa_prerender_fx()
    1181             :  *
    1182             :  * Apply gaining and copying of transport signals when needed
    1183             :  *-------------------------------------------------------------------*/
    1184             : 
    1185       32532 : void ivas_masa_prerender_fx(
    1186             :     Decoder_Struct *st_ivas,    /* i/o: IVAS decoder handle                                         */
    1187             :     Word32 *output_fx[],        /* i/o: synthesized core-coder transport channels                   */
    1188             :     Word16 *q_shift,            /* o  : specifies how much the Q-factor of output has changed by.   */
    1189             :     const Word16 output_frame,  /* i  : output frame length per channel                             */
    1190             :     const Word16 nchan_remapped /* i  : number of transports used in core                           */
    1191             : )
    1192             : {
    1193       32532 :     *q_shift = 0;
    1194       32532 :     move16();
    1195             : 
    1196       32532 :     test();
    1197       32532 :     test();
    1198       32532 :     IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && EQ_16( st_ivas->nchan_transport, 2 ) && EQ_16( nchan_remapped, 1 ) )
    1199             :     {
    1200        4501 :         IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
    1201             :         {
    1202         366 :             Copy32( output_fx[0], output_fx[1], output_frame ); /* Copy mono signal to stereo output channels */
    1203             :         }
    1204             :         ELSE
    1205             :         {
    1206        4135 :             test();
    1207        4135 :             IF( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) || EQ_32( st_ivas->renderer_type, RENDERER_DISABLE ) )
    1208             :             {
    1209        2927 :                 v_multc_fx( output_fx[0], SQRT2_FX, output_fx[0], output_frame ); /* q + 30 - 31 = q - 1*/ /* Gain transport signal when transmitting mono with cpe in order to match loudness */
    1210        2927 :                 *q_shift = -1;                                                                             /* Q has decreased by 1. */
    1211        2927 :                 move16();
    1212             :             }
    1213             :         }
    1214             :     }
    1215             : 
    1216       32532 :     return;
    1217             : }
    1218             : 
    1219             : 
    1220             : /*-------------------------------------------------------------------*
    1221             :  * Local functions
    1222             :  *-------------------------------------------------------------------*/
    1223             : 
    1224        5305 : static void index_16bits_fx(
    1225             :     IVAS_QMETADATA_HANDLE hQMetaData,
    1226             :     SPHERICAL_GRID_DATA *Sph_Grid16 )
    1227             : {
    1228             :     Word16 d, band, block;
    1229             : 
    1230       12384 :     FOR( d = 0; d < hQMetaData->no_directions; d++ )
    1231             :     {
    1232             :         /* Note: The band information is read from the first direction as it contains the full information.  */
    1233       72308 :         FOR( band = 0; band < hQMetaData->q_direction[0].cfg.nbands; band++ )
    1234             :         {
    1235      279030 :             FOR( block = 0; block < hQMetaData->q_direction[0].cfg.nblocks; block++ )
    1236             :             {
    1237      427602 :                 hQMetaData->q_direction[d].band_data[band].spherical_index[block] = index_theta_phi_16_fx( &( hQMetaData->q_direction[d].band_data[band].elevation_fx[block] ),
    1238      213801 :                                                                                                            &( hQMetaData->q_direction[d].band_data[band].azimuth_fx[block] ), Sph_Grid16 );
    1239      213801 :                 move16();
    1240             :             }
    1241             :         }
    1242             :     }
    1243             : 
    1244        5305 :     return;
    1245             : }
    1246             : 
    1247             : 
    1248             : /* Replicate subframe data when there is only one subframe sent */
    1249        5430 : static void replicate_subframes_fx(
    1250             :     IVAS_QMETADATA_HANDLE hQMetaData )
    1251             : {
    1252             :     Word16 sf, band, dir, nbands, ndirs;
    1253             : 
    1254        5430 :     nbands = hQMetaData->q_direction->cfg.nbands;
    1255        5430 :     move16();
    1256        5430 :     ndirs = hQMetaData->no_directions;
    1257        5430 :     move16();
    1258             : 
    1259       21720 :     FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1260             :     {
    1261      201813 :         FOR( band = 0; band < nbands; band++ )
    1262             :         {
    1263      421986 :             FOR( dir = 0; dir < ndirs; dir++ )
    1264             :             {
    1265      236463 :                 hQMetaData->q_direction[dir].band_data[band].spherical_index[sf] = hQMetaData->q_direction[dir].band_data[band].spherical_index[0];
    1266      236463 :                 move16();
    1267      236463 :                 hQMetaData->q_direction[dir].band_data[band].azimuth_fx[sf] = hQMetaData->q_direction[dir].band_data[band].azimuth_fx[0]; // Q22
    1268      236463 :                 move32();
    1269      236463 :                 hQMetaData->q_direction[dir].band_data[band].elevation_fx[sf] = hQMetaData->q_direction[dir].band_data[band].elevation_fx[0]; // Q22
    1270      236463 :                 move32();
    1271      236463 :                 hQMetaData->q_direction[dir].band_data[band].energy_ratio_fx[sf] = hQMetaData->q_direction[dir].band_data[band].energy_ratio_fx[0]; // Q30
    1272      236463 :                 move32();
    1273             : 
    1274      236463 :                 if ( hQMetaData->q_direction[dir].coherence_band_data != NULL )
    1275             :                 {
    1276      186894 :                     hQMetaData->q_direction[dir].coherence_band_data[band].spread_coherence[sf] = hQMetaData->q_direction[dir].coherence_band_data[band].spread_coherence[0];
    1277      186894 :                     move16();
    1278             :                 }
    1279             :             }
    1280             : 
    1281      185523 :             if ( hQMetaData->surcoh_band_data != NULL )
    1282             :             {
    1283      135954 :                 hQMetaData->surcoh_band_data[band].surround_coherence[sf] = hQMetaData->surcoh_band_data[band].surround_coherence[0];
    1284      135954 :                 move16();
    1285             :             }
    1286             :         }
    1287             :     }
    1288             : 
    1289        5430 :     return;
    1290             : }
    1291             : 
    1292             : 
    1293       23203 : static void restore_lowbitrate_masa_fx(
    1294             :     IVAS_QMETADATA_HANDLE hQMetaData,
    1295             :     const Word16 low_bitrate_mode,
    1296             :     const Word16 numCodingBands )
    1297             : {
    1298             :     Word16 sf, band;
    1299             : 
    1300       23203 :     IF( EQ_16( low_bitrate_mode, 1 ) )
    1301             :     {
    1302             :         /* With signal 1, we are in 5 frequency bands, 1 subframe mode. */
    1303             :         /* Replicate data to all subframes */
    1304       77280 :         FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1305             :         {
    1306      347760 :             FOR( band = 0; band < numCodingBands; band++ )
    1307             :             {
    1308             : 
    1309      289800 :                 hQMetaData->q_direction[0].band_data[band].spherical_index[sf] = hQMetaData->q_direction[0].band_data[band].spherical_index[0];
    1310      289800 :                 move16();
    1311      289800 :                 hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = hQMetaData->q_direction[0].band_data[band].azimuth_fx[0]; // Q22
    1312      289800 :                 move32();
    1313      289800 :                 hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = hQMetaData->q_direction[0].band_data[band].elevation_fx[0]; // Q22
    1314      289800 :                 move32();
    1315      289800 :                 hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[sf] = hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[0]; // Q30
    1316      289800 :                 move32();
    1317             : 
    1318      289800 :                 if ( hQMetaData->q_direction[0].coherence_band_data != NULL )
    1319             :                 {
    1320       80700 :                     hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[0];
    1321       80700 :                     move16();
    1322             :                 }
    1323      289800 :                 if ( hQMetaData->surcoh_band_data != NULL )
    1324             :                 {
    1325       80700 :                     hQMetaData->surcoh_band_data[band].surround_coherence[sf] = hQMetaData->surcoh_band_data[band].surround_coherence[0];
    1326       80700 :                     move16();
    1327             :                 }
    1328             :             }
    1329             :         }
    1330       19320 :         hQMetaData->q_direction->cfg.nblocks = 4;
    1331       19320 :         move16();
    1332             :     }
    1333             :     ELSE
    1334             :     {
    1335             :         /* With signal 0, we are in 1 frequency bands, 4 subframes mode. */
    1336             :         /* Replicate data to all bands */
    1337       19415 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1338             :         {
    1339       77660 :             FOR( band = 1; band < numCodingBands; band++ )
    1340             :             {
    1341       62128 :                 hQMetaData->q_direction[0].band_data[band].spherical_index[sf] = hQMetaData->q_direction[0].band_data[0].spherical_index[sf];
    1342       62128 :                 move16();
    1343       62128 :                 hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = hQMetaData->q_direction[0].band_data[0].azimuth_fx[sf]; // Q22
    1344       62128 :                 move32();
    1345       62128 :                 hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = hQMetaData->q_direction[0].band_data[0].elevation_fx[sf]; // Q22
    1346       62128 :                 move32();
    1347       62128 :                 hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[sf] = hQMetaData->q_direction[0].band_data[0].energy_ratio_fx[sf]; // Q30
    1348       62128 :                 move32();
    1349             : 
    1350       62128 :                 if ( hQMetaData->q_direction[0].coherence_band_data != NULL )
    1351             :                 {
    1352       21312 :                     hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hQMetaData->q_direction[0].coherence_band_data[0].spread_coherence[sf];
    1353       21312 :                     move16();
    1354             :                 }
    1355       62128 :                 if ( hQMetaData->surcoh_band_data != NULL )
    1356             :                 {
    1357       21312 :                     hQMetaData->surcoh_band_data[band].surround_coherence[sf] = hQMetaData->surcoh_band_data[0].surround_coherence[sf];
    1358       21312 :                     move16();
    1359             :                 }
    1360             :             }
    1361             :         }
    1362        3883 :         hQMetaData->q_direction->cfg.nbands = numCodingBands;
    1363        3883 :         move16();
    1364             :     }
    1365             : 
    1366       23203 :     return;
    1367             : }
    1368             : 
    1369             : 
    1370         289 : static ivas_error init_lfe_synth_data_fx(
    1371             :     Decoder_Struct *st_ivas,  /* i  : IVAS decoder struct     */
    1372             :     MASA_DECODER_HANDLE hMasa /* i/o: MASA decoder structure  */
    1373             : )
    1374             : {
    1375             :     Word32 output_Fs;
    1376             :     AUDIO_CONFIG output_config;
    1377             : 
    1378         289 :     output_Fs = st_ivas->hDecoderConfig->output_Fs;
    1379         289 :     move16();
    1380         289 :     output_config = st_ivas->hDecoderConfig->output_config;
    1381         289 :     move32();
    1382             : 
    1383         289 :     IF( ( hMasa->hMasaLfeSynth = (MCMASA_LFE_SYNTH_DATA_HANDLE) malloc( sizeof( MCMASA_LFE_SYNTH_DATA ) ) ) == NULL )
    1384             :     {
    1385           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
    1386             :     }
    1387             : 
    1388         289 :     hMasa->hMasaLfeSynth->transportEneSmooth_fx = 0;
    1389         289 :     move32();
    1390         289 :     hMasa->hMasaLfeSynth->transportEneSmooth_q = Q31;
    1391         289 :     move16();
    1392         289 :     hMasa->hMasaLfeSynth->protoLfeEneSmooth_fx = 0;
    1393         289 :     move32();
    1394         289 :     hMasa->hMasaLfeSynth->protoLfeEneSmooth_q = Q31;
    1395         289 :     move16();
    1396         289 :     hMasa->hMasaLfeSynth->targetEneLfeSmooth_fx = 0;
    1397         289 :     move32();
    1398         289 :     hMasa->hMasaLfeSynth->targetEneLfeSmooth_q = Q31;
    1399         289 :     move16();
    1400         289 :     hMasa->hMasaLfeSynth->targetEneTransSmooth_fx = 0;
    1401         289 :     move32();
    1402         289 :     hMasa->hMasaLfeSynth->targetEneTransSmooth_q = Q31;
    1403         289 :     move16();
    1404             : 
    1405         289 :     set16_fx( hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
    1406         289 :     hMasa->hMasaLfeSynth->lfeGainPrevIndex = 0;
    1407         289 :     move16();
    1408             : 
    1409         289 :     test();
    1410         289 :     test();
    1411         289 :     test();
    1412         289 :     test();
    1413         289 :     test();
    1414         289 :     test();
    1415         289 :     test();
    1416         289 :     test();
    1417         289 :     test();
    1418         289 :     test();
    1419         289 :     test();
    1420         289 :     test();
    1421         289 :     IF( st_ivas->hOutSetup.separateChannelEnabled &&
    1422             :         ( EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1 ) ||
    1423             :           EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) ||
    1424             :           EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) ||
    1425             :           EQ_16( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ||
    1426             :           EQ_16( output_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_HOA2 ) ||
    1427             :           EQ_16( output_config, IVAS_AUDIO_CONFIG_HOA3 ) ||
    1428             :           ( EQ_16( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && ( st_ivas->hOutSetup.num_lfe > 0 ) ) ) )
    1429          13 :     {
    1430             :         Word16 bufferSize;
    1431             :         Word16 i;
    1432             :         Word16 slot_size;
    1433             : 
    1434             :         /* Ring buffer for the filterbank of the LFE synthesis.
    1435             :          * The filterbank is using moving average lowpass filter with the crossover of 120 Hz. */
    1436             :         /* bufferSize = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES ); */
    1437          13 :         bufferSize = extract_l( Mpy_32_32_r( output_Fs, 10737418 /* 1 / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) in Q31 */ ) );
    1438             : 
    1439          13 :         IF( ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx = (Word32 *) malloc( bufferSize * sizeof( Word32 ) ) ) == NULL )
    1440             :         {
    1441           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
    1442             :         }
    1443          13 :         set32_fx( hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx, 0, bufferSize ); // Q11
    1444             : 
    1445          13 :         hMasa->hMasaLfeSynth->ringBufferLoPointer = 0;
    1446          13 :         move16();
    1447          13 :         hMasa->hMasaLfeSynth->ringBufferHiPointer = shr( bufferSize, 1 );
    1448          13 :         move16();
    1449          13 :         hMasa->hMasaLfeSynth->lowpassSum_fx = 0; // Q11
    1450          13 :         move16();
    1451          13 :         hMasa->hMasaLfeSynth->ringBufferSize = bufferSize;
    1452          13 :         move16();
    1453             : 
    1454             :         /* Ring buffer for additional lowpass filter for the LFE signal.
    1455             :          * Moving average lowpass filter with the crossover of 240 Hz. */
    1456          13 :         bufferSize = shr( bufferSize, 1 );
    1457             : 
    1458          13 :         IF( ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx = (Word32 *) malloc( bufferSize * sizeof( Word32 ) ) ) == NULL )
    1459             :         {
    1460           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
    1461             :         }
    1462          13 :         set32_fx( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx, 0, bufferSize ); // Q11
    1463             : 
    1464          13 :         hMasa->hMasaLfeSynth->ringBufferLoPointer2 = 0;
    1465          13 :         move16();
    1466          13 :         hMasa->hMasaLfeSynth->lowpassSum2_fx = 0; // Q11
    1467          13 :         move32();
    1468          13 :         hMasa->hMasaLfeSynth->ringBufferSize2 = bufferSize;
    1469          13 :         move16();
    1470             : 
    1471             :         /* Delay buffer for matching the delay of the lowpass filter */
    1472          13 :         bufferSize = shr( bufferSize, 1 ); /* The delay of the moving average lowpass filter is bufferSize / 2 */
    1473          13 :         IF( ( hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx = (Word32 *) malloc( bufferSize * sizeof( Word32 ) ) ) == NULL )
    1474             :         {
    1475           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
    1476             :         }
    1477          13 :         set32_fx( hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx, 0, bufferSize ); // Q11
    1478          13 :         hMasa->hMasaLfeSynth->delayBuffer_syncLp_size = bufferSize;
    1479          13 :         move16();
    1480             : 
    1481             :         /* Delay buffer for syncing with DirAC rendering */
    1482          13 :         bufferSize = sub( sub( NS2SA_FX2( output_Fs, IVAS_FB_DEC_DELAY_NS ), shr( hMasa->hMasaLfeSynth->ringBufferSize, 1 ) ), shr( hMasa->hMasaLfeSynth->ringBufferSize2, 1 ) );
    1483          13 :         IF( ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx = (Word32 *) malloc( bufferSize * sizeof( Word32 ) ) ) == NULL )
    1484             :         {
    1485           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
    1486             :         }
    1487          13 :         set32_fx( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx, 0, bufferSize ); // Q11
    1488          13 :         hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size = bufferSize;
    1489          13 :         move16();
    1490             : 
    1491             :         /* Interpolation between slots */
    1492          13 :         hMasa->hMasaLfeSynth->lfeGainPrev_fx = 0; // Q15
    1493          13 :         move16();
    1494          13 :         hMasa->hMasaLfeSynth->transportGainPrev_fx = MAX_WORD16; // Q15
    1495          13 :         move16();
    1496             : 
    1497             :         /* slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); */
    1498          13 :         slot_size = extract_l( Mpy_32_32( output_Fs, 2684355 /* 1 / ( FRAMES_PER_SEC * CLDFB_NO_COL_MAX ) in Q31*/ ) );
    1499             : 
    1500         753 :         FOR( i = 0; i < slot_size; i++ )
    1501             :         {
    1502         740 :             hMasa->hMasaLfeSynth->interpolator_fx[i] = div_s( add( i, 1 ), slot_size ); // Q15
    1503         740 :             move16();
    1504             :         }
    1505             :     }
    1506         276 :     ELSE IF( st_ivas->hOutSetup.separateChannelEnabled && EQ_16( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && EQ_16( st_ivas->hOutSetup.num_lfe, 0 ) )
    1507           0 :     {
    1508             :         Word16 bufferSize;
    1509             : 
    1510             :         /* Delay buffer for syncing with DirAC rendering */
    1511           0 :         bufferSize = NS2SA_FX2( output_Fs, IVAS_FB_DEC_DELAY_NS );
    1512           0 :         IF( ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx = (Word32 *) malloc( bufferSize * sizeof( Word32 ) ) ) == NULL )
    1513             :         {
    1514           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
    1515             :         }
    1516           0 :         set32_fx( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx, 0, bufferSize ); // Q11
    1517           0 :         hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size = bufferSize;
    1518           0 :         move16();
    1519             : 
    1520           0 :         hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx = NULL;
    1521           0 :         hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx = NULL;
    1522           0 :         hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx = NULL;
    1523             :     }
    1524             :     ELSE
    1525             :     {
    1526         276 :         hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx = NULL;
    1527         276 :         hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx = NULL;
    1528         276 :         hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx = NULL;
    1529         276 :         hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx = NULL;
    1530             :     }
    1531             : 
    1532         289 :     return IVAS_ERR_OK;
    1533             : }
    1534             : 
    1535             : 
    1536             : /*! r: Number of bits read */
    1537       11493 : static Word16 decode_lfe_to_total_energy_ratio_fx(
    1538             :     MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, /* i/o: McMASA LFE structure */
    1539             :     UWord16 *bitstream,                         /* i  : bitstream            */
    1540             :     Word16 *index,                              /* i/o: bitstream position   */
    1541             :     const Word32 ivas_total_brate               /* i  : total bitrate        */
    1542             : )
    1543             : {
    1544             :     Word16 i;
    1545             :     Word16 lfeToTotalEnergyRatioIndices[3];
    1546             :     Word16 VQBits;
    1547             :     Word16 log2LFEaverage_fx;
    1548             :     Word16 lfeToTotalEnergyRatioTemp_fx;
    1549             :     UWord16 byteBuffer;
    1550             :     Word16 lfeBitsRead;
    1551             : 
    1552       11493 :     lfeBitsRead = 0;
    1553       11493 :     move16();
    1554       11493 :     byteBuffer = bitstream[( *index )--];
    1555       11493 :     move16();
    1556       11493 :     lfeBitsRead = add( lfeBitsRead, 1 );
    1557       11493 :     lfeToTotalEnergyRatioIndices[0] = byteBuffer; /* First LFE index */
    1558       11493 :     move16();
    1559             : 
    1560       11493 :     IF( EQ_32( ivas_total_brate, IVAS_13k2 ) ) /* 1-bit adaptive LFE gain quantizer at 13.2 kbps */
    1561             :     {
    1562        1360 :         lfeToTotalEnergyRatioTemp_fx = hMasaLfeSynth->lfeToTotalEnergyRatio_fx[3]; // Q14 /* Take memory from the last subframe */
    1563        1360 :         move16();
    1564        1360 :         IF( EQ_16( lfeToTotalEnergyRatioIndices[0], 1 ) )
    1565             :         {
    1566         128 :             IF( EQ_16( hMasaLfeSynth->lfeGainPrevIndex, 1 ) )
    1567             :             {
    1568          86 :                 Word16 lfe_beta_theta = mult( MCMASA_LFE_THETA_Q14, MCMASA_LFE_BETA_Q15 );          // Q 14 + 15 - 15 = Q14
    1569          86 :                 lfeToTotalEnergyRatioTemp_fx = add( lfeToTotalEnergyRatioTemp_fx, lfe_beta_theta ); /* larger "bump-up" energy */
    1570             :             }
    1571             :             ELSE
    1572             :             {
    1573          42 :                 lfeToTotalEnergyRatioTemp_fx = add( lfeToTotalEnergyRatioTemp_fx, MCMASA_LFE_BETA_Q14 ); /* "bump-up" energy */
    1574             :             }
    1575             :         }
    1576             :         ELSE
    1577             :         {
    1578        1232 :             lfeToTotalEnergyRatioTemp_fx = mult( lfeToTotalEnergyRatioTemp_fx, MCMASA_LFE_ALPHA_Q15 ); // Q14
    1579             :         }
    1580        1360 :         if ( GT_16( lfeToTotalEnergyRatioTemp_fx, ONE_IN_Q14 ) )
    1581             :         {
    1582           0 :             lfeToTotalEnergyRatioTemp_fx = ONE_IN_Q14;
    1583           0 :             move16();
    1584             :         }
    1585        1360 :         hMasaLfeSynth->lfeGainPrevIndex = lfeToTotalEnergyRatioIndices[0];
    1586        1360 :         move16();
    1587        6800 :         FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    1588             :         {
    1589        5440 :             hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = lfeToTotalEnergyRatioTemp_fx; /* will always be less than 16384 */
    1590        5440 :             move16();
    1591             :         }
    1592             :     }
    1593             :     ELSE /* Bitrates >= 16.4 kbps */
    1594             :     {
    1595       10133 :         IF( EQ_16( lfeToTotalEnergyRatioIndices[0], 0 ) )
    1596             :         {
    1597       42530 :             FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    1598             :             {
    1599       34024 :                 hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = 0;
    1600       34024 :                 move16();
    1601             :             }
    1602             :         }
    1603             :         ELSE
    1604             :         {
    1605        1627 :             byteBuffer = (UWord16) L_shl( bitstream[( *index )--], 2 );
    1606        1627 :             byteBuffer = (UWord16) L_add( byteBuffer, L_shl( bitstream[( *index )--], 1 ) );
    1607        1627 :             byteBuffer = (UWord16) L_add( byteBuffer, bitstream[( *index )--] );
    1608        1627 :             move16();
    1609        1627 :             move16();
    1610        1627 :             move16();
    1611        1627 :             lfeBitsRead = add( lfeBitsRead, 3 );
    1612        1627 :             lfeToTotalEnergyRatioIndices[1] = byteBuffer; /* Scalar index */
    1613        1627 :             move16();
    1614        1627 :             log2LFEaverage_fx = usdequant_fx( lfeToTotalEnergyRatioIndices[1], MCMASA_LFE_QLOW_Q12, MCMASA_LFE_DELTA_Q11 ); // Q12
    1615             : 
    1616             :             /* 16.4 kbps sends only scalar gain, above it VQ is used */
    1617        1627 :             IF( GE_32( ivas_total_brate, IVAS_24k4 ) )
    1618             :             {
    1619             :                 /* Depending on average (scalar) gain more bits are sent for VQ LFE gain */
    1620        1522 :                 SWITCH( lfeToTotalEnergyRatioIndices[1] )
    1621             :                 {
    1622         211 :                     case 0:
    1623             :                     case 1:
    1624         211 :                         VQBits = 0;
    1625         211 :                         move16();
    1626         211 :                         BREAK;
    1627          94 :                     case 2:
    1628          94 :                         VQBits = 1;
    1629          94 :                         move16();
    1630          94 :                         BREAK;
    1631          90 :                     case 3:
    1632          90 :                         VQBits = 2;
    1633          90 :                         move16();
    1634          90 :                         BREAK;
    1635         229 :                     case 4:
    1636         229 :                         VQBits = 3;
    1637         229 :                         move16();
    1638         229 :                         BREAK;
    1639         898 :                     default:
    1640         898 :                         VQBits = 4;
    1641         898 :                         move16();
    1642             :                 }
    1643        1522 :                 byteBuffer = 0;
    1644        1522 :                 move16();
    1645        6075 :                 FOR( i = 0; i < VQBits; i++ )
    1646             :                 {
    1647        4553 :                     byteBuffer = (UWord16) L_add( byteBuffer, L_shl( bitstream[( *index )--], sub( sub( VQBits, 1 ), i ) ) );
    1648        4553 :                     move16();
    1649        4553 :                     lfeBitsRead = add( lfeBitsRead, 1 );
    1650             :                 }
    1651        1522 :                 lfeToTotalEnergyRatioIndices[2] = byteBuffer; /* VQ index */
    1652        1522 :                 move16();
    1653             :             }
    1654             : 
    1655        8135 :             FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
    1656             :             {
    1657             :                 Word16 tmp16, exp;
    1658             :                 Word32 tmp32;
    1659        6508 :                 IF( EQ_32( ivas_total_brate, IVAS_16k4 ) )
    1660             :                 {
    1661         420 :                     tmp32 = BASOP_util_Pow2( L_deposit_h( log2LFEaverage_fx ), 15 - Q12, &exp );  /* Q(31 - exp)*/
    1662         420 :                     tmp16 = round_fx( tmp32 );                                                    /* Q(31-exp) -> Q(15 - exp) */
    1663         420 :                     hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = shr_sat( tmp16, sub( 1, exp ) ); /* should saturate. Q(15 - exp) - (1 - exp)->Q14 */
    1664         420 :                     move16();
    1665             :                 }
    1666             :                 ELSE
    1667             :                 {
    1668        6088 :                     tmp16 = shr( extract_l( L_shr_r( McMASA_LFEGain_vectors_fx[4 * lfeToTotalEnergyRatioIndices[2] + i], Q12 ) ), 1 ); /* Q12 */
    1669        6088 :                     tmp16 = add( log2LFEaverage_fx, tmp16 );                                                                           /* Q12 */
    1670        6088 :                     tmp32 = BASOP_util_Pow2( L_deposit_h( tmp16 ), 15 - Q12, &exp );                                                   /* Q(31 - exp) */
    1671        6088 :                     tmp16 = round_fx( tmp32 );                                                                                         /* Q(31-exp) -> Q(15 - exp) */
    1672        6088 :                     hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = shr_sat( tmp16, sub( 1, exp ) );                                      /* should saturate. Q(15 - exp) - (1 - exp) -> Q14 */
    1673        6088 :                     move16();
    1674             :                 }
    1675             : 
    1676        6508 :                 hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = s_min( hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i], ONE_IN_Q14 );
    1677        6508 :                 move16();
    1678        6508 :                 hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = s_max( hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i], 0 );
    1679        6508 :                 move16();
    1680             :             }
    1681             :         }
    1682             :     }
    1683             : 
    1684       11493 :     return lfeBitsRead;
    1685             : }
    1686             : 
    1687             : 
    1688             : /*-------------------------------------------------------------------*
    1689             :  * ivas_masa_dec_reconfigure()
    1690             :  *
    1691             :  * Reconfigure IVAS MASA decoder
    1692             :  *-------------------------------------------------------------------*/
    1693             : 
    1694        2842 : ivas_error ivas_masa_dec_reconfigure_fx(
    1695             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder structure  */
    1696             : )
    1697             : {
    1698             :     Word16 n, tmp, num_bits;
    1699             :     Word16 sce_id, cpe_id;
    1700             :     UWord16 *bit_stream;
    1701             :     Decoder_State **sts;
    1702             :     UWord32 ivas_total_brate, last_ivas_total_brate;
    1703             :     Word16 numCldfbAnalyses_old, numCldfbSyntheses_old;
    1704             :     ivas_error error;
    1705             :     Word32 ism_total_brate;
    1706             :     Word16 pos_idx;
    1707             : 
    1708        2842 :     ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
    1709        2842 :     move32();
    1710        2842 :     last_ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate;
    1711        2842 :     move32();
    1712             : 
    1713        2842 :     test();
    1714             : #ifdef NONBE_FIX_1220_OMASA_JBM_EXT_USAN
    1715        2842 :     test();
    1716             :     /* Copy state to TC buffer if granularity matches and we are not in OMASA EXT rendering mode */
    1717        2842 :     IF( st_ivas->hSpatParamRendCom != NULL && EQ_16( st_ivas->hSpatParamRendCom->slot_size, st_ivas->hTcBuffer->n_samples_granularity ) && NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
    1718             : #else
    1719             :     IF( st_ivas->hSpatParamRendCom != NULL && EQ_16( st_ivas->hSpatParamRendCom->slot_size, st_ivas->hTcBuffer->n_samples_granularity ) )
    1720             : #endif
    1721             :     {
    1722        2514 :         Copy( st_ivas->hSpatParamRendCom->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS );
    1723        2514 :         st_ivas->hTcBuffer->nb_subframes = st_ivas->hSpatParamRendCom->nb_subframes;
    1724        2514 :         move16();
    1725        2514 :         st_ivas->hTcBuffer->subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered;
    1726        2514 :         move16();
    1727             :     }
    1728             : 
    1729        2842 :     ivas_init_dec_get_num_cldfb_instances_fx( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old );
    1730             : 
    1731             :     /* renderer might have changed, reselect */
    1732        2842 :     ivas_renderer_select( st_ivas );
    1733             : 
    1734        2842 :     test();
    1735        2842 :     test();
    1736        2842 :     test();
    1737        2842 :     test();
    1738        2842 :     test();
    1739        2842 :     test();
    1740             : #ifdef NONBE_FIX_1220_OMASA_JBM_EXT_USAN
    1741        2842 :     test();
    1742             : #endif
    1743        2842 :     IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend == NULL ) ||
    1744             :         ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin[0] == NULL ) )
    1745             :     {
    1746             :         /* init a new DirAC dec */
    1747          54 :         IF( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK )
    1748             :         {
    1749           0 :             return error;
    1750             :         }
    1751             :     }
    1752             : #ifdef NONBE_FIX_1220_OMASA_JBM_EXT_USAN
    1753        2788 :     ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_DISABLE ) || EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) || EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) )
    1754             :     {
    1755             :         /* close all unnecessary parametric decoding and rendering */
    1756         253 :         ivas_dirac_dec_close_binaural_data_fx( st_ivas->hDiracDecBin );
    1757         253 :         ivas_dirac_rend_close_fx( &( st_ivas->hDirACRend ) );
    1758         253 :         ivas_spat_hSpatParamRendCom_close_fx( &( st_ivas->hSpatParamRendCom ) );
    1759         253 :         ivas_dirac_dec_close_fx( &( st_ivas->hDirAC ) );
    1760             :     }
    1761             : #else
    1762             :     ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_DISABLE ) || EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) )
    1763             :     {
    1764             :         IF( st_ivas->hDirAC != NULL )
    1765             :         {
    1766             :             /* close all unnecessary parametric decoding and rendering */
    1767             :             ivas_dirac_dec_close_binaural_data_fx( st_ivas->hDiracDecBin );
    1768             :             ivas_dirac_rend_close_fx( &( st_ivas->hDirACRend ) );
    1769             :             ivas_spat_hSpatParamRendCom_close_fx( &( st_ivas->hSpatParamRendCom ) );
    1770             :             ivas_dirac_dec_close_fx( &( st_ivas->hDirAC ) );
    1771             :         }
    1772             :     }
    1773             : #endif
    1774             :     /* possible reconfigure is done later */
    1775             : 
    1776             :     /*-----------------------------------------------------------------*
    1777             :      * Allocate and initialize SCE/CPE and other handles
    1778             :      *-----------------------------------------------------------------*/
    1779             : 
    1780        2842 :     IF( st_ivas->hSCE[0] != NULL )
    1781             :     {
    1782        1806 :         bit_stream = st_ivas->hSCE[0]->hCoreCoder[0]->bit_stream;
    1783        1806 :         move16();
    1784             :     }
    1785             :     ELSE
    1786             :     {
    1787        1036 :         bit_stream = st_ivas->hCPE[0]->hCoreCoder[0]->bit_stream;
    1788        1036 :         move16();
    1789             :     }
    1790             : 
    1791        2842 :     num_bits = 0;
    1792        2842 :     move16();
    1793             : 
    1794             :     Word16 tmp_e;
    1795             :     Word32 tmp32;
    1796             : 
    1797        5520 :     FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
    1798             :     {
    1799             :         // st_ivas->hSCE[sce_id]->element_brate = ivas_total_brate / st_ivas->nchan_transport;
    1800        2678 :         st_ivas->hSCE[sce_id]->element_brate = L_deposit_h( BASOP_Util_Divide3216_Scale( ivas_total_brate, st_ivas->nchan_transport, &tmp_e ) );
    1801        2678 :         st_ivas->hSCE[sce_id]->element_brate = L_shr( st_ivas->hSCE[sce_id]->element_brate, sub( 15, tmp_e ) ); // Q0
    1802        2678 :         move32();
    1803        2678 :         move32();
    1804             : 
    1805        2678 :         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() */
    1806        2678 :         move32();
    1807             : 
    1808        2678 :         sts = st_ivas->hSCE[sce_id]->hCoreCoder;
    1809        2678 :         sts[0]->bit_stream = bit_stream + num_bits;
    1810             : 
    1811             :         // num_bits += (int16_t)(st_ivas->hSCE[sce_id]->element_brate / FRAMES_PER_SEC);
    1812        2678 :         tmp = extract_l( Mpy_32_32( st_ivas->hSCE[sce_id]->element_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) );
    1813        2678 :         num_bits = add( num_bits, tmp );
    1814             : 
    1815        2678 :         test();
    1816        2678 :         test();
    1817        2678 :         test();
    1818        2678 :         IF( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin[0] != NULL )
    1819             :         {
    1820        1126 :             IF( NE_32( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_RECONFIGURE ) ), IVAS_ERR_OK ) )
    1821             :             {
    1822           0 :                 return error;
    1823             :             }
    1824             :         }
    1825             :     }
    1826             : 
    1827        4995 :     FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ )
    1828             :     {
    1829             :         // st_ivas->hCPE[cpe_id]->element_brate = ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS;
    1830        2153 :         tmp32 = L_deposit_h( BASOP_Util_Divide3216_Scale( ivas_total_brate, st_ivas->nchan_transport, &tmp_e ) );
    1831        2153 :         tmp32 = L_shr( tmp32, sub( 15, tmp_e ) ); // Q0
    1832        2153 :         st_ivas->hCPE[cpe_id]->element_brate = imult3216( tmp32, CPE_CHANNELS );
    1833        2153 :         move32();
    1834             : 
    1835             :         /* prepare bitstream buffers */
    1836        6459 :         FOR( n = 0; n < CPE_CHANNELS; n++ )
    1837             :         {
    1838        4306 :             tmp = CPE_CHANNELS;
    1839        4306 :             move16();
    1840        4306 :             if ( GT_16( st_ivas->nCPE, 1 ) )
    1841             :             {
    1842           0 :                 st_ivas->nCPE = 1;
    1843           0 :                 move16();
    1844             :             }
    1845             :             /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */
    1846             :             // st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / tmp;
    1847        4306 :             tmp32 = L_deposit_h( BASOP_Util_Divide3216_Scale( st_ivas->hCPE[cpe_id]->element_brate, tmp, &tmp_e ) );
    1848        4306 :             tmp32 = L_shr( tmp32, sub( 15, tmp_e ) );
    1849        4306 :             st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = tmp32;
    1850        4306 :             move32();
    1851             :         }
    1852        2153 :         sts = st_ivas->hCPE[cpe_id]->hCoreCoder;
    1853        2153 :         sts[0]->bit_stream = bit_stream + num_bits;
    1854             : 
    1855             :         // num_bits += (int16_t) ( st_ivas->hCPE[cpe_id]->element_brate / FRAMES_PER_SEC );
    1856        2153 :         tmp = extract_l( Mpy_32_32( st_ivas->hCPE[cpe_id]->element_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) );
    1857        2153 :         num_bits = add( num_bits, tmp );
    1858             : 
    1859        2153 :         test();
    1860        2153 :         test();
    1861        2153 :         test();
    1862        2153 :         test();
    1863             : #ifdef NONBE_FIX_1143_MASA_BRSW
    1864        2153 :         test();
    1865        2153 :         test();
    1866        2153 :         IF( ( LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && GE_32( last_ivas_total_brate, MASA_STEREO_MIN_BITRATE ) ) ||
    1867             :             ( LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && EQ_32( last_ivas_total_brate, FRAME_NO_DATA ) ) ||
    1868             :             ( LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && EQ_32( last_ivas_total_brate, IVAS_SID_5k2 ) ) )
    1869             : #else
    1870             :         IF( ( LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && GE_32( last_ivas_total_brate, MASA_STEREO_MIN_BITRATE ) ) ||
    1871             :             ( LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && EQ_32( last_ivas_total_brate, FRAME_NO_DATA ) ) )
    1872             : #endif
    1873             :         {
    1874         433 :             st_ivas->hCPE[cpe_id]->nchan_out = 1;
    1875         433 :             move16();
    1876             : 
    1877         433 :             test();
    1878         433 :             test();
    1879         433 :             test();
    1880         433 :             test();
    1881         433 :             test();
    1882         433 :             IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend != NULL ) || ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin[0] != NULL ) )
    1883             :             {
    1884         351 :                 IF( NE_32( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_RECONFIGURE ) ), IVAS_ERR_OK ) )
    1885             :                 {
    1886           0 :                     return error;
    1887             :                 }
    1888             :             }
    1889             :         }
    1890        1720 :         ELSE IF( GE_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && LT_32( last_ivas_total_brate, MASA_STEREO_MIN_BITRATE ) )
    1891             :         {
    1892         445 :             st_ivas->hCPE[cpe_id]->nchan_out = CPE_CHANNELS;
    1893         445 :             move16();
    1894             : 
    1895         445 :             test();
    1896         445 :             test();
    1897         445 :             test();
    1898         445 :             test();
    1899         445 :             test();
    1900         445 :             IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend != NULL ) || ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin[0] != NULL ) )
    1901             :             {
    1902         402 :                 IF( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK )
    1903             :                 {
    1904           0 :                     return error;
    1905             :                 }
    1906             :             }
    1907             :         }
    1908             :     }
    1909             : 
    1910       25578 :     FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
    1911             :     {
    1912       22736 :         IF( st_ivas->hDiracDecBin[pos_idx] != NULL )
    1913             :         {
    1914             :             /* regularization factor is bitrate-dependent */
    1915        1252 :             st_ivas->hDiracDecBin[pos_idx]->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate );
    1916        1252 :             move16();
    1917             :         }
    1918             :     }
    1919             : 
    1920        2842 :     test();
    1921        2842 :     IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && EQ_32( st_ivas->last_ivas_format, MASA_FORMAT ) ) /* note: switching within OMASA is handled in ivas_omasa_dec_config() */
    1922             :     {
    1923             :         /*-----------------------------------------------------------------*
    1924             :          * TD Decorrelator
    1925             :          *-----------------------------------------------------------------*/
    1926             : 
    1927        1310 :         IF( st_ivas->hDiracDecBin[0] != NULL )
    1928             :         {
    1929         596 :             IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin[0]->hTdDecorr ), &( st_ivas->hDiracDecBin[0]->useTdDecorr ) ) ), IVAS_ERR_OK ) )
    1930             :             {
    1931           0 :                 return error;
    1932             :             }
    1933             :         }
    1934             : 
    1935             :         /*-----------------------------------------------------------------*
    1936             :          * CLDFB instances
    1937             :          *-----------------------------------------------------------------*/
    1938             : 
    1939        1310 :         IF( st_ivas->hSpar )
    1940             :         {
    1941           0 :             Word16 Q_tmp = getScaleFactor16( st_ivas->hSpar->hFbMixer->cldfb_cross_fade_fx, 16 );
    1942           0 :             Scale_sig( st_ivas->hSpar->hFbMixer->cldfb_cross_fade_fx, 16, Q_tmp - st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q ); // st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q -> Q_tmp
    1943           0 :             st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q = Q_tmp;
    1944           0 :             move16();
    1945             :         }
    1946             : 
    1947        1310 :         IF( NE_32( ( error = ivas_cldfb_dec_reconfig_fx( st_ivas, st_ivas->nchan_transport, numCldfbAnalyses_old, numCldfbSyntheses_old ) ), IVAS_ERR_OK ) )
    1948             :         {
    1949           0 :             return error;
    1950             :         }
    1951             :     }
    1952             : 
    1953             :     /*-----------------------------------------------------------------*
    1954             :      * Set-up MASA coding elements and bitrates
    1955             :      *-----------------------------------------------------------------*/
    1956             : 
    1957        2842 :     ism_total_brate = 0;
    1958        2842 :     move32();
    1959             : 
    1960        2842 :     test();
    1961        2842 :     test();
    1962        2842 :     test();
    1963        2842 :     test();
    1964        2842 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && GT_32( 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 ) ) )
    1965             :     {
    1966        1967 :         FOR( n = 0; n < st_ivas->nSCE; n++ )
    1967             :         {
    1968        1263 :             ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[n]->element_brate );
    1969             :         }
    1970             :     }
    1971             : 
    1972        2842 :     ivas_masa_set_elements_fx( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate );
    1973             : 
    1974             : #ifndef NONBE_1199_OMASA_JBM_BRATE_SW_FLUSH
    1975             :     IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) )
    1976             :     {
    1977             :         IF( NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
    1978             :         {
    1979             :             move16();
    1980             :             st_ivas->nchan_ism = 0; /* Initialization if it has not been already read from the end of the bitstream at the same time
    1981             :                                     with reading of the format: nchan_ism is needed in MASA format because for the EXT output in
    1982             :                                     MASA-only (pre-rendering mode of OMASA) the number of ISMs to output correct number of empty objects is needed */
    1983             :         }
    1984             :         st_ivas->ism_mode = ISM_MODE_NONE;
    1985             :         move16();
    1986             :     }
    1987             : #endif
    1988             :     {
    1989             :         Word16 tc_nchan_to_allocate;
    1990             :         Word16 tc_nchan_transport;
    1991             :         TC_BUFFER_MODE buffer_mode_new;
    1992             :         Word16 n_samples_granularity;
    1993             : 
    1994             : #ifdef NONBE_1303_REND_GRANULARITY
    1995        2842 :         n_samples_granularity = ivas_jbm_dec_get_render_granularity_fx( st_ivas->renderer_type, ivas_renderer_secondary_select_fx( st_ivas ), st_ivas->hDecoderConfig->output_Fs );
    1996             : #else
    1997             :         n_samples_granularity = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS );
    1998             :         move16();
    1999             : #endif
    2000        2842 :         buffer_mode_new = ivas_jbm_dec_get_tc_buffer_mode_fx( st_ivas );
    2001        2842 :         tc_nchan_transport = ivas_jbm_dec_get_num_tc_channels_fx( st_ivas );
    2002             : 
    2003        2842 :         tc_nchan_to_allocate = tc_nchan_transport;
    2004        2842 :         move16();
    2005             : 
    2006        2842 :         test();
    2007        2842 :         test();
    2008        2842 :         test();
    2009        2842 :         test();
    2010        2842 :         test();
    2011        2842 :         test();
    2012        2842 :         IF( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_16( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) )
    2013             :         {
    2014        1252 :             IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
    2015             :             {
    2016         470 :                 tc_nchan_to_allocate = add( BINAURAL_CHANNELS, st_ivas->nchan_ism );
    2017             :             }
    2018             :             ELSE
    2019             :             {
    2020         782 :                 tc_nchan_to_allocate = shl( BINAURAL_CHANNELS, 1 );
    2021             :             }
    2022        1252 :             test();
    2023        1252 :             test();
    2024        1252 :             test();
    2025        1252 :             IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
    2026             :             {
    2027             : #ifndef NONBE_1303_REND_GRANULARITY
    2028             :                 n_samples_granularity = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); /* Use the same granularity as tdrend */
    2029             : #endif
    2030          54 :                 IF( GT_16( n_samples_granularity, st_ivas->hTcBuffer->n_samples_granularity ) )
    2031             :                 {
    2032          54 :                     IF( NE_32( ( error = ivas_jbm_dec_set_discard_samples_fx( st_ivas ) ), IVAS_ERR_OK ) )
    2033             :                     {
    2034           0 :                         return error;
    2035             :                     }
    2036             :                 }
    2037             :             }
    2038        1198 :             ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
    2039             :             {
    2040         572 :                 IF( LT_16( n_samples_granularity, st_ivas->hTcBuffer->n_samples_granularity ) )
    2041             :                 {
    2042             :                     /* flush already done in IVAS_DEC_ReadFormat() */
    2043             :                 }
    2044             :             }
    2045             :         }
    2046        1590 :         ELSE IF( EQ_16( st_ivas->nchan_transport, 1 ) && ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && EQ_32( st_ivas->hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) ) )
    2047             :         {
    2048             :             /* addtl channel for CNG */
    2049         190 :             tc_nchan_to_allocate = add( tc_nchan_to_allocate, 1 );
    2050             :         }
    2051        1400 :         ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) || EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) ) )
    2052             :         {
    2053          37 :             tc_nchan_transport = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
    2054          37 :             tc_nchan_to_allocate = add( st_ivas->nchan_transport, st_ivas->nchan_ism );
    2055             :         }
    2056        2842 :         test();
    2057        2842 :         test();
    2058        2842 :         IF( NE_16( tc_nchan_transport, st_ivas->hTcBuffer->nchan_transport_jbm ) || NE_16( tc_nchan_to_allocate, st_ivas->hTcBuffer->nchan_transport_internal ) || NE_16( buffer_mode_new, st_ivas->hTcBuffer->tc_buffer_mode ) )
    2059             :         {
    2060        1565 :             IF( NE_32( error = ivas_jbm_dec_tc_buffer_reconfigure_fx( st_ivas, buffer_mode_new, tc_nchan_transport, tc_nchan_to_allocate, tc_nchan_to_allocate, n_samples_granularity ), IVAS_ERR_OK ) )
    2061             :             {
    2062           0 :                 return error;
    2063             :             }
    2064             :         }
    2065             : 
    2066        2842 :         test();
    2067        2842 :         IF( st_ivas->hSpatParamRendCom != NULL && EQ_16( st_ivas->hSpatParamRendCom->slot_size, st_ivas->hTcBuffer->n_samples_granularity ) )
    2068             :         {
    2069        2516 :             Copy( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hSpatParamRendCom->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS );
    2070        2516 :             st_ivas->hSpatParamRendCom->nb_subframes = st_ivas->hTcBuffer->nb_subframes;
    2071        2516 :             move16();
    2072        2516 :             st_ivas->hSpatParamRendCom->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered;
    2073        2516 :             move16();
    2074             :         }
    2075             : 
    2076        2842 :         test();
    2077        2842 :         test();
    2078        2842 :         IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
    2079             :         {
    2080          54 :             Word16 granularityMultiplier = idiv1616( st_ivas->hTcBuffer->n_samples_granularity, st_ivas->hSpatParamRendCom->slot_size );
    2081         486 :             FOR( n = 0; n < MAX_JBM_SUBFRAMES_5MS; n++ )
    2082             :             {
    2083         432 :                 st_ivas->hSpatParamRendCom->subframe_nbslots[n] = i_mult( st_ivas->hTcBuffer->subframe_nbslots[n], granularityMultiplier );
    2084         432 :                 move16();
    2085             :             }
    2086             :         }
    2087             :     }
    2088             : 
    2089        2842 :     return IVAS_ERR_OK;
    2090             : }
    2091             : 
    2092             : 
    2093             : /*-------------------------------------------------------------------*
    2094             :  * ivas_spar_param_to_masa_param_mapping()
    2095             :  *
    2096             :  * Determine MASA metadata from the SPAR metadata
    2097             :  *-------------------------------------------------------------------*/
    2098             : 
    2099      151681 : void ivas_spar_param_to_masa_param_mapping_fx(
    2100             :     Decoder_Struct *st_ivas,                                           /* i/o: IVAS decoder struct               */
    2101             :     Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i  : Input audio in CLDFB domain, real */
    2102             :     Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i  : Input audio in CLDFB domain, imag */
    2103             :     Word16 q_cldfb[6][CLDFB_SLOTS_PER_SUBFRAME],
    2104             :     const Word16 subframe /* i  : Subframe to map                   */
    2105             : )
    2106             : {
    2107             :     Word16 i, j, band, bin, slot, ch, nBins, nchan_transport;
    2108             :     Word16 mixer_mat_index;
    2109             :     Word16 dirac_write_idx;
    2110             :     DIRAC_DEC_HANDLE hDirAC;
    2111             :     DIFFUSE_DISTRIBUTION_HANDLE hDiffuseDist;
    2112             :     Word32 mixer_mat_sf_bands_real_fx[SPAR_DIRAC_SPLIT_START_BAND][FOA_CHANNELS][FOA_CHANNELS];
    2113             :     Word32 mixer_mat_sf_bins_real_fx[CLDFB_NO_CHANNELS_MAX][FOA_CHANNELS][FOA_CHANNELS];
    2114             :     Word16 *band_grouping;
    2115             :     Word16 band_start, band_end;
    2116             :     Word32 transportSignalEnergies_32[2][CLDFB_NO_CHANNELS_MAX];
    2117             :     Word64 transportSignalEnergies_64[2][CLDFB_NO_CHANNELS_MAX];
    2118             :     Word32 transportSignalCrossCorrelation_32[CLDFB_NO_CHANNELS_MAX];
    2119             :     Word64 transportSignalCrossCorrelation_64[CLDFB_NO_CHANNELS_MAX];
    2120             :     Word64 instEne_fx;
    2121             :     Word32 inCovarianceMtx_fx[FOA_CHANNELS][FOA_CHANNELS];
    2122      151681 :     Word16 q_inCovarianceMtx = 31;
    2123             :     Word32 foaCovarianceMtx_fx[FOA_CHANNELS][FOA_CHANNELS];
    2124             :     Word32 Iy_fx, Iz_fx, Ix_fx, E_fx, azi_fx, ele_fx, I_fx, ratio_float_fx;
    2125             :     Word32 diffuseGainX_fx, diffuseGainY_fx, diffuseGainZ_fx, diffuseGainSum_fx;
    2126             :     Word16 slot_idx, slot_idx_start, sf;
    2127             :     SPAR_DEC_HANDLE hSpar;
    2128             :     Word16 slot_fac_fx;
    2129      151681 :     Word16 q_slot_fac = 0;
    2130             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
    2131      151681 :     Word16 common_q = 31;
    2132             :     Word64 azi_val, ele_val;
    2133      151681 :     Word64 transportSignalEnergies_max = 0;
    2134      151681 :     Word64 transportSignalCrossCorrelation_max = 0;
    2135      151681 :     Word64 max_common_val = 0;
    2136      151681 :     Word16 azi_q = 0, ele_q = 0;
    2137             :     Word16 num_q, denom_q, res_q;
    2138      151681 :     Word16 headroom_left_max_common = 63; // 0 value
    2139      151681 :     Word16 q_max_common = 31;
    2140             :     Word32 ratio_fx; /* Q30 */
    2141      151681 :     move16();
    2142      151681 :     move16();
    2143      151681 :     move16();
    2144      151681 :     move16();
    2145      151681 :     move16();
    2146      151681 :     move16();
    2147      151681 :     move16();
    2148      151681 :     move64();
    2149      151681 :     move64();
    2150      151681 :     move64();
    2151             : 
    2152      455043 :     FOR( i = 0; i < 2; i++ )
    2153             :     {
    2154      303362 :         set64_fx( transportSignalEnergies_64[i], 0, CLDFB_NO_CHANNELS_MAX );
    2155      303362 :         set32_fx( transportSignalEnergies_32[i], 0, CLDFB_NO_CHANNELS_MAX );
    2156             :     }
    2157      151681 :     set32_fx( transportSignalCrossCorrelation_32, 0, CLDFB_NO_CHANNELS_MAX );
    2158      151681 :     set64_fx( transportSignalCrossCorrelation_64, 0, CLDFB_NO_CHANNELS_MAX );
    2159      758405 :     FOR( i = 0; i < FOA_CHANNELS; i++ )
    2160             :     {
    2161      606724 :         set32_fx( inCovarianceMtx_fx[i], 0, FOA_CHANNELS );
    2162      606724 :         set32_fx( foaCovarianceMtx_fx[i], 0, FOA_CHANNELS );
    2163             :     }
    2164             : 
    2165     1061767 :     FOR( Word16 ind = 0; ind < 6; ind++ )
    2166             :     {
    2167     4550430 :         FOR( Word16 ind2 = 0; ind2 < 4; ind2++ )
    2168             :         {
    2169     3640344 :             if ( GT_16( common_q, q_cldfb[ind][ind2] ) )
    2170             :             {
    2171      217440 :                 common_q = q_cldfb[ind][ind2];
    2172      217440 :                 move16();
    2173             :             }
    2174             :         }
    2175             :     }
    2176             :     /* Set values */
    2177      151681 :     hDirAC = st_ivas->hDirAC;
    2178      151681 :     hSpatParamRendCom = st_ivas->hSpatParamRendCom;
    2179      151681 :     hSpatParamRendCom->numParametricDirections = 1;
    2180      151681 :     move16();
    2181      151681 :     hSpatParamRendCom->numSimultaneousDirections = 1;
    2182      151681 :     move16();
    2183      151681 :     hDiffuseDist = st_ivas->hDiracDecBin[0]->hDiffuseDist;
    2184      151681 :     nchan_transport = st_ivas->nchan_transport;
    2185      151681 :     move16();
    2186      151681 :     band_grouping = hDirAC->band_grouping;
    2187      151681 :     move16();
    2188      151681 :     hSpar = st_ivas->hSpar;
    2189      151681 :     dirac_write_idx = hSpatParamRendCom->render_to_md_map[subframe];
    2190      151681 :     move16();
    2191             : 
    2192             :     /* Init arrays */
    2193      758405 :     FOR( i = 0; i < FOA_CHANNELS; i++ )
    2194             :     {
    2195      606724 :         set32_fx( inCovarianceMtx_fx[i], 0, FOA_CHANNELS );
    2196             :     }
    2197             : 
    2198             :     /* Delay the SPAR mixing matrices to have them synced with the audio */
    2199      151681 :     slot_idx_start = hSpar->slots_rendered;
    2200      151681 :     move16();
    2201      151681 :     slot_fac_fx = BASOP_Util_Divide3232_Scale( 1, hSpar->subframe_nbslots[subframe], &q_slot_fac );
    2202      151681 :     IF( q_slot_fac < 0 )
    2203             :     {
    2204      148931 :         slot_fac_fx = shr( slot_fac_fx, -1 * q_slot_fac ); // Q15
    2205             :     }
    2206      752907 :     FOR( slot_idx = 0; slot_idx < hSpar->subframe_nbslots[subframe]; slot_idx++ )
    2207             :     {
    2208      601226 :         IF( hSpar->render_to_md_map[slot_idx + slot_idx_start] == 0 )
    2209             :         {
    2210       37588 :             sf = 0;
    2211       37588 :             move16();
    2212             :         }
    2213             :         ELSE
    2214             :         {
    2215      563638 :             sf = shr( hSpar->render_to_md_map[slot_idx + slot_idx_start], JBM_CLDFB_SLOTS_IN_SUBFRAME_LOG2 );
    2216             :         }
    2217             : 
    2218      601226 :         IF( LT_16( sf, SPAR_META_DELAY_SUBFRAMES ) )
    2219             :         {
    2220      300626 :             mixer_mat_index = add( sf, add( sub( MAX_PARAM_SPATIAL_SUBFRAMES, SPAR_META_DELAY_SUBFRAMES ), 1 ) );
    2221     2705634 :             FOR( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ )
    2222             :             {
    2223    12025040 :                 FOR( i = 0; i < FOA_CHANNELS; i++ )
    2224             :                 {
    2225    48100160 :                     FOR( j = 0; j < FOA_CHANNELS; j++ )
    2226             :                     {
    2227    38480128 :                         mixer_mat_sf_bands_real_fx[band][i][j] = L_shl( Mpy_32_16_1( st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[mixer_mat_index][i][j][band], slot_fac_fx ), 1 ); // 30//making q to 31
    2228    38480128 :                         move32();
    2229             :                     }
    2230             :                 }
    2231             :             }
    2232             :         }
    2233             :         ELSE
    2234             :         {
    2235      300600 :             mixer_mat_index = ( ivas_get_spar_dec_md_num_subframes( st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ) == 1 ) ? 0 : ( sf - SPAR_META_DELAY_SUBFRAMES );
    2236     2705400 :             FOR( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ )
    2237             :             {
    2238    12024000 :                 FOR( i = 0; i < FOA_CHANNELS; i++ )
    2239             :                 {
    2240    48096000 :                     FOR( j = 0; j < FOA_CHANNELS; j++ )
    2241             :                     {
    2242    38476800 :                         mixer_mat_sf_bands_real_fx[band][i][j] = L_shl( Mpy_32_16_1( st_ivas->hSpar->hMdDec->mixer_mat_fx[i][j][band + mixer_mat_index * IVAS_MAX_NUM_BANDS], slot_fac_fx ), 1 ); // 30//making q to 31
    2243    38476800 :                         move32();
    2244             :                     }
    2245             :                 }
    2246             :             }
    2247             :         }
    2248             :     }
    2249             : 
    2250             :     /* Map the mixing matrices from the frequency bands to frequency bins */
    2251      151681 :     bin = 0;
    2252      151681 :     move16();
    2253     1365129 :     FOR( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ )
    2254             :     {
    2255     1213448 :         band_start = band_grouping[band];
    2256     1213448 :         move16();
    2257     1213448 :         band_end = band_grouping[band + 1];
    2258     1213448 :         move16();
    2259     2881939 :         FOR( bin = band_start; bin < band_end; bin++ )
    2260             :         {
    2261     8342455 :             FOR( i = 0; i < FOA_CHANNELS; i++ )
    2262             :             {
    2263    33369820 :                 FOR( j = 0; j < FOA_CHANNELS; j++ )
    2264             :                 {
    2265    26695856 :                     mixer_mat_sf_bins_real_fx[bin][i][j] = mixer_mat_sf_bands_real_fx[band][i][j]; // 31
    2266    26695856 :                     move32();
    2267             :                 }
    2268             :             }
    2269             :         }
    2270             :     }
    2271             : 
    2272      151681 :     nBins = bin;
    2273      151681 :     move16();
    2274             : 
    2275             :     /* Determine MASA metadata */
    2276             :     /* Determine transport signal energies and cross correlations when more than 1 TC */
    2277      151681 :     IF( EQ_16( nchan_transport, 2 ) )
    2278             :     {
    2279      428615 :         FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    2280             :         {
    2281     4112316 :             FOR( bin = 0; bin < nBins; bin++ )
    2282             :             {
    2283    11308869 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2284             :                 {
    2285     7539246 :                     instEne_fx = W_mult0_32_32( L_shr_sat( inRe_fx[ch][slot][bin], sub( q_cldfb[ch][slot], common_q ) ), L_shr_sat( inRe_fx[ch][slot][bin], sub( q_cldfb[ch][slot], common_q ) ) );                               // Q(2 * common_q)
    2286     7539246 :                     instEne_fx = W_add( instEne_fx, W_mult0_32_32( (Word64) L_shr_sat( inIm_fx[ch][slot][bin], sub( q_cldfb[ch][slot], common_q ) ), L_shr_sat( inIm_fx[ch][slot][bin], sub( q_cldfb[ch][slot], common_q ) ) ) ); // Q(2 * common_q)
    2287     7539246 :                     transportSignalEnergies_64[ch][bin] = W_add( transportSignalEnergies_64[ch][bin], instEne_fx );                                                                                                               // Q(2 * common_q)
    2288     7539246 :                     move64();
    2289     7539246 :                     move64();
    2290             :                 }
    2291     3769623 :                 transportSignalCrossCorrelation_64[bin] = W_add( transportSignalCrossCorrelation_64[bin], W_mult0_32_32( L_shr_sat( inRe_fx[0][slot][bin], sub( q_cldfb[0][slot], common_q ) ), L_shr_sat( inRe_fx[1][slot][bin], sub( q_cldfb[0][slot], common_q ) ) ) ); // Q(2 * common_q)
    2292     3769623 :                 transportSignalCrossCorrelation_64[bin] = W_add( transportSignalCrossCorrelation_64[bin], W_mult0_32_32( L_shr_sat( inIm_fx[0][slot][bin], sub( q_cldfb[0][slot], common_q ) ), L_shr_sat( inIm_fx[1][slot][bin], sub( q_cldfb[0][slot], common_q ) ) ) ); // Q(2 * common_q)
    2293     3769623 :                 move64();
    2294     3769623 :                 move64();
    2295             :             }
    2296             :         }
    2297             : 
    2298             : 
    2299     1031064 :         FOR( bin = 0; bin < nBins; bin++ )
    2300             :         {
    2301     2835426 :             FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2302             :             {
    2303             :                 // transportSignalEnergies_max = GT_64( transportSignalEnergies_max, transportSignalEnergies_64[ch][bin] ) ? transportSignalEnergies_max : transportSignalEnergies_64[ch][bin];
    2304             : 
    2305     1890284 :                 if ( LE_64( transportSignalEnergies_max, transportSignalEnergies_64[ch][bin] ) )
    2306             :                 {
    2307      118209 :                     transportSignalEnergies_max = transportSignalEnergies_64[ch][bin]; // Q(2 * common_q)
    2308      118209 :                     move64();
    2309             :                 }
    2310             :             }
    2311             : 
    2312             :             // transportSignalCrossCorrelation_max = GT_64( transportSignalCrossCorrelation_max, transportSignalCrossCorrelation_64[bin] ) ? transportSignalCrossCorrelation_max : transportSignalCrossCorrelation_64[bin];
    2313             : 
    2314      945142 :             if ( LE_64( transportSignalCrossCorrelation_max, transportSignalCrossCorrelation_64[bin] ) )
    2315             :             {
    2316      117527 :                 transportSignalCrossCorrelation_max = transportSignalCrossCorrelation_64[bin]; // Q(2 * common_q)
    2317      117527 :                 move64();
    2318             :             }
    2319             :         }
    2320             : 
    2321             :         // max_common_val = GT_64( transportSignalEnergies_max, transportSignalCrossCorrelation_max ) ? transportSignalEnergies_max : transportSignalCrossCorrelation_max;
    2322             : 
    2323       85922 :         IF( GT_64( transportSignalEnergies_max, transportSignalCrossCorrelation_max ) )
    2324             :         {
    2325       85859 :             max_common_val = transportSignalEnergies_max; // Q(2 * common_q)
    2326             :         }
    2327             :         ELSE
    2328             :         {
    2329          63 :             max_common_val = transportSignalCrossCorrelation_max; // Q(2 * common_q)
    2330             :         }
    2331       85922 :         move64();
    2332             : 
    2333       85922 :         IF( max_common_val != 0 )
    2334             :         {
    2335       85859 :             headroom_left_max_common = W_norm( max_common_val );
    2336       85859 :             IF( GT_16( headroom_left_max_common, 32 ) )
    2337             :             {
    2338       34716 :                 FOR( bin = 0; bin < nBins; bin++ )
    2339             :                 {
    2340       95469 :                     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2341             :                     {
    2342       63646 :                         transportSignalEnergies_32[ch][bin] = W_extract_l( transportSignalEnergies_64[ch][bin] ); // Q(q_max_common)
    2343       63646 :                         move32();
    2344             :                     }
    2345       31823 :                     transportSignalCrossCorrelation_32[bin] = W_extract_l( transportSignalCrossCorrelation_64[bin] ); // Q(q_max_common)
    2346       31823 :                     move32();
    2347             :                 }
    2348        2893 :                 q_max_common = shl( common_q, 1 );
    2349             :             }
    2350             :             ELSE
    2351             :             {
    2352      995592 :                 FOR( bin = 0; bin < nBins; bin++ )
    2353             :                 {
    2354     2737878 :                     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2355             :                     {
    2356     1825252 :                         transportSignalEnergies_32[ch][bin] = W_extract_l( W_shr( transportSignalEnergies_64[ch][bin], sub( 32, headroom_left_max_common ) ) ); // Q(q_max_common)
    2357     1825252 :                         move32();
    2358             :                     }
    2359      912626 :                     transportSignalCrossCorrelation_32[bin] = W_extract_l( W_shr( transportSignalCrossCorrelation_64[bin], sub( 32, headroom_left_max_common ) ) ); // Q(q_max_common)
    2360      912626 :                     move32();
    2361             :                 }
    2362       82966 :                 q_max_common = sub( shl( common_q, 1 ), sub( 32, headroom_left_max_common ) );
    2363             :             }
    2364             :         }
    2365             :         ELSE
    2366             :         {
    2367         756 :             FOR( bin = 0; bin < nBins; bin++ )
    2368             :             {
    2369        2079 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2370             :                 {
    2371        1386 :                     transportSignalEnergies_32[ch][bin] = 0; // Q(q_max_common)
    2372        1386 :                     move32();
    2373             :                 }
    2374         693 :                 transportSignalCrossCorrelation_32[bin] = 0; // Q(q_max_common)
    2375         693 :                 move32();
    2376             :             }
    2377          63 :             q_max_common = 31;
    2378          63 :             move16();
    2379             :         }
    2380             :     }
    2381             : 
    2382             : 
    2383      151681 :     IF( hDiffuseDist != NULL )
    2384             :     {
    2385      151681 :         set32_fx( hDiffuseDist->diffuseRatioX_fx, 0, CLDFB_NO_CHANNELS_MAX );
    2386      151681 :         set32_fx( hDiffuseDist->diffuseRatioY_fx, 0, CLDFB_NO_CHANNELS_MAX );
    2387      151681 :         set32_fx( hDiffuseDist->diffuseRatioZ_fx, 0, CLDFB_NO_CHANNELS_MAX );
    2388             :     }
    2389             : 
    2390     1820172 :     FOR( bin = 0; bin < nBins; bin++ )
    2391             :     {
    2392             :         /* Set the energy of the first transport signal */
    2393     1668491 :         IF( EQ_16( nchan_transport, 1 ) )
    2394             :         {
    2395      723349 :             inCovarianceMtx_fx[0][0] = ONE_IN_Q31; /* In case of 1TC, fixed value can be used, Q(q_inCovarianceMtx)*/
    2396      723349 :             move32();
    2397      723349 :             q_inCovarianceMtx = 31; /* In case of 1TC, fixed value can be used */
    2398      723349 :             move16();
    2399             :         }
    2400             :         ELSE
    2401             :         {
    2402      945142 :             inCovarianceMtx_fx[0][0] = transportSignalEnergies_32[0][bin]; /* In case of 2TC, use actual energies */
    2403      945142 :             move32();
    2404      945142 :             q_inCovarianceMtx = q_max_common; /* In case of 1TC, fixed value can be used */
    2405      945142 :             move16();
    2406             :         }
    2407             : 
    2408             :         /* Decorrelated channels assumed to have the same energy as the source channel */
    2409     1668491 :         inCovarianceMtx_fx[1][1] = inCovarianceMtx_fx[0][0];
    2410     1668491 :         move32();
    2411     1668491 :         inCovarianceMtx_fx[2][2] = inCovarianceMtx_fx[0][0];
    2412     1668491 :         move32();
    2413     1668491 :         inCovarianceMtx_fx[3][3] = inCovarianceMtx_fx[0][0];
    2414     1668491 :         move32();
    2415             : 
    2416             :         /* In case residuals were transmitted, use their actual energies and cross correlations */
    2417     1668491 :         IF( EQ_16( nchan_transport, 2 ) )
    2418             :         {
    2419             : 
    2420      945142 :             inCovarianceMtx_fx[1][1] = transportSignalEnergies_32[1][bin];
    2421      945142 :             move32();
    2422      945142 :             inCovarianceMtx_fx[0][1] = transportSignalCrossCorrelation_32[bin];
    2423      945142 :             move32();
    2424      945142 :             inCovarianceMtx_fx[1][0] = inCovarianceMtx_fx[0][1];
    2425      945142 :             move32();
    2426      945142 :             q_inCovarianceMtx = q_max_common;
    2427      945142 :             move16();
    2428             :         }
    2429             : 
    2430     1668491 :         compute_foa_cov_matrix_fx( foaCovarianceMtx_fx, inCovarianceMtx_fx, mixer_mat_sf_bins_real_fx[bin] );
    2431             : 
    2432     1668491 :         Iy_fx = foaCovarianceMtx_fx[0][1]; /* Intensity in Y direction */ // Q(q_inCovarianceMtx) + 2 * Q(31) - 62
    2433     1668491 :         move32();
    2434     1668491 :         Iz_fx = foaCovarianceMtx_fx[0][2]; /* Intensity in Z direction */ // Q(q_inCovarianceMtx) + 2 * Q(31) - 62
    2435     1668491 :         move32();
    2436     1668491 :         Ix_fx = foaCovarianceMtx_fx[0][3]; /* Intensity in X direction */ // Q(q_inCovarianceMtx) + 2 * Q(31) - 62
    2437     1668491 :         move32();
    2438             : 
    2439     1668491 :         Word64 I1 = W_mult0_32_32( Ix_fx, Ix_fx );   // 2 * (Q(q_inCovarianceMtx) + 2 * Q(31) - 62)
    2440     1668491 :         Word64 I2 = W_mult0_32_32( Iy_fx, Iy_fx );   // 2 * (Q(q_inCovarianceMtx) + 2 * Q(31) - 62)
    2441     1668491 :         Word64 I3 = W_mult0_32_32( Iz_fx, Iz_fx );   // 2 * (Q(q_inCovarianceMtx) + 2 * Q(31) - 62)
    2442     1668491 :         Word64 I_res = W_add( W_add( I1, I2 ), I3 ); // 2 * (Q(q_inCovarianceMtx) + 2 * Q(31) - 62)
    2443             : 
    2444     1668491 :         Word64 E_fx_64 = W_add( W_add( W_add( foaCovarianceMtx_fx[0][0], foaCovarianceMtx_fx[1][1] ), foaCovarianceMtx_fx[2][2] ), foaCovarianceMtx_fx[3][3] ); // Q(q_inCovarianceMtx)
    2445     1668491 :         E_fx = L_shr_sat( L_add_sat( L_add_sat( L_add_sat( foaCovarianceMtx_fx[0][0], foaCovarianceMtx_fx[1][1] ), foaCovarianceMtx_fx[2][2] ), foaCovarianceMtx_fx[3][3] ), 1 );
    2446     1668491 :         E_fx_64 = W_shr( E_fx_64, 1 );
    2447             : 
    2448     1668491 :         Word16 headroom_left_I_res = W_norm( I_res );
    2449             :         Word16 q_I_res;
    2450     1668491 :         IF( LT_16( headroom_left_I_res, 32 ) )
    2451             :         {
    2452     1337759 :             I_res = W_shr( I_res, sub( 32, headroom_left_I_res ) ); // q_I_res
    2453     1337759 :             q_I_res = sub( 31, sub( shl( q_inCovarianceMtx, 1 ), sub( 32, headroom_left_I_res ) ) );
    2454             :         }
    2455             :         ELSE
    2456             :         {
    2457      330732 :             q_I_res = sub( 31, shl( q_inCovarianceMtx, 1 ) );
    2458             :         }
    2459     1668491 :         I_fx = Sqrt32( (Word32) I_res, &q_I_res );
    2460     1668491 :         IF( q_I_res < 0 )
    2461             :         {
    2462      682672 :             I_fx = L_shr( I_fx, -1 * q_I_res );
    2463      682672 :             q_I_res = 0;
    2464      682672 :             move16();
    2465             :         }
    2466     1668491 :         azi_q = 0;
    2467     1668491 :         move16();
    2468     1668491 :         azi_fx = BASOP_util_atan2( Iy_fx, Ix_fx, azi_q ); /* Azimuth Q13*/
    2469             : 
    2470     1668491 :         Word64 I_ele_x = W_mult0_32_32( Ix_fx, Ix_fx ); // Q(ele_q)
    2471     1668491 :         Word64 I_ele_y = W_mult0_32_32( Iy_fx, Iy_fx ); // Q(ele_q)
    2472     1668491 :         Word64 I_ele = W_add( I_ele_x, I_ele_y );       // Q(ele_q)
    2473     1668491 :         Word16 headroom_left_I_ele = W_norm( I_ele );
    2474     1668491 :         IF( LT_16( headroom_left_I_ele, 32 ) )
    2475             :         {
    2476     1328804 :             I_ele = W_shr( I_ele, sub( 32, headroom_left_I_ele ) );
    2477     1328804 :             ele_q = sub( 31, sub( shl( q_inCovarianceMtx, 1 ), sub( 32, headroom_left_I_ele ) ) );
    2478             :         }
    2479             :         ELSE
    2480             :         {
    2481      339687 :             ele_q = sub( 31, shl( q_inCovarianceMtx, 1 ) );
    2482             :         }
    2483     1668491 :         I_ele = Sqrt32( W_extract_l( I_ele ), &ele_q );
    2484     1668491 :         IF( ele_q < 0 )
    2485             :         {
    2486      668772 :             I_ele = W_shr( I_ele, negate( ele_q ) ); // Q0
    2487      668772 :             ele_q = 0;
    2488      668772 :             move16();
    2489             :         }
    2490     1668491 :         ele_fx = BASOP_util_atan2( Iz_fx, W_extract_l( I_ele ), sub( sub( 31, q_inCovarianceMtx ), ele_q ) ); // Q13
    2491             : 
    2492     1668491 :         num_q = sub( 31, q_I_res );
    2493     1668491 :         denom_q = q_inCovarianceMtx;
    2494     1668491 :         move16();
    2495     1668491 :         res_q = 0;
    2496     1668491 :         move16();
    2497     1668491 :         IF( E_fx <= 0 )
    2498             :         {
    2499        4294 :             E_fx = 1;
    2500        4294 :             move32();
    2501             :         }
    2502     1668491 :         ratio_float_fx = BASOP_Util_Divide3232_Scale( I_fx, E_fx, &res_q );
    2503     1668491 :         res_q = sub( res_q, sub( num_q, denom_q ) );
    2504     1668491 :         ratio_fx = L_shl_sat( ratio_float_fx, add( Q15, res_q ) ); // Q(15 + res_q)
    2505             : 
    2506     1668491 :         ratio_fx = L_max( 0, L_min( ratio_fx, ONE_IN_Q30 ) ); // Q30
    2507             : 
    2508     1668491 :         azi_val = W_mult0_32_32( azi_fx, ONE_BY_PI_OVER_180_Q25 ); // Q13 + Q25
    2509     1668491 :         IF( azi_val < 0 )
    2510             :         {
    2511     1066212 :             azi_val = W_shr( W_neg( azi_val ), 13 + 25 ); // Q0
    2512     1066212 :             azi_val = W_neg( azi_val );
    2513             :         }
    2514             :         ELSE
    2515             :         {
    2516      602279 :             azi_val = W_shr( azi_val, 13 + 25 ); // Q0
    2517             :         }
    2518     1668491 :         ele_val = W_mult0_32_32( ele_fx, ONE_BY_PI_OVER_180_Q25 ); // Q13 + q25
    2519     1668491 :         IF( ele_val < 0 )
    2520             :         {
    2521      616438 :             ele_val = W_shr( W_neg( ele_val ), 13 + 25 ); // Q0
    2522      616438 :             ele_val = W_neg( ele_val );                   // Q0
    2523             :         }
    2524             :         ELSE
    2525             :         {
    2526     1052053 :             ele_val = W_shr( ele_val, 13 + 25 ); // Q0
    2527             :         }
    2528             : 
    2529     1668491 :         hSpatParamRendCom->azimuth[dirac_write_idx][bin] = extract_l( W_extract_l( azi_val ) ); // Q0
    2530     1668491 :         move16();
    2531     1668491 :         hSpatParamRendCom->elevation[dirac_write_idx][bin] = extract_l( W_extract_l( ele_val ) ); // Q0
    2532     1668491 :         move16();
    2533     1668491 :         hSpatParamRendCom->energy_ratio1_fx[dirac_write_idx][bin] = ratio_fx; // Q30
    2534     1668491 :         move32();
    2535     1668491 :         hSpatParamRendCom->diffuseness_vector_fx[dirac_write_idx][bin] = L_sub( ONE_IN_Q30, ratio_fx ); // Q30
    2536     1668491 :         move32();
    2537             : 
    2538     1668491 :         hSpatParamRendCom->spreadCoherence_fx[dirac_write_idx][bin] = 0; // Q15
    2539     1668491 :         move16();
    2540     1668491 :         hSpatParamRendCom->surroundingCoherence_fx[dirac_write_idx][bin] = 0; // q15
    2541     1668491 :         move16();
    2542             : 
    2543             :         /* Determine directional distribution of the indirect audio based on the SPAR mixing matrices (and the transport audio signals when 2 TC) */
    2544     1668491 :         IF( hDiffuseDist != NULL )
    2545             :         {
    2546     1668491 :             IF( EQ_16( nchan_transport, 1 ) )
    2547             :             {
    2548      723349 :                 diffuseGainY_fx = L_abs( mixer_mat_sf_bins_real_fx[bin][1][1] ); // Q31
    2549      723349 :                 diffuseGainX_fx = L_abs( mixer_mat_sf_bins_real_fx[bin][3][2] ); // Q31
    2550      723349 :                 diffuseGainZ_fx = L_abs( mixer_mat_sf_bins_real_fx[bin][2][3] ); // Q31
    2551             :             }
    2552      945142 :             ELSE IF( EQ_16( nchan_transport, 2 ) )
    2553             :             {
    2554      945142 :                 diffuseGainY_fx = L_abs( Mpy_32_32( mixer_mat_sf_bins_real_fx[bin][1][1], transportSignalEnergies_32[1][bin] ) );                                                                                                              // Q(q_max_common)
    2555      945142 :                 diffuseGainX_fx = L_add_sat( L_abs( Mpy_32_32( mixer_mat_sf_bins_real_fx[bin][3][2], transportSignalEnergies_32[0][bin] ) ), L_abs( Mpy_32_32( mixer_mat_sf_bins_real_fx[bin][3][1], transportSignalEnergies_32[1][bin] ) ) ); // Q(q_max_common)
    2556      945142 :                 diffuseGainZ_fx = L_add_sat( L_abs( Mpy_32_32( mixer_mat_sf_bins_real_fx[bin][2][3], transportSignalEnergies_32[0][bin] ) ), L_abs( Mpy_32_32( mixer_mat_sf_bins_real_fx[bin][2][1], transportSignalEnergies_32[1][bin] ) ) ); // Q(q_max_common)
    2557             :             }
    2558             :             ELSE
    2559             :             {
    2560           0 :                 diffuseGainY_fx = ONE_IN_Q31;
    2561           0 :                 move32();
    2562           0 :                 diffuseGainX_fx = ONE_IN_Q31;
    2563           0 :                 move32();
    2564           0 :                 diffuseGainZ_fx = ONE_IN_Q31;
    2565           0 :                 move32();
    2566             :             }
    2567     1668491 :             diffuseGainSum_fx = L_add_sat( L_add_sat( diffuseGainY_fx, diffuseGainX_fx ), diffuseGainZ_fx );
    2568             : 
    2569     1668491 :             IF( diffuseGainSum_fx == 0 )
    2570             :             {
    2571       31067 :                 hDiffuseDist->diffuseRatioX_fx[bin] = 715827904; //(1.0f / 3.0f) in Q31
    2572       31067 :                 move32();
    2573       31067 :                 hDiffuseDist->diffuseRatioY_fx[bin] = 715827904;
    2574       31067 :                 move32();
    2575       31067 :                 hDiffuseDist->diffuseRatioZ_fx[bin] = 715827904;
    2576       31067 :                 move32();
    2577             :             }
    2578             :             ELSE
    2579             :             {
    2580     1637424 :                 Word16 temp_q = 0;
    2581     1637424 :                 move16();
    2582             :                 Word16 intermediate_results; // temp_q
    2583     1637424 :                 intermediate_results = BASOP_Util_Divide3232_Scale( diffuseGainX_fx, L_add_sat( diffuseGainSum_fx, EPSILON_FX_SMALL ), &temp_q );
    2584             :                 // saturating value to less than 1
    2585     1637424 :                 IF( temp_q <= 0 )
    2586             :                 {
    2587     1444122 :                     intermediate_results = shr( intermediate_results, negate( temp_q ) ); // Q15
    2588             :                 }
    2589             :                 ELSE
    2590             :                 {
    2591      193302 :                     intermediate_results = shl_sat( intermediate_results, temp_q ); // Q15
    2592             :                 }
    2593     1637424 :                 hDiffuseDist->diffuseRatioX_fx[bin] = L_deposit_h( intermediate_results ); // Q31
    2594     1637424 :                 move32();
    2595             : 
    2596     1637424 :                 intermediate_results = BASOP_Util_Divide3232_Scale( diffuseGainY_fx, L_add_sat( diffuseGainSum_fx, EPSILON_FX_SMALL ), &temp_q );
    2597             :                 // saturating value to less than 1
    2598     1637424 :                 IF( temp_q <= 0 )
    2599             :                 {
    2600     1557163 :                     intermediate_results = shr( intermediate_results, negate( temp_q ) ); // Q15
    2601             :                 }
    2602             :                 ELSE
    2603             :                 {
    2604       80261 :                     intermediate_results = shl_sat( intermediate_results, temp_q ); // Q15
    2605             :                 }
    2606     1637424 :                 hDiffuseDist->diffuseRatioY_fx[bin] = L_deposit_h( intermediate_results ); // Q31
    2607     1637424 :                 move32();
    2608             : 
    2609     1637424 :                 intermediate_results = BASOP_Util_Divide3232_Scale( diffuseGainZ_fx, L_add_sat( diffuseGainSum_fx, EPSILON_FX_SMALL ), &temp_q );
    2610             :                 // saturating value to less than 1
    2611     1637424 :                 IF( temp_q <= 0 )
    2612             :                 {
    2613     1425217 :                     intermediate_results = shr( intermediate_results, negate( temp_q ) ); // Q15
    2614             :                 }
    2615             :                 ELSE
    2616             :                 {
    2617      212207 :                     intermediate_results = shl_sat( intermediate_results, temp_q ); // Q15
    2618             :                 }
    2619     1637424 :                 hDiffuseDist->diffuseRatioZ_fx[bin] = L_deposit_h( intermediate_results ); // Q31
    2620     1637424 :                 move32();
    2621             :             }
    2622             :         }
    2623             :     }
    2624             : 
    2625      151681 :     return;
    2626             : }
    2627             : 
    2628             : 
    2629             : /* Estimate FOA properties: foaCov = mixMtx * inCov * mixMtx' */
    2630     1668491 : static void compute_foa_cov_matrix_fx(
    2631             :     Word32 foaCov_fx[FOA_CHANNELS][FOA_CHANNELS], /* o  : Estimated FOA covariance matrix Qx*/
    2632             :     Word32 inCov_fx[FOA_CHANNELS][FOA_CHANNELS],  /* i  : Input covariance matrix         Qx*/
    2633             :     Word32 mixMtx_fx[FOA_CHANNELS][FOA_CHANNELS]  /* i  : Mixing matrix                   Q31*/
    2634             : )
    2635             : {
    2636             :     Word32 tmpMtx_fx[FOA_CHANNELS][FOA_CHANNELS];
    2637             :     Word16 i, j, k;
    2638             :     /* tmpMtx = mixMtx * inCov */
    2639     8342455 :     FOR( i = 0; i < FOA_CHANNELS; i++ )
    2640             :     {
    2641    33369820 :         FOR( j = 0; j < FOA_CHANNELS; j++ )
    2642             :         {
    2643    26695856 :             tmpMtx_fx[i][j] = 0;
    2644    26695856 :             move32();
    2645   133479280 :             FOR( k = 0; k < FOA_CHANNELS; k++ )
    2646             :             {
    2647   106783424 :                 tmpMtx_fx[i][j] = L_add_sat( tmpMtx_fx[i][j], Mpy_32_32( mixMtx_fx[i][k], inCov_fx[k][j] ) ); // Qx
    2648   106783424 :                 move32();
    2649             :             }
    2650             :         }
    2651             :     }
    2652             : 
    2653             :     /* foaCov = inCov * mixMtx' */
    2654     8342455 :     FOR( i = 0; i < FOA_CHANNELS; i++ )
    2655             :     {
    2656    33369820 :         FOR( j = 0; j < FOA_CHANNELS; j++ )
    2657             :         {
    2658    26695856 :             foaCov_fx[i][j] = 0;
    2659    26695856 :             move32();
    2660   133479280 :             FOR( k = 0; k < FOA_CHANNELS; k++ )
    2661             :             {
    2662   106783424 :                 foaCov_fx[i][j] = L_add_sat( foaCov_fx[i][j], Mpy_32_32( tmpMtx_fx[i][k], mixMtx_fx[j][k] ) ); // Qx
    2663   106783424 :                 move32();
    2664             :             }
    2665             :         }
    2666             :     }
    2667             : 
    2668     1668491 :     return;
    2669             : }
    2670             : 
    2671             : 
    2672        5608 : static void create_masa_ext_out_meta_fx(
    2673             :     MASA_DECODER *hMasa,
    2674             :     IVAS_QMETADATA_HANDLE hQMetaData,
    2675             :     const Word16 nchan_transport )
    2676             : {
    2677             :     Word16 i, sf, b_old, b_new, dir;
    2678             :     MASA_DECRIPTIVE_META *descMeta;
    2679             :     Word16 *bandMap;
    2680             :     UWord8 numCodingBands;
    2681             :     UWord8 numDirections;
    2682             :     MASA_DECODER_EXT_OUT_META *extOutMeta;
    2683             : 
    2684        5608 :     numDirections = hMasa->config.numberOfDirections;
    2685        5608 :     move16();
    2686        5608 :     numCodingBands = hMasa->config.numCodingBands;
    2687        5608 :     move16();
    2688        5608 :     bandMap = hMasa->data.band_mapping;
    2689        5608 :     move16();
    2690        5608 :     extOutMeta = hMasa->data.extOutMeta;
    2691        5608 :     descMeta = &hMasa->data.extOutMeta->descriptiveMeta;
    2692             : 
    2693             :     /* Construct descriptive meta */
    2694       50472 :     FOR( i = 0; i < 8; i++ )
    2695             :     {
    2696       44864 :         descMeta->formatDescriptor[i] = ivasmasaFormatDescriptor[i];
    2697       44864 :         move16();
    2698             :     }
    2699        5608 :     descMeta->numberOfDirections = (UWord8) sub( numDirections, 1 );
    2700        5608 :     descMeta->numberOfChannels = (UWord8) ( sub( nchan_transport, 1 ) );
    2701             :     /* Following correspond to "unknown" values until transmission is implemented */
    2702        5608 :     descMeta->sourceFormat = 0x0u;
    2703        5608 :     descMeta->transportDefinition = 0x0u;
    2704        5608 :     descMeta->channelAngle = 0x0u;
    2705        5608 :     descMeta->channelDistance = 0x0u;
    2706        5608 :     descMeta->channelLayout = 0x0u;
    2707             : 
    2708        5608 :     move16();
    2709        5608 :     move16();
    2710        5608 :     move16();
    2711        5608 :     move16();
    2712        5608 :     move16();
    2713        5608 :     move16();
    2714        5608 :     move16();
    2715             : 
    2716             :     /* Construct spatial metadata from qmetadata */
    2717       28040 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    2718             :     {
    2719       52020 :         FOR( dir = 0; dir < numDirections; dir++ )
    2720             :         {
    2721             :             /* Spherical index */
    2722      301152 :             FOR( b_old = 0; b_old < numCodingBands; b_old++ )
    2723             :             {
    2724      976480 :                 FOR( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ )
    2725             :                 {
    2726      704916 :                     extOutMeta->directionIndex[dir][sf][b_new] = hQMetaData->q_direction[dir].band_data[b_old].spherical_index[sf];
    2727      704916 :                     move16();
    2728             :                 }
    2729             :             }
    2730             : 
    2731             :             /* Direct-to-total ratio */
    2732      301152 :             FOR( b_old = 0; b_old < numCodingBands; b_old++ )
    2733             :             {
    2734      976480 :                 FOR( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ )
    2735             :                 {
    2736      704916 :                     UWord8 tmp = (UWord8) W_extract_h( W_mult_32_16( hQMetaData->q_direction[dir].band_data[b_old].energy_ratio_fx[sf], UINT8_MAX << 1 ) ); // Q0
    2737      704916 :                     move16();
    2738      704916 :                     extOutMeta->directToTotalRatio[dir][sf][b_new] = tmp; // Q0
    2739      704916 :                     move16();
    2740             :                 }
    2741             :             }
    2742             : 
    2743             :             /* Spread coherence */
    2744       29588 :             IF( hQMetaData->q_direction[dir].coherence_band_data != NULL )
    2745             :             {
    2746      252216 :                 FOR( b_old = 0; b_old < numCodingBands; b_old++ )
    2747             :                 {
    2748      745152 :                     FOR( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ )
    2749             :                     {
    2750      514368 :                         extOutMeta->spreadCoherence[dir][sf][b_new] = hQMetaData->q_direction[dir].coherence_band_data[b_old].spread_coherence[sf];
    2751      514368 :                         move16();
    2752             :                     }
    2753             :                 }
    2754             :             }
    2755             :             ELSE
    2756             :             {
    2757      203900 :                 FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
    2758             :                 {
    2759      195744 :                     extOutMeta->spreadCoherence[dir][sf][i] = 0;
    2760      195744 :                     move16();
    2761             :                 }
    2762             :             }
    2763             :         }
    2764             : 
    2765             :         /* Fill second direction with zero energy data for EXT output */
    2766       22432 :         IF( EQ_16( numDirections, 1 ) )
    2767             :         {
    2768      381900 :             FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
    2769             :             {
    2770      366624 :                 extOutMeta->directionIndex[1][sf][i] = SPH_IDX_FRONT;
    2771      366624 :                 move16();
    2772             :             }
    2773             : 
    2774      381900 :             FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
    2775             :             {
    2776      366624 :                 extOutMeta->directToTotalRatio[1][sf][i] = 0;
    2777      366624 :                 move16();
    2778             :             }
    2779             : 
    2780      381900 :             FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
    2781             :             {
    2782      366624 :                 extOutMeta->spreadCoherence[1][sf][i] = 0;
    2783      366624 :                 move16();
    2784             :             }
    2785             :         }
    2786             : 
    2787             :         /* Common spatial meta */
    2788             :         /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
    2789      208428 :         FOR( b_old = 0; b_old < numCodingBands; b_old++ )
    2790             :         {
    2791      719168 :             FOR( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ )
    2792             :             {
    2793      533172 :                 extOutMeta->diffuseToTotalRatio[sf][b_new] = UINT8_MAX;
    2794      533172 :                 move16();
    2795     1238088 :                 FOR( dir = 0; dir < numDirections; dir++ )
    2796             :                 {
    2797             : 
    2798      704916 :                     UWord8 tmp = (UWord8) W_extract_h( W_mult_32_16( hQMetaData->q_direction[dir].band_data[b_old].energy_ratio_fx[sf], UINT8_MAX << 1 ) ); // Q0
    2799      704916 :                     move16();
    2800      704916 :                     extOutMeta->diffuseToTotalRatio[sf][b_new] = (UWord8) sub( extOutMeta->diffuseToTotalRatio[sf][b_new], tmp ); // Q8
    2801      704916 :                     move16();
    2802             :                 }
    2803             :             }
    2804             :         }
    2805             : 
    2806             :         /* Surround coherence */
    2807       22432 :         IF( hQMetaData->surcoh_band_data != NULL )
    2808             :         {
    2809      159492 :             FOR( b_old = 0; b_old < numCodingBands; b_old++ )
    2810             :             {
    2811      487840 :                 FOR( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ )
    2812             :                 {
    2813      342624 :                     extOutMeta->surroundCoherence[sf][b_new] = hQMetaData->surcoh_band_data[b_old].surround_coherence[sf];
    2814      342624 :                     move16();
    2815             :                 }
    2816             :             }
    2817             :         }
    2818             :         ELSE
    2819             :         {
    2820      203900 :             FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
    2821             :             {
    2822      195744 :                 extOutMeta->surroundCoherence[sf][i] = 0;
    2823      195744 :                 move16();
    2824             :             }
    2825             :         }
    2826             :     }
    2827             : 
    2828        5608 :     return;
    2829             : }
    2830             : 
    2831             : 
    2832        5902 : static void decode_index_slice_fx(
    2833             :     Word16 index,           /* i  : index to decode                        */
    2834             :     Word16 *ratio_idx_ism,  /* o  : decodec array of integers              Q0*/
    2835             :     const Word16 nchan_ism, /* i  : number of elements in array (objects)  */
    2836             :     const Word16 K          /* i  : sum of array elements                  Q0*/
    2837             : )
    2838             : {
    2839             :     Word16 i, j, sum, elem;
    2840             :     Word16 base[MAX_NUM_OBJECTS];
    2841             : 
    2842        5902 :     SWITCH( nchan_ism )
    2843             :     {
    2844         218 :         case 2:
    2845         218 :             ratio_idx_ism[0] = index;
    2846         218 :             move16();
    2847         218 :             ratio_idx_ism[1] = sub( K, ratio_idx_ism[0] );
    2848         218 :             move16();
    2849         218 :             BREAK;
    2850        5684 :         case 3:
    2851             :         case 4:
    2852             :         {
    2853        5684 :             j = 0;
    2854        5684 :             move16();
    2855      793586 :             WHILE( index >= 0 )
    2856             :             {
    2857      787902 :                 IF( valid_ratio_index_fx( j, K, nchan_ism - 1 ) )
    2858             :                 {
    2859      217283 :                     index = sub( index, 1 );
    2860             :                 }
    2861      787902 :                 j = add( j, 1 );
    2862             :             }
    2863        5684 :             j = sub( j, 1 );
    2864        5684 :             base[0] = 1;
    2865        5684 :             move16();
    2866       15263 :             FOR( i = 1; i < nchan_ism - 1; i++ )
    2867             :             {
    2868        9579 :                 base[i] = i_mult( base[i - 1], 10 );
    2869        9579 :                 move16();
    2870             :             }
    2871        5684 :             sum = 0;
    2872        5684 :             move16();
    2873       20947 :             FOR( i = nchan_ism - 2; i >= 0; i-- )
    2874             :             {
    2875       15263 :                 IF( EQ_16( j, 0 ) )
    2876             :                 {
    2877        3283 :                     elem = 0;
    2878        3283 :                     move16();
    2879             :                 }
    2880             :                 ELSE
    2881             :                 {
    2882       11980 :                     elem = idiv1616( j, base[i] );
    2883             :                 }
    2884       15263 :                 ratio_idx_ism[nchan_ism - i - 2] = elem;
    2885       15263 :                 move16();
    2886       15263 :                 sum = add( sum, elem );
    2887       15263 :                 j = sub( j, i_mult( elem, base[i] ) );
    2888             :             }
    2889        5684 :             ratio_idx_ism[nchan_ism - 1] = sub( K, sum );
    2890        5684 :             move16();
    2891             :         }
    2892             : 
    2893        5684 :         default:
    2894        5684 :             BREAK;
    2895             :     }
    2896             : 
    2897        5902 :     return;
    2898             : }
    2899             : 
    2900             : 
    2901        4934 : static void read_ism_ratio_index_fx(
    2902             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],         /* o  : ISM read ratio indexes                                        Q0*/
    2903             :     const Word16 nchan_ism,                                              /* i  : number of objects                                             */
    2904             :     const Word16 numCodingBands,                                         /* i  : number of subbands                                            */
    2905             :     const Word16 sf,                                                     /* i  : index of subframe                                             */
    2906             :     Word16 ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* i  : previous subframe ISM ratio indexes                           Q0*/
    2907             :     UWord16 *bit_stream,                                                 /* i  : bitstream                                                     */
    2908             :     Word16 *next_bit_pos,                                                /* i/o: position in bitstream                                         */
    2909             :     const Word32 *masa_to_total_energy_ratio_fx,                         /* i  : masa to total ratios                                          Q30*/
    2910             :     const Word16 idx_sep_obj,                                            /* i  : index of separated index, -1 if none                          */
    2911             :     Word16 *num_zeros                                                    /* i/o: number of zero values in first subframe for separated object  */
    2912             : )
    2913             : {
    2914             :     Word16 b, i, b_signif;
    2915             :     Word16 index;
    2916             :     Word16 GR_order, differential_subframe;
    2917             :     Word16 buf;
    2918             :     Word16 no_levels_ratio_ism;
    2919             :     Word16 bits_index;
    2920             :     Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
    2921             :     Word16 idx_sep_obj_local, shift_one;
    2922             : 
    2923        4934 :     idx_sep_obj_local = idx_sep_obj;
    2924        4934 :     move16();
    2925             : 
    2926        4934 :     IF( GT_16( idx_sep_obj, -1 ) )
    2927             :     {
    2928        4934 :         test();
    2929        4934 :         if ( EQ_16( idx_sep_obj, sub( nchan_ism, 1 ) ) && GT_16( nchan_ism, 2 ) )
    2930             :         {
    2931         762 :             idx_sep_obj_local = 0;
    2932         762 :             move16();
    2933             :         }
    2934             :     }
    2935             : 
    2936        4934 :     b_signif = 0;
    2937        4934 :     move16();
    2938        4934 :     no_levels_ratio_ism = sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 );
    2939             : 
    2940        5427 :     WHILE( ( LT_16( b_signif, numCodingBands ) ) && ( GE_32( masa_to_total_energy_ratio_fx[b_signif], MASA2TOTAL_THR_Q30 ) ) )
    2941             :     {
    2942         493 :         test();
    2943             :         /* distribute evenly the objects */
    2944         493 :         distribute_evenly_ism_fx( ratio_ism_idx[b_signif], no_levels_ratio_ism, nchan_ism );
    2945         493 :         b_signif = add( b_signif, 1 );
    2946             :     }
    2947             : 
    2948        4934 :     IF( EQ_16( b_signif, numCodingBands ) )
    2949             :     {
    2950          69 :         return;
    2951             :     }
    2952             :     ELSE
    2953             :     {
    2954             : 
    2955        4865 :         IF( sf == 0 )
    2956             :         {
    2957        1591 :             bits_index = bits_index_ism_ratio_fx( nchan_ism );
    2958             : 
    2959             :             /* read coding type */
    2960        1591 :             IF( EQ_32( bit_stream[( *next_bit_pos )--], 1 ) )
    2961             :             {
    2962             :                 /* independent coding*/
    2963        6873 :                 FOR( b = 0; b < numCodingBands; b++ )
    2964             :                 {
    2965        5892 :                     IF( LT_32( masa_to_total_energy_ratio_fx[b], MASA2TOTAL_THR_Q30 ) )
    2966             :                     {
    2967        5292 :                         index = 0;
    2968        5292 :                         move16();
    2969       40505 :                         FOR( i = 0; i < bits_index; i++ )
    2970             :                         {
    2971       35213 :                             index = add( shl( index, 1 ), (Word16) bit_stream[( *next_bit_pos )--] );
    2972             :                         }
    2973        5292 :                         decode_index_slice_fx( index, ratio_ism_idx[b], nchan_ism, no_levels_ratio_ism );
    2974        5292 :                         test();
    2975        5292 :                         IF( GT_16( idx_sep_obj, -1 ) && EQ_16( ratio_ism_idx[b][idx_sep_obj_local], 0 ) )
    2976             :                         {
    2977        4798 :                             *num_zeros = add( *num_zeros, 1 );
    2978        4798 :                             move16();
    2979             :                         }
    2980             :                     }
    2981             :                     ELSE
    2982             :                     {
    2983             :                         /* distribute evenly the objects */
    2984         600 :                         distribute_evenly_ism_fx( ratio_ism_idx[b], no_levels_ratio_ism, nchan_ism );
    2985             :                     }
    2986             :                 }
    2987             :             }
    2988             :             ELSE
    2989             :             {
    2990             :                 /* differential coding */
    2991         610 :                 index = 0;
    2992         610 :                 move16();
    2993        4050 :                 FOR( i = 0; i < bits_index; i++ )
    2994             :                 {
    2995        3440 :                     index = add( shl( index, 1 ), (Word16) bit_stream[( *next_bit_pos )--] );
    2996             :                 }
    2997         610 :                 decode_index_slice_fx( index, ratio_ism_idx[b_signif], nchan_ism, no_levels_ratio_ism );
    2998         610 :                 test();
    2999         610 :                 IF( GT_16( idx_sep_obj, -1 ) && ratio_ism_idx[b_signif][idx_sep_obj_local] == 0 )
    3000             :                 {
    3001         553 :                     *num_zeros = add( *num_zeros, 1 );
    3002         553 :                     move16();
    3003             :                 }
    3004         610 :                 Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
    3005        4510 :                 FOR( b = b_signif + 1; b < numCodingBands; b++ )
    3006             :                 {
    3007        3900 :                     IF( LT_32( masa_to_total_energy_ratio_fx[b], MASA2TOTAL_THR_Q30 ) )
    3008             :                     {
    3009        3490 :                         ratio_ism_idx[b][nchan_ism - 1] = no_levels_ratio_ism;
    3010        3490 :                         move16();
    3011       11267 :                         FOR( i = 0; i < nchan_ism - 1; i++ )
    3012             :                         {
    3013        7777 :                             buf = ivas_qmetadata_DecodeExtendedGR( bit_stream, next_bit_pos, 100, 0 );
    3014        7777 :                             IF( EQ_16( buf % 2, 0 ) )
    3015             :                             {
    3016        6575 :                                 ratio_ism_idx[b][i] = negate( shr( buf, 1 ) );
    3017        6575 :                                 move16();
    3018             :                             }
    3019             :                             ELSE
    3020             :                             {
    3021        1202 :                                 ratio_ism_idx[b][i] = shr( add( buf, 1 ), 1 );
    3022        1202 :                                 move16();
    3023             :                             }
    3024        7777 :                             ratio_ism_idx[b][i] = add( ratio_ism_idx[b][i], ratio_ism_idx_ref[i] );
    3025        7777 :                             move16();
    3026        7777 :                             ratio_ism_idx[b][nchan_ism - 1] = sub( ratio_ism_idx[b][nchan_ism - 1], ratio_ism_idx[b][i] );
    3027        7777 :                             move16();
    3028             :                         }
    3029        3490 :                         Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
    3030        3490 :                         test();
    3031        3490 :                         IF( GT_16( idx_sep_obj, -1 ) && EQ_16( ratio_ism_idx[b][idx_sep_obj_local], 0 ) )
    3032             :                         {
    3033        3106 :                             *num_zeros = add( *num_zeros, 1 );
    3034        3106 :                             move16();
    3035             :                         }
    3036             :                     }
    3037             :                     ELSE
    3038             :                     {
    3039             :                         /* distribute evenly the objects */
    3040         410 :                         distribute_evenly_ism_fx( ratio_ism_idx[b], no_levels_ratio_ism, nchan_ism );
    3041             :                     }
    3042             :                 }
    3043             :             }
    3044             :         }
    3045             :         ELSE
    3046             :         {
    3047        3274 :             IF( GT_16( numCodingBands, 1 ) )
    3048             :             {
    3049             :                 /* read prediction type */
    3050        3228 :                 differential_subframe = bit_stream[( *next_bit_pos )--];
    3051        3228 :                 move16();
    3052             :             }
    3053             :             ELSE
    3054             :             {
    3055          46 :                 differential_subframe = 1;
    3056          46 :                 move16();
    3057             :             }
    3058             : 
    3059        3274 :             IF( EQ_16( *num_zeros, numCodingBands ) )
    3060             :             {
    3061        1839 :                 shift_one = 1;
    3062        1839 :                 move16();
    3063             :             }
    3064             :             ELSE
    3065             :             {
    3066        1435 :                 shift_one = 0;
    3067        1435 :                 move16();
    3068             :             }
    3069             : 
    3070        3274 :             test();
    3071        3274 :             IF( EQ_16( shift_one, 1 ) && EQ_16( nchan_ism, 2 ) )
    3072             :             {
    3073             :                 /* nothing has been sent ; values can be inferred */
    3074          84 :                 FOR( b = b_signif; b < numCodingBands; b++ )
    3075             :                 {
    3076          42 :                     IF( LT_32( masa_to_total_energy_ratio_fx[b], MASA2TOTAL_THR_Q30 ) )
    3077             :                     {
    3078          42 :                         IF( idx_sep_obj_local == 0 )
    3079             :                         {
    3080          30 :                             ratio_ism_idx[b][0] = 0;
    3081          30 :                             move16();
    3082          30 :                             ratio_ism_idx[b][1] = 7;
    3083          30 :                             move16();
    3084             :                         }
    3085             :                         ELSE
    3086             :                         {
    3087          12 :                             ratio_ism_idx[b][0] = 7;
    3088          12 :                             move16();
    3089          12 :                             ratio_ism_idx[b][1] = 0;
    3090          12 :                             move16();
    3091             :                         }
    3092             :                     }
    3093             :                 }
    3094             :             }
    3095             :             ELSE
    3096             :             {
    3097             :                 /* read GR order */
    3098        3232 :                 GR_order = bit_stream[( *next_bit_pos )--];
    3099        3232 :                 move16();
    3100             : 
    3101       19199 :                 FOR( b = b_signif; b < numCodingBands; b++ )
    3102             :                 {
    3103       15967 :                     IF( LT_32( masa_to_total_energy_ratio_fx[b], MASA2TOTAL_THR_Q30 ) )
    3104             :                     {
    3105       42183 :                         FOR( i = 0; i < nchan_ism - ( 1 + shift_one ); i++ )
    3106             :                         {
    3107       27805 :                             buf = ivas_qmetadata_DecodeExtendedGR( bit_stream, next_bit_pos, 100, GR_order );
    3108       27805 :                             IF( ( buf % 2 ) == 0 )
    3109             :                             {
    3110       22282 :                                 ratio_ism_idx[b][i] = negate( shr( buf, 1 ) );
    3111       22282 :                                 move16();
    3112             :                             }
    3113             :                             ELSE
    3114             :                             {
    3115        5523 :                                 ratio_ism_idx[b][i] = shr( add( buf, 1 ), 1 );
    3116        5523 :                                 move16();
    3117             :                             }
    3118             :                         }
    3119             : 
    3120             :                         /* insert separated obj */
    3121       14378 :                         IF( shift_one )
    3122             :                         {
    3123       26332 :                             FOR( i = nchan_ism - 1; i > idx_sep_obj_local; i-- )
    3124             :                             {
    3125       17753 :                                 ratio_ism_idx[b][i] = ratio_ism_idx[b][i - 1];
    3126       17753 :                                 move16();
    3127             :                             }
    3128        8579 :                             ratio_ism_idx[b][idx_sep_obj_local] = 0; /* this is only difference; need to pdate later as well  */
    3129        8579 :                             move16();
    3130             :                         }
    3131             :                     }
    3132             :                 }
    3133        3232 :                 IF( differential_subframe )
    3134             :                 {
    3135             :                     /* differential to previous subframe */
    3136       17308 :                     FOR( b = b_signif; b < numCodingBands; b++ )
    3137             :                     {
    3138       14392 :                         IF( LT_32( masa_to_total_energy_ratio_fx[b], MASA2TOTAL_THR_Q30 ) )
    3139             :                         {
    3140       12982 :                             ratio_ism_idx[b][sub( nchan_ism, 1 )] = no_levels_ratio_ism;
    3141       12982 :                             move16();
    3142       45998 :                             FOR( i = 0; i < nchan_ism - 1; i++ )
    3143             :                             {
    3144       33016 :                                 ratio_ism_idx[b][i] = add( ratio_ism_idx[b][i], ratio_ism_idx_prev_sf[b][i] );
    3145       33016 :                                 move16();
    3146             : 
    3147       33016 :                                 test();
    3148       33016 :                                 if ( ( shift_one != 0 ) && EQ_16( i, idx_sep_obj_local ) )
    3149             :                                 {
    3150        8195 :                                     ratio_ism_idx[b][i] = 0;
    3151        8195 :                                     move16();
    3152             :                                 }
    3153       33016 :                                 ratio_ism_idx[b][nchan_ism - 1] = sub( ratio_ism_idx[b][nchan_ism - 1], ratio_ism_idx[b][i] );
    3154             :                             }
    3155             :                         }
    3156             :                         ELSE
    3157             :                         {
    3158             :                             /* distribute evenly the objects */
    3159        1410 :                             distribute_evenly_ism_fx( ratio_ism_idx[b], no_levels_ratio_ism, nchan_ism );
    3160             :                         }
    3161             :                     }
    3162             :                 }
    3163             :                 ELSE
    3164             :                 {
    3165             :                     /* difference to previous subband */
    3166         316 :                     ratio_ism_idx[b_signif][nchan_ism - 1] = no_levels_ratio_ism;
    3167         316 :                     move16();
    3168             : 
    3169             :                     /* first significant subband - differential to previous subframe */
    3170        1075 :                     FOR( i = 0; i < nchan_ism - 1; i++ )
    3171             :                     {
    3172         759 :                         ratio_ism_idx[b_signif][i] = add( ratio_ism_idx[b_signif][i], ratio_ism_idx_prev_sf[b_signif][i] );
    3173         759 :                         move16();
    3174             : 
    3175         759 :                         test();
    3176         759 :                         if ( ( shift_one != 0 ) && EQ_16( i, idx_sep_obj_local ) )
    3177             :                         {
    3178          80 :                             ratio_ism_idx[b_signif][i] = 0;
    3179          80 :                             move16();
    3180             :                         }
    3181         759 :                         ratio_ism_idx[b_signif][nchan_ism - 1] = sub( ratio_ism_idx[b_signif][nchan_ism - 1], ratio_ism_idx[b_signif][i] );
    3182         759 :                         move16();
    3183             :                     }
    3184             : 
    3185             :                     /* rest of subbands differential to previous subband */
    3186         316 :                     Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
    3187        1575 :                     FOR( b = b_signif + 1; b < numCodingBands; b++ )
    3188             :                     {
    3189        1259 :                         IF( LT_32( masa_to_total_energy_ratio_fx[b], MASA2TOTAL_THR_Q30 ) )
    3190             :                         {
    3191        1080 :                             ratio_ism_idx[b][nchan_ism - 1] = no_levels_ratio_ism;
    3192        1080 :                             move16();
    3193             : 
    3194        3689 :                             FOR( i = 0; i < nchan_ism - 1; i++ )
    3195             :                             {
    3196        2609 :                                 ratio_ism_idx[b][i] = add( ratio_ism_idx[b][i], ratio_ism_idx_ref[i] );
    3197        2609 :                                 move16();
    3198             : 
    3199        2609 :                                 test();
    3200        2609 :                                 if ( NE_16( shift_one, 0 ) && EQ_16( i, idx_sep_obj_local ) )
    3201             :                                 {
    3202         304 :                                     ratio_ism_idx[b][i] = 0;
    3203         304 :                                     move16();
    3204             :                                 }
    3205        2609 :                                 ratio_ism_idx[b][nchan_ism - 1] = sub( ratio_ism_idx[b][nchan_ism - 1], ratio_ism_idx[b][i] );
    3206        2609 :                                 move16();
    3207             :                             }
    3208        1080 :                             Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
    3209             :                         }
    3210             :                         ELSE
    3211             :                         {
    3212             :                             /* distribute evenly the objects */
    3213         179 :                             distribute_evenly_ism_fx( ratio_ism_idx[b], no_levels_ratio_ism, nchan_ism );
    3214             :                         }
    3215             :                     }
    3216             :                 }
    3217             :             }
    3218             :         }
    3219             : 
    3220        4865 :         return;
    3221             :     }
    3222             : }
    3223             : 
    3224             : 
    3225        1634 : static void decode_ism_ratios_fx(
    3226             :     UWord16 *bit_stream,                                                                     /* i  : bitstream                      */
    3227             :     Word16 *next_bit_pos,                                                                    /* i/o: position in bitstream          */
    3228             :     Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i  : masa_to_total energy ratios    Q30*/
    3229             :     Word32 ratio_ism[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],    /* o  : ISM ratios                     Q30*/
    3230             :     const Word16 n_ism,                                                                      /* i  : number of objects              */
    3231             :     const Word16 nbands,                                                                     /* i  : number of subbands             */
    3232             :     const Word16 numSf,                                                                      /* i  : number of subframes            */
    3233             :     const Word16 idx_separated_object                                                        /* i  : index of separated object      */
    3234             : )
    3235             : {
    3236             :     Word16 sf, band;
    3237             :     Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
    3238             :     Word16 ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
    3239             :     Word32 tmp32_fx;
    3240             :     Word16 num_zeros;
    3241        1634 :     num_zeros = 0;
    3242        1634 :     move16();
    3243             : 
    3244             :     /* hQMetaData->q_direction->cfg.nblocks; */
    3245        6568 :     FOR( sf = 0; sf < numSf; sf++ )
    3246             :     {
    3247             :         /* read ism ratio indexes */
    3248        4934 :         read_ism_ratio_index_fx( ratio_ism_idx, n_ism, nbands, sf, ratio_ism_idx_prev_sf, bit_stream, next_bit_pos, masa_to_total_energy_ratio_fx[sf], idx_separated_object, &num_zeros );
    3249             :         /* save previous subframe index values */
    3250        4934 :         IF( LT_16( sf, sub( numSf, 1 ) ) )
    3251             :         {
    3252       19560 :             FOR( band = 0; band < nbands; band++ )
    3253             :             {
    3254       16260 :                 Copy( ratio_ism_idx[band], ratio_ism_idx_prev_sf[band], n_ism );
    3255             :             }
    3256             :         }
    3257             : 
    3258             :         /* reconstructed values */
    3259       31804 :         FOR( band = 0; band < nbands; band++ )
    3260             :         {
    3261       26870 :             reconstruct_ism_ratios_fx( ratio_ism_idx[band], n_ism, STEP_PARAM_ISM_POW_RATIO_NBITS_Q31, ratio_ism[sf][band] );
    3262             :         }
    3263             : 
    3264        4934 :         test();
    3265        4934 :         IF( GT_16( n_ism, 2 ) && ( EQ_16( idx_separated_object, sub( n_ism, 1 ) ) ) )
    3266             :         {
    3267             :             /* rotate */
    3268        4586 :             FOR( band = 0; band < nbands; band++ )
    3269             :             {
    3270        3824 :                 IF( LT_32( masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
    3271             :                 {
    3272        3335 :                     tmp32_fx = ratio_ism[sf][band][n_ism - 1]; // Q30
    3273        3335 :                     move32();
    3274        3335 :                     ratio_ism[sf][band][n_ism - 1] = ratio_ism[sf][band][0];
    3275        3335 :                     move32();
    3276        3335 :                     ratio_ism[sf][band][0] = tmp32_fx;
    3277        3335 :                     move32();
    3278             :                 }
    3279             :             }
    3280             :         }
    3281             : 
    3282        4934 :         IF( EQ_16( nbands, 1 ) )
    3283             :         {
    3284         400 :             FOR( band = 1; band < 5; band++ )
    3285             :             {
    3286         320 :                 Copy32( ratio_ism[sf][0], ratio_ism[sf][band], n_ism );
    3287             :             }
    3288             :         }
    3289             :     }
    3290             : 
    3291        1634 :     IF( EQ_16( numSf, 1 ) )
    3292             :     {
    3293        2136 :         FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    3294             :         {
    3295       17172 :             FOR( band = 0; band < nbands; band++ )
    3296             :             {
    3297       15570 :                 Copy32( ratio_ism[0][band], ratio_ism[sf][band], n_ism );
    3298             :             }
    3299             :         }
    3300             :     }
    3301             : 
    3302        1634 :     return;
    3303             : }
    3304             : 
    3305             : 
    3306        1634 : static Word16 ivas_decode_masaism_metadata_fx(
    3307             :     IVAS_QMETADATA_HANDLE hQMetaData,
    3308             :     MASA_DECODER_HANDLE hMasa,
    3309             :     MASA_ISM_DATA_HANDLE hMasaIsmData,
    3310             :     const Word16 nchan_ism,
    3311             :     UWord16 *bit_stream,
    3312             :     Word16 *next_bit_pos,
    3313             :     const Word16 idx_separated_object,
    3314             :     const Word16 ism_imp,
    3315             :     const Word16 dirac_bs_md_write_idx,
    3316             :     const Word16 dirac_md_buffer_length )
    3317             : {
    3318             :     Word16 sf, band, dir, nbands, nblocks, obj, i;
    3319             :     Word32 energy_ratio_ism_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; // Q30
    3320             :     Word16 *band_mapping;
    3321             :     Word16 b;
    3322             :     Word16 bits_ism[MAX_NUM_OBJECTS], index;
    3323             :     UWord16 idx_el, idx_az;
    3324             :     Word32 azimuth, elevation; // Q22
    3325             :     Word16 nb_bits_read;
    3326             :     Word32 delta_phi; // Q22
    3327             :     Word16 meta_write_index;
    3328             : 
    3329        1634 :     nb_bits_read = *next_bit_pos;
    3330        1634 :     move16();
    3331        1634 :     nbands = hQMetaData->q_direction->cfg.nbands;
    3332        1634 :     move16();
    3333        1634 :     nblocks = hQMetaData->q_direction->cfg.nblocks;
    3334        1634 :     move16();
    3335             : 
    3336             :     /* Read MASA-to-total energy ratios */
    3337        1634 :     ivas_omasa_decode_masa_to_total_fx( bit_stream, next_bit_pos, hMasaIsmData->masa_to_total_energy_ratio_fx, nbands, nblocks );
    3338             : 
    3339        1634 :     IF( GT_16( nchan_ism, 1 ) )
    3340             :     {
    3341             :         /* read ISM ratios */
    3342        1634 :         decode_ism_ratios_fx( bit_stream, next_bit_pos, hMasaIsmData->masa_to_total_energy_ratio_fx, energy_ratio_ism_fx, nchan_ism, nbands, nblocks, idx_separated_object );
    3343             :     }
    3344             :     ELSE
    3345             :     {
    3346           0 :         FOR( sf = 0; sf < nblocks; sf++ )
    3347             :         {
    3348           0 :             FOR( band = 0; band < nbands; band++ )
    3349             :             {
    3350           0 :                 energy_ratio_ism_fx[sf][band][0] = ONE_IN_Q30;
    3351           0 :                 move32();
    3352             :             }
    3353             :         }
    3354             :     }
    3355             : 
    3356             :     /* read ISM metadata */
    3357        1634 :     calculate_nbits_meta_fx( nchan_ism, energy_ratio_ism_fx, hMasaIsmData->masa_to_total_energy_ratio_fx, nblocks, nbands, bits_ism, idx_separated_object, ism_imp );
    3358             : 
    3359        7132 :     FOR( obj = 0; obj < nchan_ism; obj++ )
    3360             :     {
    3361             : #ifdef OMASA_OBJECT_EDITING
    3362        5498 :         hMasaIsmData->bits_ism[obj] = bits_ism[obj];
    3363             : #endif
    3364        5498 :         index = 0;
    3365        5498 :         move16();
    3366        5498 :         IF( LT_16( bits_ism[obj], 8 ) ) /* if low resolution, can look to the past */
    3367             :         {
    3368             :             /* read if same as previous */
    3369        1678 :             IF( bit_stream[( *next_bit_pos )--] )
    3370             :             {
    3371         196 :                 azimuth = hMasaIsmData->q_azimuth_old_fx[obj]; // Q22
    3372         196 :                 move32();
    3373         196 :                 elevation = hMasaIsmData->q_elevation_old_fx[obj]; // Q22
    3374         196 :                 move32();
    3375             :             }
    3376             :             ELSE
    3377             :             {
    3378       10910 :                 FOR( i = 0; i < bits_ism[obj]; i++ )
    3379             :                 {
    3380        9428 :                     index = add( shl( index, 1 ), (Word16) bit_stream[( *next_bit_pos )--] );
    3381             :                 }
    3382             : 
    3383        1482 :                 deindex_spherical_component_fx( index, &azimuth, &elevation, &idx_az, &idx_el, bits_ism[obj], MC_LS_SETUP_INVALID );
    3384             : 
    3385        1482 :                 test();
    3386        1482 :                 test();
    3387        1482 :                 test();
    3388             :                 /*  if ( azimuth * hMasaIsmData->q_azimuth_old[obj] > 0 ) */
    3389        1482 :                 IF( ( ( azimuth > 0 ) && ( hMasaIsmData->q_azimuth_old_fx[obj] > 0 ) ) || ( ( azimuth < 0 ) && ( hMasaIsmData->q_azimuth_old_fx[obj] < 0 ) ) )
    3390             :                 {
    3391             :                     Word16 tmp_e;
    3392         643 :                     delta_phi = L_deposit_h( BASOP_Util_Divide1616_Scale( 180, no_phi_masa[bits_ism[obj] - 1][idx_el], &tmp_e ) );
    3393         643 :                     delta_phi = L_shr( delta_phi, sub( 9, tmp_e ) ); /* to maintain Q22 */
    3394             : 
    3395             :                     Word32 tmp_32;
    3396             :                     Word64 tmp_64;
    3397         643 :                     tmp_32 = L_sub( azimuth, hMasaIsmData->q_azimuth_old_fx[obj] );
    3398         643 :                     tmp_64 = W_mult_32_16( tmp_32, no_phi_masa[bits_ism[obj] - 1][idx_el] );
    3399             : 
    3400         643 :                     IF( GT_64( tmp_64, TOLERANCE_360_Q22 ) ) /* >= 360 in Q22 (because there is an additional shift left in W_mult_32_16) + 0.02 in Q22 to counteract for precision loss, */
    3401             :                     {
    3402          61 :                         azimuth = L_sub( azimuth, delta_phi );
    3403             :                     }
    3404             :                     ELSE
    3405             :                     {
    3406         582 :                         IF( GT_64( MINUS_TOLERANCE_360_Q22, tmp_64 ) )
    3407             :                         {
    3408          53 :                             azimuth = L_add( azimuth, delta_phi );
    3409             :                         }
    3410             :                     }
    3411             :                 }
    3412             : 
    3413        1482 :                 hMasaIsmData->q_azimuth_old_fx[obj] = azimuth;
    3414        1482 :                 move32();
    3415        1482 :                 hMasaIsmData->q_elevation_old_fx[obj] = elevation;
    3416        1482 :                 move32();
    3417             :             }
    3418             :         }
    3419             :         ELSE
    3420             :         {
    3421       41999 :             FOR( i = 0; i < bits_ism[obj]; i++ )
    3422             :             {
    3423       38179 :                 index = add( shl( index, 1 ), (Word16) bit_stream[( *next_bit_pos )--] );
    3424             :             }
    3425        3820 :             deindex_spherical_component_fx( index, &azimuth, &elevation, &idx_az, &idx_el, bits_ism[obj], MC_LS_SETUP_INVALID );
    3426             : 
    3427        3820 :             hMasaIsmData->q_azimuth_old_fx[obj] = azimuth;
    3428        3820 :             move32();
    3429        3820 :             hMasaIsmData->q_elevation_old_fx[obj] = elevation;
    3430        3820 :             move32();
    3431             :         }
    3432             : 
    3433       27490 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    3434             :         {
    3435       21992 :             meta_write_index = add( dirac_bs_md_write_idx, sf ) % dirac_md_buffer_length;
    3436             : 
    3437       21992 :             Word16 int_azi = rint_fx( L_shr( azimuth, Q22 - 16 ) );   // Q0, extra -16 is added as int_azi is W16 and azimuth is W32
    3438       21992 :             Word16 int_ele = rint_fx( L_shr( elevation, Q22 - 16 ) ); // Q0
    3439             : 
    3440       21992 :             hMasaIsmData->azimuth_ism_fx[obj][meta_write_index] = int_azi; // Q0
    3441       21992 :             move16();
    3442       21992 :             hMasaIsmData->elevation_ism_fx[obj][meta_write_index] = int_ele; // Q0
    3443       21992 :             move16();
    3444             :         }
    3445             :     }
    3446             : 
    3447             :     /* Modify ISM metadata based on the MASA-to-total energy ratios */
    3448        6568 :     FOR( sf = 0; sf < nblocks; sf++ )
    3449             :     {
    3450       31804 :         FOR( band = 0; band < nbands; band++ )
    3451             :         {
    3452      120554 :             FOR( dir = 0; dir < nchan_ism; dir++ )
    3453             :             {
    3454       93684 :                 energy_ratio_ism_fx[sf][band][dir] = L_shl( Mpy_32_32( energy_ratio_ism_fx[sf][band][dir], L_sub( ONE_IN_Q30, hMasaIsmData->masa_to_total_energy_ratio_fx[sf][band] ) ), 1 ); // Q30 + Q30 - 31 = Q29 + 1 = Q30
    3455       93684 :                 move32();
    3456             :             }
    3457             :         }
    3458             :     }
    3459             : 
    3460             :     /* Set data to struct in bins */
    3461        1634 :     band_mapping = hMasa->data.band_mapping;
    3462        1634 :     move16();
    3463       12324 :     FOR( band = 0; band < hMasa->config.numCodingBands; ++band )
    3464             :     {
    3465       95610 :         FOR( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b )
    3466             :         {
    3467      424600 :             FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; ++sf )
    3468             :             {
    3469      339680 :                 IF( EQ_16( nblocks, 1 ) )
    3470             :                 {
    3471      122880 :                     i = 0;
    3472      122880 :                     move16();
    3473             :                 }
    3474             :                 ELSE
    3475             :                 {
    3476      216800 :                     i = sf;
    3477      216800 :                     move16();
    3478             :                 }
    3479             : 
    3480      339680 :                 meta_write_index = ( add( dirac_bs_md_write_idx, sf ) ) % dirac_md_buffer_length;
    3481             : 
    3482     1496000 :                 FOR( dir = 0; dir < nchan_ism; dir++ )
    3483             :                 {
    3484     1156320 :                     hMasaIsmData->energy_ratio_ism_fx[dir][meta_write_index][b] = energy_ratio_ism_fx[i][band][dir];
    3485     1156320 :                     move32();
    3486             :                 }
    3487             : 
    3488      339680 :                 IF( hMasaIsmData->hExtData != NULL )
    3489             :                 {
    3490        9600 :                     hMasaIsmData->hExtData->masa_render_masa_to_total[meta_write_index][b] =
    3491        9600 :                         hMasaIsmData->masa_to_total_energy_ratio_fx[i][band];
    3492        9600 :                     move32();
    3493             :                 }
    3494             :             }
    3495             :         }
    3496             :     }
    3497             : 
    3498        1634 :     return sub( nb_bits_read, *next_bit_pos );
    3499             : }
    3500             : 
    3501             : 
    3502             : /*
    3503             :     Fixed point implementation of rint().
    3504             : */
    3505             : /* returns in Q0 */
    3506       43984 : static Word16 rint_fx(
    3507             :     const Word32 num /* num in Q0     */
    3508             : )
    3509             : {
    3510       43984 :     Word32 frac_part = L_and( L_abs( num ), 0x0000FFFF ); // Q15
    3511       43984 :     Word16 int_part = extract_h( L_abs( num ) );
    3512       43984 :     Word16 res = int_part;
    3513       43984 :     move16();
    3514             : 
    3515       43984 :     test();
    3516       43984 :     test();
    3517       43984 :     if ( GT_32( frac_part, ONE_IN_Q15 ) || ( EQ_32( frac_part, ONE_IN_Q15 ) && EQ_16( s_and( int_part, 1 ), 1 ) ) )
    3518             :     {
    3519       10088 :         res = add( res, 1 );
    3520             :     }
    3521       43984 :     if ( num < 0 )
    3522             :     {
    3523       19136 :         res = negate( res );
    3524             :     }
    3525       43984 :     return res;
    3526             : }

Generated by: LCOV version 1.14