LCOV - code coverage report
Current view: top level - lib_dec - ivas_stereo_cng_dec.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 869 903 96.2 %
Date: 2025-05-03 01:55:50 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdint.h>
      34             : #include "options.h"
      35             : #include <math.h>
      36             : #include "cnst.h"
      37             : #include "prot_fx.h"
      38             : #include "ivas_cnst.h"
      39             : #include "ivas_rom_com.h"
      40             : #include "wmc_auto.h"
      41             : #include "ivas_prot_fx.h"
      42             : #include "ivas_rom_com_fx.h"
      43             : 
      44             : /*-------------------------------------------------------------------
      45             :  * Local constants
      46             :  *-------------------------------------------------------------------*/
      47             : 
      48             : #define A_GFILT_FX           ( Word16 )( 0x6666 ) /* LP-filter coefficient for coherence and sidegain */
      49             : #define ONE_MINUS_A_GFILT_FX ( Word16 )( 0x199A ) /* LP-filter coefficient for coherence and sidegain */
      50             : #define SKIP_XFADE_FRAMES    2
      51             : 
      52             : /* DTX/CNG */
      53             : #define MAX_K                                50
      54             : #define ONE_BY_MAX_K                         ( Word16 )( 0x028F )
      55             : #define STEREO_TD_PS_CORR_FILT_FX            1717986918
      56             : #define STEREO_TD_PS_CORR_FILT_Q31           1717986944
      57             : #define ONE_MINUS_STEREO_TD_PS_CORR_FILT_Q31 429496704
      58             : #define MAX_XFADE_FX                         50
      59             : #define CM_INIT                              50
      60             : #define CORR_INIT                            8
      61             : #define SID_INIT                             6
      62             : #define STEREO_CNA_LR_CORR_LT_FILT_FX        2040109440 /* long-term averaging factor for L/R correlation estimation in stereo CNA */
      63             : #define STEREO_CNA_ILD_LT_FILT_FX            1932735283 /* long-term averaging factor for ILD estimation in stereo CNA */
      64             : 
      65             : /*-------------------------------------------------------------------
      66             :  * stereo_dft_dec_sid_coh()
      67             :  *
      68             :  * Decode coherence vector
      69             :  *-------------------------------------------------------------------*/
      70             : 
      71             : /*-------------------------------------------------------------------
      72             :  * stereo_dft_generate_comfort_noise_fx()
      73             :  *
      74             :  * Generate the comfort noise based on the target noise level for the CLDFB part
      75             :  *-------------------------------------------------------------------*/
      76             : 
      77       10940 : static void stereo_dft_generate_comfort_noise_fx(
      78             :     STEREO_DFT_DEC_DATA_HANDLE hStereoDft,        /* i/o: DFT Stereo decoder handle                       */
      79             :     STEREO_CNG_DEC_HANDLE hStereoCng,             /* i/o: Stereo CNG data structure                                               */
      80             :     const Word16 last_element_mode,               /* i  : last element mode                                                             Q0*/
      81             :     Decoder_State *st,                            /* i/o: Core coder decoder state                                                */
      82             :     Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers                                q_dft*/
      83             :     Decoder_State *st1,                           /* i/o: Core coder decoder state secondary channel      */
      84             :     const Word16 targetGain,                      /* i  : ICA target gain                                                          Q13*/
      85             :     const Word16 chan,                            /* i  : channel number                                                                Q0*/
      86             :     const Word16 output_frame,                    /* i  : output frame size                                                             Q0*/
      87             :     Word16 q_dft                                  /* i  : Q of DFT                                                                                */
      88             : )
      89             : {
      90             :     Word16 i, j, k;
      91             :     Word32 *ptr_level, *ptr_shb, *ptr_r, *ptr_i;
      92             :     HANDLE_FD_CNG_COM hFdCngCom;
      93             :     Word16 numSlots;
      94             :     Word16 scale, inv_scale, tmp_16;
      95             :     Word32 lp_noise;
      96             :     Word16 lp_noise_e;
      97             :     Word32 tmp, enr;
      98             :     Word16 q_enr;
      99             :     Word32 shb_shape[L_FRAME16k];
     100             :     Word16 q_shb_shape;
     101             :     Word32 *ptr0, *ptr1, *ptr2;
     102             :     Word16 dmpf[M + 2], Atmp[M + 2];
     103             :     Word32 cngNoiseLevel_upd[L_FRAME16k], cngNoiseLevel_hist[L_FRAME16k - 2];
     104             :     Word16 e_norm_temp[L_FRAME16k];
     105             :     Word32 *ptr_tmp, *ptr_cng;
     106             :     Word64 E0, E1;
     107             :     Word16 E0_e, E1_e;
     108             :     Word16 b, q_cngNoiseLevel_upd, q_cngNoiseLevel;
     109             :     Word32 *pSideGain;
     110             :     Word16 gamma;
     111             :     Word16 c, c_e;
     112             :     Word16 scaleMS;
     113             :     Word16 scaleAvg, scaleAvg_e;
     114             :     Word16 LR_ratio; /* Q15 */
     115             :     Word32 factor;
     116             :     Word16 alpha;
     117             :     Word32 ftmp;
     118             :     Word16 trigo_dec[STEREO_DFT32MS_N_16k / 2 + 1];
     119             :     const Word16 *pTrigo;
     120             :     Word16 trigo_step;
     121             :     Word32 tmp32_1, tmp32_2;
     122             :     Word16 q_div, q_sqrt1, q_sqrt2, q_sqrt, sqrt_res;
     123             :     Word16 q_shift, q_shift_1, q_shift_2, min_q;
     124             : 
     125       10940 :     hFdCngCom = st->hFdCngDec->hFdCngCom;
     126             : 
     127       10940 :     push_wmops( "DFT_CNG" );
     128             : 
     129       10940 :     set16_fx( dmpf, 0, M + 2 );
     130       10940 :     set16_fx( Atmp, 0, M + 2 );
     131             : 
     132       10940 :     set_zero_fx( DFT[chan], STEREO_DFT_BUF_MAX );
     133       10940 :     set32_fx( cngNoiseLevel_upd, 0, L_FRAME16k );
     134             : 
     135       10940 :     enr = 0; /* Eliminates compiler warning. They are always set before they are used */
     136       10940 :     move32();
     137       10940 :     q_enr = 0;
     138       10940 :     move16();
     139       10940 :     E0 = 0;
     140       10940 :     move64();
     141       10940 :     E0_e = 0;
     142       10940 :     move16();
     143       10940 :     E1 = 0;
     144       10940 :     move64();
     145       10940 :     E1_e = 0;
     146       10940 :     move16();
     147       10940 :     lp_noise = 0;
     148       10940 :     move32();
     149       10940 :     lp_noise_e = 0;
     150       10940 :     move16();
     151       10940 :     q_shb_shape = 0;
     152       10940 :     move16();
     153             : 
     154       10940 :     IF( chan == 0 )
     155             :     {
     156        5470 :         pSideGain = hStereoDft->side_gain_fx + STEREO_DFT_NBDIV * STEREO_DFT_BAND_MAX; /* Q31 */
     157       37322 :         FOR( b = 0; b < hStereoDft->nbands; b++ )
     158             :         {
     159       31852 :             IF( hStereoCng->xfade_frame_counter == 0 )
     160             :             {
     161         646 :                 hStereoDft->g_state_fx[b] = extract_h( *pSideGain++ ); /* Q15 */
     162         646 :                 move16();
     163             :             }
     164             :             ELSE
     165             :             {
     166       31206 :                 hStereoDft->g_state_fx[b] = add( mult( ONE_MINUS_A_GFILT_FX, extract_h( *pSideGain++ ) ), mult( A_GFILT_FX, hStereoDft->g_state_fx[b] ) ); /* Q15 */
     167       31206 :                 move16();
     168             :             }
     169             : 
     170       31852 :             test();
     171       31852 :             IF( hStereoCng->first_SID )
     172             :             {
     173          86 :                 IF( hStereoCng->first_SID_after_TD )
     174             :                 {
     175           0 :                     hStereoCng->cm_fx[b] = extract_h( Mpy_32_32( hStereoCng->c_LR_LT_fx, hStereoCng->c_LR_LT_fx ) ); /* Q15 */
     176           0 :                     move16();
     177             :                 }
     178             :                 ELSE
     179             :                 {
     180          86 :                     hStereoCng->cm_fx[b] = hStereoCng->coh_fx[b]; /* Q15 */
     181          86 :                     move16();
     182             :                 }
     183             :             }
     184       31766 :             ELSE IF( LT_16( hStereoCng->nr_dft_frames, CM_INIT ) && LT_16( hStereoCng->nr_sid_frames, SID_INIT ) )
     185             :             {
     186           0 :                 IF( GT_16( hStereoCng->nr_corr_frames, CORR_INIT ) )
     187             :                 {
     188           0 :                     hStereoCng->cm_fx[b] = extract_h( Mpy_32_32( hStereoCng->c_LR_LT_fx, hStereoCng->c_LR_LT_fx ) ); /* Q15 */
     189           0 :                     move16();
     190             :                 }
     191             :                 ELSE
     192             :                 {
     193           0 :                     hStereoCng->cm_fx[b] = add( mult( ONE_MINUS_A_GFILT_FX, hStereoCng->coh_fx[b] ), mult( A_GFILT_FX, hStereoCng->cm_fx[b] ) ); /* Q15 */
     194           0 :                     move16();
     195             :                 }
     196             :             }
     197             :             ELSE
     198             :             {
     199       31766 :                 hStereoCng->cm_fx[b] = add( mult( ONE_MINUS_A_GFILT_FX, hStereoCng->coh_fx[b] ), mult( A_GFILT_FX, hStereoCng->cm_fx[b] ) ); /* Q15 */
     200       31766 :                 move16();
     201             :             }
     202             :         }
     203             : 
     204        5470 :         IF( hStereoCng->first_SID_after_TD )
     205             :         {
     206          14 :             scaleAvg = 0;
     207          14 :             move16();
     208          14 :             scaleAvg_e = 15;
     209          14 :             move16();
     210          93 :             FOR( b = 0; b < hStereoDft->nbands; b++ )
     211             :             {
     212          79 :                 IF( LT_16( hStereoCng->cm_fx[b], 0x7333 ) )
     213             :                 {
     214          79 :                     gamma = hStereoCng->cm_fx[b]; /* Q15 */
     215          79 :                     move16();
     216          79 :                     gamma = BASOP_Util_Divide1616_Scale( gamma, sub( 32767, gamma ), &q_div ); /* e(q_div) */
     217          79 :                     q_sqrt2 = add( q_div, 16 );
     218          79 :                     tmp32_1 = BASOP_Util_Add_Mant32Exp( gamma, add( q_div, 16 ), sub( 32767, mult_r( hStereoDft->g_state_fx[b], hStereoDft->g_state_fx[b] ) ), 16, &q_sqrt1 ); /* e(q_sqrt1) */
     219          79 :                     tmp32_1 = Sqrt32( tmp32_1, &q_sqrt1 );                                                                                                                     /* e(q_sqrt1) */
     220          79 :                     tmp32_2 = Sqrt32( gamma, &q_sqrt2 );                                                                                                                       /* e(q_sqrt2) */
     221          79 :                     tmp32_1 = BASOP_Util_Add_Mant32Exp( tmp32_1, q_sqrt1, L_negate( tmp32_2 ), q_sqrt2, &q_sqrt1 );                                                            /* e(q_sqrt1) */
     222          79 :                     gamma = extract_h( L_shl( tmp32_1, q_sqrt1 ) );                                                                                                            /* Q15 */
     223             :                 }
     224             :                 ELSE
     225             :                 {
     226           0 :                     gamma = 0;
     227           0 :                     move16();
     228             :                 }
     229             : 
     230          79 :                 LR_ratio = extract_h( tdm_ratio_tabl_fx[hStereoCng->last_tdm_idx] ); /* Q15 */
     231         237 :                 c = BASOP_Util_Divide3232_Scale(
     232          79 :                     L_add( L_mult( add( ONE_IN_Q13, shr( hStereoDft->g_state_fx[b], 2 ) ),
     233          79 :                                    add( ONE_IN_Q13, shr( hStereoDft->g_state_fx[b], 2 ) ) ),
     234             :                            L_shr( L_mult( gamma, gamma ), 4 ) ),
     235          79 :                     L_add( L_mult( sub( ONE_IN_Q13, shr( hStereoDft->g_state_fx[b], 2 ) ),
     236          79 :                                    sub( ONE_IN_Q13, shr( hStereoDft->g_state_fx[b], 2 ) ) ),
     237             :                            L_shr( L_mult( gamma, gamma ), 4 ) ),
     238             :                     &c_e );
     239          79 :                 q_sqrt = c_e;
     240          79 :                 move16();
     241          79 :                 sqrt_res = Sqrt16( mult( c, hStereoCng->cm_fx[b] ), &q_sqrt );
     242          79 :                 tmp32_1 = L_add( L_add( L_shl( 1, sub( Q15, c_e ) ), c ), L_shl( L_deposit_l( sqrt_res ), sub( add( q_sqrt, 1 ), c_e ) ) ); /* Q(15 - c_e) */ /* +1 to account for multiplication with 2 */
     243          79 :                 move16();
     244             :                 // scaleMS = (1 + c + 2 * sqrtf(c * hStereoCng->cm[b])) / (4 * (c * LR_ratio * LR_ratio + (1 - LR_ratio) * (1 - LR_ratio) * targetGain * targetGain + 2 * LR_ratio * (1 - LR_ratio) * targetGain * sqrtf(c * hStereoCng->cm[b])));
     245          79 :                 sqrt_res = Sqrt16( mult( c, hStereoCng->cm_fx[b] ), &q_sqrt );
     246          79 :                 tmp32_2 = L_deposit_l( mult( c, mult( LR_ratio, LR_ratio ) ) ); /* Q(15 - c_e) */
     247             :                 /* (1 - LR_ratio) * (1 - LR_ratio) * targetGain * targetGain */
     248          79 :                 tmp32_2 = L_add( tmp32_2, L_shl( mult( mult( sub( MAX_16, LR_ratio ), sub( MAX_16, LR_ratio ) ), mult( targetGain, targetGain ) ), sub( Q4, c_e ) ) ); /* Q(15 - c_e) */
     249             :                 /* 2 * LR_ratio * (1 - LR_ratio) * targetGain * sqrtf(c * hStereoCng->cm[b]) */
     250          79 :                 tmp32_2 = L_add( tmp32_2, L_shl( L_deposit_l( mult( mult( LR_ratio, sub( MAX_16, LR_ratio ) ), mult( targetGain, sqrt_res ) ) ), sub( add( q_sqrt, 3 ), c_e ) ) ); /* Q(15 - c_e) */ /* +1 to account for multiplication with 2 */
     251          79 :                 tmp32_2 = L_shl( tmp32_2, 2 );
     252          79 :                 scaleMS = BASOP_Util_Divide3232_Scale( tmp32_1, tmp32_2, &c_e );
     253          79 :                 q_sqrt = c_e;
     254          79 :                 move16();
     255          79 :                 scaleMS = Sqrt16( scaleMS, &q_sqrt );
     256          79 :                 scaleAvg_e = BASOP_Util_Add_MantExp( scaleAvg, scaleAvg_e, scaleMS, q_sqrt, &scaleAvg );
     257             :             }
     258          14 :             scaleAvg = BASOP_Util_Divide1616_Scale( scaleAvg, hStereoDft->nbands, &c_e );
     259          14 :             c_e = sub( add( c_e, scaleAvg_e ), 15 );
     260          14 :             hStereoDft->scale_fx = shl_sat( scaleAvg, c_e );
     261          14 :             move16();
     262             :         }
     263             :     }
     264             : 
     265       10940 :     IF( st->cng_type == LP_CNG )
     266             :     {
     267        2474 :         set32_fx( cngNoiseLevel_upd, 0, st->L_frame );
     268             : 
     269             :         /* Deemphasis */
     270        2474 :         dmpf[0] = MAX_16;
     271        2474 :         move16();
     272        2474 :         dmpf[1] = negate( st->preemph_fac );
     273        2474 :         move16();
     274        2474 :         Copy( st->Aq_cng, Atmp, M + 1 );
     275        2474 :         conv_fx_32( Atmp, dmpf, cngNoiseLevel_upd, M + 2 );
     276             : 
     277        2474 :         IF( EQ_16( st->L_frame, L_FRAME ) )
     278             :         {
     279         710 :             pTrigo = hStereoDft->dft_trigo_12k8_fx; /* Q15 */
     280         710 :             trigo_step = STEREO_DFT_TRIGO_SRATE_12k8_STEP * STEREO_DFT_TRIGO_DEC_STEP;
     281         710 :             move16();
     282             :         }
     283             :         ELSE
     284             :         {
     285        1764 :             pTrigo = hStereoDft->dft_trigo_16k_fx; /* Q15 */
     286        1764 :             trigo_step = STEREO_DFT_TRIGO_SRATE_16k_STEP * STEREO_DFT_TRIGO_DEC_STEP;
     287        1764 :             move16();
     288             :         }
     289             : 
     290      189034 :         FOR( i = 0; i < st->L_frame / 4; i++ )
     291             :         {
     292      186560 :             trigo_dec[i] = pTrigo[i * trigo_step]; /* Q15 */
     293      186560 :             move16();
     294      186560 :             trigo_dec[st->L_frame / 2 - i] = pTrigo[i * trigo_step]; /* Q15 */
     295      186560 :             move16();
     296             :         }
     297        2474 :         trigo_dec[st->L_frame / 4] = pTrigo[st->L_frame / 4 * trigo_step]; /* Q15 */
     298        2474 :         move16();
     299             : 
     300        2474 :         Word16 rshift_cng = sub( find_guarded_bits_fx( st->L_frame ), getScaleFactor32( cngNoiseLevel_upd, st->L_frame ) );
     301        2474 :         v_shr_32( cngNoiseLevel_upd, cngNoiseLevel_upd, st->L_frame, rshift_cng );
     302        2474 :         q_cngNoiseLevel_upd = sub( Q30, rshift_cng );
     303             : 
     304        2474 :         rfft_fx( cngNoiseLevel_upd, trigo_dec, st->L_frame, -1 );
     305             : 
     306        2474 :         Word16 shift = sub( getScaleFactor32( cngNoiseLevel_upd, st->L_frame ), 1 );
     307        2474 :         scale_sig32( cngNoiseLevel_upd, st->L_frame, shift );
     308        2474 :         q_cngNoiseLevel_upd = add( q_cngNoiseLevel_upd, shift );
     309        2474 :         set16_fx( e_norm_temp, q_cngNoiseLevel_upd, st->L_frame );
     310             : 
     311             :         /* Compute 1/|A| */
     312        2474 :         ptr0 = cngNoiseLevel_upd;
     313        2474 :         ptr1 = ptr0 + 2;
     314        2474 :         ptr2 = ptr1 + 1;
     315        2474 :         assert( st->lp_ener_fx > 0 );
     316             : 
     317             :         // lp_ener_fx will be in Q6 at this point.
     318             :         // So applying appropriate left shift on the denominator.
     319        2474 :         factor = L_shr( BASOP_Util_Divide3232_Scale_newton( st->lp_ener_fx, L_shl( st->L_frame, Q6 ), &q_div ), 1 ); /* fixed factor  in the loop below */ /* q_div */
     320        2474 :         factor = Sqrt32( factor, &q_div );
     321        2474 :         q_div = add( q_div, 1 );
     322             : 
     323             :         Word16 q_tmp;
     324      373120 :         FOR( i = 0; i < st->L_frame / 2 - 1; i++ )
     325             :         {
     326      370646 :             ftmp = Madd_32_32( Mpy_32_32( *ptr1, *ptr1 ), *ptr2, *ptr2 ); /* q_cngNoiseLevel_upd */
     327      370646 :             assert( ftmp > 0 );
     328      370646 :             q_sqrt = sub( 62, shl( q_cngNoiseLevel_upd, 1 ) );
     329      370646 :             IF( ftmp == 0 )
     330             :             {
     331           0 :                 ftmp = EPSILLON_FX;
     332           0 :                 move32();
     333           0 :                 q_sqrt = s_max( 0, q_sqrt );
     334             :             }
     335      370646 :             tmp = ISqrt32( ftmp, &q_sqrt );
     336      370646 :             e_norm_temp[i] = sub( 31, add( q_sqrt, q_div ) );
     337      370646 :             move16();
     338      370646 :             *ptr0++ = Mpy_32_32( factor, tmp ); /* 2 * q_div + q_sqrt - 31 */
     339      370646 :             move32();
     340      370646 :             ptr1 += 2;
     341      370646 :             ptr2 += 2;
     342             :         }
     343             : 
     344      373120 :         FOR( i = 0; i < st->L_frame / 2 - 1; i++ )
     345             :         {
     346      370646 :             q_cngNoiseLevel_upd = s_min( q_cngNoiseLevel_upd, add( e_norm_temp[i], norm_l( cngNoiseLevel_upd[i] ) ) );
     347             :         }
     348      748714 :         FOR( i = 0; i < st->L_frame; i++ )
     349             :         {
     350      746240 :             cngNoiseLevel_upd[i] = L_shl( cngNoiseLevel_upd[i], sub( q_cngNoiseLevel_upd, e_norm_temp[i] ) );
     351      746240 :             move32();
     352             :         }
     353             : 
     354        2474 :         IF( sub( s_min( output_frame, L_FRAME32k ), hFdCngCom->stopFFTbin ) > 0 )
     355             :         {
     356             :             /* Transform shb LP spectrum */
     357        2120 :             set32_fx( shb_shape, 0, L_FRAME16k );
     358        2120 :             Copy_Scale_sig_16_32_DEPREC( st->hTdCngDec->shb_lpcCNG_fx, shb_shape, LPC_SHB_ORDER + 1, Q15 ); // Q30
     359             : 
     360        2120 :             IF( NE_16( st->L_frame, L_FRAME16k ) )
     361             :             {
     362         710 :                 pTrigo = hStereoDft->dft_trigo_16k_fx; /* Q15 */
     363         710 :                 trigo_step = STEREO_DFT_TRIGO_SRATE_16k_STEP * STEREO_DFT_TRIGO_DEC_STEP;
     364         710 :                 move16();
     365             : 
     366       57510 :                 FOR( i = 0; i < L_FRAME16k / 4; i++ )
     367             :                 {
     368       56800 :                     trigo_dec[i] = pTrigo[i * trigo_step]; /* Q15 */
     369       56800 :                     move16();
     370       56800 :                     trigo_dec[L_FRAME16k / 2 - i] = pTrigo[i * trigo_step]; /* Q15 */
     371       56800 :                     move16();
     372             :                 }
     373         710 :                 trigo_dec[L_FRAME16k / 4] = pTrigo[L_FRAME16k / 4 * trigo_step]; /* Q15 */
     374         710 :                 move16();
     375             :             }
     376             : 
     377        2120 :             Word16 rshift_shb = sub( find_guarded_bits_fx( L_FRAME16k ), getScaleFactor32( shb_shape, L_FRAME16k ) );
     378        2120 :             v_shr_32( shb_shape, shb_shape, L_FRAME16k, rshift_shb );
     379        2120 :             q_shb_shape = sub( Q30, rshift_shb );
     380             : 
     381        2120 :             rfft_fx( shb_shape, trigo_dec, L_FRAME16k, -1 );
     382             : 
     383        2120 :             shift = sub( getScaleFactor32( shb_shape, L_FRAME16k ), 1 );
     384        2120 :             scale_sig32( shb_shape, L_FRAME16k, shift ); /* q_shb_shape + shift */
     385        2120 :             q_shb_shape = add( q_shb_shape, shift );
     386             : 
     387             :             /* Compute 1/|A| */
     388        2120 :             enr = Madd_32_32( Mpy_32_32( shb_shape[0], shb_shape[0] ), shb_shape[1], shb_shape[1] ); /* 62 - 2*q_shb_shape */
     389        2120 :             q_enr = sub( 62, shl( q_shb_shape, 1 ) );
     390        2120 :             ptr0 = shb_shape;
     391        2120 :             ptr1 = ptr0 + 2;
     392        2120 :             ptr2 = ptr1 + 1;
     393        2120 :             set16_fx( e_norm_temp, q_shb_shape, L_FRAME16k );
     394             : 
     395      339200 :             FOR( i = 0; i < L_FRAME16k / 2 - 1; i++ )
     396             :             {
     397      337080 :                 ftmp = Madd_32_32( Mpy_32_32( *ptr1, *ptr1 ), *ptr2, *ptr2 ); /* 2*q_shape - 31 */
     398      337080 :                 q_tmp = sub( shl( q_shb_shape, 1 ), 31 );
     399      337080 :                 assert( ftmp > 0 );
     400      337080 :                 q_div = 0;
     401      337080 :                 move16();
     402      337080 :                 ftmp = BASOP_Util_Divide3232_Scale_newton( L_shl( 1, q_tmp ), ftmp, &q_div ); /* q_div */
     403             :                 /* in float:
     404             :                 both a = "div"=(1/(x^2+y^2) and sqrt(a)  is used and summed up in the same loop.
     405             : 
     406             :                 in BASOP:
     407             :                 sum up  using inv_sqrt( *ptr1 * *ptr1 + *ptr2 * *ptr2 ), in this loop
     408             :                 and then sum up  enr = sum( *ptr0 * *ptr0 ),  in a subsequent MAC loop  */
     409      337080 :                 enr = BASOP_Util_Add_Mant32Exp( enr, q_enr, ftmp, q_div, &q_enr ); /* q_enr */
     410      337080 :                 tmp32_1 = Sqrt32( ftmp, &q_div );                                  /* q_div */
     411      337080 :                 *ptr0++ = tmp32_1;
     412      337080 :                 move32();
     413      337080 :                 e_norm_temp[i] = sub( 31, q_div );
     414      337080 :                 move16();
     415      337080 :                 ptr1 += 2;
     416      337080 :                 ptr2 += 2;
     417             :             }
     418        2120 :             q_shb_shape = MAX_16;
     419        2120 :             move16();
     420             : 
     421      680520 :             FOR( i = 0; i < L_FRAME16k; i++ )
     422             :             {
     423      678400 :                 q_shb_shape = s_min( q_shb_shape, add( e_norm_temp[i], norm_l( shb_shape[i] ) ) );
     424             :             }
     425      680520 :             FOR( i = 0; i < L_FRAME16k; i++ )
     426             :             {
     427      678400 :                 shb_shape[i] = L_shl( shb_shape[i], sub( q_shb_shape, e_norm_temp[i] ) ); /* q_shb_shape */
     428      678400 :                 move32();
     429             :             }
     430             :         }
     431             : 
     432             :         /* Update CNG noise level from MS noise estimation */
     433        2474 :         Copy32( st->hFdCngDec->bandNoiseShape, cngNoiseLevel_hist, sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ) ); /* exp(bandNoiseShape_exp)*/
     434        2474 :         ptr_cng = cngNoiseLevel_hist;
     435      373120 :         FOR( i = 0; i < ( st->last_L_frame - hFdCngCom->startBand ) / 2; i++ )
     436             :         {
     437      370646 :             tmp = L_shr( *( cngNoiseLevel_hist + shl( i, 1 ) ), 1 );
     438      370646 :             move32();
     439      370646 :             tmp = L_add( tmp, L_shr( *( cngNoiseLevel_hist + add( shl( i, 1 ), 1 ) ), 1 ) ); /* exp(bandNoiseShape_exp)*/
     440      370646 :             *ptr_cng++ = tmp;
     441      370646 :             move32();
     442             :         }
     443             : 
     444        2474 :         test();
     445        2474 :         test();
     446        2474 :         test();
     447        2474 :         IF( EQ_16( last_element_mode, IVAS_CPE_TD ) && ( chan == 0 ) && ( hStereoCng->xfade_frame_counter == 0 ) && GE_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
     448             :         {
     449           7 :             ptr_cng = cngNoiseLevel_hist + hFdCngCom->startBand;
     450           7 :             ptr_tmp = cngNoiseLevel_upd + hFdCngCom->startBand;
     451             :             Word32 temppp;
     452           7 :             Word16 shift_g = shr( find_guarded_bits_fx( shr( sub( st->last_L_frame, hFdCngCom->startBand ), 1 ) ), 1 );
     453        1120 :             FOR( i = 0; i < ( st->last_L_frame - hFdCngCom->startBand ) / 2; i++ )
     454             :             {
     455        1113 :                 E0 = W_add( E0, *ptr_cng++ ); /* exp(bandNoiseShape_exp - E0_e) */
     456        1113 :                 temppp = L_shr( ( *ptr_tmp ), shift_g );
     457        1113 :                 E1 = W_mac_32_32( E1, temppp, temppp ); /* 2*(q_cngNoiseLevel_upd - shift_g) + 1*/
     458        1113 :                 ptr_tmp++;
     459             :             }
     460           7 :             E0_e = W_norm( E0 );
     461           7 :             E0 = W_shl( E0, E0_e );
     462           7 :             E0_e = add( sub( st->hFdCngDec->bandNoiseShape_exp, E0_e ), 32 );
     463           7 :             E1_e = W_norm( E1 );
     464           7 :             E1 = W_shl( E1, E1_e );
     465           7 :             E1_e = sub( 63, add( E1_e, add( shl( sub( q_cngNoiseLevel_upd, shift_g ), 1 ), 1 ) ) );
     466             : 
     467           7 :             IF( BASOP_Util_Cmp_Mant32Exp( W_extract_h( E0 ), E0_e, W_extract_h( E1 ), E1_e ) < 0 )
     468             :             {
     469           7 :                 tmp_16 = BASOP_Util_Divide3232_Scale( W_extract_h( E0 ), W_extract_h( E1 ), &q_div ); /* q_div + E0_e - E1_e */
     470           7 :                 q_div = add( q_div, sub( E0_e, E1_e ) );
     471           7 :                 tmp_16 = Sqrt16( tmp_16, &q_div );
     472           7 :                 tmp_16 = shl( tmp_16, q_div );
     473           7 :                 hStereoCng->xfade_length = sub( MAX_XFADE_FX, extract_l( L_shr( imult3216( MAX_XFADE_FX, tmp_16 ), Q15 ) ) ); /* Q0 */
     474           7 :                 move16();
     475             :             }
     476             :             ELSE
     477             :             {
     478           0 :                 tmp_16 = BASOP_Util_Divide3232_Scale( W_extract_h( E1 ), W_extract_h( E0 ), &q_div ); /* q_div + E0_e - E1_e */
     479           0 :                 q_div = add( q_div, sub( E1_e, E0_e ) );
     480           0 :                 tmp_16 = Sqrt16( tmp_16, &q_div );
     481           0 :                 tmp_16 = shl( tmp_16, q_div );
     482           0 :                 hStereoCng->xfade_length = sub( MAX_XFADE_FX, extract_l( L_shr( imult3216( MAX_XFADE_FX, tmp_16 ), Q15 ) ) ); /* Q0 */
     483           0 :                 move16();
     484             :             }
     485             :         }
     486             : 
     487        2474 :         IF( LT_16( hStereoCng->xfade_frame_counter, hStereoCng->xfade_length ) )
     488             :         {
     489          74 :             ptr_cng = cngNoiseLevel_hist + hFdCngCom->startBand;
     490          74 :             ptr_tmp = cngNoiseLevel_upd + hFdCngCom->startBand;
     491       11840 :             FOR( i = 0; i < ( st->last_L_frame - hFdCngCom->startBand ) / 2; i++ )
     492             :             {
     493       11766 :                 q_sqrt = st->hFdCngDec->bandNoiseShape_exp;
     494       11766 :                 move16();
     495       11766 :                 tmp_16 = BASOP_Util_Divide1616_Scale( hStereoCng->xfade_frame_counter, hStereoCng->xfade_length, &q_div ); /* Q0 */
     496       11766 :                 tmp_16 = shl( tmp_16, q_div );
     497       11766 :                 tmp = Sqrt32( *ptr_cng++, &q_sqrt );
     498       11766 :                 tmp = L_shl( tmp, sub( add( q_cngNoiseLevel_upd, q_sqrt ), 31 ) );
     499       11766 :                 *ptr_tmp = L_add( Mpy_32_16_1( *ptr_tmp, tmp_16 ), Mpy_32_16_1( Mpy_32_16_1( tmp, sub( MAX_16, tmp_16 ) ), hStereoDft->scale_fx ) ); /* q_cngNoiseLevel_upd + q_div */
     500       11766 :                 move32();
     501       11766 :                 ptr_tmp++;
     502             :             }
     503             :         }
     504             : 
     505        7422 :         FOR( k = 0; k < STEREO_DFT_NBDIV; k++ )
     506             :         {
     507             :             /* low band */
     508        4948 :             ptr_level = cngNoiseLevel_upd;                                                      // Q(q_cngNoiseLevel_upd)
     509        4948 :             ptr_r = DFT[chan] + add( hFdCngCom->startBand, i_mult( k, STEREO_DFT32MS_N_MAX ) ); // Q(q_dft)
     510        4948 :             ptr_i = ptr_r + 1;
     511        4948 :             scale = shr( output_frame, 1 );
     512             : 
     513      746240 :             FOR( i = 0; i < ( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2; i++ )
     514             :             {
     515             :                 /* Real part in FFT bins */
     516      741292 :                 rand_gauss_fx( ptr_r, &st->hTdCngDec->cng_seed, q_dft );
     517      741292 :                 tmp32_1 = Mpy_32_16_1( *ptr_level, scale ); // Q(q_cngNoiseLevel_upd - 15)
     518      741292 :                 q_shift = norm_l( tmp32_1 );
     519      741292 :                 if ( GT_16( q_shift, sub( 46, q_cngNoiseLevel_upd ) ) )
     520             :                 {
     521         352 :                     q_shift = sub( 46, q_cngNoiseLevel_upd );
     522             :                 }
     523      741292 :                 tmp32_1 = L_shl( tmp32_1, q_shift );
     524      741292 :                 q_shift = sub( sub( 46, q_cngNoiseLevel_upd ), q_shift );
     525             : 
     526      741292 :                 ( *ptr_r ) = L_shl( Mpy_32_32( ( *ptr_r ), tmp32_1 ), q_shift ); /* q_dft */
     527      741292 :                 move32();
     528      741292 :                 ptr_r += 2;
     529             : 
     530             :                 /* Imaginary part in FFT bins */
     531      741292 :                 rand_gauss_fx( ptr_i, &st->hTdCngDec->cng_seed, q_dft );
     532      741292 :                 ( *ptr_i ) = L_shl( Mpy_32_32( ( *ptr_i ), tmp32_1 ), q_shift ); /* q_dft */
     533      741292 :                 move32();
     534      741292 :                 ptr_i += 2;
     535      741292 :                 ptr_level++;
     536             :             }
     537             : 
     538        4948 :             IF( sub( s_min( output_frame, L_FRAME32k ), hFdCngCom->stopFFTbin ) > 0 )
     539             :             {
     540             :                 Word32 scale_32;
     541             :                 Word16 q_res;
     542             :                 /* high band generation, flipped spectrum */
     543        4240 :                 assert( enr != 0 );
     544             :                 // 10 ^ (0.1 * st->hTdCngDec->shb_cng_gain)
     545             :                 // Above expression equivalent to 2 ^ (3.321928094 * 0.1 * st->hTdCngDec->shb_cng_gain)
     546             :                 // 3.321928094 * 0.1 = 0.3321928094
     547             :                 // st->hTdCngDec->shb_cng_gain_fx_32 Q is 11
     548        4240 :                 scale_32 = BASOP_util_Pow2( Mpy_32_16_1( st->hTdCngDec->shb_cng_gain_fx_32, (Word16) 0x2A85 ), Q31 - Q11, &q_res );
     549             :                 // Q of scale_32 is Q31 - q_res, Q of enr is
     550             :                 // scale_32 = L_shl(scale_32, sub( q_enr, sub(Q31, q_res)));
     551        4240 :                 q_div = 0;
     552        4240 :                 move16();
     553        4240 :                 scale = BASOP_Util_Divide3232_Scale( scale_32, enr, &q_div );
     554             :                 // q_res = add(q_div, sub( q_enr, sub(Q31, q_res))); move16();
     555        4240 :                 q_res = add( sub( q_res, q_enr ), q_div );
     556             :                 // q_div = sub(Q15, q_res); move16();
     557        4240 :                 q_div = q_res;
     558        4240 :                 move16();
     559        4240 :                 inv_scale = ISqrt16( scale, &q_res );
     560        4240 :                 scale = Sqrt16( scale, &q_div );
     561        4240 :                 ptr_shb = shb_shape + ( L_FRAME16k / 2 - 1 );
     562             :                 /* Averaging for Nyquist frequency */
     563             :                 Word16 q1, q2;
     564        4240 :                 tmp32_1 = Mpy_32_16_1( cngNoiseLevel_upd[( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2 - 1], inv_scale ); /* q_cngNoiseLevel_upd + 1 - q_res */
     565        4240 :                 tmp32_2 = *( ptr_shb - 1 );                                                                                      /* q_shb_shape */
     566        4240 :                 move32();
     567        4240 :                 q1 = sub( add( q_cngNoiseLevel_upd, 1 ), q_res );
     568        4240 :                 q2 = q_shb_shape;
     569        4240 :                 move16();
     570        4240 :                 *ptr_shb = BASOP_Util_Add_Mant32Exp( tmp32_1, sub( Q31, q1 ), tmp32_2, sub( Q31, q2 ), &q_tmp );
     571        4240 :                 move32();
     572        4240 :                 q_tmp = sub( q_tmp, 1 );
     573        4240 :                 IF( LT_16( sub( Q31, q_tmp ), q_shb_shape ) )
     574             :                 {
     575         216 :                     scale_sig32( shb_shape, L_FRAME16k, sub( sub( Q31, q_tmp ), q_shb_shape ) ); /* Q31 - q_tmp */
     576         216 :                     q_shb_shape = sub( Q31, q_tmp );
     577             :                 }
     578             : 
     579        4240 :                 *ptr_shb = L_shl( *ptr_shb, sub( q_shb_shape, sub( Q31, q_tmp ) ) ); /* Q31 - q_tmp */
     580        4240 :                 move32();
     581             : 
     582             :                 // *ptr_shb = 0.5f * ( cngNoiseLevel_upd[( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2 - 1] / scale + *( ptr_shb - 1 ) );
     583             : 
     584        4240 :                 ptr_r = DFT[chan] + add( hFdCngCom->stopFFTbin, i_mult( k, STEREO_DFT32MS_N_MAX ) ); /* q_dft */
     585        4240 :                 ptr_i = ptr_r + 1;
     586             : 
     587        4240 :                 Word16 len = shr( ( sub( s_min( output_frame, i_mult( hFdCngCom->regularStopBand, 16 ) ), hFdCngCom->stopFFTbin ) ), 1 );
     588      517360 :                 FOR( i = 0; i < len; i++ )
     589             :                 {
     590             :                     /* Real part in FFT bins */
     591      513120 :                     rand_gauss_fx( ptr_r, &st->hTdCngDec->cng_seed, q_dft );
     592      513120 :                     tmp32_1 = *ptr_shb;
     593      513120 :                     move32();
     594      513120 :                     q_shift = norm_l( tmp32_1 );
     595      513120 :                     IF( GT_16( q_shift, sub( 31, q_shb_shape ) ) )
     596             :                     {
     597       23900 :                         q_shift = sub( 31, q_shb_shape );
     598             :                     }
     599      513120 :                     tmp32_1 = L_shl( tmp32_1, q_shift );
     600      513120 :                     q_shift = sub( sub( 31, q_shb_shape ), q_shift );
     601             : 
     602      513120 :                     ( *ptr_r ) = L_shl( Mpy_32_32( ( *ptr_r ), tmp32_1 ), q_shift );
     603      513120 :                     move32();
     604      513120 :                     ptr_r += 2;
     605             :                     /* Imaginary part in FFT bins */
     606      513120 :                     rand_gauss_fx( ptr_i, &st->hTdCngDec->cng_seed, q_dft );
     607      513120 :                     ( *ptr_i ) = L_shl( Mpy_32_32( ( *ptr_i ), tmp32_1 ), q_shift ); /* q_dft + q_shift */
     608      513120 :                     move32();
     609      513120 :                     ptr_i += 2;
     610      513120 :                     ptr_shb--;
     611             :                 }
     612             : 
     613             :                 /* rescale */
     614        4240 :                 tmp32_1 = L_mult0( scale, shr( output_frame, 1 ) );
     615        4240 :                 q_shift = norm_l( tmp32_1 );
     616        4240 :                 IF( GT_16( q_shift, add( Q16, q_div ) ) )
     617             :                 {
     618         400 :                     q_shift = add( Q16, q_div );
     619             :                 }
     620        4240 :                 tmp32_1 = L_shl( tmp32_1, q_shift );
     621        4240 :                 q_shift = sub( add( Q16, q_div ), q_shift );
     622             : 
     623        4240 :                 ptr_r = DFT[chan] + add( hFdCngCom->stopFFTbin, i_mult( k, STEREO_DFT32MS_N_MAX ) ); /* q_dft */
     624        4240 :                 ptr_i = ptr_r + 1;
     625        4240 :                 tmp = shr( sub( s_min( output_frame, i_mult( hFdCngCom->regularStopBand, 16 ) ), hFdCngCom->stopFFTbin ), 1 );
     626      517360 :                 FOR( i = 0; i < tmp; i++ )
     627             :                 {
     628      513120 :                     ( *ptr_r ) = L_shl( Mpy_32_32( ( *ptr_r ), tmp32_1 ), q_shift ); /* q_dft + q_shift */
     629      513120 :                     move32();
     630      513120 :                     ( *ptr_i ) = L_shl( Mpy_32_32( ( *ptr_i ), tmp32_1 ), q_shift ); /* q_dft + q_shift */
     631      513120 :                     move32();
     632      513120 :                     ptr_r += 2;
     633      513120 :                     ptr_i += 2;
     634             :                 }
     635             :             }
     636             :         }
     637             : 
     638             :         /* Expand cngNoiseLevel_flt from 0-159 to 0-318, compute noise level */
     639        2474 :         lp_noise = 0;
     640        2474 :         move32();
     641        2474 :         lp_noise_e = 0;
     642        2474 :         move16();
     643        2474 :         ptr_level = hFdCngCom->cngNoiseLevel + sub( hFdCngCom->stopFFTbin, add( hFdCngCom->startBand, 1 ) );  /* q_cngNoiseLevel */
     644        2474 :         ptr_tmp = cngNoiseLevel_upd + sub( shr( sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ), 1 ), 1 ); /* q_cngNoiseLevel_upd */
     645             : 
     646        2474 :         q_tmp = s_max( hFdCngCom->cngNoiseLevelExp, shl( sub( Q31, q_cngNoiseLevel_upd ), 1 ) );
     647        2474 :         scale_sig32( hFdCngCom->cngNoiseLevel, FFTCLDFBLEN, sub( hFdCngCom->cngNoiseLevelExp, q_tmp ) ); /* q_tmp */
     648        2474 :         hFdCngCom->cngNoiseLevelExp = q_tmp;
     649        2474 :         move16();
     650             : 
     651      373120 :         FOR( i = 0; i < ( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2; i++ )
     652             :         {
     653      370646 :             *ptr_level-- = L_shl( Mpy_32_32( *ptr_tmp, *ptr_tmp ), sub( shl( sub( Q31, q_cngNoiseLevel_upd ), 1 ), hFdCngCom->cngNoiseLevelExp ) ); /* q_cngNoiseLevel */
     654      370646 :             move32();
     655      370646 :             ptr_tmp--;
     656      370646 :             *ptr_level = *( ptr_level + 1 );
     657      370646 :             move32();
     658      370646 :             lp_noise = BASOP_Util_Add_Mant32Exp( lp_noise, lp_noise_e, *ptr_level--, add( hFdCngCom->cngNoiseLevelExp, 1 ), &lp_noise_e );
     659             :         }
     660             :     }
     661             :     ELSE
     662             :     {
     663             :         /* FD-CNG */
     664        8466 :         IF( !LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
     665             :         {
     666        8466 :             test();
     667        8466 :             test();
     668        8466 :             IF( LE_16( hStereoCng->xfade_frame_counter, (Word16) MAX_K ) && EQ_16( hStereoCng->last_act_element_mode, IVAS_CPE_TD ) && ( chan == 0 ) )
     669             :             {
     670             :                 /* Fade MS -> SID/MS */
     671          59 :                 j = 0;
     672          59 :                 move16();
     673        1180 :                 FOR( k = 0; k < ( hFdCngCom->nFFTpart - 2 ); k++ )
     674             :                 {
     675        1121 :                     factor = BASOP_Util_Divide3232_Scale_newton( L_add( hFdCngCom->sidNoiseEstLp[k], DELTA_FX ), L_add( st->hFdCngDec->partNoiseShape[k], DELTA_FX ), &q_div ); /* q_div */
     676        1121 :                     q_div = add( q_div, sub( hFdCngCom->sidNoiseEstExp, st->hFdCngDec->partNoiseShape_exp ) );
     677        1121 :                     IF( q_div < 0 )
     678             :                     {
     679           0 :                         factor = L_shl( factor, q_div ); // Q31
     680           0 :                         q_div = 0;
     681           0 :                         move16();
     682             :                     }
     683        1121 :                     factor = L_min( L_add( L_shl( hStereoDft->scale_fx, sub( 16, q_div ) ), W_extract_l( W_mult0_32_32( Mpy_32_16_1( L_sub( factor, L_shl( hStereoDft->scale_fx, sub( 16, q_div ) ) ), ONE_BY_MAX_K ), hStereoCng->xfade_frame_counter ) ) ), factor ); /* q_div */
     684       13570 :                     FOR( ; j <= hFdCngCom->part[k]; j++ )
     685             :                     {
     686             :                         /* NOTE: saturation is added here as part of issue 1218 fix. After rescaling the fdcng noise estimation buffers, due to slight precision loss, values may slightly overflow */
     687       12449 :                         hFdCngCom->cngNoiseLevel[j] = L_shl_sat( Mpy_32_32( st->hFdCngDec->bandNoiseShape[j], factor ), q_div ); /* exp(st->hFdCngDec->bandNoiseShape_exp)  */
     688       12449 :                         move32();
     689             :                     }
     690             :                 }
     691          59 :                 hFdCngCom->cngNoiseLevelExp = st->hFdCngDec->bandNoiseShape_exp;
     692          59 :                 move16();
     693             :             }
     694             :         }
     695        8466 :         scale = shr( output_frame, 1 );
     696        8466 :         numSlots = shr( hFdCngCom->numSlots, 1 );
     697       25398 :         FOR( k = 0; k < STEREO_DFT_NBDIV; k++ )
     698             :         {
     699       16932 :             ptr_level = hFdCngCom->cngNoiseLevel;
     700       16932 :             ptr_r = DFT[chan] + add( hFdCngCom->startBand, i_mult( k, STEREO_DFT32MS_N_MAX ) ); /* qDFT */
     701       16932 :             ptr_i = ptr_r + 1;
     702       16932 :             q_cngNoiseLevel = sub( Q31, hFdCngCom->cngNoiseLevelExp );
     703     2436736 :             FOR( i = 0; i < ( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2; i++ )
     704             :             {
     705             :                 /* Real part in FFT bins */
     706     2419804 :                 tmp = L_shr( *ptr_level++, 1 );
     707     2419804 :                 tmp = L_add( tmp, L_shr( *ptr_level++, 1 ) );
     708     2419804 :                 rand_gauss_fx( ptr_r, &st->hTdCngDec->cng_seed, q_dft );
     709     2419804 :                 q_sqrt = sub( Q31, q_cngNoiseLevel );
     710     2419804 :                 tmp = Sqrt32( tmp, &q_sqrt );
     711     2419804 :                 *( ptr_r ) = imult3216( Mpy_32_32( *( ptr_r ), tmp ), scale ); /* qDFT */
     712     2419804 :                 move32();
     713     2419804 :                 ( *ptr_r ) = L_shl( ( *ptr_r ), q_sqrt ); /* qDFT */
     714     2419804 :                 move32();
     715     2419804 :                 ptr_r += 2;
     716             :                 /* Imaginary part in FFT bins */
     717     2419804 :                 rand_gauss_fx( ptr_i, &st->hTdCngDec->cng_seed, q_dft );
     718     2419804 :                 ( *ptr_i ) = L_shl( imult3216( Mpy_32_32( ( *ptr_i ), tmp ), scale ), q_sqrt ); /* qDFT */
     719     2419804 :                 move32();
     720     2419804 :                 ptr_i += 2;
     721             :             }
     722       16932 :             ptr_level = hFdCngCom->cngNoiseLevel + sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand );
     723       16932 :             ptr_r = DFT[chan] + add( hFdCngCom->stopFFTbin, i_mult( k, STEREO_DFT32MS_N_MAX ) ); /* qDFT */
     724       16932 :             ptr_i = ptr_r + 1;
     725      249380 :             FOR( j = hFdCngCom->numCoreBands; j < hFdCngCom->regularStopBand; j++ )
     726             :             {
     727     2092032 :                 FOR( i = 0; i < numSlots; i++ )
     728             :                 {
     729             :                     /* Real part in FFT bins */
     730     1859584 :                     rand_gauss_fx( ptr_r, &st->hTdCngDec->cng_seed, q_dft );
     731     1859584 :                     q_sqrt = sub( Q31, q_cngNoiseLevel );
     732     1859584 :                     tmp = Sqrt32( *ptr_level, &q_sqrt );
     733     1859584 :                     tmp = Mpy_32_16_1( tmp, scale );       // 15 + q_sqrt
     734     1859584 :                     ( *ptr_r ) = Mpy_32_32( *ptr_r, tmp ); // q_dft + 15 + q_sqrt - 31
     735     1859584 :                     ( *ptr_r ) = L_shl_sat( ( *ptr_r ), add( 15, q_sqrt ) );
     736     1859584 :                     move32();
     737     1859584 :                     ptr_r += 2;
     738             :                     /* Imaginary part in FFT bins */
     739     1859584 :                     rand_gauss_fx( ptr_i, &st->hTdCngDec->cng_seed, q_dft );
     740     1859584 :                     ( *ptr_i ) = Mpy_32_32( *ptr_i, tmp ); // q_dft + 15 + q_sqrt - 31
     741     1859584 :                     ( *ptr_i ) = L_shl_sat( ( *ptr_i ), add( 15, q_sqrt ) );
     742     1859584 :                     move32();
     743     1859584 :                     ptr_i += 2;
     744             :                 }
     745      232448 :                 ptr_level++;
     746             :             }
     747             :         }
     748             : 
     749             :         /* Compute noise level */
     750        8466 :         lp_noise = 0;
     751        8466 :         move32();
     752        8466 :         lp_noise_e = 0;
     753        8466 :         move16();
     754        8466 :         ptr_level = hFdCngCom->cngNoiseLevel;
     755     2428270 :         FOR( i = 0; i < hFdCngCom->stopFFTbin - hFdCngCom->startBand; i++ )
     756             :         {
     757             :             // lp_noise = L_add( lp_noise, *ptr_level++ );
     758     2419804 :             lp_noise = BASOP_Util_Add_Mant32Exp( lp_noise, lp_noise_e, *ptr_level++, hFdCngCom->cngNoiseLevelExp, &lp_noise_e );
     759             :         }
     760             :     }
     761             : 
     762       10940 :     test();
     763       10940 :     IF( EQ_16( hStereoCng->last_act_element_mode, IVAS_CPE_TD ) && ( chan > 0 ) )
     764          96 :     {
     765          96 :         Word32 log_lp_noise = L_add( L_shl( lp_noise_e, Q25 ), BASOP_Util_Log2( L_add( lp_noise, DELTA_FX ) ) ); /* Q25 */
     766             :         // log10(x) is computed as log2(x) * log10(2)
     767             :         // log_lp_noise at this stage is in Q25. where as the structure value is in Q23
     768             :         // Hence the 16-bit constant log10(2) will be stored in Q13
     769          96 :         log_lp_noise = Mpy_32_16_1( log_lp_noise, 2466 /* log10(2) in Q13 */ );                       /* Q23 */
     770          96 :         st1->lp_noise = L_add( Mpy_32_16_1( st1->lp_noise, 29491 /* 0.9f in Q15 */ ), log_lp_noise ); /* Q23 */
     771          96 :         move32();
     772             :     }
     773       10844 :     ELSE IF( ( chan == 0 ) )
     774             :     {
     775        5470 :         Word16 q_lp_noise = 0; // st->hFdCngDec->q_lp_noise; // to be populated appropriately.
     776        5470 :         move16();
     777        5470 :         Word32 log_lp_noise = L_add( L_shl( lp_noise_e, Q25 ), BASOP_Util_Log2( L_add( lp_noise, DELTA_FX ) ) ); /* Q25 */
     778             :         // log10(x) is computed as log2(x) * log10(2)
     779             :         // log_lp_noise at this stage is in Q25. where as the structure value is in Q23
     780             :         // Hence the 16-bit constant log10(2) will be stored in Q13
     781        5470 :         log_lp_noise = Mpy_32_16_1( log_lp_noise, 2466 /* log10(2) in Q13 */ );                                           /* Q23 */
     782        5470 :         st->hFdCngDec->lp_noise = L_add( Mpy_32_16_1( st->hFdCngDec->lp_noise, 29491 /* 0.9f in Q15 */ ), log_lp_noise ); /* Q23 */
     783        5470 :         move32();
     784        5470 :         st->lp_noise = st->hFdCngDec->lp_noise; /* Q23 */
     785        5470 :         move32();
     786        5470 :         st->hFdCngDec->hFdCngCom->flag_noisy_speech = extract_l( LT_32( L_shr( L_sub( st->hFdCngDec->lp_speech, st->hFdCngDec->lp_noise ), q_lp_noise ), 28 ) ); /* Q0 */
     787        5470 :         move16();
     788        5470 :         st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = add( mult_r( 32440 /* 0.99 in Q15 */, st->hFdCngDec->hFdCngCom->likelihood_noisy_speech ),
     789        5470 :                                                                  mult_r( 328 /* 0.01 in Q15 */, st->hFdCngDec->hFdCngCom->flag_noisy_speech ) ); /* Q15 */
     790        5470 :         move16();
     791             :     }
     792             : 
     793       10940 :     test();
     794       10940 :     IF( ( chan == 0 ) && LE_32( st->core_brate, SID_2k40 ) )
     795             :     {
     796             :         /* update smoothed periodogram used by stereo CNA in SID and NO_DATA frames from cngNoiseLevel_flt */
     797        5470 :         q_shift_1 = L_norm_arr( st->hFdCngDec->smoothed_psd_fx, L_FRAME16k );
     798        5470 :         q_shift_2 = L_norm_arr( hFdCngCom->cngNoiseLevel, FFTCLDFBLEN );
     799             : 
     800        5470 :         min_q = sub( s_min( add( q_shift_1, sub( Q31, st->hFdCngDec->smoothed_psd_exp ) ), add( q_shift_2, sub( Q31, hFdCngCom->cngNoiseLevelExp ) ) ), 1 /* Guard bit */ );
     801             : 
     802        5470 :         scale_sig32( st->hFdCngDec->smoothed_psd_fx, L_FRAME16k, sub( min_q, sub( Q31, st->hFdCngDec->smoothed_psd_exp ) ) ); /* Q31 - st->hFdCngDec->smoothed_psd_exp */
     803        5470 :         st->hFdCngDec->smoothed_psd_exp = sub( Q31, min_q );
     804        5470 :         move16();
     805        5470 :         scale_sig32( hFdCngCom->cngNoiseLevel, FFTCLDFBLEN, sub( min_q, sub( Q31, hFdCngCom->cngNoiseLevelExp ) ) ); /* Q31 - hFdCngCom->cngNoiseLevelExp */
     806        5470 :         hFdCngCom->cngNoiseLevelExp = st->hFdCngDec->smoothed_psd_exp;
     807        5470 :         move16();
     808             : 
     809     1586018 :         FOR( i = hFdCngCom->startBand; i < hFdCngCom->stopFFTbin; i++ )
     810             :         {
     811     1580548 :             ftmp = hFdCngCom->cngNoiseLevel[i - hFdCngCom->startBand];
     812     1580548 :             move32();
     813     1580548 :             IF( !st->hFdCngDec->first_cna_noise_updated )
     814             :             {
     815             :                 /* very first update */
     816        2606 :                 alpha = 0;
     817        2606 :                 move16();
     818             :             }
     819             :             ELSE
     820             :             {
     821     1577942 :                 alpha = (Word16) ( 0x799A );
     822     1577942 :                 move16();
     823     1577942 :                 test();
     824     1577942 :                 IF( ( st->hFdCngDec->smoothed_psd_fx[i] > 0 ) && GT_32( Mpy_32_16_1( ftmp, (Word16) 0x3333 ), st->hFdCngDec->smoothed_psd_fx[i] ) )
     825             :                 {
     826             :                     /* prevent abrupt upward update steps */
     827      105819 :                     ftmp = L_add( L_shl( st->hFdCngDec->smoothed_psd_fx[i], 1 ), L_shr( st->hFdCngDec->smoothed_psd_fx[i], 1 ) ); /* st->hFdCngDec->smoothed_psd_exp */
     828      105819 :                     move16();
     829             :                 }
     830     1472123 :                 ELSE IF( LT_32( ftmp, st->hFdCngDec->smoothed_psd_fx[i] ) )
     831             :                 {
     832             :                     /* faster downward updates */
     833      323320 :                     alpha = (Word16) ( 0x599A );
     834      323320 :                     move16();
     835             :                 }
     836             :             }
     837             : 
     838             :             /* smoothing */
     839     1580548 :             st->hFdCngDec->smoothed_psd_fx[i] = L_add( Mpy_32_16_1( st->hFdCngDec->smoothed_psd_fx[i], alpha ), Mpy_32_16_1( ftmp, sub( MAX_16, alpha ) ) ); /* st->hFdCngDec->smoothed_psd_exp */
     840     1580548 :             move32();
     841             :         }
     842             : 
     843             :         /* update msNoiseEst in SID and NO_DATA frames */
     844        5470 :         bandcombinepow( &st->hFdCngDec->smoothed_psd_fx[hFdCngCom->startBand], st->hFdCngDec->smoothed_psd_exp, sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ), st->hFdCngDec->part_shaping, st->hFdCngDec->nFFTpart_shaping, st->hFdCngDec->psize_inv_shaping, st->hFdCngDec->msNoiseEst, &st->hFdCngDec->msNoiseEst_exp );
     845             : 
     846             :         Word32 max_l;
     847        5470 :         maximum_32_fx( st->hFdCngDec->msNoiseEst, NPART_SHAPING, &max_l );
     848        5470 :         IF( max_l )
     849             :         {
     850        5470 :             q_shift = sub( norm_l( max_l ), 2 );
     851        5470 :             scale_sig32( st->hFdCngDec->msNoiseEst, NPART_SHAPING, q_shift ); /* st->hFdCngDec->msNoiseEst_exp - q_shift */
     852        5470 :             st->hFdCngDec->msNoiseEst_exp = sub( st->hFdCngDec->msNoiseEst_exp, q_shift );
     853        5470 :             move16();
     854             :         }
     855        5470 :         st->hFdCngDec->first_cna_noise_updated = 1;
     856        5470 :         move16();
     857        5470 :         Copy32( st->hFdCngDec->msNoiseEst, st->hFdCngDec->msPeriodog_ST_fx, st->hFdCngDec->nFFTpart_shaping ); /* st->hFdCngDec->msNoiseEst_exp - q_shift */
     858        5470 :         st->hFdCngDec->msPeriodog_ST_exp = st->hFdCngDec->msNoiseEst_exp;
     859        5470 :         st->hFdCngDec->ms_last_inactive_bwidth = st->bwidth; /* Q0 */
     860        5470 :         move16();
     861             :     }
     862             : 
     863       10940 :     pop_wmops();
     864       10940 :     return;
     865             : }
     866             : 
     867             : /*-------------------------------------------------------------------
     868             :  * stereo_dtf_cng()
     869             :  *
     870             :  * DFT stereo CNG
     871             :  *-------------------------------------------------------------------*/
     872       42046 : void stereo_dtf_cng_fx(
     873             :     CPE_DEC_HANDLE hCPE,                          /* i/o: CPE decoder structure                   */
     874             :     const Word32 ivas_total_brate,                /* i  : IVAS total bitrate                    Q0*/
     875             :     Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers                            q_dft*/
     876             :     const Word16 output_frame,                    /* i  : output frame size                             Q0*/
     877             :     Word16 q_dft                                  /* i  : Q factor of the DFT data                */
     878             : )
     879             : {
     880             :     Decoder_State **sts;
     881             :     Word16 n;
     882             : 
     883       42046 :     sts = hCPE->hCoreCoder;
     884             : 
     885       42046 :     IF( hCPE->hStereoCng != NULL )
     886             :     {
     887       42046 :         IF( LT_16( hCPE->hStereoCng->nr_dft_frames, CM_INIT ) )
     888             :         {
     889        5605 :             hCPE->hStereoCng->nr_dft_frames = add( hCPE->hStereoCng->nr_dft_frames, 1 ); /* Q0 */
     890        5605 :             move16();
     891             :         }
     892             : 
     893       42046 :         IF( LE_32( ivas_total_brate, IVAS_SID_5k2 ) )
     894             :         {
     895        5470 :             test();
     896        5470 :             IF( LT_16( hCPE->hStereoCng->nr_sid_frames, SID_INIT ) && EQ_32( ivas_total_brate, IVAS_SID_5k2 ) )
     897             :             {
     898          90 :                 hCPE->hStereoCng->nr_sid_frames = add( hCPE->hStereoCng->nr_sid_frames, 1 ); /* Q0 */
     899          90 :                 move16();
     900             :             }
     901             : 
     902       16410 :             FOR( n = 0; n < CPE_CHANNELS; n++ )
     903             :             {
     904       10940 :                 stereo_dft_generate_comfort_noise_fx( hCPE->hStereoDft, hCPE->hStereoCng, hCPE->last_element_mode, sts[0], DFT, sts[1], extract_h( hCPE->hStereoTCA->targetGain_fx ), n, output_frame, q_dft );
     905             :             }
     906             :         }
     907             :     }
     908             : 
     909       42046 :     return;
     910             : }
     911             : 
     912             : 
     913             : /*-------------------------------------------------------------------
     914             :  * stereo_cng_dec_update()
     915             :  *
     916             :  * Update counters used for TD->DFT-CNG cross fade and stereo SID parameters
     917             :  *-------------------------------------------------------------------*/
     918             : 
     919       62798 : void stereo_cng_dec_update(
     920             :     CPE_DEC_HANDLE hCPE,          /* i/o: CPE decoder structure       */
     921             :     const Word32 ivas_total_brate /* i  : IVAS total bitrate            Q0*/
     922             : )
     923             : {
     924       62798 :     IF( GT_32( hCPE->hCoreCoder[0]->core_brate, SID_2k40 ) )
     925             :     {
     926       52447 :         hCPE->hStereoCng->last_act_element_mode = hCPE->element_mode;
     927       52447 :         move16();
     928       52447 :         IF( GT_16( hCPE->hStereoCng->active_frame_counter, SKIP_XFADE_FRAMES ) )
     929             :         {
     930       49613 :             hCPE->hStereoCng->xfade_frame_counter = 0;
     931       49613 :             move16();
     932       49613 :             hCPE->hStereoCng->xfade_length = 0;
     933       49613 :             move16();
     934             :         }
     935       52447 :         IF( LT_16( hCPE->hStereoCng->active_frame_counter, MAX_FRAME_COUNTER ) )
     936             :         {
     937       33860 :             hCPE->hStereoCng->active_frame_counter = add( hCPE->hStereoCng->active_frame_counter, 1 ); /* Q0 */
     938       33860 :             move16();
     939             :         }
     940             :     }
     941             :     ELSE
     942             :     {
     943       10351 :         hCPE->hStereoCng->active_frame_counter = 0;
     944       10351 :         move16();
     945       10351 :         IF( LT_16( hCPE->hStereoCng->xfade_frame_counter, MAX_FRAME_COUNTER ) )
     946             :         {
     947       10351 :             hCPE->hStereoCng->xfade_frame_counter = add( hCPE->hStereoCng->xfade_frame_counter, 1 ); /* Q0 */
     948       10351 :             move16();
     949             :         }
     950             :     }
     951             : 
     952       62798 :     IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) )
     953             :     {
     954       59047 :         test();
     955       59047 :         IF( EQ_32( ivas_total_brate, IVAS_SID_5k2 ) || ( ivas_total_brate == FRAME_NO_DATA ) )
     956             :         {
     957       10351 :             hCPE->hStereoCng->prev_sid_nodata = 1;
     958       10351 :             move16();
     959             :         }
     960             :         ELSE
     961             :         {
     962       48696 :             hCPE->hStereoCng->prev_sid_nodata = 0;
     963       48696 :             move16();
     964             :         }
     965             :     }
     966             : 
     967       62798 :     hCPE->hCoreCoder[0]->hFdCngDec->hFdCngCom->active_frame_counter = hCPE->hStereoCng->active_frame_counter; /* Q0 */
     968       62798 :     move16();
     969             : 
     970       62798 :     return;
     971             : }
     972             : 
     973             : 
     974             : /*-------------------------------------------------------------------*
     975             :  * Function stereo_cng_compute_PScorr()
     976             :  *
     977             :  * CNA for TD stereo, compute PS correlation
     978             :  *-------------------------------------------------------------------*/
     979        3751 : void stereo_cng_compute_PScorr_fx(
     980             :     Word32 output_fx0[], /* i  : Output signal     Qx = 1 temp*/
     981             :     Word32 output_fx1[], /* i  : Output signal     Qx*/
     982             :     Word16 *output_Q,
     983             :     Word32 *c_PS_LT_fx,
     984             :     Word16 Q_c_PS_LT_fx,
     985             :     const Word16 L_frame_0, /* i  : L_frame channel 0           Q0*/
     986             :     const Word16 L_frame_1  /* i  : L_frame channel 1           Q0*/
     987             : )
     988             : {
     989             :     Word16 i;
     990        3751 :     Word32 enrP_fx = 0, enrS_fx = 0, dotPS_fx = 0, c_PS_fx;
     991        3751 :     move32();
     992        3751 :     move32();
     993        3751 :     move32();
     994             :     Word32 outputResamp_fx[L_FRAME16k];
     995             :     Word32 *outputPptr_fx, *outputSptr_fx;
     996        3751 :     Word16 outputPptr_Q = 0, outputSptr_Q = 0;
     997        3751 :     move16();
     998        3751 :     move16();
     999        3751 :     Word32 tmp1 = 0, tmp2 = 0, tmp3 = 0;
    1000        3751 :     move32();
    1001        3751 :     move32();
    1002        3751 :     move32();
    1003             : 
    1004        3751 :     IF( GT_16( L_frame_0, L_frame_1 ) )
    1005             :     {
    1006        2082 :         outputPptr_fx = output_fx0;
    1007        2082 :         L_lerp_fx( output_fx1, outputResamp_fx, L_frame_0, L_frame_1, output_Q );
    1008        2082 :         outputPptr_Q = *output_Q;
    1009        2082 :         move16();
    1010        2082 :         outputSptr_fx = outputResamp_fx;
    1011        2082 :         outputSptr_Q = 1;
    1012        2082 :         move16();
    1013             :     }
    1014        1669 :     ELSE IF( GT_16( L_frame_1, L_frame_0 ) )
    1015             :     {
    1016           0 :         outputSptr_fx = output_fx1;
    1017           0 :         L_lerp_fx( output_fx0, outputResamp_fx, L_frame_1, L_frame_0, output_Q );
    1018           0 :         outputSptr_Q = *output_Q;
    1019           0 :         move16();
    1020           0 :         outputPptr_fx = outputResamp_fx;
    1021           0 :         outputPptr_Q = 1;
    1022           0 :         move16();
    1023             :     }
    1024             :     ELSE
    1025             :     {
    1026        1669 :         outputPptr_fx = output_fx0;
    1027        1669 :         outputSptr_fx = output_fx1;
    1028        1669 :         outputPptr_Q = *output_Q;
    1029        1669 :         move16();
    1030        1669 :         outputSptr_Q = *output_Q;
    1031        1669 :         move16();
    1032             :     }
    1033             : 
    1034        3751 :     Word16 guard_bits = find_guarded_bits_fx( L_frame_0 );
    1035             : 
    1036     1097255 :     FOR( i = 0; i < L_frame_0; i++ )
    1037             :     {
    1038     1093504 :         tmp1 = Mpy_32_32( *outputPptr_fx, *outputPptr_fx ); // 2*outputPptr_Q  - 31
    1039     1093504 :         tmp1 = L_shr( tmp1, guard_bits );                   // 2*outputPptr_Q - 31 - guard_bits
    1040     1093504 :         enrP_fx = L_add( enrP_fx, tmp1 );
    1041     1093504 :         tmp2 = Mpy_32_32( *outputSptr_fx, *outputSptr_fx ); // 2*outputSptr_Q - 31
    1042     1093504 :         tmp2 = L_shr( tmp2, guard_bits );                   // 2 * outputSptr_Q - 31 - guard_bits
    1043     1093504 :         enrS_fx = L_add( enrS_fx, tmp2 );
    1044             : 
    1045     1093504 :         tmp3 = Mpy_32_32( *outputPptr_fx++, *outputSptr_fx++ ); // outputSptr_Q + outputPptr_Q - 31
    1046     1093504 :         tmp3 = L_shr( tmp3, add( guard_bits, 1 ) );             // outputSptr_Q + outputPptr_Q  - 31 - guard_bits
    1047     1093504 :         dotPS_fx = L_add( dotPS_fx, tmp3 );
    1048             :     }
    1049             : 
    1050        3751 :     Word32 Var1 = Mpy_32_32( enrP_fx, enrS_fx ); // 2*( outputPptr_Q - 31 - guard_bits + outputSptr_Q - 31 - guard_bits )
    1051        3751 :     Word16 exp = sub( 31, shl( add( sub( sub( outputPptr_Q, 31 ), guard_bits ), sub( sub( outputSptr_Q, 31 ), guard_bits ) ), 1 ) );
    1052             : 
    1053        3751 :     if ( Var1 == 0 )
    1054             :     {
    1055        3712 :         Var1 = 1;
    1056        3712 :         move32();
    1057             :     }
    1058             : 
    1059             :     Word32 Var2, Var3;
    1060        3751 :     Var2 = ISqrt32( Var1, &exp );
    1061        3751 :     Var3 = L_add( dotPS_fx, 1 );       /*adding one in order to make temp non-zero.  q = Q_outputSptr + Q_outputPptr - guard_bits*/
    1062        3751 :     c_PS_fx = Mpy_32_32( Var3, Var2 ); /* outputSptr_Q + outputPptr_Q - guard_bits - exp */
    1063             : 
    1064        3751 :     Word16 c_PS_fx_Q = add( outputSptr_Q, sub( sub( sub( outputPptr_Q, guard_bits ), exp ), 31 ) );
    1065        3751 :     Word32 a = 0, b = 0;
    1066        3751 :     move32();
    1067        3751 :     move32();
    1068        3751 :     Word16 a_q = 0, b_q = 0, ab_q = 0;
    1069        3751 :     move16();
    1070        3751 :     move16();
    1071        3751 :     move16();
    1072             : 
    1073        3751 :     a = Mpy_32_32( c_PS_fx, ONE_MINUS_STEREO_TD_PS_CORR_FILT_Q31 ); // Q(c_PS_fx_Q)
    1074        3751 :     a_q = c_PS_fx_Q;
    1075        3751 :     move16();
    1076        3751 :     b = Mpy_32_32( STEREO_TD_PS_CORR_FILT_Q31, *c_PS_LT_fx ); // Q(Q_c_PS_LT_fx)
    1077        3751 :     b_q = Q_c_PS_LT_fx;
    1078        3751 :     move16();
    1079             : 
    1080        3751 :     IF( GT_16( a_q, b_q ) )
    1081             :     {
    1082        3751 :         ab_q = sub( a_q, b_q );
    1083        3751 :         *c_PS_LT_fx = L_add( L_shr( a, ab_q ), b );
    1084        3751 :         move32();
    1085        3751 :         Q_c_PS_LT_fx = b_q;
    1086        3751 :         move16();
    1087             :     }
    1088           0 :     ELSE IF( LT_16( b_q, a_q ) )
    1089             :     {
    1090           0 :         ab_q = sub( b_q, a_q );
    1091           0 :         *c_PS_LT_fx = L_add( a, L_shr( b, ab_q ) );
    1092           0 :         move32();
    1093           0 :         Q_c_PS_LT_fx = a_q;
    1094           0 :         move16();
    1095             :     }
    1096             : 
    1097        3751 :     return;
    1098             : }
    1099             : 
    1100             : 
    1101             : /*-------------------------------------------------------------------*
    1102             :  * Function stereo_cng_compute_LRcorr()
    1103             :  *
    1104             :  * CNA for TD stereo, compute LR correlation
    1105             :  *-------------------------------------------------------------------*/
    1106             : 
    1107        3751 : static void stereo_cng_compute_LRcorr_fx(
    1108             :     CPE_DEC_HANDLE hCPE,             /* i/o: CPE handle                                                 */
    1109             :     Word32 *output_fx[CPE_CHANNELS], /* i  : Output signal                  OUTPUT_Q*/
    1110             :     const Word16 output_frame,       /* i  : Output frame length                  Q0*/
    1111             :     const Word16 tdm_ratio_idx       /* i  : TDM ratio index                      Q0*/
    1112             : )
    1113             : {
    1114             :     Word16 i;
    1115             :     Word32 c_LR_fx, c_fx, tmp_fx, sc_fx;
    1116             :     Word16 c_q;
    1117             :     Word64 enrL_fx, enrR_fx, dotLR_fx;
    1118             :     Word32 beta_fx;
    1119             :     Word16 enrL_q, enrR_q, dotLR_q;
    1120             :     Word16 enrL_inv_q, enrR_inv_q;
    1121             :     Word16 sc_q;
    1122             :     Word16 headroom_left_enrL, headroom_left_enrR, headroom_left_dotLR;
    1123             :     Word32 temp_x_inv, temp_y_inv, energy_xy_fx;
    1124             :     Word16 res_q;
    1125             :     Word32 numer_1, numer_2, numer_3, num;
    1126             :     Word16 numer_1_q, numer_2_q, numer_3_q, num_q;
    1127             :     Word32 denom_1, denom_2, denom_3, denom;
    1128             :     Word16 denom_1_q, denom_2_q, denom_3_q, denom_q;
    1129             :     Word32 beta_sqr, one_minus_beta_sqr;
    1130        3751 :     beta_fx = tdm_ratio_tabl_fx[tdm_ratio_idx];
    1131        3751 :     move32();
    1132             : 
    1133        3751 :     enrL_fx = 0;
    1134        3751 :     move64();
    1135        3751 :     enrR_fx = 0;
    1136        3751 :     move64();
    1137        3751 :     dotLR_fx = 0;
    1138        3751 :     move64();
    1139             : 
    1140     2406951 :     FOR( i = 0; i < output_frame; i++ )
    1141             :     {
    1142     2403200 :         enrL_fx = W_add( enrL_fx, W_mult0_32_32( output_fx[0][i], output_fx[0][i] ) );   /* 2 * OUTPUT_Q */
    1143     2403200 :         enrR_fx = W_add( enrR_fx, W_mult0_32_32( output_fx[1][i], output_fx[1][i] ) );   /* 2 * OUTPUT_Q */
    1144     2403200 :         dotLR_fx = W_add( dotLR_fx, W_mult0_32_32( output_fx[0][i], output_fx[1][i] ) ); /* 2 * OUTPUT_Q */
    1145             :     }
    1146        3751 :     dotLR_fx = W_add( dotLR_fx, EPSILON_FX_SMALL );
    1147        3751 :     if ( dotLR_fx < 0 )
    1148             :     {
    1149         669 :         dotLR_fx = W_neg( dotLR_fx );
    1150             :     }
    1151        3751 :     enrL_fx = W_add( enrL_fx, EPSILON_FX_SMALL );
    1152        3751 :     enrR_fx = W_add( enrR_fx, EPSILON_FX_SMALL );
    1153             : 
    1154        3751 :     headroom_left_enrL = W_norm( enrL_fx );
    1155        3751 :     headroom_left_enrR = W_norm( enrR_fx );
    1156             : 
    1157             :     {
    1158             : 
    1159        3751 :         IF( LT_16( headroom_left_enrL, 32 ) )
    1160             :         {
    1161        3587 :             enrL_fx = W_shr( enrL_fx, sub( 32, headroom_left_enrL ) );
    1162        3587 :             enrL_q = sub( 31, sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_enrL ) ) );
    1163             :         }
    1164             :         ELSE
    1165             :         {
    1166         164 :             enrL_q = sub( 31, ( 2 * OUTPUT_Q ) );
    1167             :         }
    1168        3751 :         IF( LT_16( headroom_left_enrR, 32 ) )
    1169             :         {
    1170        3692 :             enrR_fx = W_shr( enrR_fx, sub( 32, headroom_left_enrR ) );
    1171        3692 :             enrR_q = sub( 31, sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_enrR ) ) );
    1172             :         }
    1173             :         ELSE
    1174             :         {
    1175          59 :             enrR_q = sub( 31, ( 2 * OUTPUT_Q ) );
    1176             :         }
    1177             : 
    1178        3751 :         enrL_inv_q = enrL_q;
    1179        3751 :         move16();
    1180        3751 :         enrR_inv_q = enrR_q;
    1181        3751 :         move16();
    1182             : 
    1183        3751 :         temp_x_inv = ISqrt32( W_extract_l( enrL_fx ), &enrL_inv_q );
    1184        3751 :         temp_y_inv = ISqrt32( W_extract_l( enrR_fx ), &enrR_inv_q );
    1185        3751 :         energy_xy_fx = Mpy_32_32( temp_x_inv, temp_y_inv ); /* enrL_inv_q + enrR_inv_q - 31 */
    1186        3751 :         res_q = add( enrL_inv_q, enrR_inv_q );
    1187        3751 :         headroom_left_dotLR = W_norm( dotLR_fx );
    1188        3751 :         dotLR_q = OUTPUT_Q * 2;
    1189        3751 :         move16();
    1190        3751 :         IF( LT_16( headroom_left_dotLR, 32 ) )
    1191             :         {
    1192        3643 :             dotLR_fx = W_shr( dotLR_fx, sub( 32, headroom_left_dotLR ) );
    1193        3643 :             dotLR_q = sub( dotLR_q, sub( 32, headroom_left_dotLR ) );
    1194             :         }
    1195        3751 :         dotLR_fx = Mpy_32_32( W_extract_l( dotLR_fx ), energy_xy_fx );
    1196        3751 :         dotLR_q = add( dotLR_q, sub( sub( 31, res_q ), 31 ) );
    1197        3751 :         dotLR_fx = W_shl( dotLR_fx, sub( 31, dotLR_q ) );
    1198             :     }
    1199        3751 :     c_LR_fx = extract_h( W_extract_l( dotLR_fx ) );
    1200             : 
    1201        3751 :     Word16 div_q = 0;
    1202        3751 :     move16();
    1203        3751 :     c_fx = BASOP_Util_Divide3232_Scale( W_extract_l( enrL_fx ), W_extract_l( enrR_fx ), &div_q ); /* div_q */
    1204        3751 :     c_q = add( sub( 15, div_q ), sub( enrR_q, enrL_q ) );
    1205             : 
    1206        3751 :     hCPE->hStereoTD->c_LR_LT_fx = L_add( Mpy_32_32( STEREO_TD_PS_CORR_FILT_FX, hCPE->hStereoTD->c_LR_LT_fx ),
    1207        3751 :                                          Mpy_32_32( L_sub( ONE_IN_Q31, STEREO_TD_PS_CORR_FILT_FX ), L_deposit_h( extract_l( c_LR_fx ) ) ) ); /* Q31 */
    1208        3751 :     move32();
    1209        3751 :     hCPE->hStereoCng->c_LR_LT_fx = hCPE->hStereoTD->c_LR_LT_fx; /* Q31 */
    1210        3751 :     move32();
    1211             : 
    1212        3751 :     Word16 sqrt_q = sub( 31, c_q );
    1213        3751 :     Word32 sqrt_res = Sqrt32( c_fx, &sqrt_q );
    1214        3751 :     tmp_fx = Mpy_32_32( beta_fx, L_sub( ONE_IN_Q31, beta_fx ) );
    1215        3751 :     tmp_fx = Mpy_32_32( tmp_fx, hCPE->hStereoTD->c_LR_LT_fx );
    1216        3751 :     tmp_fx = Mpy_32_32( tmp_fx, sqrt_res );
    1217        3751 :     Word16 tmp_q = sub( sub( 31, sqrt_q ), 1 ); // *2 handled with q reduction
    1218             : 
    1219        3751 :     beta_sqr = Mpy_32_32( beta_fx, beta_fx );                                                     /* Q31 */
    1220        3751 :     one_minus_beta_sqr = Mpy_32_32( L_sub( ONE_IN_Q31, beta_fx ), L_sub( ONE_IN_Q31, beta_fx ) ); /* Q31 */
    1221             : 
    1222        3751 :     numer_1 = Mpy_32_16_1( one_minus_beta_sqr, extract_l( c_fx ) ); // c_q+31-15
    1223        3751 :     numer_1_q = add( c_q, 31 - 15 );
    1224        3751 :     numer_2 = beta_sqr; // 31
    1225        3751 :     move32();
    1226        3751 :     numer_2_q = 31;
    1227        3751 :     move16();
    1228        3751 :     numer_3 = tmp_fx; // tmp_q
    1229        3751 :     move32();
    1230        3751 :     numer_3_q = tmp_q;
    1231        3751 :     move16();
    1232        3751 :     num_q = 31;
    1233        3751 :     move16();
    1234             : 
    1235        3751 :     num_q = s_min( num_q, numer_1_q );
    1236             : 
    1237        3751 :     num_q = s_min( num_q, numer_2_q );
    1238             : 
    1239        3751 :     num_q = s_min( num_q, numer_3_q );
    1240             : 
    1241        3751 :     denom_1 = Mpy_32_16_1( beta_sqr, extract_l( c_fx ) ); // c_q+31-15;
    1242        3751 :     denom_1_q = add( c_q, 31 - 15 );
    1243        3751 :     denom_2 = one_minus_beta_sqr; // 31
    1244        3751 :     move32();
    1245        3751 :     denom_2_q = 31;
    1246        3751 :     move16();
    1247        3751 :     denom_3 = tmp_fx; // tmp_q
    1248        3751 :     move32();
    1249        3751 :     denom_3_q = tmp_q;
    1250        3751 :     move16();
    1251        3751 :     denom_q = 31;
    1252        3751 :     move16();
    1253             : 
    1254        3751 :     denom_q = s_min( denom_q, denom_1_q );
    1255             : 
    1256        3751 :     denom_q = s_min( denom_q, denom_2_q );
    1257             : 
    1258        3751 :     denom_q = s_min( denom_q, denom_3_q );
    1259             : 
    1260        3751 :     num = L_add( L_add( L_shr( numer_1, sub( numer_1_q, num_q ) ), L_sub( L_shr( numer_2, sub( numer_2_q, num_q ) ), L_shr( numer_3, sub( numer_3_q, num_q ) ) ) ), DELTA_FX );         /* num_q */
    1261        3751 :     denom = L_add( L_add( L_shr( denom_1, sub( denom_1_q, denom_q ) ), L_add( L_shr( denom_2, sub( denom_2_q, denom_q ) ), L_shr( denom_3, sub( denom_3_q, denom_q ) ) ) ), DELTA_FX ); /* denom_q */
    1262        3751 :     Word16 q = 0;
    1263        3751 :     move16();
    1264        3751 :     sc_fx = BASOP_Util_Divide3232_Scale( num, denom, &q );
    1265        3751 :     sc_q = sub( sub( 15, sub( num_q, denom_q ) ), q );
    1266        3751 :     Word32 sc_thr = L_shr( sc_fx, sc_q );
    1267        3751 :     IF( GT_32( sc_thr, 4 ) )
    1268             :     {
    1269         547 :         sc_fx = MAX_WORD16;
    1270         547 :         move32();
    1271             :     }
    1272             :     ELSE
    1273             :     {
    1274        3204 :         sc_fx = L_shr( sc_fx, sub( sc_q, 13 ) );
    1275             :     }
    1276        3751 :     sqrt_q = 2;
    1277        3751 :     move16();
    1278        3751 :     sqrt_res = Sqrt32( L_shl_sat( sc_fx, 16 ), &sqrt_q );
    1279        3751 :     IF( sqrt_q < 0 )
    1280             :     {
    1281         680 :         sqrt_res = L_shr( sqrt_res, ( -sqrt_q ) );
    1282         680 :         sqrt_q = 0;
    1283         680 :         move16();
    1284             :     }
    1285        3751 :     hCPE->hStereoTD->SP_ratio_LT_fx = L_add_sat( Mpy_32_32( 1932735283, hCPE->hStereoTD->SP_ratio_LT_fx ),
    1286             :                                                  L_shl_sat( Mpy_32_32( 214748364, sqrt_res ), sqrt_q ) ); /* sqrt_q */
    1287        3751 :     move32();
    1288             : 
    1289        3751 :     IF( LT_16( hCPE->hStereoCng->nr_corr_frames, CM_INIT ) )
    1290             :     {
    1291        1757 :         hCPE->hStereoCng->nr_corr_frames = add( hCPE->hStereoCng->nr_corr_frames, 1 ); /* Q0 */
    1292        1757 :         move16();
    1293             :     }
    1294             : 
    1295        3751 :     hCPE->hStereoCng->nr_dft_frames = 0;
    1296        3751 :     move16();
    1297             : 
    1298        3751 :     return;
    1299             : }
    1300             : 
    1301             : 
    1302             : /*-------------------------------------------------------------------*
    1303             :  * FindEmEs()
    1304             :  *
    1305             :  * Find the energie ratio between the mono and the side
    1306             :  *-------------------------------------------------------------------*/
    1307             : 
    1308             : 
    1309       40452 : static void FindEmEs_fx(
    1310             :     const Word32 *ch1_fx, /* i  : Left channel          OUTPUT_Q*/
    1311             :     const Word32 *ch2_fx, /* i  : right channel         OUTPUT_Q*/
    1312             :     const Word16 len,     /* i  : length                                         Q0*/
    1313             :     Word32 *lt_es_em_fx   /* i/o: LT energy ratio                       Q24*/
    1314             : )
    1315             : {
    1316             :     Word16 i;
    1317             :     Word32 mono_i_fx;
    1318             :     Word32 es_em_fx;
    1319             :     Word32 side_i_fx;
    1320             :     Word64 ener_fx, ener_side_fx;
    1321             :     Word16 headroom_left_ener_fx, headroom_left_ener_side_fx;
    1322             :     Word16 ener_q, ener_side_q;
    1323       40452 :     ener_fx = 1;
    1324       40452 :     move64();
    1325       40452 :     ener_side_fx = 1;
    1326       40452 :     move64();
    1327             :     Word32 square_res, log_res, division_res;
    1328       40452 :     Word16 temp_q = 0;
    1329       40452 :     move16();
    1330    26006532 :     FOR( i = 0; i < len; i++ )
    1331             :     {
    1332    25966080 :         mono_i_fx = L_add( L_shr( ch1_fx[i], 1 ), L_shr( ch2_fx[i], 1 ) );
    1333    25966080 :         ener_fx = W_add( ener_fx, W_mult0_32_32( mono_i_fx, mono_i_fx ) ); /* 2 * OUTPUT_Q */
    1334    25966080 :         side_i_fx = L_sub( L_shr( ch1_fx[i], 1 ), L_shr( ch2_fx[i], 1 ) );
    1335    25966080 :         ener_side_fx = W_add( ener_side_fx, W_mult0_32_32( side_i_fx, side_i_fx ) ); /* 2 * OUTPUT_Q */
    1336             :     }
    1337       40452 :     headroom_left_ener_fx = W_norm( ener_fx );
    1338       40452 :     headroom_left_ener_side_fx = W_norm( ener_side_fx );
    1339             : 
    1340       40452 :     IF( LT_16( headroom_left_ener_fx, 32 ) )
    1341             :     {
    1342       39065 :         ener_fx = W_shr( ener_fx, sub( 32, headroom_left_ener_fx ) ); /* 2 * OUTPUT_Q - 32 * headroom_left_ener_fx */
    1343       39065 :         ener_q = sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_ener_fx ) );
    1344             :     }
    1345             :     ELSE
    1346             :     {
    1347        1387 :         ener_q = ( 2 * OUTPUT_Q );
    1348        1387 :         move16();
    1349             :     }
    1350       40452 :     IF( LT_16( headroom_left_ener_side_fx, 32 ) )
    1351             :     {
    1352       37909 :         ener_side_fx = W_shr( ener_side_fx, sub( 32, headroom_left_ener_side_fx ) ); /* 2 * OUTPUT_Q - 32 * headroom_left_ener_fx */
    1353       37909 :         ener_side_q = sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_ener_side_fx ) );
    1354             :     }
    1355             :     ELSE
    1356             :     {
    1357        2543 :         ener_side_q = ( 2 * OUTPUT_Q );
    1358        2543 :         move16();
    1359             :     }
    1360             : 
    1361             :     /**es_em = 10 * ( log10( sqrt( ener_side / len ) ) - log10( sqrt( ener / len ) ) ); */
    1362       40452 :     division_res = BASOP_Util_Divide3232_Scale( W_extract_l( ener_side_fx ), W_extract_l( ener_fx ), &temp_q );
    1363       40452 :     temp_q = sub( temp_q, sub( ener_side_q, ener_q ) );
    1364       40452 :     square_res = Sqrt32( L_deposit_h( extract_l( division_res ) ), &temp_q ); /* temp_q */
    1365       40452 :     IF( temp_q < 0 )
    1366             :     {
    1367       19803 :         square_res = L_shr( square_res, ( -temp_q ) );
    1368       19803 :         temp_q = 0;
    1369       19803 :         move16();
    1370             :     }
    1371       40452 :     log_res = BASOP_Util_Log2( square_res );
    1372       40452 :     es_em_fx = Mpy_32_32( log_res, 1616107501 ); // 25+30-31
    1373             :     /* long-term estimate */
    1374       40452 :     *lt_es_em_fx = L_add( Mpy_32_32( 858993459, *lt_es_em_fx ), Mpy_32_32( 1288490188, es_em_fx ) ); /* Q24 */
    1375       40452 :     move32();
    1376       40452 :     return;
    1377             : }
    1378             : 
    1379             : 
    1380             : /*-------------------------------------------------------------------*
    1381             :  * Function stereo_cna_update_params()
    1382             :  *
    1383             :  * compute LR correlation and update long-term parameters for stereo CNA
    1384             :  *-------------------------------------------------------------------*/
    1385             : 
    1386      145402 : void stereo_cna_update_params_fx(
    1387             :     CPE_DEC_HANDLE hCPE,             /* i/o: CPE decoder structure                              */
    1388             :     Word32 *output_fx[CPE_CHANNELS], /* i  : Output signal                              OUTPUT_Q*/
    1389             :     const Word16 output_frame,       /* i  : Output frame length                          Q0*/
    1390             :     const Word16 tdm_ratio_idx       /* i  : TDM ratio index                              Q0*/
    1391             : )
    1392             : {
    1393             :     Word16 i;
    1394             :     Word64 enrL_fx, enrR_fx, dotLR_fx;
    1395             :     Word32 c_fx, c_LR_fx, c_ILD_fx;
    1396             :     Decoder_State **sts;
    1397             :     HANDLE_FD_CNG_DEC hFdCngDec;
    1398             :     Word16 dotLR_fx_q;
    1399             :     Word32 temp_x_inv, temp_y_inv, energy_xy_fx;
    1400             :     Word16 headroom_left_x, headroom_left_y;
    1401             :     Word16 headroom_left_dotLR_fx;
    1402             :     Word16 x_q, y_q, c_q;
    1403             :     Word16 x_inv_q, y_inv_q;
    1404             :     Word16 temp_res_q;
    1405      145402 :     sts = hCPE->hCoreCoder;
    1406             : 
    1407      145402 :     hFdCngDec = sts[0]->hFdCngDec;
    1408             : 
    1409      145402 :     IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) )
    1410             :     {
    1411       59047 :         IF( GT_16( hCPE->nchan_out, 1 ) )
    1412             :         {
    1413       36701 :             FindEmEs_fx( output_fx[0], output_fx[1], output_frame, &hCPE->lt_es_em_fx );
    1414             :         }
    1415             :         ELSE
    1416             :         {
    1417       22346 :             hCPE->lt_es_em_fx = 0;
    1418       22346 :             move32();
    1419             :         }
    1420             :     }
    1421       86355 :     ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) )
    1422             :     {
    1423        3751 :         FindEmEs_fx( output_fx[0], output_fx[1], output_frame, &hCPE->lt_es_em_fx );
    1424             : 
    1425             : 
    1426        3751 :         hCPE->hStereoCng->first_SID_after_TD = 1; /* Q0 */
    1427        3751 :         move16();
    1428        3751 :         stereo_cng_compute_LRcorr_fx( hCPE, output_fx, output_frame, tdm_ratio_idx );
    1429             :     }
    1430             :     ELSE
    1431             :     {
    1432       82604 :         return;
    1433             :     }
    1434             : 
    1435       62798 :     enrL_fx = 0;
    1436       62798 :     move64();
    1437       62798 :     enrR_fx = 0;
    1438       62798 :     move64();
    1439       62798 :     dotLR_fx = 0;
    1440       62798 :     move64();
    1441             : 
    1442       62798 :     test();
    1443       62798 :     test();
    1444       62798 :     test();
    1445       62798 :     IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) || ( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && GT_32( sts[0]->core_brate, SID_2k40 ) && ( sts[0]->VAD == 0 ) ) )
    1446             :     {
    1447        6853 :         IF( EQ_16( hCPE->nchan_out, 1 ) )
    1448             :         {
    1449             : #ifdef OPT_STEREO_32KBPS_V1
    1450        2851 :             c_LR_fx = MAX_32;
    1451             : #else  /* OPT_STEREO_32KBPS_V1 */
    1452             :             c_LR_fx = MAX_WORD16;
    1453             : #endif /* OPT_STEREO_32KBPS_V1 */
    1454        2851 :             move32();
    1455        2851 :             c_ILD_fx = 0;
    1456        2851 :             move32();
    1457             :         }
    1458             :         ELSE
    1459             :         {
    1460     2730722 :             FOR( i = 0; i < output_frame; i++ )
    1461             :             {
    1462     2726720 :                 enrL_fx = W_add( enrL_fx, W_mult0_32_32( output_fx[0][i], output_fx[0][i] ) );   /* 2 * OUTPUT_Q */
    1463     2726720 :                 enrR_fx = W_add( enrR_fx, W_mult0_32_32( output_fx[1][i], output_fx[1][i] ) );   /* 2 * OUTPUT_Q */
    1464     2726720 :                 dotLR_fx = W_add( dotLR_fx, W_mult0_32_32( output_fx[0][i], output_fx[1][i] ) ); /* 2 * OUTPUT_Q */
    1465             :             }
    1466        4002 :             dotLR_fx = W_add( dotLR_fx, EPSILON_FX_SMALL );
    1467        4002 :             if ( dotLR_fx < 0 )
    1468             :             {
    1469         743 :                 dotLR_fx = W_neg( dotLR_fx );
    1470             :             }
    1471        4002 :             enrL_fx = W_add( enrL_fx, EPSILON_FX_SMALL );
    1472        4002 :             enrR_fx = W_add( enrR_fx, EPSILON_FX_SMALL );
    1473        4002 :             headroom_left_x = W_norm( enrL_fx );
    1474        4002 :             headroom_left_y = W_norm( enrR_fx );
    1475             : 
    1476        4002 :             IF( LT_16( headroom_left_x, 32 ) )
    1477             :             {
    1478        3877 :                 enrL_fx = W_shr( enrL_fx, sub( 32, headroom_left_x ) ); /* 2 * OUTPUT_Q - 32 * headroom_left_x */
    1479        3877 :                 x_q = sub( 31, sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_x ) ) );
    1480             :             }
    1481             :             ELSE
    1482             :             {
    1483         125 :                 x_q = sub( 31, ( 2 * OUTPUT_Q ) );
    1484             :             }
    1485        4002 :             IF( LT_16( headroom_left_y, 32 ) )
    1486             :             {
    1487        3959 :                 enrR_fx = W_shr( enrR_fx, sub( 32, headroom_left_y ) ); /* 2 * OUTPUT_Q - 32 * headroom_left_x */
    1488        3959 :                 y_q = sub( 31, sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_y ) ) );
    1489             :             }
    1490             :             ELSE
    1491             :             {
    1492          43 :                 y_q = sub( 31, ( 2 * OUTPUT_Q ) );
    1493             :             }
    1494             : 
    1495        4002 :             x_inv_q = x_q;
    1496        4002 :             move16();
    1497        4002 :             y_inv_q = y_q;
    1498        4002 :             move16();
    1499             : 
    1500        4002 :             temp_x_inv = ISqrt32( W_extract_l( enrL_fx ), &x_inv_q );
    1501        4002 :             temp_y_inv = ISqrt32( W_extract_l( enrR_fx ), &y_inv_q );
    1502        4002 :             energy_xy_fx = Mpy_32_32( temp_x_inv, temp_y_inv ); /* x_inv_q + y_inv_q */
    1503        4002 :             temp_res_q = add( x_inv_q, y_inv_q );
    1504        4002 :             headroom_left_dotLR_fx = W_norm( dotLR_fx );
    1505        4002 :             dotLR_fx_q = OUTPUT_Q * 2;
    1506        4002 :             move16();
    1507        4002 :             IF( LT_16( headroom_left_dotLR_fx, 32 ) )
    1508             :             {
    1509        3922 :                 dotLR_fx = W_shr( dotLR_fx, sub( 32, headroom_left_dotLR_fx ) ); /* dotLR_fx_q - (32 * headroom_left_dotLR_fx) */
    1510        3922 :                 dotLR_fx_q = sub( dotLR_fx_q, sub( 32, headroom_left_dotLR_fx ) );
    1511             :             }
    1512        4002 :             dotLR_fx = Mpy_32_32( W_extract_l( dotLR_fx ), energy_xy_fx ); /* dotLR_fx_q + ((31 - temp_res_q) - 31)) */
    1513        4002 :             dotLR_fx_q = add( dotLR_fx_q, sub( sub( 31, temp_res_q ), 31 ) );
    1514        4002 :             dotLR_fx = W_deposit32_l( L_shl_sat( W_extract_l( dotLR_fx ), sub( 31, dotLR_fx_q ) ) ); /* Q31 */
    1515             :                                                                                                      /* estimate L/R correlation factor and ILD in time domain */
    1516             : #ifdef OPT_STEREO_32KBPS_V1
    1517        4002 :             c_LR_fx = W_extract_l( dotLR_fx ); /* Q31 */
    1518             : #else                                          /* OPT_STEREO_32KBPS_V1 */
    1519             :             c_LR_fx = extract_h( W_extract_l( dotLR_fx ) ); /* Q15 */
    1520             : #endif                                         /* OPT_STEREO_32KBPS_V1 */
    1521             : 
    1522        4002 :             temp_res_q = 0;
    1523        4002 :             move16();
    1524        4002 :             c_fx = BASOP_Util_Divide3232_Scale( W_extract_l( enrL_fx ), W_extract_l( enrR_fx ), &temp_res_q );
    1525        4002 :             c_q = add( sub( 15, temp_res_q ), sub( y_q, x_q ) );
    1526             : 
    1527             :             Word32 one_in_c_q;
    1528        4002 :             IF( GT_16( c_q, 31 ) )
    1529             :             {
    1530          69 :                 c_q = 31;
    1531          69 :                 move16();
    1532          69 :                 c_fx = L_shr_sat( c_fx, sub( c_q, 31 ) ); /* Q31 */
    1533          69 :                 one_in_c_q = ONE_IN_Q31;
    1534          69 :                 move32();
    1535             :             }
    1536             :             ELSE
    1537             :             {
    1538        3933 :                 one_in_c_q = L_shl_sat( 1, c_q );
    1539             :             }
    1540             : 
    1541        4002 :             Word32 num_c_fx = L_sub_sat( c_fx, one_in_c_q );
    1542        4002 :             Word32 denom_c_fx = L_add_sat( c_fx, one_in_c_q );
    1543        4002 :             Word16 num_c_headroom = norm_l( L_sub_sat( c_fx, one_in_c_q ) );
    1544        4002 :             Word16 denom_c_headroom = norm_l( L_add_sat( c_fx, one_in_c_q ) );
    1545        4002 :             Word16 min_headroom_left = s_min( num_c_headroom, denom_c_headroom );
    1546        4002 :             move16();
    1547        4002 :             temp_res_q = 0;
    1548        4002 :             move16();
    1549        4002 :             c_ILD_fx = BASOP_Util_Divide3232_Scale( L_shl_sat( num_c_fx, min_headroom_left ), L_shl_sat( denom_c_fx, min_headroom_left ), &temp_res_q ); /* temp_res_q */
    1550        4002 :             IF( temp_res_q < 0 )
    1551             :             {
    1552        1974 :                 c_ILD_fx = L_shr( c_ILD_fx, negate( temp_res_q ) );
    1553             :             }
    1554             :         }
    1555             : 
    1556             :         /* update of long-term ILD and LR correlation factors for stereo CNA */
    1557        6853 :         IF( !hFdCngDec->first_cna_noise_updated )
    1558             :         {
    1559             : #ifdef OPT_STEREO_32KBPS_V1
    1560        2543 :             hFdCngDec->cna_LR_LT_fx = extract_h( c_LR_fx );
    1561             : #else  /* OPT_STEREO_32KBPS_V1 */
    1562             :             hFdCngDec->cna_LR_LT_fx = extract_l( c_LR_fx );
    1563             : #endif /* OPT_STEREO_32KBPS_V1 */
    1564        2543 :             move16();
    1565        2543 :             hFdCngDec->cna_ILD_LT_fx = extract_l( c_ILD_fx );
    1566        2543 :             move16();
    1567             :         }
    1568             :         ELSE
    1569             :         {
    1570             : #ifdef OPT_STEREO_32KBPS_V1
    1571        4310 :             hFdCngDec->cna_LR_LT_fx = extract_h( L_add_sat( Mpy_32_16_1( STEREO_CNA_LR_CORR_LT_FILT_FX, hFdCngDec->cna_LR_LT_fx ),
    1572             :                                                             Mpy_32_32( ONE_IN_Q31 - STEREO_CNA_LR_CORR_LT_FILT_FX, c_LR_fx ) ) ); /* Q31 */
    1573             : #else                                                                                                                             /* OPT_STEREO_32KBPS_V1 */
    1574             :             hFdCngDec->cna_LR_LT_fx = extract_h( L_add_sat( Mpy_32_16_1( STEREO_CNA_LR_CORR_LT_FILT_FX, hFdCngDec->cna_LR_LT_fx ),
    1575             :                                                             Mpy_32_16_1( L_sub( ONE_IN_Q31, STEREO_CNA_LR_CORR_LT_FILT_FX ), extract_l( c_LR_fx ) ) ) ); /* Q31 */
    1576             : #endif                                                                                                                            /* OPT_STEREO_32KBPS_V1 */
    1577        4310 :             move16();
    1578             : 
    1579        4310 :             hFdCngDec->cna_ILD_LT_fx = extract_h( L_add_sat( Mpy_32_16_1( STEREO_CNA_ILD_LT_FILT_FX, hFdCngDec->cna_ILD_LT_fx ),
    1580        4310 :                                                              Mpy_32_16_1( L_sub( ONE_IN_Q31, STEREO_CNA_ILD_LT_FILT_FX ), extract_l( c_ILD_fx ) ) ) ); /* Q31 */
    1581        4310 :             move16();
    1582             :         }
    1583             : 
    1584        6853 :         set16_fx( hFdCngDec->cna_g_state_fx, hFdCngDec->cna_ILD_LT_fx, hFdCngDec->cna_nbands );
    1585        6853 :         set16_fx( hFdCngDec->cna_cm_fx, hFdCngDec->cna_LR_LT_fx, hFdCngDec->cna_nbands );
    1586             :     }
    1587             : 
    1588             : 
    1589             :     /* Soft VAD for stereo CNA */
    1590       62798 :     test();
    1591       62798 :     IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) || EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) )
    1592             :     {
    1593       62798 :         IF( !hFdCngDec->first_cna_noise_updated )
    1594             :         {
    1595       31174 :             hFdCngDec->cna_act_fact_fx = 0;
    1596       31174 :             move16();
    1597             :         }
    1598             :         ELSE
    1599             :         {
    1600       31624 :             IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) )
    1601             :             {
    1602             :                 /* quickly decrease in TD stereo mode */
    1603        1686 :                 hFdCngDec->cna_act_fact_fx = extract_h( Mpy_32_16_1( 1503238553, hFdCngDec->cna_act_fact_fx ) ); /* Q15 */
    1604        1686 :                 move16();
    1605             :             }
    1606       29938 :             ELSE IF( GT_32( L_mult0( sts[0]->VAD, MAX_WORD16 ), hFdCngDec->cna_act_fact_fx ) ) // VAD is one bit
    1607             :             {
    1608             :                 /* quickly increase during active frames in DFT stereo mode */
    1609       16977 :                 hFdCngDec->cna_act_fact_fx = extract_h( L_add( Mpy_32_16_1( 1503238553, hFdCngDec->cna_act_fact_fx ), ( 644245094 * sts[0]->VAD ) ) ); /* Q15 */
    1610       16977 :                 move16();
    1611             :             }
    1612             :             ELSE
    1613             :             {
    1614             :                 /* slowly decrease during inactive frames in DFT stereo mode */
    1615       12961 :                 hFdCngDec->cna_act_fact_fx = extract_h( L_add( Mpy_32_16_1( 2040109440, hFdCngDec->cna_act_fact_fx ), ( 107374184 * sts[0]->VAD ) ) ); /* Q15 */
    1616       12961 :                 move16();
    1617             :             }
    1618             :         }
    1619             :     }
    1620             : 
    1621       62798 :     return;
    1622             : }
    1623             : 
    1624             : 
    1625             : /*-------------------------------------------------------------------
    1626             :  * stereo_cng_init_dec()
    1627             :  *
    1628             :  * Initialized stereo CNG
    1629             :  *-------------------------------------------------------------------*/
    1630             : 
    1631         764 : void stereo_cng_init_dec_fx(
    1632             :     STEREO_CNG_DEC_HANDLE hStereoCng, /* i/o: stereo CNG decoder structure                                                                        */
    1633             :     const Word16 *frameSize           /* i  : pointer to frameSize of channel 0 to be used for channel 1        Q0*/
    1634             : )
    1635             : {
    1636         764 :     hStereoCng->prev_sid_nodata = 0;
    1637         764 :     move16();
    1638         764 :     set16_fx( hStereoCng->coh_fx, 8192 /*0.5 in Q14*/, STEREO_DFT_BAND_MAX + 1 );
    1639         764 :     set16_fx( hStereoCng->cm_fx, 0, STEREO_DFT_BAND_MAX );
    1640         764 :     hStereoCng->first_SID = 1;
    1641         764 :     move16();
    1642         764 :     hStereoCng->first_SID_after_TD = 0;
    1643         764 :     move16();
    1644         764 :     hStereoCng->active_frame_counter = 0;
    1645         764 :     move16();
    1646         764 :     hStereoCng->xfade_frame_counter = 0;
    1647         764 :     move16();
    1648         764 :     hStereoCng->xfade_length = 0;
    1649         764 :     move16();
    1650         764 :     hStereoCng->nr_dft_frames = 0;
    1651         764 :     move16();
    1652         764 :     hStereoCng->nr_corr_frames = 0;
    1653         764 :     move16();
    1654         764 :     hStereoCng->nr_sid_frames = 0;
    1655         764 :     move16();
    1656         764 :     set16_fx( hStereoCng->olapBufferSynth22_fx, 0, FFTLEN );
    1657         764 :     hStereoCng->flag_cna_fade = 0;
    1658         764 :     move16();
    1659         764 :     set16_fx( hStereoCng->maskingNoiseS_fx, 0, L_FRAME16k );
    1660         764 :     hStereoCng->enableSecCNA = 0;
    1661         764 :     move16();
    1662         764 :     hStereoCng->c_PS_LT_fx = 16384; /* 0.5 in Q15 */
    1663         764 :     move16();
    1664         764 :     hStereoCng->frameSize = frameSize;
    1665         764 :     hStereoCng->last_act_element_mode = IVAS_CPE_DFT;
    1666         764 :     move16();
    1667             : 
    1668         764 :     return;
    1669             : }

Generated by: LCOV version 1.14