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 "options.h"
      34             : #include <stdlib.h>
      35             : #include <math.h>
      36             : #include "ivas_cnst.h"
      37             : #include "ivas_prot_fx.h"
      38             : #include "prot_fx.h"
      39             : #include "ivas_prot_rend_fx.h"
      40             : #include "ivas_rom_com.h"
      41             : #include "wmc_auto.h"
      42             : #include "ivas_prot_fx.h"
      43             : 
      44             : 
      45             : /*-------------------------------------------------------------------------
      46             :  * Local constants
      47             :  *------------------------------------------------------------------------*/
      48             : 
      49             : #ifdef FIX_2082_FP_LEFTOVERS_OMASA_DEC
      50             : #define MULT_17_DIV_20_Q15              27853      /* (Word16) ( ( 17.0/20.0 ) * 2^15 + 0.5 ) */
      51             : #define MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 2048       /* (Word16) ( ( 1.0 / CLDFB_NO_COL_MAX ) * 2^15 + 0.5 ) */
      52             : #define ONEMINUX_EXT_RENDER_IIR_FAC_Q31 107374182  /* (Word32) ( ( 1.0 - 0.95 ) * 2^31 + 0.5f );  0.95 is EXT_RENDER_IIR_FAC  */
      53             : #define EXT_RENDER_IIR_FAC_Q31          2040109465 /* (Word32) ( 0.95 * 2^31 + 0.5 ) */
      54             : #else
      55             : #define EXT_RENDER_IIR_FAC              0.95f
      56             : #define MULT_17_DIV_20_Q15              ( Word16 )( ( 17.0 / 20.0f ) * pow( 2, 15 ) + 0.5f )
      57             : #define MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 ( Word16 )( ( 1.0 / CLDFB_NO_COL_MAX ) * pow( 2, 15 ) + 0.5f )
      58             : #define ONEMINUX_EXT_RENDER_IIR_FAC_Q31 ( Word32 )( ( 1.0f - EXT_RENDER_IIR_FAC ) * pow( 2, 31 ) + 0.5f )
      59             : #define EXT_RENDER_IIR_FAC_Q31          ( Word32 )( EXT_RENDER_IIR_FAC * pow( 2, 31 ) + 0.5f )
      60             : #endif
      61             : 
      62             : // Calculated as (Word16)(((1.0f / (50 * MAX_PARAM_SPATIAL_SUBFRAMES)) * pow(2, 15)) + 0.5f)
      63             : #define OMASA_DELAYFRAMES_PER_SEC_Q15 (Word16) 164 // Q15
      64             : 
      65             : static Word16 interpolator_table_48k_q15[] = {
      66             :     0, 137, 273, 410, 546, 683, 819, 956, 1092, 1229,
      67             :     1365, 1502, 1638, 1775, 1911, 2048, 2185, 2321, 2458, 2594,
      68             :     2731, 2867, 3004, 3140, 3277, 3413, 3550, 3686, 3823, 3959,
      69             :     4096, 4233, 4369, 4506, 4642, 4779, 4915, 5052, 5188, 5325,
      70             :     5461, 5598, 5734, 5871, 6007, 6144, 6281, 6417, 6554, 6690,
      71             :     6827, 6963, 7100, 7236, 7373, 7509, 7646, 7782, 7919, 8055,
      72             :     8192, 8329, 8465, 8602, 8738, 8875, 9011, 9148, 9284, 9421,
      73             :     9557, 9694, 9830, 9967, 10103, 10240, 10377, 10513, 10650, 10786,
      74             :     10923, 11059, 11196, 11332, 11469, 11605, 11742, 11878, 12015, 12151,
      75             :     12288, 12425, 12561, 12698, 12834, 12971, 13107, 13244, 13380, 13517,
      76             :     13653, 13790, 13926, 14063, 14199, 14336, 14473, 14609, 14746, 14882,
      77             :     15019, 15155, 15292, 15428, 15565, 15701, 15838, 15974, 16111, 16247,
      78             :     16384, 16521, 16657, 16794, 16930, 17067, 17203, 17340, 17476, 17613,
      79             :     17749, 17886, 18022, 18159, 18295, 18432, 18569, 18705, 18842, 18978,
      80             :     19115, 19251, 19388, 19524, 19661, 19797, 19934, 20070, 20207, 20343,
      81             :     20480, 20617, 20753, 20890, 21026, 21163, 21299, 21436, 21572, 21709,
      82             :     21845, 21982, 22118, 22255, 22391, 22528, 22665, 22801, 22938, 23074,
      83             :     23211, 23347, 23484, 23620, 23757, 23893, 24030, 24166, 24303, 24439,
      84             :     24576, 24713, 24849, 24986, 25122, 25259, 25395, 25532, 25668, 25805,
      85             :     25941, 26078, 26214, 26351, 26487, 26624, 26761, 26897, 27034, 27170,
      86             :     27307, 27443, 27580, 27716, 27853, 27989, 28126, 28262, 28399, 28535,
      87             :     28672, 28809, 28945, 29082, 29218, 29355, 29491, 29628, 29764, 29901,
      88             :     30037, 30174, 30310, 30447, 30583, 30720, 30857, 30993, 31130, 31266,
      89             :     31403, 31539, 31676, 31812, 31949, 32085, 32222, 32358, 32495, 32631
      90             : };
      91             : 
      92             : static Word16 interpolator_table_32k_q15[] = {
      93             :     0, 205, 410, 614, 819, 1024, 1229, 1434, 1638, 1843,
      94             :     2048, 2253, 2458, 2662, 2867, 3072, 3277, 3482, 3686, 3891,
      95             :     4096, 4301, 4506, 4710, 4915, 5120, 5325, 5530, 5734, 5939,
      96             :     6144, 6349, 6554, 6758, 6963, 7168, 7373, 7578, 7782, 7987,
      97             :     8192, 8397, 8602, 8806, 9011, 9216, 9421, 9626, 9830, 10035,
      98             :     10240, 10445, 10650, 10854, 11059, 11264, 11469, 11674, 11878, 12083,
      99             :     12288, 12493, 12698, 12902, 13107, 13312, 13517, 13722, 13926, 14131,
     100             :     14336, 14541, 14746, 14950, 15155, 15360, 15565, 15770, 15974, 16179,
     101             :     16384, 16589, 16794, 16998, 17203, 17408, 17613, 17818, 18022, 18227,
     102             :     18432, 18637, 18842, 19046, 19251, 19456, 19661, 19866, 20070, 20275,
     103             :     20480, 20685, 20890, 21094, 21299, 21504, 21709, 21914, 22118, 22323,
     104             :     22528, 22733, 22938, 23142, 23347, 23552, 23757, 23962, 24166, 24371,
     105             :     24576, 24781, 24986, 25190, 25395, 25600, 25805, 26010, 26214, 26419,
     106             :     26624, 26829, 27034, 27238, 27443, 27648, 27853, 28058, 28262, 28467,
     107             :     28672, 28877, 29082, 29286, 29491, 29696, 29901, 30106, 30310, 30515,
     108             :     30720, 30925, 31130, 31334, 31539, 31744, 31949, 32154, 32358, 32563
     109             : };
     110             : 
     111             : static Word16 interpolator_table_16k_q15[] = {
     112             :     0, 410, 819, 1229, 1638, 2048, 2458, 2867, 3277, 3686,
     113             :     4096, 4506, 4915, 5325, 5734, 6144, 6554, 6963, 7373, 7782,
     114             :     8192, 8602, 9011, 9421, 9830, 10240, 10650, 11059, 11469, 11878,
     115             :     12288, 12698, 13107, 13517, 13926, 14336, 14746, 15155, 15565, 15974,
     116             :     16384, 16794, 17203, 17613, 18022, 18432, 18842, 19251, 19661, 20070,
     117             :     20480, 20890, 21299, 21709, 22118, 22528, 22938, 23347, 23757, 24166,
     118             :     24576, 24986, 25395, 25805, 26214, 26624, 27034, 27443, 27853, 28262,
     119             :     28672, 29082, 29491, 29901, 30310, 30720, 31130, 31539, 31949, 32358
     120             : };
     121             : 
     122             : 
     123             : /*-------------------------------------------------------------------------
     124             :  * Local functions
     125             :  *------------------------------------------------------------------------*/
     126             : 
     127             : /**
     128             :  * Calculate mantissa (Q31) * gain (Q31).
     129             :  *
     130             :  * Exponent for the mantissa value is also included as input parameter.
     131             :  * Adjust the result so that accuracy of the mantissa multiplication is maximixed
     132             :  * and the corresponding exponent is minimized.
     133             :  */
     134             : 
     135     2772480 : static Word32 mult32_mantissa_fx(
     136             :     const Word32 mantissa,
     137             :     const Word32 gain,
     138             :     const Word16 exp,
     139             :     Word16 *exp_result )
     140             : {
     141     2772480 :     Word64 mult = W_mult_32_32( mantissa, gain ); // Q31 * Q31 -> Q63
     142     2772480 :     Word16 norm = W_norm( mult );
     143     2772480 :     Word32 result = W_extract_h( W_shl( mult, norm ) ); // Q63 -> Q31
     144     2772480 :     *exp_result = sub( exp, norm );
     145             : 
     146     2772480 :     return result;
     147             : }
     148             : 
     149             : 
     150             : /**
     151             :  * Calculate re^2 + im^2 using exponent (Q0) and mantissa (Q31) format.
     152             :  */
     153      334080 : static Word32 sample_energy_fx(
     154             :     const Word32 re_m,
     155             :     const Word16 re_e,
     156             :     const Word32 im_m,
     157             :     const Word16 im_e,
     158             :     Word16 *exp_result )
     159             : {
     160      334080 :     Word16 re_exp = add( re_e, re_e );
     161      334080 :     Word32 re_mult = mult32_mantissa_fx( re_m, re_m, re_exp, &re_exp );
     162      334080 :     move32();
     163             : 
     164      334080 :     Word16 im_exp = add( im_e, im_e );
     165      334080 :     Word32 im_mult = mult32_mantissa_fx( im_m, im_m, im_exp, &im_exp );
     166      334080 :     move32();
     167             : 
     168      334080 :     return BASOP_Util_Add_Mant32Exp( re_mult, re_exp, im_mult, im_exp, exp_result );
     169             : }
     170             : 
     171             : 
     172             : /**
     173             :  * Accumulate sum of re^2 + im^2 over the specified length using exponent (Q0) and mantissa (Q31) format.
     174             :  */
     175       41472 : static void sample_energy_acc_fx(
     176             :     Word32 *re_m,
     177             :     Word16 *re_e,
     178             :     Word32 *im_m,
     179             :     Word16 *im_e,
     180             :     Word32 *out_m,
     181             :     Word16 *out_e,
     182             :     const Word16 len )
     183             : {
     184             :     Word16 i;
     185             : 
     186      145152 :     FOR( i = 0; i < len; i++ )
     187             :     {
     188             :         Word16 exp;
     189             : 
     190             :         // energy = re^2 + im^2
     191      103680 :         Word32 mantissa = sample_energy_fx( re_m[i], re_e[i], im_m[i], im_e[i], &exp );
     192      103680 :         move32();
     193             : 
     194             :         // Accumulate energy
     195      103680 :         *out_m = BASOP_Util_Add_Mant32Exp( *out_m, *out_e, mantissa, exp, out_e );
     196      103680 :         move32();
     197             :     }
     198             : 
     199       41472 :     return;
     200             : }
     201             : 
     202             : // Multiplication of vector (comprising of exponent and mantissa parts) by constant value (Q31)
     203        5120 : static void v_multc_exp_mantissa_fx(
     204             :     const Word32 *in_mantissa,
     205             :     const Word16 *in_exp,
     206             :     const Word32 c,
     207             :     Word32 *out_mantissa,
     208             :     Word16 *out_exp,
     209             :     const Word16 len )
     210             : {
     211             :     Word16 i;
     212             : 
     213      312320 :     FOR( i = 0; i < len; i++ )
     214             :     {
     215      307200 :         out_mantissa[i] = mult32_mantissa_fx( in_mantissa[i], c, in_exp[i], &out_exp[i] );
     216      307200 :         move32();
     217             :     }
     218        5120 :     return;
     219             : }
     220             : 
     221             : 
     222             : // Multiplication of vector (comprising of exponent and mantissa parts) by constant acumulate to the output
     223        5264 : static void v_multc_acc_exp_mantissa_fx(
     224             :     const Word32 *in_mantissa,
     225             :     const Word16 *in_exp,
     226             :     const Word32 c,
     227             :     Word32 *out_mantissa,
     228             :     Word16 *out_exp,
     229             :     const Word16 len )
     230             : {
     231             :     Word16 i;
     232             : 
     233      364304 :     FOR( i = 0; i < len; i++ )
     234             :     {
     235             :         Word16 exp;
     236      359040 :         Word32 mantissa = mult32_mantissa_fx( in_mantissa[i], c, in_exp[i], &exp );
     237      359040 :         move32();
     238             : 
     239      359040 :         out_mantissa[i] = BASOP_Util_Add_Mant32Exp( out_mantissa[i], out_exp[i], mantissa, exp, &out_exp[i] );
     240      359040 :         move32();
     241             :     }
     242             : 
     243        5264 :     return;
     244             : }
     245             : 
     246             : 
     247             : // Calculate min( 4, sqrtf( target / proto ) )
     248             : // target and proto values are expressed using exponent and mantissa
     249             : 
     250      192000 : static Word32 get_processing_gain_fx(
     251             :     const Word32 proto_m,
     252             :     const Word16 proto_e,
     253             :     const Word32 target_m,
     254             :     const Word16 target_e,
     255             :     Word16 *exp )
     256             : {
     257      192000 :     Word16 b = extract_h( proto_m );
     258      192000 :     IF( EQ_16( b, 0 ) )
     259             :     {
     260        2700 :         b = 1;
     261        2700 :         move16();
     262             :     }
     263             : 
     264             :     Word16 mantissa;
     265      192000 :     BASOP_Util_Divide_MantExp( extract_h( target_m ), target_e, b, proto_e, &mantissa, exp );
     266             : 
     267      192000 :     Word32 sqrt_mantissa = Sqrt32( L_shl( mantissa, 16 ), exp );
     268             : 
     269      192000 :     Word16 norm = norm_l( sqrt_mantissa );
     270      192000 :     sqrt_mantissa = L_shl( sqrt_mantissa, norm );
     271      192000 :     *exp = sub( *exp, norm );
     272             : 
     273      192000 :     test();
     274      192000 :     IF( GT_16( *exp, 2 ) && NE_32( sqrt_mantissa, 0 ) )
     275             :     {
     276             :         // (2^3) * (1073741824 / 2^31) == 4.0
     277           0 :         sqrt_mantissa = ONE_IN_Q30; // 0.5 in Q31
     278           0 :         *exp = 3;
     279           0 :         move32();
     280           0 :         move16();
     281             :     }
     282             : 
     283      192000 :     return sqrt_mantissa;
     284             : }
     285             : 
     286             : 
     287        7752 : static void mantissa_exp_to_qvalue(
     288             :     Word16 *exp,
     289             :     Word32 *output,
     290             :     const Word16 target_exp,
     291             :     const Word16 len )
     292             : {
     293             :     Word16 bin;
     294             : 
     295      537672 :     FOR( bin = 0; bin < len; bin++ )
     296             :     {
     297      529920 :         IF( LT_16( exp[bin], -Q31 ) )
     298             :         {
     299           0 :             output[bin] = 0;
     300           0 :             move32();
     301             :         }
     302             :         ELSE
     303             :         {
     304      529920 :             Word16 shift = sub( target_exp, exp[bin] );
     305      529920 :             output[bin] = W_sat_l( W_shr( output[bin], shift ) );
     306             :         }
     307             :     }
     308             : 
     309        7752 :     return;
     310             : }
     311             : 
     312             : 
     313             : /*-------------------------------------------------------------------*
     314             :  * ivas_omasa_data_open()
     315             :  *
     316             :  * Allocate and initialize MASA_ISM rendering handle
     317             :  *-------------------------------------------------------------------*/
     318             : 
     319         288 : ivas_error ivas_omasa_data_open_fx(
     320             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder handle  */
     321             : )
     322             : {
     323             :     MASA_ISM_DATA_HANDLE hMasaIsmData;
     324             :     Word16 ch, band_idx;
     325             :     Word16 sf, obj_idx;
     326             : 
     327         288 :     IF( ( hMasaIsmData = (MASA_ISM_DATA_HANDLE) malloc( sizeof( MASA_ISM_DATA ) ) ) == NULL )
     328             :     {
     329           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA ISM data\n" ) );
     330             :     }
     331             : 
     332        7200 :     FOR( band_idx = 0; band_idx < MASA_FREQUENCY_BANDS; band_idx++ )
     333             :     {
     334       20736 :         FOR( ch = 0; ch < 2; ch++ )
     335             :         {
     336             : 
     337       13824 :             hMasaIsmData->ismPreprocMatrix_fx[ch][ch][band_idx] = ONE_IN_Q28;
     338       13824 :             move32();
     339       13824 :             hMasaIsmData->ismPreprocMatrix_fx[sub( 1, ch )][ch][band_idx] = 0;
     340       13824 :             move32();
     341       13824 :             hMasaIsmData->eneMoveIIR_fx[ch][band_idx] = 0;
     342       13824 :             move32();
     343       13824 :             hMasaIsmData->eneMoveIIR_e[ch][band_idx] = 0;
     344       13824 :             move16();
     345       13824 :             hMasaIsmData->enePreserveIIR_fx[ch][band_idx] = 0;
     346       13824 :             move32();
     347       13824 :             hMasaIsmData->enePreserveIIR_e[ch][band_idx] = 0;
     348       13824 :             move16();
     349             :         }
     350             : 
     351        6912 :         hMasaIsmData->eneOrigIIR_fx[band_idx] = 0;
     352        6912 :         move32();
     353        6912 :         hMasaIsmData->eneOrigIIR_e[band_idx] = 0;
     354        6912 :         move16();
     355        6912 :         hMasaIsmData->preprocEneTarget_fx[band_idx] = 0;
     356        6912 :         move32();
     357        6912 :         hMasaIsmData->preprocEneRealized_fx[band_idx] = 0;
     358        6912 :         move32();
     359             :     }
     360             : 
     361         288 :     hMasaIsmData->objectsEdited = 0;
     362         288 :     move32();
     363         288 :     hMasaIsmData->delayBuffer_fx = NULL;
     364         288 :     move16();
     365             : 
     366        1440 :     FOR( ch = 0; ch < MAX_NUM_OBJECTS; ch++ )
     367             :     {
     368        1152 :         hMasaIsmData->ism_dir_is_edited[ch] = 0;
     369        1152 :         hMasaIsmData->ism_gain_is_edited[ch] = 0;
     370        1152 :         hMasaIsmData->q_elevation_old_fx[ch] = 0; // Q22
     371        1152 :         move32();
     372        1152 :         hMasaIsmData->q_azimuth_old_fx[ch] = 0; // Q22
     373        1152 :         move32();
     374             :     }
     375             : 
     376         288 :     hMasaIsmData->masa_gain_is_edited = 0;
     377         288 :     hMasaIsmData->idx_separated_ism = -1;
     378         288 :     move16();
     379             : 
     380        1440 :     FOR( obj_idx = 0; obj_idx < MAX_NUM_OBJECTS; obj_idx++ )
     381             :     {
     382        1152 :         set16_fx( hMasaIsmData->azimuth_ism_fx[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
     383        1152 :         set16_fx( hMasaIsmData->elevation_ism_fx[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
     384        8064 :         FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR; sf++ )
     385             :         {
     386        6912 :             set32_fx( hMasaIsmData->energy_ratio_ism_fx[obj_idx][sf], 0, CLDFB_NO_CHANNELS_MAX );
     387             :         }
     388             :     }
     389         288 :     set16_fx( hMasaIsmData->azimuth_separated_ism_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
     390         288 :     set16_fx( hMasaIsmData->elevation_separated_ism_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
     391             : 
     392         288 :     hMasaIsmData->hExtData = NULL;
     393         288 :     move32();
     394             : 
     395         288 :     IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
     396             :     {
     397             :         MASA_ISM_EXT_DATA_HANDLE hExtData;
     398           4 :         hExtData = (MASA_ISM_EXT_DATA_HANDLE) malloc( sizeof( MASA_ISM_EXT_DATA ) );
     399           4 :         move32();
     400             : 
     401           4 :         IF( hExtData == NULL )
     402             :         {
     403           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA ISM data\n" ) );
     404             :         }
     405             : 
     406           4 :         hExtData->prev_idx_separated_ism = 0;
     407           4 :         move16();
     408             : 
     409          20 :         FOR( ch = 0; ch < MAX_NUM_OBJECTS; ch++ )
     410             :         {
     411          16 :             set32_fx( hExtData->prev_panning_gains[ch], 0, 2 );
     412             :         }
     413             : 
     414          20 :         FOR( ch = 0; ch < MAX_NUM_OBJECTS; ch++ )
     415             :         {
     416          16 :             set32_fx( hExtData->ism_render_proto_energy_frac[ch], 0, CLDFB_NO_CHANNELS_MAX );
     417          16 :             set16_fx( hExtData->ism_render_proto_energy_exp[ch], 0, CLDFB_NO_CHANNELS_MAX );
     418          16 :             set32_fx( hExtData->ism_render_target_energy_frac[ch], 0, CLDFB_NO_CHANNELS_MAX );
     419          16 :             set16_fx( hExtData->ism_render_target_energy_exp[ch], 0, CLDFB_NO_CHANNELS_MAX );
     420             :         }
     421             : 
     422           4 :         set32_fx( hExtData->masa_render_proto_energy_frac, 0, CLDFB_NO_CHANNELS_MAX );
     423           4 :         set16_fx( hExtData->masa_render_proto_energy_exp, 0, CLDFB_NO_CHANNELS_MAX );
     424           4 :         set32_fx( hExtData->masa_render_target_energy_frac, 0, CLDFB_NO_CHANNELS_MAX );
     425           4 :         set16_fx( hExtData->masa_render_target_energy_exp, 0, CLDFB_NO_CHANNELS_MAX );
     426             : 
     427          28 :         FOR( sf = 0; sf < add( MAX_PARAM_SPATIAL_SUBFRAMES, DELAY_MASA_PARAM_DEC_SFR ); sf++ )
     428             :         {
     429          24 :             set32_fx( hExtData->masa_render_masa_to_total[sf], 0, CLDFB_NO_CHANNELS_MAX );
     430             :         }
     431             : 
     432           4 :         hMasaIsmData->hExtData = hExtData;
     433           4 :         move32();
     434             :     }
     435             : 
     436         288 :     st_ivas->hMasaIsmData = hMasaIsmData;
     437             : 
     438         288 :     return IVAS_ERR_OK;
     439             : }
     440             : 
     441             : 
     442             : /*-------------------------------------------------------------------*
     443             :  * ivas_omasa_data_close()
     444             :  *
     445             :  * Deallocate MASA_ISM rendering handle
     446             :  *-------------------------------------------------------------------*/
     447             : 
     448         868 : void ivas_omasa_data_close_fx(
     449             :     MASA_ISM_DATA_HANDLE *hMasaIsmData /* i/o: MASA_ISM rendering handle    */
     450             : )
     451             : {
     452             :     Word16 i;
     453             : 
     454         868 :     test();
     455         868 :     IF( hMasaIsmData == NULL || *hMasaIsmData == NULL )
     456             :     {
     457         580 :         return;
     458             :     }
     459             : 
     460         288 :     IF( ( *hMasaIsmData )->delayBuffer_fx != NULL )
     461             :     {
     462          49 :         FOR( i = 0; i < ( *hMasaIsmData )->delayBuffer_nchan; i++ )
     463             :         {
     464          34 :             free( ( *hMasaIsmData )->delayBuffer_fx[i] ); // Q11
     465             :         }
     466          15 :         free( ( *hMasaIsmData )->delayBuffer_fx );
     467          15 :         ( *hMasaIsmData )->delayBuffer_fx = NULL;
     468             :     }
     469             : 
     470         288 :     IF( ( *hMasaIsmData )->hExtData != NULL )
     471             :     {
     472           4 :         free( ( *hMasaIsmData )->hExtData );
     473           4 :         ( *hMasaIsmData )->hExtData = NULL;
     474           4 :         move32();
     475             :     }
     476             : 
     477         288 :     free( *hMasaIsmData );
     478         288 :     *hMasaIsmData = NULL;
     479             : 
     480         288 :     return;
     481             : }
     482             : 
     483             : 
     484             : /*--------------------------------------------------------------------------*
     485             :  * ivas_omasa_dec_config()
     486             :  *
     487             :  * oMASA decoder configuration
     488             :  *--------------------------------------------------------------------------*/
     489             : 
     490        1606 : ivas_error ivas_omasa_dec_config_fx(
     491             :     Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure     */
     492             :     Word16 *num_src,
     493             :     Word16 SrcInd[MAX_NUM_TDREND_CHANNELS] )
     494             : {
     495             :     Word16 k, sce_id, nSCE_old, nchan_hp20_old, numCldfbAnalyses_old, numCldfbSyntheses_old;
     496             :     Word32 ivas_total_brate, ism_total_brate, cpe_brate;
     497             :     Word32 brate_SCE, brate_CPE;
     498             :     ISM_MODE ism_mode_old;
     499             :     IVAS_FORMAT ivas_format_orig;
     500             : #ifdef FIX_1330_JBM_MEMORY
     501             :     Word16 nchan_out_buff;
     502             : #else
     503             :     Word16 nchan_out_buff, nchan_out_buff_old;
     504             : #endif
     505             :     ivas_error error;
     506             :     RENDERER_TYPE old_renderer_type;
     507             : 
     508             :     /* initializations */
     509        1606 :     ism_total_brate = 0;
     510        1606 :     move32();
     511        1606 :     ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
     512        1606 :     move32();
     513             : 
     514             :     /* save previous frame parameters */
     515        1606 :     ism_mode_old = ivas_omasa_ism_mode_select_fx( st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->nchan_ism );
     516        1606 :     move16();
     517        1606 :     st_ivas->ism_mode = ism_mode_old;
     518        1606 :     move16();
     519             : 
     520        1606 :     ivas_format_orig = st_ivas->ivas_format;
     521        1606 :     move16();
     522        1606 :     st_ivas->ivas_format = st_ivas->last_ivas_format;
     523        1606 :     move16();
     524        1606 :     ivas_init_dec_get_num_cldfb_instances_fx( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old );
     525             : #ifndef FIX_1330_JBM_MEMORY
     526             :     nchan_out_buff_old = ivas_get_nchan_buffers_dec_fx( st_ivas, -1, -1 );
     527             :     move16();
     528             : #endif
     529        1606 :     st_ivas->ivas_format = ivas_format_orig;
     530        1606 :     move16();
     531             : 
     532        1606 :     nSCE_old = st_ivas->nSCE;
     533        1606 :     move16();
     534        1606 :     nchan_hp20_old = getNumChanSynthesis( st_ivas );
     535        1606 :     move16();
     536             : 
     537             :     /* set ism_mode of current frame */
     538        1606 :     st_ivas->ism_mode = ivas_omasa_ism_mode_select_fx( ivas_total_brate, st_ivas->nchan_ism );
     539        1606 :     move16();
     540             : 
     541             :     /*-----------------------------------------------------------------*
     542             :      * Renderer selection
     543             :      *-----------------------------------------------------------------*/
     544             : 
     545        1606 :     old_renderer_type = st_ivas->renderer_type;
     546        1606 :     move32();
     547             : 
     548             :     /* MASA reconfig. */
     549        1606 :     cpe_brate = calculate_cpe_brate_MASA_ISM_fx( st_ivas->ism_mode, ivas_total_brate, st_ivas->nchan_ism );
     550        1606 :     move32();
     551        1606 :     test();
     552        1606 :     test();
     553        1606 :     test();
     554        1606 :     IF( ( st_ivas->ini_active_frame == 0 ) && ( ivas_total_brate != FRAME_NO_DATA ) && LT_32( cpe_brate, MASA_STEREO_MIN_BITRATE ) && EQ_16( st_ivas->nCPE, 1 ) )
     555             :     {
     556           0 :         st_ivas->hCPE[0]->nchan_out = 1;
     557           0 :         move16();
     558             :     }
     559             :     ELSE
     560             :     {
     561        1606 :         IF( NE_32( ( error = ivas_masa_dec_reconfigure_fx( st_ivas ) ), IVAS_ERR_OK ) )
     562             :         {
     563           0 :             return error;
     564             :         }
     565             :     }
     566             : 
     567        1606 :     IF( LT_32( cpe_brate, MASA_STEREO_MIN_BITRATE ) )
     568             :     {
     569         543 :         st_ivas->hCPE[0]->nchan_out = 1;
     570         543 :         move16();
     571             :     }
     572             :     ELSE
     573             :     {
     574        1063 :         st_ivas->hCPE[0]->nchan_out = 2;
     575        1063 :         move16();
     576             :     }
     577             : 
     578             :     /* OMASA reconfig. */
     579        1606 :     test();
     580        1606 :     IF( st_ivas->hMasaIsmData == NULL && EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     581             :     {
     582           2 :         IF( NE_32( ( error = ivas_omasa_data_open_fx( st_ivas ) ), IVAS_ERR_OK ) )
     583             :         {
     584           0 :             return error;
     585             :         }
     586             :     }
     587             : 
     588        1606 :     ivas_set_omasa_TC_fx( st_ivas->ism_mode, st_ivas->nchan_ism, &st_ivas->nSCE, &st_ivas->nCPE );
     589             : 
     590             :     /* re-configure hp20 memories */
     591        1606 :     IF( NE_32( ( error = ivas_hp20_dec_reconfig_fx( st_ivas, nchan_hp20_old ) ), IVAS_ERR_OK ) )
     592             :     {
     593           0 :         return error;
     594             :     }
     595             : 
     596             :     /* reconfigure core-coders for ISMs */
     597        1606 :     k = 0;
     598        1606 :     move16();
     599       12671 :     WHILE( LT_16( k, SIZE_IVAS_BRATE_TBL ) && NE_32( ivas_total_brate, ivas_brate_tbl[k] ) )
     600             :     {
     601       11065 :         k = add( k, 1 );
     602             :     }
     603             : 
     604        3679 :     FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
     605             :     {
     606        2073 :         ism_total_brate = L_add( ism_total_brate, sep_object_brate[k - 2][st_ivas->nSCE - 1] );
     607             :     }
     608             : 
     609        1606 :     brate_SCE = 0;
     610        1606 :     move32();
     611        1606 :     IF( st_ivas->nSCE > 0 )
     612             :     {
     613        1168 :         brate_SCE = sep_object_brate[k - 2][st_ivas->nSCE - 1];
     614        1168 :         move32();
     615             :     }
     616        1606 :     brate_CPE = L_sub( ivas_total_brate, ism_total_brate );
     617             : 
     618        1606 :     IF( NE_32( ( error = ivas_corecoder_dec_reconfig_fx( st_ivas, nSCE_old, 1, 2, 0, brate_SCE, brate_CPE ) ), IVAS_ERR_OK ) )
     619             :     {
     620           0 :         return error;
     621             :     }
     622             : 
     623        1606 :     IF( NE_16( ism_mode_old, st_ivas->ism_mode ) )
     624             :     {
     625             :         /* ISM MD reconfig. */
     626        1605 :         IF( st_ivas->hIsmMetaData[0] == NULL )
     627             :         {
     628           2 :             IF( ( error = ivas_ism_metadata_dec_create_fx( st_ivas, st_ivas->nchan_ism, NULL ) ) != IVAS_ERR_OK )
     629             :             {
     630           0 :                 return error;
     631             :             }
     632             :         }
     633             :         ELSE
     634             :         {
     635        6781 :             FOR( k = 0; k < st_ivas->nchan_ism; k++ )
     636             :             {
     637        5178 :                 ivas_ism_reset_metadata_handle_dec_fx( st_ivas->hIsmMetaData[k] );
     638             :             }
     639             :         }
     640             : 
     641        1605 :         st_ivas->hCPE[0]->element_brate = L_sub( ivas_total_brate, ism_total_brate );
     642             : 
     643             :         /*-----------------------------------------------------------------*
     644             :          * Renderer selection
     645             :          *-----------------------------------------------------------------*/
     646             : 
     647        1605 :         ivas_renderer_select( st_ivas );
     648             : 
     649             :         /*-------------------------------------------------------------------*
     650             :          * Reallocate rendering handles
     651             :          *--------------------------------------------------------------------*/
     652             : 
     653        1605 :         IF( NE_16( old_renderer_type, st_ivas->renderer_type ) )
     654             :         {
     655         138 :             IF( EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) )
     656             :             {
     657          38 :                 IF( NE_32( ( error = ivas_mono_dmx_renderer_open( st_ivas ) ), IVAS_ERR_OK ) )
     658             :                 {
     659           0 :                     return error;
     660             :                 }
     661             :             }
     662             :             ELSE
     663             :             {
     664         100 :                 ivas_mono_dmx_renderer_close( &st_ivas->hMonoDmxRenderer );
     665             :             }
     666             :         }
     667             : 
     668             :         /* objects renderer reconfig. */
     669        1605 :         test();
     670        1605 :         IF( st_ivas->hMasaIsmData != NULL || st_ivas->hIsmRendererData != NULL )
     671             :         {
     672             :             /* this calls also ivas_ism_renderer_close() closing st_ivas->hIsmRendererData used by the EXT renderers. also cleans st_ivas->hMasaIsmData */
     673        1605 :             ivas_omasa_separate_object_renderer_close( st_ivas );
     674             :         }
     675             : 
     676        1605 :         test();
     677        1605 :         IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) && st_ivas->hMasaIsmData != NULL ) /* this structure is in use only in ISM_MASA_MODE_PARAM_ONE_OBJ */
     678             :         {
     679         395 :             MASA_ISM_DATA_HANDLE hMasaIsmData = st_ivas->hMasaIsmData;
     680        1975 :             FOR( Word16 obj_idx = 0; obj_idx < MAX_NUM_OBJECTS; obj_idx++ )
     681             :             {
     682        1580 :                 set_s( hMasaIsmData->azimuth_ism_fx[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
     683        1580 :                 set_s( hMasaIsmData->elevation_ism_fx[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
     684       11060 :                 FOR( int16_t sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR; sf++ )
     685             :                 {
     686        9480 :                     set_l( hMasaIsmData->energy_ratio_ism_fx[obj_idx][sf], 0, CLDFB_NO_CHANNELS_MAX );
     687             :                 }
     688             :             }
     689         395 :             set_s( hMasaIsmData->azimuth_separated_ism_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
     690         395 :             set_s( hMasaIsmData->elevation_separated_ism_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR );
     691             :         }
     692             : 
     693        1605 :         IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) )
     694             :         {
     695         295 :             IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
     696             :             {
     697             :                 /* Allocate TD renderer for the objects in DISC mode */
     698          78 :                 if ( st_ivas->hBinRendererTd == NULL )
     699             :                 {
     700          78 :                     IF( NE_32( ( error = ivas_td_binaural_open_fx( st_ivas, SrcInd, num_src ) ), IVAS_ERR_OK ) )
     701             :                     {
     702           0 :                         return error;
     703             :                     }
     704             : 
     705          78 :                     IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
     706             :                     {
     707           0 :                         IF( NE_32( ( error = ivas_reverb_open_fx( &st_ivas->hReverb, st_ivas->hHrtfStatistics, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ), IVAS_ERR_OK ) )
     708             :                         {
     709           0 :                             return error;
     710             :                         }
     711             :                     }
     712             :                 }
     713             : 
     714             :                 /* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */
     715          78 :                 IF( NE_32( ( error = ivas_omasa_objects_delay_open_fx( st_ivas ) ), IVAS_ERR_OK ) )
     716             :                 {
     717           0 :                     return error;
     718             :                 }
     719             :             }
     720             :             ELSE
     721             :             {
     722         217 :                 if ( st_ivas->hBinRendererTd != NULL )
     723             :                 {
     724             :                     /* TD renderer handle */
     725          79 :                     ivas_td_binaural_close_fx( &st_ivas->hBinRendererTd );
     726             :                 }
     727             : 
     728             :                 /* ISM renderer handle + ISM data handle */
     729         217 :                 ivas_omasa_separate_object_renderer_close( st_ivas );
     730             :             }
     731             :         }
     732             : 
     733        1605 :         IF( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) )
     734             :         {
     735         667 :             IF( NE_32( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_RECONFIGURE ) ), IVAS_ERR_OK ) )
     736             :             {
     737           0 :                 return error;
     738             :             }
     739             : 
     740         667 :             test();
     741         667 :             test();
     742         667 :             IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
     743             :             {
     744             :                 /* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */
     745         485 :                 IF( NE_32( ( error = ivas_omasa_objects_delay_open_fx( st_ivas ) ), IVAS_ERR_OK ) )
     746             :                 {
     747           0 :                     return error;
     748             :                 }
     749             : 
     750         485 :                 IF( NE_32( ( error = ivas_omasa_separate_object_renderer_open( st_ivas ) ), IVAS_ERR_OK ) )
     751             :                 {
     752           0 :                     return error;
     753             :                 }
     754             :             }
     755             :             ELSE
     756             :             {
     757             :                 /* ISM renderer handle + ISM data handle */
     758         182 :                 ivas_omasa_separate_object_renderer_close( st_ivas );
     759             :             }
     760             :         }
     761             : 
     762        1605 :         IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) )
     763             :         {
     764             :             /* Allocate 'hIsmRendererData' handle */
     765          18 :             error = ivas_omasa_combine_separate_ism_with_masa_open_fx( st_ivas );
     766          18 :             move32();
     767          18 :             IF( NE_32( error, IVAS_ERR_OK ) )
     768             :             {
     769           0 :                 return error;
     770             :             }
     771             :         }
     772             : 
     773        1605 :         IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) )
     774             :         {
     775             :             DIRAC_CONFIG_FLAG common_rend_config_flag;
     776          19 :             IF( st_ivas->hSpatParamRendCom == NULL )
     777             :             {
     778          19 :                 common_rend_config_flag = DIRAC_OPEN;
     779             :             }
     780             :             ELSE
     781             :             {
     782           0 :                 common_rend_config_flag = DIRAC_RECONFIGURE;
     783             :             }
     784          19 :             move32();
     785             : 
     786             :             /* Allocate 'hIsmRendererData' handle and memory for delay buffer within 'hMasaIsmData' */
     787          19 :             IF( NE_32( ( error = ivas_omasa_objects_delay_open_fx( st_ivas ) ), IVAS_ERR_OK ) )
     788             :             {
     789           0 :                 return error;
     790             :             }
     791             : 
     792          19 :             IF( NE_32( ( error = ivas_spat_hSpatParamRendCom_config_fx( &st_ivas->hSpatParamRendCom, common_rend_config_flag, 0, st_ivas->ivas_format, st_ivas->mc_mode, st_ivas->hDecoderConfig->output_Fs, 0, 0 ) ), IVAS_ERR_OK ) )
     793             :             {
     794           0 :                 return error;
     795             :             }
     796             :         }
     797             : 
     798             :         /*-----------------------------------------------------------------*
     799             :          * TD Decorrelator
     800             :          *-----------------------------------------------------------------*/
     801             : 
     802        1605 :         IF( st_ivas->hDiracDecBin[0] != NULL )
     803             :         {
     804         729 :             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 ) )
     805             :             {
     806           0 :                 return error;
     807             :             }
     808             :         }
     809             : 
     810             :         /*-----------------------------------------------------------------*
     811             :          * CLDFB instances
     812             :          *-----------------------------------------------------------------*/
     813             : 
     814        1605 :         IF( NE_32( ( error = ivas_cldfb_dec_reconfig_fx( st_ivas, 2, numCldfbAnalyses_old, numCldfbSyntheses_old ) ), IVAS_ERR_OK ) )
     815             :         {
     816           0 :             return error;
     817             :         }
     818             : 
     819             :         /*-----------------------------------------------------------------*
     820             :          * output audio buffers
     821             :          *-----------------------------------------------------------------*/
     822             : 
     823        1605 :         nchan_out_buff = ivas_get_nchan_buffers_dec_fx( st_ivas, -1, -1 );
     824             : #ifdef FIX_1330_JBM_MEMORY
     825        1605 :         IF( ( error = ivas_output_buff_dec_fx( st_ivas->p_output_fx, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK )
     826             : #else
     827             :         IF( NE_32( ( error = ivas_output_buff_dec_fx( st_ivas->p_output_fx, nchan_out_buff_old, nchan_out_buff ) ), IVAS_ERR_OK ) )
     828             : #endif
     829             :         {
     830           0 :             return error;
     831             :         }
     832             :     }
     833             : 
     834        1606 :     return IVAS_ERR_OK;
     835             : }
     836             : 
     837             : 
     838             : /*--------------------------------------------------------------------------*
     839             :  * ivas_set_surplus_brate_dec()
     840             :  *
     841             :  * set bit-rate surplus in combined format coding
     842             :  *--------------------------------------------------------------------------*/
     843        7084 : void ivas_set_surplus_brate_dec(
     844             :     Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
     845             :     Word32 *ism_total_brate  /* i/o: ISM total bitrate      */
     846             : )
     847             : {
     848             :     Word16 n, bits_ism, bits_element[MAX_NUM_OBJECTS];
     849             :     Word32 ism_total_brate_ref, element_brate[MAX_NUM_OBJECTS];
     850             : 
     851        7084 :     *ism_total_brate = 0;
     852        7084 :     move32();
     853             : 
     854        7084 :     test();
     855        7084 :     IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     856             :     {
     857        3935 :         *ism_total_brate = ivas_interformat_brate_fx( st_ivas->ism_mode, 1, st_ivas->hSCE[0]->element_brate, st_ivas->hIsmMetaData[0]->ism_imp, 0 );
     858        3935 :         move32();
     859             : 
     860        3935 :         st_ivas->hCPE[0]->brate_surplus = L_sub( st_ivas->hSCE[0]->element_brate, *ism_total_brate );
     861        3935 :         move32();
     862             : 
     863             :         /* set 'st->total_brate'; there are no meta-data in ISM_MASA_MODE_PARAM_ONE_OBJ mode */
     864        3935 :         st_ivas->hSCE[0]->hCoreCoder[0]->total_brate = *ism_total_brate;
     865        3935 :         move32();
     866             : 
     867        3935 :         st_ivas->hSCE[0]->hCoreCoder[0]->low_rate_mode = 0;
     868        3935 :         move16();
     869        3935 :         if ( EQ_16( st_ivas->hIsmMetaData[0]->ism_imp, ISM_NO_META ) )
     870             :         {
     871           0 :             st_ivas->hSCE[0]->hCoreCoder[0]->low_rate_mode = 1;
     872           0 :             move16();
     873             :         }
     874             :     }
     875        3149 :     ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
     876             :     {
     877             :         Word16 brate_limit_flag, ism_imp[MAX_NUM_OBJECTS], tmp;
     878             : 
     879       11618 :         FOR( n = 0; n < st_ivas->nchan_ism; n++ )
     880             :         {
     881        8469 :             ism_imp[n] = st_ivas->hIsmMetaData[n]->ism_imp;
     882        8469 :             move16();
     883             :         }
     884             : 
     885        3149 :         brate_limit_flag = calculate_brate_limit_flag_fx( ism_imp, st_ivas->nchan_ism );
     886             : 
     887        3149 :         ism_total_brate_ref = 0;
     888        3149 :         move32();
     889       11618 :         FOR( n = 0; n < st_ivas->nchan_ism; n++ )
     890             :         {
     891        8469 :             ism_total_brate_ref = L_add( ism_total_brate_ref, st_ivas->hSCE[n]->element_brate );
     892             :         }
     893             : 
     894             :         /* bits_ism = (int16_t) ( ism_total_brate_ref / FRAMES_PER_SEC ); */
     895        3149 :         bits_ism = extract_l( Mpy_32_32( ism_total_brate_ref, ONE_BY_FRAMES_PER_SEC_Q31 ) );
     896             : 
     897        3149 :         tmp = 0;
     898        3149 :         move16();
     899        3149 :         IF( bits_ism != 0 )
     900             :         {
     901        3149 :             tmp = idiv1616( bits_ism, st_ivas->nchan_ism );
     902             :         }
     903        3149 :         set16_fx( bits_element, tmp, st_ivas->nchan_ism );
     904        3149 :         bits_element[st_ivas->nchan_ism - 1] = add( bits_element[st_ivas->nchan_ism - 1], bits_ism % st_ivas->nchan_ism );
     905        3149 :         move16();
     906        3149 :         bitbudget_to_brate( bits_element, element_brate, st_ivas->nchan_ism );
     907             : 
     908        3149 :         *ism_total_brate = 0;
     909        3149 :         move32();
     910       11618 :         FOR( n = 0; n < st_ivas->nchan_ism; n++ )
     911             :         {
     912        8469 :             st_ivas->hSCE[n]->element_brate = element_brate[n];
     913        8469 :             move32();
     914             : 
     915        8469 :             *ism_total_brate = L_add( *ism_total_brate, ivas_interformat_brate_fx( ISM_MASA_MODE_DISC, st_ivas->nchan_ism, st_ivas->hSCE[n]->element_brate, st_ivas->hIsmMetaData[n]->ism_imp, brate_limit_flag ) );
     916        8469 :             move32();
     917             : 
     918        8469 :             test();
     919        8469 :             test();
     920        8469 :             IF( GT_16( ism_imp[n], 1 ) && EQ_16( st_ivas->flag_omasa_brate, 1 ) && brate_limit_flag >= 0 )
     921             :             {
     922         436 :                 *ism_total_brate = L_sub( *ism_total_brate, ADJUST_ISM_BRATE_NEG );
     923         436 :                 move32();
     924             :             }
     925             : 
     926        8469 :             test();
     927        8469 :             test();
     928        8469 :             test();
     929        8469 :             IF( EQ_16( brate_limit_flag, -1 ) && GE_16( ism_imp[n], 1 ) && GE_16( st_ivas->nchan_ism, 3 ) && GT_32( L_sub( ism_total_brate_ref, *ism_total_brate ), IVAS_48k ) )
     930             :             {
     931           0 :                 *ism_total_brate = L_add( *ism_total_brate, ADJUST_ISM_BRATE_POS );
     932           0 :                 move32();
     933             :             }
     934             :         }
     935        3149 :         st_ivas->hCPE[0]->brate_surplus = L_sub( ism_total_brate_ref, *ism_total_brate );
     936        3149 :         move32();
     937             : 
     938             :         /* 'st->total_brate' is set in ivas_ism_config */
     939             :     }
     940             :     ELSE
     941             :     {
     942           0 :         st_ivas->hCPE[0]->brate_surplus = 0;
     943           0 :         move32();
     944             :     }
     945             : 
     946        7084 :     return;
     947             : }
     948             : 
     949             : 
     950             : /*--------------------------------------------------------------------------*
     951             :  * ivas_omasa_ism_metadata_dec()
     952             :  *
     953             :  * decode ISM metadata in OMASA format
     954             :  *--------------------------------------------------------------------------*/
     955             : 
     956        7084 : ivas_error ivas_omasa_ism_metadata_dec_fx(
     957             :     Decoder_Struct *st_ivas,            /* i/o: IVAS decoder structure            */
     958             :     const Word32 ism_total_brate,       /* i  : ISM total bitrate                 */
     959             :     Word16 *nchan_ism,                  /* o  : number of ISM separated channels  */
     960             :     Word16 *nchan_transport_ism,        /* o  : number of ISM TCs                 */
     961             :     const Word16 dirac_bs_md_write_idx, /* i  : DirAC bitstream write index       */
     962             :     Word16 nb_bits_metadata[]           /* o  : number of ISM metadata bits       */
     963             : )
     964             : {
     965             :     Word16 n, block;
     966             :     Word16 azimuth_ism, elevation_ism, meta_write_index;
     967             :     ivas_error error;
     968             : 
     969             :     /* set ISM parameters */
     970        7084 :     *nchan_ism = st_ivas->nchan_ism;
     971        7084 :     move16();
     972        7084 :     *nchan_transport_ism = st_ivas->nchan_ism;
     973        7084 :     move16();
     974             : 
     975        7084 :     IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     976             :     {
     977        2068 :         *nchan_ism = 1;
     978        2068 :         move16();
     979        2068 :         *nchan_transport_ism = 1;
     980        2068 :         move16();
     981             :     }
     982        5016 :     ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     983             :     {
     984        1867 :         *nchan_ism = 0;
     985        1867 :         move16();
     986        1867 :         *nchan_transport_ism = 1;
     987        1867 :         move16();
     988             :     }
     989             : 
     990        7084 :     test();
     991        7084 :     test();
     992        7084 :     IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     993             :     {
     994             :         /* decode ISM metadata */
     995        5217 :         IF( NE_32( ( error = ivas_ism_metadata_dec_fx( ism_total_brate, *nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi,
     996             :                                                        nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt, st_ivas->hSCE[0]->hCoreCoder[0] ) ),
     997             :                    IVAS_ERR_OK ) )
     998             :         {
     999           0 :             return error;
    1000             :         }
    1001             : 
    1002        5217 :         IF( st_ivas->hDirAC != NULL )
    1003             :         {
    1004        3942 :             IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
    1005             :             {
    1006        7803 :                 FOR( n = 0; n < st_ivas->nchan_ism; n++ )
    1007             :                 {
    1008             :                     // azimuth_ism = (int16_t) ( st_ivas->hIsmMetaData[n]->azimuth + 0.5f );
    1009             :                     // elevation_ism = (int16_t) ( st_ivas->hIsmMetaData[n]->elevation + 0.5f );
    1010        5673 :                     azimuth_ism = extract_l( L_shr_r( L_abs( st_ivas->hIsmMetaData[n]->azimuth_fx /*Q22*/ ), 22 ) ); // Q0
    1011        5673 :                     if ( st_ivas->hIsmMetaData[n]->azimuth_fx < 0 )
    1012             :                     {
    1013        2994 :                         azimuth_ism = negate( azimuth_ism );
    1014             :                     }
    1015        5673 :                     elevation_ism = extract_l( L_shr_r( L_abs( st_ivas->hIsmMetaData[n]->elevation_fx /*Q22*/ ), 22 ) ); // Q0
    1016        5673 :                     if ( st_ivas->hIsmMetaData[n]->elevation_fx < 0 )
    1017             :                     {
    1018        1885 :                         elevation_ism = negate( elevation_ism );
    1019             :                     }
    1020             : 
    1021       28365 :                     FOR( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ )
    1022             :                     {
    1023       22692 :                         meta_write_index = ( add( dirac_bs_md_write_idx, block ) ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length;
    1024       22692 :                         move16();
    1025       22692 :                         st_ivas->hMasaIsmData->azimuth_ism_fx[n][meta_write_index] = azimuth_ism;
    1026       22692 :                         move16();
    1027       22692 :                         st_ivas->hMasaIsmData->elevation_ism_fx[n][meta_write_index] = elevation_ism;
    1028       22692 :                         move16();
    1029             :                     }
    1030             :                 }
    1031             :             }
    1032             :             ELSE /* ISM_MASA_MODE_MASA_ONE_OBJ */
    1033             :             {
    1034        1812 :                 azimuth_ism = extract_l( L_shr_r( L_abs( st_ivas->hIsmMetaData[0]->azimuth_fx ), 22 ) );
    1035        1812 :                 if ( st_ivas->hIsmMetaData[0]->azimuth_fx < 0 )
    1036             :                 {
    1037         983 :                     azimuth_ism = negate( azimuth_ism );
    1038             :                 }
    1039        1812 :                 elevation_ism = extract_l( L_shr_r( L_abs( st_ivas->hIsmMetaData[0]->elevation_fx ), 22 ) );
    1040        1812 :                 if ( st_ivas->hIsmMetaData[0]->elevation_fx < 0 )
    1041             :                 {
    1042         563 :                     elevation_ism = negate( elevation_ism );
    1043             :                 }
    1044             : 
    1045        9060 :                 FOR( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ )
    1046             :                 {
    1047        7248 :                     meta_write_index = ( add( dirac_bs_md_write_idx, block ) ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length;
    1048        7248 :                     move16();
    1049        7248 :                     st_ivas->hMasaIsmData->azimuth_separated_ism_fx[meta_write_index] = azimuth_ism;
    1050        7248 :                     move16();
    1051        7248 :                     st_ivas->hMasaIsmData->elevation_separated_ism_fx[meta_write_index] = elevation_ism;
    1052        7248 :                     move16();
    1053             :                 }
    1054             :             }
    1055             :         }
    1056        1275 :         ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) && EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) )
    1057             :         {
    1058          36 :             azimuth_ism = extract_l( L_shr_r( L_abs( st_ivas->hIsmMetaData[0]->azimuth_fx ), 22 ) );
    1059          36 :             if ( st_ivas->hIsmMetaData[0]->azimuth_fx < 0 )
    1060             :             {
    1061          19 :                 azimuth_ism = negate( azimuth_ism );
    1062             :             }
    1063          36 :             elevation_ism = extract_l( L_shr_r( L_abs( st_ivas->hIsmMetaData[0]->elevation_fx ), 22 ) );
    1064          36 :             if ( st_ivas->hIsmMetaData[0]->elevation_fx < 0 )
    1065             :             {
    1066           3 :                 elevation_ism = negate( elevation_ism );
    1067             :             }
    1068             : 
    1069         108 :             FOR( block = 0; block < 2; block++ )
    1070             :             {
    1071          72 :                 st_ivas->hMasaIsmData->azimuth_separated_ism_fx[block] = st_ivas->hMasaIsmData->azimuth_separated_ism_fx[add( block, 2 )];
    1072          72 :                 st_ivas->hMasaIsmData->elevation_separated_ism_fx[block] = st_ivas->hMasaIsmData->elevation_separated_ism_fx[add( block, 2 )];
    1073          72 :                 move16();
    1074          72 :                 move16();
    1075             :             }
    1076         108 :             FOR( block = 2; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ )
    1077             :             {
    1078          72 :                 st_ivas->hMasaIsmData->azimuth_separated_ism_fx[block] = azimuth_ism;
    1079          72 :                 st_ivas->hMasaIsmData->elevation_separated_ism_fx[block] = elevation_ism;
    1080          72 :                 move16();
    1081          72 :                 move16();
    1082             :             }
    1083             :         }
    1084             :     }
    1085             : 
    1086        7084 :     return IVAS_ERR_OK;
    1087             : }
    1088             : 
    1089             : /*--------------------------------------------------------------------------*
    1090             :  * ivas_omasa_dirac_rend_jbm_fx()
    1091             :  *
    1092             :  * Rendering in OMASA format for JBM
    1093             :  *--------------------------------------------------------------------------*/
    1094             : 
    1095        2979 : void ivas_omasa_dirac_rend_jbm_fx(
    1096             :     Decoder_Struct *st_ivas,      /* i/o: IVAS decoder handle                      */
    1097             :     const UWord16 nSamplesAsked,  /* i  : number of samples requested              */
    1098             :     UWord16 *nSamplesRendered,    /* o  : number of samples rendered               */
    1099             :     UWord16 *nSamplesAvailable,   /* o  : number of samples still to render        */
    1100             :     const Word16 nchan_transport, /* i  : number of transport channels             */
    1101             :     Word32 *output_fx[]           /* o  : rendered time signal                     Q11*/
    1102             : )
    1103             : {
    1104             :     Word16 subframes_rendered;
    1105             : #ifndef FIX_1330_JBM_MEMORY
    1106             :     Word16 slots_rendered;
    1107             : #endif
    1108             :     Word16 n;
    1109             :     Word32 data_separated_objects[MAX_NUM_OBJECTS][L_FRAME48k];
    1110             : 
    1111             : #ifndef FIX_1330_JBM_MEMORY
    1112             :     test();
    1113             :     IF( !st_ivas->hDecoderConfig->Opt_tsm )
    1114             :     {
    1115             : #endif
    1116        2979 :         *nSamplesRendered = s_min( nSamplesAsked, st_ivas->hTcBuffer->n_samples_available );
    1117             : 
    1118        2979 :         test();
    1119        2979 :         IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
    1120             :         {
    1121        1652 :             Copy32( &output_fx[CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[0], *nSamplesRendered );
    1122             : 
    1123             : #ifdef FIX_1330_JBM_MEMORY
    1124        1652 :             IF( !st_ivas->hDecoderConfig->Opt_tsm && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
    1125             : #else
    1126             :         IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
    1127             : #endif
    1128             :             {
    1129             :                 /* Gain separated object, if edited */
    1130        2036 :                 FOR( n = 0; n < st_ivas->nchan_ism; n++ )
    1131             :                 {
    1132        1584 :                     test();
    1133        1584 :                     IF( st_ivas->hMasaIsmData->ism_gain_is_edited[n] && EQ_16( st_ivas->hMasaIsmData->idx_separated_ism, n ) )
    1134             :                     {
    1135           0 :                         v_multc_fx_16( data_separated_objects[0], st_ivas->hMasaIsmData->gain_ism_edited_fx[n], data_separated_objects[0], *nSamplesRendered ); // Q = 8
    1136           0 :                         Scale_sig32( data_separated_objects[0], *nSamplesRendered, Q3 );                                                                        // Q = 11
    1137             :                     }
    1138             :                 }
    1139             :             }
    1140             :         }
    1141             :         ELSE
    1142             :         {
    1143        4592 :             FOR( n = 0; n < st_ivas->nchan_ism; n++ )
    1144             :             {
    1145        3265 :                 Copy32( &output_fx[n + CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[n], *nSamplesRendered );
    1146             : 
    1147             :                 /* Gain discrete objects, if edited */
    1148             : #ifdef FIX_1330_JBM_MEMORY
    1149        3265 :                 IF( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hMasaIsmData->ism_gain_is_edited[n] )
    1150             : #else
    1151             :             IF( st_ivas->hMasaIsmData->ism_gain_is_edited[n] )
    1152             : #endif
    1153             :                 {
    1154           0 :                     v_multc_fx_16( data_separated_objects[n], st_ivas->hMasaIsmData->gain_ism_edited_fx[n], data_separated_objects[n], *nSamplesRendered ); // Q = 8
    1155           0 :                     Scale_sig32( data_separated_objects[n], *nSamplesRendered, Q3 );                                                                        // Q = 11
    1156             :                 }
    1157             :             }
    1158             : 
    1159             :             /* Gain MASA part, if edited */
    1160             : #ifdef FIX_1330_JBM_MEMORY
    1161        1327 :             IF( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hMasaIsmData->masa_gain_is_edited )
    1162             : #else
    1163             :         IF( st_ivas->hMasaIsmData->masa_gain_is_edited )
    1164             : #endif
    1165             :             {
    1166           0 :                 FOR( n = 0; n < 2; n++ )
    1167             :                 {
    1168           0 :                     v_multc_fx_16( output_fx[n], st_ivas->hMasaIsmData->gain_masa_edited_fx, output_fx[n], *nSamplesRendered ); // Q = 8
    1169           0 :                     Scale_sig32( output_fx[n], *nSamplesRendered, Q3 );                                                         // Q = 11
    1170             :                 }
    1171             :             }
    1172             :         }
    1173             : #ifndef FIX_1330_JBM_MEMORY
    1174             :     }
    1175             : #endif
    1176             : 
    1177        2979 :     subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered;
    1178        2979 :     move16();
    1179             : #ifndef FIX_1330_JBM_MEMORY
    1180             :     slots_rendered = st_ivas->hSpatParamRendCom->slots_rendered;
    1181             :     move16();
    1182             : #endif
    1183             : 
    1184        2979 :     ivas_dirac_dec_render_fx( st_ivas, nchan_transport, nSamplesAsked, nSamplesRendered, nSamplesAvailable, output_fx );
    1185             : 
    1186       14895 :     FOR( Word16 ind1 = 0; ind1 < MAX_NUM_OBJECTS; ind1++ )
    1187             :     {
    1188       11916 :         scale_sig32( st_ivas->hIsmRendererData->prev_gains_fx[ind1], MAX_OUTPUT_CHANNELS, -1 ); // Q30 -> Q29
    1189             :     }
    1190             : 
    1191             : #ifdef FIX_1330_JBM_MEMORY
    1192        2979 :     ivas_omasa_separate_object_render_jbm_fx( st_ivas, *nSamplesRendered, data_separated_objects, output_fx, subframes_rendered );
    1193             : #else
    1194             :     ivas_omasa_separate_object_render_jbm_fx( st_ivas, *nSamplesRendered, data_separated_objects, output_fx, subframes_rendered, slots_rendered );
    1195             : #endif
    1196             : 
    1197       14895 :     FOR( Word16 ind1 = 0; ind1 < MAX_NUM_OBJECTS; ind1++ )
    1198             :     {
    1199       11916 :         scale_sig32( st_ivas->hIsmRendererData->prev_gains_fx[ind1], MAX_OUTPUT_CHANNELS, 1 ); // Q29 -> Q30
    1200             :     }
    1201             : 
    1202        2979 :     return;
    1203             : }
    1204             : 
    1205             : 
    1206             : /*--------------------------------------------------------------------------*
    1207             :  * ivas_omasa_dirac_td_binaural_render()
    1208             :  *
    1209             :  * Binaural rendering in OMASA format for JBM
    1210             :  *--------------------------------------------------------------------------*/
    1211             : 
    1212         419 : ivas_error ivas_omasa_dirac_td_binaural_jbm_fx(
    1213             :     Decoder_Struct *st_ivas,      /* i/o: IVAS decoder handle                      */
    1214             :     const UWord16 nSamplesAsked,  /* i  : number of samples requested              */
    1215             :     UWord16 *nSamplesRendered,    /* o  : number of samples rendered               */
    1216             :     UWord16 *nSamplesAvailable,   /* o  : number of samples still to render        */
    1217             :     const Word16 nchan_transport, /* i  : number of transport channels             */
    1218             :     Word32 *output_fx[]           /* o  : rendered time signal                     Q11*/
    1219             : )
    1220             : {
    1221             :     Word16 n;
    1222             :     ivas_error error;
    1223             :     Word32 *p_sepobj_fx[BINAURAL_CHANNELS]; // Q11
    1224             :     Word32 data_separated_objects_fx[BINAURAL_CHANNELS][L_FRAME48k];
    1225             :     Word16 slot_idx_start;
    1226             : 
    1227         419 :     slot_idx_start = st_ivas->hSpatParamRendCom->slots_rendered;
    1228         419 :     move16();
    1229             : 
    1230        1257 :     FOR( n = 0; n < BINAURAL_CHANNELS; n++ )
    1231             :     {
    1232         838 :         p_sepobj_fx[n] = &data_separated_objects_fx[n][0];
    1233             :     }
    1234             : 
    1235             :     /* Delay the object signals to match the CLDFB delay. Delay the whole buffer with the first rendering call of the stretched buffer. */
    1236             : 
    1237         419 :     ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailable, nchan_transport, output_fx );
    1238             : 
    1239             :     /* reset combined orientation access index before calling the td renderer */
    1240         419 :     ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData );
    1241             : 
    1242         419 :     IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    1243           0 :     {
    1244             :         Word16 slot_idx, num_cldfb_bands, nchan_transport_orig, cldfb_slots;
    1245             :         Word32 Cldfb_RealBuffer[CLDFB_NO_CHANNELS_MAX];
    1246             :         Word32 Cldfb_ImagBuffer[CLDFB_NO_CHANNELS_MAX];
    1247             :         Word32 *p_rend_obj[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; /* [8 * 2] */
    1248           0 :         Word16 q_cldfb, q_in = 11;
    1249           0 :         move16();
    1250             : 
    1251           0 :         FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); n++ )
    1252             :         {
    1253           0 :             p_rend_obj[n] = &output_fx[n][0];
    1254           0 :             move32();
    1255             :         }
    1256             : 
    1257           0 :         num_cldfb_bands = st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[0]->no_channels;
    1258           0 :         move16();
    1259           0 :         nchan_transport_orig = st_ivas->nchan_transport;
    1260           0 :         move16();
    1261           0 :         st_ivas->nchan_transport = st_ivas->nchan_ism;
    1262           0 :         move16();
    1263             : 
    1264           0 :         IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_rend_obj, *nSamplesRendered ) ) != IVAS_ERR_OK ) /* objects are read from st_ivas->hTcBuffer->tc[2..(1+n_isms)] */
    1265             :         {
    1266           0 :             return error;
    1267             :         }
    1268             : 
    1269           0 :         st_ivas->nchan_transport = nchan_transport_orig;
    1270           0 :         move16();
    1271           0 :         cldfb_slots = *nSamplesRendered / num_cldfb_bands;
    1272             : 
    1273           0 :         FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); ++n )
    1274             :         {
    1275           0 :             q_cldfb = q_in;
    1276           0 :             Scale_sig32( st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->cldfb_state_fx,
    1277           0 :                          sub( st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->p_filter_length, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->no_channels ),
    1278           0 :                          sub( q_cldfb, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->Q_cldfb_state ) );
    1279           0 :             st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->Q_cldfb_state = q_cldfb;
    1280           0 :             FOR( slot_idx = 0; slot_idx < cldfb_slots; slot_idx++ )
    1281             :             {
    1282           0 :                 q_cldfb = q_in;
    1283           0 :                 cldfbAnalysis_ts_fx_fixed_q( &( p_rend_obj[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n], &q_cldfb );
    1284             : 
    1285           0 :                 Scale_sig32( Cldfb_RealBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) );
    1286           0 :                 Scale_sig32( Cldfb_ImagBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) );
    1287             :                 /* note: this intentionally differs from OSBA by: no scaling by 0.5 */
    1288           0 :                 v_add_fx( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx], Cldfb_RealBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx], num_cldfb_bands );
    1289           0 :                 v_add_fx( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx], Cldfb_ImagBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx], num_cldfb_bands );
    1290             :             }
    1291             :         }
    1292             :     }
    1293             :     else
    1294             :     {
    1295         419 :         IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_sepobj_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) )
    1296             :         {
    1297           0 :             return error;
    1298             :         }
    1299             : 
    1300        1257 :         FOR( n = 0; n < BINAURAL_CHANNELS; n++ )
    1301             :         {
    1302         838 :             v_add_fx( output_fx[n], p_sepobj_fx[n], output_fx[n], *nSamplesRendered );
    1303             :         }
    1304             :     }
    1305             : 
    1306         419 :     return IVAS_ERR_OK;
    1307             : }
    1308             : 
    1309             : 
    1310             : /*--------------------------------------------------------------------------*
    1311             :  * ivas_omasa_rearrange_channels()
    1312             :  *
    1313             :  * in case of external rendering, rearrange the channels order
    1314             :  *--------------------------------------------------------------------------*/
    1315             : 
    1316         753 : void ivas_omasa_rearrange_channels_fx(
    1317             :     Word32 *output[],                 /* o  : output synthesis signal         Q11*/
    1318             :     const Word16 nchan_transport_ism, /* o  : number of ISM TCs               */
    1319             :     const Word16 output_frame         /* i  : output frame length per channel */
    1320             : )
    1321             : {
    1322             :     Word16 n;
    1323             :     Word32 tmp_buff[CPE_CHANNELS][L_FRAME48k]; // Q11
    1324             : 
    1325         753 :     Copy32( output[0], tmp_buff[0], output_frame );
    1326         753 :     Copy32( output[1], tmp_buff[1], output_frame );
    1327             : 
    1328        2865 :     FOR( n = 0; n < nchan_transport_ism; n++ )
    1329             :     {
    1330        2112 :         Copy32( output[CPE_CHANNELS + n], output[n], output_frame );
    1331             :     }
    1332         753 :     Copy32( tmp_buff[0], output[n], output_frame );
    1333         753 :     Copy32( tmp_buff[1], output[add( n, 1 )], output_frame );
    1334             : 
    1335         753 :     return;
    1336             : }
    1337             : 
    1338             : 
    1339             : /*-------------------------------------------------------------------------*
    1340             :  * ivas_omasa_combine_separate_ism_with_masa_open_fx()
    1341             :  *
    1342             :  * Open structures, reserve memory, and init values.
    1343             :  *-------------------------------------------------------------------------*/
    1344             : 
    1345          18 : ivas_error ivas_omasa_combine_separate_ism_with_masa_open_fx(
    1346             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
    1347             : )
    1348             : {
    1349             :     Word16 i;
    1350             :     Word16 *tmp;
    1351             : 
    1352          18 :     st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) );
    1353          18 :     move32();
    1354             : 
    1355          18 :     IF( st_ivas->hIsmRendererData == NULL )
    1356             :     {
    1357           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM renderer \n" ) );
    1358             :     }
    1359             : 
    1360          90 :     FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
    1361             :     {
    1362          72 :         set_zero_fx( st_ivas->hIsmRendererData->prev_gains_fx[i], MAX_OUTPUT_CHANNELS );
    1363             :     }
    1364             : 
    1365          18 :     test();
    1366          18 :     test();
    1367          18 :     IF( EQ_32( st_ivas->hDecoderConfig->output_Fs, 16000 ) ||
    1368             :         EQ_32( st_ivas->hDecoderConfig->output_Fs, 32000 ) ||
    1369             :         EQ_32( st_ivas->hDecoderConfig->output_Fs, 48000 ) )
    1370             :     {
    1371          18 :         IF( EQ_32( st_ivas->hDecoderConfig->output_Fs, 16000 ) )
    1372             :         {
    1373           0 :             st_ivas->hIsmRendererData->interpolator_len = 80;
    1374           0 :             tmp = interpolator_table_16k_q15;
    1375             :         }
    1376          18 :         ELSE IF( EQ_32( st_ivas->hDecoderConfig->output_Fs, 32000 ) )
    1377             :         {
    1378           0 :             st_ivas->hIsmRendererData->interpolator_len = 160;
    1379           0 :             tmp = interpolator_table_32k_q15;
    1380             :         }
    1381             :         ELSE
    1382             :         {
    1383          18 :             st_ivas->hIsmRendererData->interpolator_len = 240;
    1384          18 :             tmp = interpolator_table_48k_q15;
    1385             :         }
    1386          18 :         move16();
    1387          18 :         move32();
    1388             : 
    1389          18 :         st_ivas->hIsmRendererData->interpolator_fx = (Word16 *) malloc( sizeof( Word16 ) * st_ivas->hIsmRendererData->interpolator_len );
    1390             : 
    1391          18 :         IF( st_ivas->hIsmRendererData->interpolator_fx == NULL )
    1392             :         {
    1393           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA ISM renderer interpolator\n" ) );
    1394             :         }
    1395             : 
    1396        4338 :         FOR( i = 0; i < st_ivas->hIsmRendererData->interpolator_len; i++ )
    1397             :         {
    1398        4320 :             st_ivas->hIsmRendererData->interpolator_fx[i] = tmp[i];
    1399        4320 :             move16();
    1400             :         }
    1401             :     }
    1402             :     ELSE
    1403             :     {
    1404           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Unsupported output sample rate\n" ) );
    1405             :     }
    1406             : 
    1407          18 :     return IVAS_ERR_OK;
    1408             : }
    1409             : 
    1410             : 
    1411             : /*--------------------------------------------------------------------------*
    1412             :  * ivas_omasa_combine_separate_ism_with_masa_fx()
    1413             :  *
    1414             :  * in case of external rendering, combine separated ISM signal with MASA stream
    1415             :  *--------------------------------------------------------------------------*/
    1416             : 
    1417          36 : void ivas_omasa_combine_separate_ism_with_masa_fx(
    1418             :     Decoder_Struct *st_ivas,  /* i/o: IVAS decoder handle             */
    1419             :     Word32 *output[],         /* i/o: output synthesis signal         */
    1420             :     Word16 *output_q,         /* i/o: output Q value                  */
    1421             :     const Word16 nchan_ism,   /* i  : number of ISMs                  */
    1422             :     const Word16 output_frame /* i  : output frame length per channel */
    1423             : )
    1424             : {
    1425             :     Word16 n, sf, band, k;
    1426             :     MASA_DECODER_EXT_OUT_META_HANDLE masaMetaHandle;
    1427             :     MASA_DECODER_EXT_OUT_META_HANDLE ismMetaHandle;
    1428             :     MASA_DECODER_EXT_OUT_META ismMeta;
    1429             :     Word32 inRe[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1430             :     Word32 inIm[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1431             :     UWord16 directionIndex;
    1432             :     Word16 nchan_in;
    1433             :     Word16 nBins;
    1434             :     Word16 slot;
    1435             :     Word16 mrange[2], brange[2];
    1436             :     Word16 processing_len, offset;
    1437             : 
    1438             :     Word32 old_panning_gains_fx[2];
    1439             :     Word32 new_panning_gains_fx[2];
    1440             : 
    1441             :     Word16 inRe_exp[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1442             :     Word16 inIm_exp[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1443             :     Word16 out_exp[MASA_MAX_TRANSPORT_CHANNELS + 1][L_FRAME48k];
    1444             : 
    1445             :     Word16 eneMasa_exp[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1446             :     Word32 eneMasa_frac[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1447             :     Word16 eneIsm_exp[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1448             :     Word32 eneIsm_frac[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    1449             : 
    1450             :     Word16 old_panning_gains_q15_fx[2];
    1451             :     Word16 new_panning_gains_q15_fx[2];
    1452             : 
    1453             :     Word16 exp;
    1454             : 
    1455          36 :     masaMetaHandle = st_ivas->hMasa->data.extOutMeta;
    1456          36 :     ismMetaHandle = &ismMeta;
    1457          36 :     move32();
    1458          36 :     move32();
    1459             : 
    1460             :     /* Compute CLDFB analysis */
    1461          36 :     nchan_in = add( st_ivas->nchan_transport, 1 );
    1462          36 :     nBins = mult( output_frame, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 ); // Q15
    1463         612 :     FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
    1464             :     {
    1465        2304 :         FOR( n = 0; n < nchan_in; n++ )
    1466             :         {
    1467        1728 :             Word16 in_q = *output_q;
    1468        1728 :             move16();
    1469             : 
    1470        1728 :             cldfbAnalysis_ts_fx_var_q( &( output[n][L_mult0( nBins, slot )] ),
    1471        1728 :                                        inRe[n][slot],
    1472        1728 :                                        inIm[n][slot],
    1473             :                                        nBins, st_ivas->cldfbAnaDec[n], &in_q );
    1474             : 
    1475             :             /* Assign input exponent */
    1476        1728 :             exp = sub( Q31, in_q );
    1477        1728 :             set16_fx( inRe_exp[n][slot], exp, nBins );
    1478        1728 :             set16_fx( inIm_exp[n][slot], exp, nBins );
    1479             :         }
    1480             :     }
    1481             : 
    1482             :     /* Convert output to exponent+mantissa representation */
    1483          36 :     exp = sub( Q31, *output_q );
    1484         144 :     FOR( n = 0; n < add( MASA_MAX_TRANSPORT_CHANNELS, 1 ); n++ )
    1485             :     {
    1486         108 :         set16_fx( out_exp[n], exp, output_frame );
    1487             :     }
    1488             : 
    1489         180 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1490             :     {
    1491         144 :         set16_fx( eneMasa_exp[sf], 0, MASA_FREQUENCY_BANDS );
    1492         144 :         set32_fx( eneMasa_frac[sf], 0, MASA_FREQUENCY_BANDS );
    1493             : 
    1494         144 :         set16_fx( eneIsm_exp[sf], 0, MASA_FREQUENCY_BANDS );
    1495         144 :         set32_fx( eneIsm_frac[sf], 0, MASA_FREQUENCY_BANDS );
    1496             :     }
    1497             : 
    1498             :     /* Determine energies */
    1499         180 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1500             :     {
    1501         144 :         mrange[0] = st_ivas->hMasa->config.block_grouping[sf];
    1502         144 :         mrange[1] = st_ivas->hMasa->config.block_grouping[add( sf, 1 )];
    1503         144 :         move16();
    1504         144 :         move16();
    1505             : 
    1506         720 :         FOR( slot = mrange[0]; slot < mrange[1]; slot++ )
    1507             :         {
    1508       14400 :             FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
    1509             :             {
    1510       13824 :                 brange[0] = st_ivas->hMasa->config.band_grouping[band];
    1511       13824 :                 brange[1] = st_ivas->hMasa->config.band_grouping[add( band, 1 )];
    1512       13824 :                 move16();
    1513       13824 :                 move16();
    1514             : 
    1515       13824 :                 IF( GT_16( brange[1], nBins ) )
    1516             :                 {
    1517           0 :                     brange[1] = nBins;
    1518           0 :                     move16();
    1519             :                 }
    1520             : 
    1521       13824 :                 Word16 len = sub( brange[1], brange[0] );
    1522             : 
    1523       41472 :                 FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
    1524             :                 {
    1525       27648 :                     sample_energy_acc_fx( &inRe[n][slot][brange[0]],
    1526       27648 :                                           &inRe_exp[n][slot][brange[0]],
    1527       27648 :                                           &inIm[n][slot][brange[0]],
    1528       27648 :                                           &inIm_exp[n][slot][brange[0]],
    1529       27648 :                                           &eneMasa_frac[sf][band],
    1530       27648 :                                           &eneMasa_exp[sf][band],
    1531             :                                           len );
    1532             :                 }
    1533             : 
    1534       13824 :                 sample_energy_acc_fx( &inRe[MASA_MAX_TRANSPORT_CHANNELS][slot][brange[0]],
    1535       13824 :                                       &inRe_exp[MASA_MAX_TRANSPORT_CHANNELS][slot][brange[0]],
    1536       13824 :                                       &inIm[MASA_MAX_TRANSPORT_CHANNELS][slot][brange[0]],
    1537       13824 :                                       &inIm_exp[MASA_MAX_TRANSPORT_CHANNELS][slot][brange[0]],
    1538       13824 :                                       &eneIsm_frac[sf][band],
    1539       13824 :                                       &eneIsm_exp[sf][band],
    1540             :                                       len );
    1541             :             }
    1542             :         }
    1543             :     }
    1544             : 
    1545             :     /* Determine MASA metadata for the object */
    1546          36 :     ismMetaHandle->descriptiveMeta.numberOfDirections = 0u;
    1547          36 :     move16();
    1548             : 
    1549         180 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1550             :     {
    1551             :         Word32 ele, azi;
    1552             : 
    1553         144 :         ele = st_ivas->hMasaIsmData->elevation_separated_ism_fx[sf];
    1554         144 :         azi = st_ivas->hMasaIsmData->azimuth_separated_ism_fx[sf];
    1555             : 
    1556         144 :         directionIndex = index_theta_phi_16_fx( &ele, &azi, st_ivas->hMasa->data.sph_grid16 );
    1557             : 
    1558        3600 :         FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
    1559             :         {
    1560        3456 :             ismMetaHandle->directionIndex[0][sf][band] = directionIndex;
    1561        3456 :             ismMetaHandle->directToTotalRatio[0][sf][band] = UINT8_MAX;
    1562        3456 :             ismMetaHandle->spreadCoherence[0][sf][band] = 0;
    1563        3456 :             ismMetaHandle->surroundCoherence[sf][band] = 0;
    1564        3456 :             ismMetaHandle->diffuseToTotalRatio[sf][band] = 0;
    1565        3456 :             move16();
    1566        3456 :             move16();
    1567        3456 :             move16();
    1568        3456 :             move16();
    1569        3456 :             move16();
    1570             :         }
    1571             :     }
    1572             : 
    1573             :     /* Merge MASA metadatas */
    1574          36 :     ivas_prerend_merge_masa_metadata_fx( masaMetaHandle, masaMetaHandle,
    1575             :                                          IVAS_REND_AUDIO_CONFIG_TYPE_MASA,
    1576             :                                          eneMasa_frac, eneMasa_exp, ismMetaHandle, IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED,
    1577             :                                          eneIsm_frac, eneIsm_exp );
    1578             : 
    1579             :     /* Mix the separated object audio signal to the MASA audio signals */
    1580          36 :     ivas_get_stereo_panning_gains_fx( st_ivas->hMasaIsmData->azimuth_separated_ism_fx[0],
    1581          36 :                                       st_ivas->hMasaIsmData->elevation_separated_ism_fx[0], old_panning_gains_q15_fx );
    1582          36 :     ivas_get_stereo_panning_gains_fx( st_ivas->hMasaIsmData->azimuth_separated_ism_fx[2],
    1583          36 :                                       st_ivas->hMasaIsmData->elevation_separated_ism_fx[2], new_panning_gains_q15_fx );
    1584             : 
    1585             :     /* Subsequent processing in Q31 format */
    1586         108 :     FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
    1587             :     {
    1588          72 :         new_panning_gains_fx[n] = L_shl( new_panning_gains_q15_fx[n], Q16 );
    1589          72 :         old_panning_gains_fx[n] = L_shl( old_panning_gains_q15_fx[n], Q16 );
    1590             :     }
    1591             : 
    1592          36 :     processing_len = shr( output_frame, 1 );
    1593         108 :     FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
    1594             :     {
    1595          72 :         v_multc_acc_exp_mantissa_fx( output[MASA_MAX_TRANSPORT_CHANNELS],
    1596             :                                      out_exp[MASA_MAX_TRANSPORT_CHANNELS],
    1597             :                                      old_panning_gains_fx[n],
    1598          72 :                                      output[n],
    1599          72 :                                      out_exp[n],
    1600             :                                      processing_len );
    1601             :     }
    1602          36 :     offset = processing_len;
    1603          36 :     move16();
    1604             : 
    1605          36 :     processing_len = shr( output_frame, 2 ); /*  divide by MAX_PARAM_SPATIAL_SUBFRAMES; */
    1606         108 :     FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
    1607             :     {
    1608             :         Word32 mantissa;
    1609             : 
    1610             :         /* k == 0->gain == old_panning_gains[n] */
    1611             :         /* output[n][offset] += gain * output[MASA_MAX_TRANSPORT_CHANNELS][offset]; */
    1612          72 :         mantissa = mult32_mantissa_fx( output[MASA_MAX_TRANSPORT_CHANNELS][offset],
    1613             :                                        old_panning_gains_fx[n],
    1614          72 :                                        out_exp[MASA_MAX_TRANSPORT_CHANNELS][offset], &exp );
    1615             : 
    1616         144 :         output[n][offset] = BASOP_Util_Add_Mant32Exp( output[n][offset], out_exp[n][offset],
    1617          72 :                                                       mantissa, exp, &out_exp[n][offset] );
    1618          72 :         move32();
    1619          72 :         move32();
    1620             : 
    1621       17280 :         FOR( k = 1; k < processing_len; k++ )
    1622             :         {
    1623       17208 :             Word16 index = add( k, offset );
    1624             : 
    1625       17208 :             Word32 g1_fx = L_shl( st_ivas->hIsmRendererData->interpolator_fx[k], Q16 );
    1626             : 
    1627             :             /* 1.0f - g1 */
    1628       17208 :             Word32 g2_fx = L_sub( MAX_32, L_sub( g1_fx, 1 ) );
    1629             : 
    1630             :             /* g1 *new_panning_gains[n] + g2 *old_panning_gains[n] */
    1631       17208 :             Word32 gain_k = W_extract_h( W_add( W_mult_32_32( g1_fx, new_panning_gains_fx[n] ),
    1632             :                                                 W_mult_32_32( g2_fx, old_panning_gains_fx[n] ) ) );
    1633             : 
    1634             :             /* output[n][k + offset] += gain_k * output[MASA_MAX_TRANSPORT_CHANNELS][k + offset]; */
    1635       17208 :             mantissa = mult32_mantissa_fx( output[MASA_MAX_TRANSPORT_CHANNELS][index], gain_k,
    1636       17208 :                                            out_exp[MASA_MAX_TRANSPORT_CHANNELS][index], &exp );
    1637       34416 :             output[n][index] = BASOP_Util_Add_Mant32Exp( output[n][index], out_exp[n][index],
    1638       17208 :                                                          mantissa, exp, &out_exp[n][index] );
    1639       17208 :             move32();
    1640       17208 :             move32();
    1641             :         }
    1642             :     }
    1643          36 :     offset = add( offset, processing_len );
    1644             : 
    1645         108 :     FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
    1646             :     {
    1647          72 :         v_multc_acc_exp_mantissa_fx( &output[MASA_MAX_TRANSPORT_CHANNELS][offset],
    1648          72 :                                      &out_exp[MASA_MAX_TRANSPORT_CHANNELS][offset],
    1649             :                                      new_panning_gains_fx[n],
    1650          72 :                                      &output[n][offset],
    1651          72 :                                      &out_exp[n][offset],
    1652             :                                      processing_len );
    1653             :     }
    1654             : 
    1655             :     /* Convert output from exponent+mantissa representation to Q11 */
    1656         108 :     FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
    1657             :     {
    1658          72 :         mantissa_exp_to_qvalue( &out_exp[n][0], &output[n][0], Q20, output_frame );
    1659             :     }
    1660             : 
    1661             :     /* Zero output object channels */
    1662         180 :     FOR( n = 0; n < nchan_ism; n++ )
    1663             :     {
    1664         144 :         set_zero_fx( output[add( MASA_MAX_TRANSPORT_CHANNELS, n )], output_frame );
    1665             :     }
    1666             : 
    1667          36 :     return;
    1668             : }
    1669             : 
    1670             : 
    1671             : /*-------------------------------------------------------------------------*
    1672             :  * ivas_omasa_objects_delay_open()
    1673             :  *
    1674             :  * Open structures, reserve memory, and init values for dela buffers of objects.
    1675             :  *-------------------------------------------------------------------------*/
    1676             : 
    1677         596 : ivas_error ivas_omasa_objects_delay_open_fx(
    1678             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
    1679             : )
    1680             : {
    1681             :     Word16 i;
    1682             :     Word32 size;
    1683             : 
    1684         596 :     test();
    1685         596 :     IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
    1686             :     {
    1687         341 :         st_ivas->hMasaIsmData->delayBuffer_nchan = 1;
    1688         341 :         move16();
    1689             :     }
    1690             :     ELSE
    1691             :     {
    1692         255 :         st_ivas->hMasaIsmData->delayBuffer_nchan = st_ivas->nchan_ism;
    1693         255 :         move16();
    1694             :     }
    1695             : 
    1696         596 :     st_ivas->hMasaIsmData->delayBuffer_size = extract_l( Mult_32_16( st_ivas->hDecoderConfig->output_Fs,
    1697             :                                                                      OMASA_DELAYFRAMES_PER_SEC_Q15 ) );
    1698             : 
    1699         596 :     size = L_mult0( st_ivas->hMasaIsmData->delayBuffer_nchan, sizeof( Word16 * ) );
    1700         596 :     st_ivas->hMasaIsmData->delayBuffer_fx = (Word32 **) malloc( size );
    1701         596 :     move32();
    1702             : 
    1703         596 :     IF( st_ivas->hMasaIsmData->delayBuffer_fx == NULL )
    1704             :     {
    1705           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
    1706             :     }
    1707             : 
    1708         596 :     size = L_mult0( st_ivas->hMasaIsmData->delayBuffer_size, sizeof( Word32 ) );
    1709        1777 :     FOR( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ )
    1710             :     {
    1711        1181 :         st_ivas->hMasaIsmData->delayBuffer_fx[i] = (Word32 *) malloc( size );
    1712        1181 :         move32();
    1713             : 
    1714        1181 :         IF( st_ivas->hMasaIsmData->delayBuffer_fx[i] == NULL )
    1715             :         {
    1716           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
    1717             :         }
    1718        1181 :         set_zero_fx( st_ivas->hMasaIsmData->delayBuffer_fx[i], st_ivas->hMasaIsmData->delayBuffer_size );
    1719             :     }
    1720             : 
    1721         596 :     return IVAS_ERR_OK;
    1722             : }
    1723             : 
    1724             : 
    1725             : /*--------------------------------------------------------------------------*
    1726             :  * ivas_omasa_render_objects_from_mix()
    1727             :  *
    1728             :  * In case of external rendering, render objects from the transport signal
    1729             :  * mix containing MASA audio and object audio.
    1730             :  *--------------------------------------------------------------------------*/
    1731             : 
    1732          40 : void ivas_omasa_render_objects_from_mix_fx(
    1733             :     Decoder_Struct *st_ivas,   /* i/o: IVAS decoder handle             */
    1734             :     Word32 *output[],          /* o  : output synthesis signal         */
    1735             :     const Word16 nchan_ism,    /* i  : number of ISMs                  */
    1736             :     const Word16 output_frame, /* i  : output frame length per channel */
    1737             :     Word16 *output_q           /* i/o: output Q value                  */
    1738             : )
    1739             : {
    1740             :     Word16 n, m, i;
    1741             :     MASA_ISM_EXT_DATA_HANDLE hExtData;
    1742             :     Word32 separated_object[L_FRAME48k];
    1743             :     Word32 rendered_objects[MAX_NUM_OBJECTS][L_FRAME48k];
    1744             :     Word16 coding_delay;
    1745             :     Word32 inRe[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1746             :     Word32 inIm[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1747             :     Word32 outRe[MAX_NUM_OBJECTS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1748             :     Word32 outIm[MAX_NUM_OBJECTS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1749             :     Word16 slot;
    1750             :     Word16 sf;
    1751             :     Word16 bin;
    1752             :     Word16 nchan_transport;
    1753             :     Word16 nBins;
    1754             : 
    1755             :     Word16 inRe_exp[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1756             :     Word16 inIm_exp[3][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1757             :     Word16 outRe_exp[MAX_NUM_OBJECTS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1758             :     Word16 outIm_exp[MAX_NUM_OBJECTS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1759             : 
    1760             :     Word16 transport_energy_exp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1761             :     Word32 transport_energy_frac[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1762             : 
    1763             :     /* Create slot to metadata map */
    1764          40 :     slot = 0;
    1765          40 :     move16();
    1766         200 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1767             :     {
    1768             :         Word16 index;
    1769             : 
    1770         800 :         FOR( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
    1771             :         {
    1772         640 :             st_ivas->hSpatParamRendCom->render_to_md_map[slot] = st_ivas->hSpatParamRendCom->dirac_read_idx;
    1773         640 :             move16();
    1774         640 :             slot = add( slot, 1 );
    1775             :         }
    1776             : 
    1777         160 :         index = add( st_ivas->hSpatParamRendCom->dirac_read_idx, 1 );
    1778         160 :         IF( GE_16( index, st_ivas->hSpatParamRendCom->dirac_md_buffer_length ) )
    1779             :         {
    1780          20 :             index = 0;
    1781          20 :             move16();
    1782             :         }
    1783         160 :         st_ivas->hSpatParamRendCom->dirac_read_idx = index;
    1784         160 :         move16();
    1785             :     }
    1786             : 
    1787             :     /* Move separated object signal and object channels */
    1788          40 :     mvl2l( output[CPE_CHANNELS], separated_object, output_frame );
    1789         200 :     FOR( n = 0; n < nchan_ism; n++ )
    1790             :     {
    1791         160 :         set_zero_fx( output[CPE_CHANNELS + n], output_frame );
    1792             :     }
    1793             : 
    1794             :     /* Delay the separated object signal by the CLDFB delay */
    1795          40 :     delay_signal32_fx( separated_object, output_frame, st_ivas->hMasaIsmData->delayBuffer_fx[0],
    1796          40 :                        st_ivas->hMasaIsmData->delayBuffer_size );
    1797             : 
    1798             :     /* Set object metadata to the ism struct */
    1799         200 :     FOR( n = 0; n < nchan_ism; n++ )
    1800             :     {
    1801             :         // Q0 -> Q22
    1802         160 :         Word32 azi = L_shl( st_ivas->hMasaIsmData->azimuth_ism_fx[n][st_ivas->hSpatParamRendCom->dirac_read_idx], Q22 );
    1803         160 :         Word32 ele = L_shl( st_ivas->hMasaIsmData->elevation_ism_fx[n][st_ivas->hSpatParamRendCom->dirac_read_idx], Q22 );
    1804             : 
    1805         160 :         st_ivas->hIsmMetaData[n]->azimuth_fx = azi;
    1806         160 :         st_ivas->hIsmMetaData[n]->elevation_fx = ele;
    1807         160 :         move16();
    1808         160 :         move16();
    1809             :     }
    1810             : 
    1811             :     /* Move the separated object signal to the correct output channel */
    1812          40 :     hExtData = st_ivas->hMasaIsmData->hExtData;
    1813          40 :     move32();
    1814          40 :     coding_delay = mult( output_frame, MULT_17_DIV_20_Q15 ); /* Q15: 17 ms of coding and CLDFB delay */
    1815          40 :     mvl2l( separated_object, output[add( CPE_CHANNELS, hExtData->prev_idx_separated_ism )], coding_delay );
    1816          80 :     mvl2l( &separated_object[coding_delay],
    1817          40 :            &output[add( CPE_CHANNELS, st_ivas->hMasaIsmData->idx_separated_ism )][coding_delay],
    1818          40 :            sub( output_frame, coding_delay ) );
    1819             : 
    1820             :     /* Compute CLDFB analysis */
    1821          40 :     nchan_transport = st_ivas->nchan_transport;
    1822          40 :     move16();
    1823          40 :     nBins = mult( output_frame, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 ); // Q15
    1824             : 
    1825         680 :     FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
    1826             :     {
    1827        1920 :         FOR( n = 0; n < nchan_transport; n++ )
    1828             :         {
    1829        1280 :             Word16 in_q = *output_q;
    1830        1280 :             move16();
    1831             : 
    1832        1280 :             cldfbAnalysis_ts_fx_var_q( &( output[n][L_mult0( nBins, slot )] ),
    1833        1280 :                                        inRe[n][slot],
    1834        1280 :                                        inIm[n][slot],
    1835             :                                        nBins, st_ivas->cldfbAnaDec[n], &in_q );
    1836             : 
    1837             :             /* Assign input exponent */
    1838        1280 :             Word16 exp = sub( Q31, in_q );
    1839        1280 :             set16_fx( inRe_exp[n][slot], exp, nBins );
    1840        1280 :             set16_fx( inIm_exp[n][slot], exp, nBins );
    1841             :         }
    1842             :     }
    1843             : 
    1844             :     /* Create prototype signals */
    1845         200 :     for ( n = 0; n < nchan_ism; n++ )
    1846             :     {
    1847             :         Word32 panning_gains_fx[2];
    1848             :         Word16 new_panning_gains_fx[2];
    1849             :         Word16 azimuth_fx, elevation_fx;
    1850             : 
    1851             :         // Q22 -> Q0
    1852         160 :         azimuth_fx = extract_l( L_shr( st_ivas->hIsmMetaData[n]->azimuth_fx, Q22 ) );
    1853         160 :         elevation_fx = extract_l( L_shr( st_ivas->hIsmMetaData[n]->elevation_fx, Q22 ) );
    1854         160 :         ivas_get_stereo_panning_gains_fx( azimuth_fx, elevation_fx, new_panning_gains_fx );
    1855             : 
    1856         160 :         Word16 interpValInc = 0;
    1857         160 :         move16();
    1858             : 
    1859             :         // Represents (1.0f - interpVal) value
    1860         160 :         Word16 interpValDec = extract_l( L_sub( -MIN16B, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 ) );
    1861             : 
    1862        2560 :         FOR( slot = 0; slot < sub( CLDFB_NO_COL_MAX, 1 ); slot++ )
    1863             :         {
    1864        2400 :             interpValInc = add( interpValInc, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 );
    1865             : 
    1866        7200 :             FOR( m = 0; m < 2; m++ )
    1867             :             {
    1868        4800 :                 Word32 prev_gain = hExtData->prev_panning_gains[n][m];
    1869        4800 :                 move32();
    1870             : 
    1871        4800 :                 Word32 new_gain = L_shl( new_panning_gains_fx[m], 16 ); // Q15 -> Q31
    1872             : 
    1873        4800 :                 panning_gains_fx[m] = L_add( Mpy_32_16( extract_h( prev_gain ), extract_l( prev_gain ),
    1874             :                                                         interpValDec ),
    1875        4800 :                                              Mpy_32_16( extract_h( new_gain ), extract_l( new_gain ),
    1876             :                                                         interpValInc ) );
    1877             :             }
    1878             : 
    1879        2400 :             interpValDec = sub( interpValDec, MULT_1_DIV_CLDFB_NO_COL_MAX_Q15 );
    1880             : 
    1881        2400 :             v_multc_exp_mantissa_fx( inRe[0][slot], inRe_exp[0][slot], panning_gains_fx[0],
    1882        2400 :                                      outRe[n][slot], outRe_exp[n][slot], nBins );
    1883        2400 :             v_multc_exp_mantissa_fx( inIm[0][slot], inIm_exp[0][slot], panning_gains_fx[0],
    1884        2400 :                                      outIm[n][slot], outIm_exp[n][slot], nBins );
    1885             : 
    1886        2400 :             v_multc_acc_exp_mantissa_fx( inRe[1][slot], inRe_exp[1][slot], panning_gains_fx[1],
    1887        2400 :                                          outRe[n][slot], outRe_exp[n][slot], nBins );
    1888        2400 :             v_multc_acc_exp_mantissa_fx( inIm[1][slot], inIm_exp[1][slot], panning_gains_fx[1],
    1889        2400 :                                          outIm[n][slot], outIm_exp[n][slot], nBins );
    1890             :         }
    1891             : 
    1892             :         // Special case where (1.0f - interpVal) = 0 and interpVal = 1
    1893         480 :         FOR( m = 0; m < 2; m++ )
    1894             :         {
    1895         320 :             panning_gains_fx[m] = L_shl( new_panning_gains_fx[m], 16 ); // Q15 -> Q31
    1896             :         }
    1897             : 
    1898         160 :         v_multc_exp_mantissa_fx( inRe[0][slot], inRe_exp[0][slot], panning_gains_fx[0],
    1899         160 :                                  outRe[n][slot], outRe_exp[n][slot], nBins );
    1900         160 :         v_multc_exp_mantissa_fx( inIm[0][slot], inIm_exp[0][slot], panning_gains_fx[0],
    1901         160 :                                  outIm[n][slot], outIm_exp[n][slot], nBins );
    1902             : 
    1903         160 :         v_multc_acc_exp_mantissa_fx( inRe[1][slot], inRe_exp[1][slot], panning_gains_fx[1],
    1904         160 :                                      outRe[n][slot], outRe_exp[n][slot], nBins );
    1905         160 :         v_multc_acc_exp_mantissa_fx( inIm[1][slot], inIm_exp[1][slot], panning_gains_fx[1],
    1906         160 :                                      outIm[n][slot], outIm_exp[n][slot], nBins );
    1907             : 
    1908         480 :         FOR( m = 0; m < 2; m++ )
    1909             :         {
    1910         320 :             hExtData->prev_panning_gains[n][m] = panning_gains_fx[m];
    1911         320 :             move32();
    1912             :         }
    1913             :     }
    1914             : 
    1915             :     /* Determine transport energy */
    1916         680 :     FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
    1917             :     {
    1918         640 :         set_zero_fx( &transport_energy_frac[slot][0], nBins );
    1919         640 :         set16_zero_fx( &transport_energy_exp[slot][0], nBins );
    1920             :     }
    1921         120 :     FOR( n = 0; n < CPE_CHANNELS; n++ )
    1922             :     {
    1923        1360 :         FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
    1924             :         {
    1925       78080 :             FOR( bin = 0; bin < nBins; bin++ )
    1926             :             {
    1927             :                 Word16 exp;
    1928             : 
    1929             :                 // energy = re^2 + im^2
    1930       76800 :                 Word32 mantissa = sample_energy_fx( inRe[n][slot][bin], inRe_exp[n][slot][bin],
    1931       76800 :                                                     inIm[n][slot][bin], inIm_exp[n][slot][bin], &exp );
    1932       76800 :                 move32();
    1933             : 
    1934             :                 // Accumulate energy
    1935      153600 :                 transport_energy_frac[slot][bin] = BASOP_Util_Add_Mant32Exp( transport_energy_frac[slot][bin],
    1936       76800 :                                                                              transport_energy_exp[slot][bin],
    1937             :                                                                              mantissa,
    1938             :                                                                              exp,
    1939       76800 :                                                                              &transport_energy_exp[slot][bin] );
    1940       76800 :                 move32();
    1941             :             }
    1942             :         }
    1943             :     }
    1944             : 
    1945             :     /* Determine temporally smoothed energies and determine gains using them */
    1946         200 :     FOR( n = 0; n < nchan_ism; n++ )
    1947             :     {
    1948        2720 :         FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
    1949             :         {
    1950        2560 :             Word16 md_idx = st_ivas->hSpatParamRendCom->render_to_md_map[slot];
    1951        2560 :             move16();
    1952             : 
    1953      156160 :             FOR( bin = 0; bin < nBins; bin++ )
    1954             :             {
    1955             :                 Word16 exp, exp_mult, proto_e, target_e;
    1956             :                 Word32 mantissa, proto_m, target_m;
    1957             : 
    1958             :                 Word32 ism_target_energy_frac;
    1959             :                 Word16 ism_target_energy_exp;
    1960             : 
    1961             :                 Word32 ism_proto_energy_frac;
    1962             :                 Word16 ism_proto_energy_exp;
    1963             : 
    1964             :                 // r1 = transport_energy[slot][bin] * st_ivas->hMasaIsmData->energy_ratio_ism[n][md_idx][bin]
    1965      153600 :                 ism_target_energy_frac = mult32_mantissa_fx( transport_energy_frac[slot][bin],
    1966      153600 :                                                              st_ivas->hMasaIsmData->energy_ratio_ism_fx[n][md_idx][bin],
    1967      153600 :                                                              add( transport_energy_exp[slot][bin], 1 ),
    1968             :                                                              &ism_target_energy_exp );
    1969      153600 :                 move32();
    1970             : 
    1971             :                 // r2 = r1 * (1.0 - EXT_RENDER_IIR_FAC)
    1972      153600 :                 ism_target_energy_frac = mult32_mantissa_fx( ism_target_energy_frac,
    1973             :                                                              ONEMINUX_EXT_RENDER_IIR_FAC_Q31,
    1974             :                                                              ism_target_energy_exp,
    1975             :                                                              &ism_target_energy_exp );
    1976      153600 :                 move32();
    1977             : 
    1978             :                 // r3 = re^2 + im^2
    1979      153600 :                 mantissa = sample_energy_fx( outRe[n][slot][bin],
    1980      153600 :                                              outRe_exp[n][slot][bin],
    1981             :                                              outIm[n][slot][bin],
    1982      153600 :                                              outIm_exp[n][slot][bin],
    1983             :                                              &exp );
    1984      153600 :                 move32();
    1985             : 
    1986             :                 // r4 = r3 * (1 - EXT_RENDER_IIR_FAC)
    1987      153600 :                 ism_proto_energy_frac = mult32_mantissa_fx( mantissa, ONEMINUX_EXT_RENDER_IIR_FAC_Q31,
    1988             :                                                             exp, &ism_proto_energy_exp );
    1989      153600 :                 move32();
    1990             : 
    1991             : 
    1992             :                 // r5 = ism_render_proto_energy[n][bin] * EXT_RENDER_IIR_FAC
    1993      153600 :                 proto_m = mult32_mantissa_fx( hExtData->ism_render_proto_energy_frac[n][bin], EXT_RENDER_IIR_FAC_Q31,
    1994      153600 :                                               hExtData->ism_render_proto_energy_exp[n][bin], &proto_e );
    1995      153600 :                 move32();
    1996             : 
    1997             :                 // r6 = r5 + r4
    1998      153600 :                 proto_m = BASOP_Util_Add_Mant32Exp( proto_m, proto_e,
    1999             :                                                     ism_proto_energy_frac,
    2000             :                                                     ism_proto_energy_exp,
    2001             :                                                     &proto_e );
    2002      153600 :                 move32();
    2003             : 
    2004             :                 // r7 = ism_render_target_energy[n][bin] * EXT_RENDER_IIR_FAC
    2005      153600 :                 target_m = mult32_mantissa_fx( hExtData->ism_render_target_energy_frac[n][bin], EXT_RENDER_IIR_FAC_Q31,
    2006      153600 :                                                hExtData->ism_render_target_energy_exp[n][bin], &target_e );
    2007      153600 :                 move32();
    2008             : 
    2009             :                 // r8 = r7 + r2
    2010      153600 :                 target_m = BASOP_Util_Add_Mant32Exp( target_m, target_e,
    2011             :                                                      ism_target_energy_frac,
    2012             :                                                      ism_target_energy_exp,
    2013             :                                                      &target_e );
    2014      153600 :                 move32();
    2015             : 
    2016      153600 :                 hExtData->ism_render_proto_energy_frac[n][bin] = proto_m;
    2017      153600 :                 hExtData->ism_render_proto_energy_exp[n][bin] = proto_e;
    2018      153600 :                 move32();
    2019      153600 :                 move16();
    2020             : 
    2021      153600 :                 hExtData->ism_render_target_energy_frac[n][bin] = target_m;
    2022      153600 :                 hExtData->ism_render_target_energy_exp[n][bin] = target_e;
    2023      153600 :                 move32();
    2024      153600 :                 move16();
    2025             : 
    2026             :                 // r9 = sqrt(r8 / r6)
    2027      153600 :                 mantissa = get_processing_gain_fx( proto_m, proto_e, target_m, target_e, &exp );
    2028      153600 :                 move32();
    2029             : 
    2030             :                 // outRe[n][slot][bin] *= r9
    2031      153600 :                 exp_mult = add( exp, outRe_exp[n][slot][bin] );
    2032      307200 :                 outRe[n][slot][bin] = mult32_mantissa_fx( outRe[n][slot][bin], mantissa, exp_mult,
    2033      153600 :                                                           &outRe_exp[n][slot][bin] );
    2034      153600 :                 move32();
    2035             : 
    2036             :                 // outIm[n][slot][bin] *= r9
    2037      153600 :                 exp_mult = add( exp, outIm_exp[n][slot][bin] );
    2038      307200 :                 outIm[n][slot][bin] = mult32_mantissa_fx( outIm[n][slot][bin], mantissa, exp_mult,
    2039      153600 :                                                           &outIm_exp[n][slot][bin] );
    2040      153600 :                 move32();
    2041             :             }
    2042             :         }
    2043             :     }
    2044             : 
    2045         680 :     FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
    2046             :     {
    2047         640 :         Word16 md_idx = st_ivas->hSpatParamRendCom->render_to_md_map[slot];
    2048         640 :         move16();
    2049             : 
    2050       39040 :         FOR( bin = 0; bin < nBins; bin++ )
    2051             :         {
    2052             :             Word16 exp, proto_e, target_e, transport_exp;
    2053             :             Word32 mantissa, proto_m, target_m, transport_mantissa;
    2054             : 
    2055             :             Word32 masa_target_energy_frac;
    2056             :             Word16 masa_target_energy_exp;
    2057             : 
    2058             :             // r1 = transport_energy[slot][bin] * hExtData->masa_render_masa_to_total[md_idx][bin]
    2059       38400 :             masa_target_energy_frac = mult32_mantissa_fx( transport_energy_frac[slot][bin],
    2060             :                                                           hExtData->masa_render_masa_to_total[md_idx][bin],
    2061       38400 :                                                           add( transport_energy_exp[slot][bin], 1 ),
    2062             :                                                           &masa_target_energy_exp );
    2063       38400 :             move32();
    2064             : 
    2065             :             // r2 = r1 * EXT_RENDER_IIR_FAC
    2066       38400 :             masa_target_energy_frac = mult32_mantissa_fx( masa_target_energy_frac,
    2067             :                                                           ONEMINUX_EXT_RENDER_IIR_FAC_Q31,
    2068             :                                                           masa_target_energy_exp,
    2069             :                                                           &masa_target_energy_exp );
    2070       38400 :             move32();
    2071             : 
    2072             :             // r3 = masa_render_proto_energy[bin] * EXT_RENDER_IIR_FAC
    2073       38400 :             proto_m = mult32_mantissa_fx( hExtData->masa_render_proto_energy_frac[bin], EXT_RENDER_IIR_FAC_Q31,
    2074       38400 :                                           hExtData->masa_render_proto_energy_exp[bin], &proto_e );
    2075       38400 :             move32();
    2076             : 
    2077             :             // r4 = transport_energy[slot][bin] * EXT_RENDER_IIR_FAC
    2078       38400 :             transport_mantissa = mult32_mantissa_fx( transport_energy_frac[slot][bin],
    2079             :                                                      ONEMINUX_EXT_RENDER_IIR_FAC_Q31,
    2080       38400 :                                                      transport_energy_exp[slot][bin], &transport_exp );
    2081       38400 :             move32();
    2082             : 
    2083             :             // r5 = r3 + r4
    2084       38400 :             proto_m = BASOP_Util_Add_Mant32Exp( proto_m, proto_e,
    2085             :                                                 transport_mantissa,
    2086             :                                                 transport_exp,
    2087             :                                                 &proto_e );
    2088       38400 :             move32();
    2089             : 
    2090             :             // r6 =  masa_render_target_energy[bin] * EXT_RENDER_IIR_FAC
    2091       38400 :             target_m = mult32_mantissa_fx( hExtData->masa_render_target_energy_frac[bin], EXT_RENDER_IIR_FAC_Q31,
    2092       38400 :                                            hExtData->masa_render_target_energy_exp[bin], &target_e );
    2093       38400 :             move32();
    2094             : 
    2095             :             // r7 = r6 + r2
    2096       38400 :             target_m = BASOP_Util_Add_Mant32Exp( target_m, target_e,
    2097             :                                                  masa_target_energy_frac,
    2098             :                                                  masa_target_energy_exp,
    2099             :                                                  &target_e );
    2100       38400 :             move32();
    2101             : 
    2102       38400 :             hExtData->masa_render_proto_energy_frac[bin] = proto_m;
    2103       38400 :             hExtData->masa_render_proto_energy_exp[bin] = proto_e;
    2104       38400 :             move16();
    2105       38400 :             move32();
    2106             : 
    2107       38400 :             hExtData->masa_render_target_energy_frac[bin] = target_m;
    2108       38400 :             hExtData->masa_render_target_energy_exp[bin] = target_e;
    2109       38400 :             move16();
    2110       38400 :             move32();
    2111             : 
    2112             :             // r8 = sqrt(r7 / r5)
    2113       38400 :             mantissa = get_processing_gain_fx( proto_m, proto_e, target_m, target_e, &exp );
    2114       38400 :             move32();
    2115             : 
    2116      115200 :             FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ )
    2117             :             {
    2118             :                 Word16 exp_mult;
    2119             : 
    2120             :                 // inRe[n][slot][bin] *= r8
    2121       76800 :                 exp_mult = add( exp, inRe_exp[n][slot][bin] );
    2122      153600 :                 inRe[n][slot][bin] = mult32_mantissa_fx( inRe[n][slot][bin], mantissa, exp_mult,
    2123       76800 :                                                          &inRe_exp[n][slot][bin] );
    2124       76800 :                 move32();
    2125             : 
    2126             :                 // inIm[n][slot][bin] *= r8
    2127       76800 :                 exp_mult = add( exp, inIm_exp[n][slot][bin] );
    2128      153600 :                 inIm[n][slot][bin] = mult32_mantissa_fx( inIm[n][slot][bin], mantissa, exp_mult,
    2129       76800 :                                                          &inIm_exp[n][slot][bin] );
    2130       76800 :                 move32();
    2131             :             }
    2132             :         }
    2133             :     }
    2134             : 
    2135          40 :     *output_q = Q11;
    2136             : 
    2137             :     /* Compute CLDFB synthesis */
    2138         680 :     FOR( slot = 0; slot < CLDFB_NO_COL_MAX; slot++ )
    2139             :     {
    2140             :         Word32 *outSlotRePr, *outSlotImPr;
    2141         640 :         Word32 index = L_mult0( nBins, slot );
    2142             : 
    2143        1920 :         FOR( n = 0; n < nchan_transport; n++ )
    2144             :         {
    2145        1280 :             outSlotRePr = &( inRe[n][slot][0] );
    2146        1280 :             outSlotImPr = &( inIm[n][slot][0] );
    2147        1280 :             move32();
    2148        1280 :             move32();
    2149             : 
    2150       78080 :             FOR( bin = 0; bin < nBins; bin++ )
    2151             :             {
    2152       76800 :                 inRe_exp[n][slot][bin] = sub( inRe_exp[n][slot][bin], Q2 );
    2153       76800 :                 inIm_exp[n][slot][bin] = sub( inIm_exp[n][slot][bin], Q2 );
    2154             :             }
    2155             : 
    2156        1280 :             mantissa_exp_to_qvalue( &inRe_exp[n][slot][0], &inRe[n][slot][0], Q20, nBins );
    2157        1280 :             mantissa_exp_to_qvalue( &inIm_exp[n][slot][0], &inIm[n][slot][0], Q20, nBins );
    2158             : 
    2159        1280 :             cldfbSynthesis_ivas_fx( &outSlotRePr, &outSlotImPr, &output[n][index],
    2160             :                                     nBins, Q2, 1, st_ivas->cldfbSynDec[n] );
    2161             :         }
    2162             : 
    2163        3200 :         FOR( n = 0; n < nchan_ism; n++ )
    2164             :         {
    2165        2560 :             Word32 index2 = add( n, CPE_CHANNELS );
    2166             : 
    2167        2560 :             outSlotRePr = &( outRe[n][slot][0] );
    2168        2560 :             outSlotImPr = &( outIm[n][slot][0] );
    2169        2560 :             move32();
    2170        2560 :             move32();
    2171             : #ifdef FIX_2092_ASSERT_IN_OMASA_RENDER
    2172        2560 :             mantissa_exp_to_qvalue( &outRe_exp[n][slot][0], &outRe[n][slot][0], Q20 + Q2, nBins ); // + Q2: add two bits headroom to prevent overflow in cldfbSynthesis_ivas_fx().
    2173        2560 :             mantissa_exp_to_qvalue( &outIm_exp[n][slot][0], &outIm[n][slot][0], Q20 + Q2, nBins );
    2174             : 
    2175        2560 :             cldfbSynthesis_ivas_fx( &outSlotRePr, &outSlotImPr, &rendered_objects[n][index],
    2176             :                                     nBins, 0, 1 + Q2, st_ivas->cldfbSynDec[index2] );
    2177             : #else
    2178             :             mantissa_exp_to_qvalue( &outRe_exp[n][slot][0], &outRe[n][slot][0], Q20, nBins );
    2179             :             mantissa_exp_to_qvalue( &outIm_exp[n][slot][0], &outIm[n][slot][0], Q20, nBins );
    2180             : 
    2181             :             cldfbSynthesis_ivas_fx( &outSlotRePr, &outSlotImPr, &rendered_objects[n][index],
    2182             :                                     nBins, 0, 1, st_ivas->cldfbSynDec[index2] );
    2183             : #endif
    2184             :         }
    2185             :     }
    2186             : 
    2187             :     /* Combine the rendered objects with the separated objects */
    2188         200 :     FOR( n = 0; n < nchan_ism; n++ )
    2189             :     {
    2190         160 :         Word16 index = add( CPE_CHANNELS, n );
    2191         160 :         v_add_32( output[index], rendered_objects[n], output[index], output_frame );
    2192             :     }
    2193             : 
    2194          40 :     hExtData->prev_idx_separated_ism = st_ivas->hMasaIsmData->idx_separated_ism;
    2195          40 :     move16();
    2196             : 
    2197          40 :     return;
    2198             : }
    2199             : 
    2200             : /*--------------------------------------------------------------------------*
    2201             :  * ivas_omasa_gain_masa_tc_fx()
    2202             :  *
    2203             :  * in case of external rendering with object editing, MASA transport channels
    2204             :  * need to be gained
    2205             :  *--------------------------------------------------------------------------*/
    2206             : 
    2207           0 : void ivas_omasa_gain_masa_tc_fx(
    2208             :     Word32 *output_fx[],              /* i/o: output synthesis signal, Q11    */
    2209             :     const Word16 gainMasa_fx,         /* i  : gain, Q12                       */
    2210             :     const Word16 nchan_transport_ism, /* i  : number of ISM TCs               */
    2211             :     const Word16 output_frame         /* i  : output frame length per channel */
    2212             : )
    2213             : {
    2214             :     /* Edited OMASA EXT MASA transport gaining */
    2215           0 :     FOR( Word16 ch = 0; ch < 2; ch++ )
    2216             :     {
    2217           0 :         v_multc_fx_16( output_fx[nchan_transport_ism + ch], gainMasa_fx, output_fx[nchan_transport_ism + ch], output_frame ); // Q8
    2218           0 :         Scale_sig32( output_fx[nchan_transport_ism + ch], output_frame, Q3 );                                                 // Q8 -> Q11
    2219             :     }
    2220             : 
    2221           0 :     return;
    2222             : }
       |