LCOV - code coverage report
Current view: top level - lib_com - fd_cng_com_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ da9cc8ead0679b4682d329fdff98cf1616159273 Lines: 1564 1690 92.5 %
Date: 2025-10-13 22:24:20 Functions: 29 32 90.6 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <assert.h>
       6             : #include <stdint.h>
       7             : #include "options.h"
       8             : #include "basop_util.h"
       9             : #include "options.h"
      10             : #include "rom_basop_util.h"
      11             : #include "rom_com.h"
      12             : #include "prot_fx.h"
      13             : #include "prot_fx_enc.h"
      14             : #include "ivas_prot_fx.h"
      15             : 
      16             : #define FFT_SCALING_512 1073741824 // Q22
      17             : #define FFT_SCALING_640 1342177280 // Q22
      18             : 
      19             : #define DELTA_SHIFT      2
      20             : #define DELTA_SHIFT_LD64 67108864l /*DELTA_SHIFT/64.0 Q31*/
      21             : #define CNG_HS           4         /* 4 bit headroom for dot product */
      22             : #define CNG_S            6         /* 1 sign bit, 6 bit integer part, 9 bit frational part for input and output data */
      23             : 
      24             : 
      25             : /*-------------------------------------------------------------------
      26             :  * Local function prototypes
      27             :  *-------------------------------------------------------------------*/
      28             : static void getmidbands( const Word16 *part, const Word16 npart, Word16 *midband, Word16 *psize, Word16 *psize_norm, Word16 *psize_norm_exp, Word16 *psize_inv );
      29             : 
      30             : 
      31             : /*-------------------------------------------------------------------
      32             :  * createFdCngCom()
      33             :  *
      34             :  * Create an instance of type FD_CNG_COM
      35             :  *-------------------------------------------------------------------*/
      36        7619 : ivas_error createFdCngCom_fx(
      37             :     HANDLE_FD_CNG_COM *hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
      38             : )
      39             : {
      40             :     HANDLE_FD_CNG_COM hs;
      41             : 
      42             :     /* Allocate memory */
      43        7619 :     hs = (HANDLE_FD_CNG_COM) malloc( sizeof( FD_CNG_COM ) );
      44             : 
      45        7619 :     if ( hs == NULL )
      46             :     {
      47           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD CNG COM" );
      48             :     }
      49             : 
      50        7619 :     *hFdCngCom = hs;
      51             : 
      52        7619 :     return IVAS_ERR_OK;
      53             : }
      54             : /*-------------------------------------------------------------------
      55             :  * initFdCngCom()
      56             :  *
      57             :  *
      58             :  *-------------------------------------------------------------------*/
      59             : 
      60        7136 : void ivas_initFdCngCom_fx( HANDLE_FD_CNG_COM hFdCngCom, Word16 scale )
      61             : {
      62             :     /* Calculate CLDFB scaling factor */
      63             :     /* shl(i_mult2(scale, scale), 3) does not fit in 16 bit */
      64             :     /*hFdCngCom->scalingFactor = div_s(1, shl(i_mult2(scale, scale), 3));*/
      65        7136 :     assert( 2048 /*1.0/(1<<4) Q15*/ < mult( scale, scale ) );
      66             :     /* Exponent invScalingFactor: -16 = -(2*7 (scale) + 2 (8.0) */
      67        7136 :     hFdCngCom->invScalingFactor = shl( mult( scale, scale ), 1 );
      68             :     /* Exponent scalingFactor: -15 = -(2*7 (scale) + 2 (8.0) - 1 (1.0)) */
      69        7136 :     hFdCngCom->scalingFactor = div_s( 0x4000, hFdCngCom->invScalingFactor );
      70             : 
      71             :     /* Initialize the overlap-add */
      72        7136 :     set16_fx( hFdCngCom->timeDomainBuffer, 0, L_FRAME16k );
      73        7136 :     hFdCngCom->olapBufferAna = NULL;
      74        7136 :     set16_fx( hFdCngCom->olapBufferAna_fx, 0, FFTLEN );
      75             : 
      76        7136 :     move16();
      77        7136 :     set16_fx( hFdCngCom->olapBufferSynth, 0, FFTLEN );
      78        7136 :     hFdCngCom->olapBufferSynth2 = NULL;
      79        7136 :     move16();
      80             : 
      81             :     /* Initialize the comfort noise generation */
      82        7136 :     set32_fx( hFdCngCom->fftBuffer, 0, FFTLEN );
      83        7136 :     set32_fx( hFdCngCom->cngNoiseLevel, 0, FFTCLDFBLEN );
      84        7136 :     set16_fx( &hFdCngCom->cngNoiseLevelExp, 0, 1 );
      85             : 
      86             :     /* Initialize quantizer */
      87        7136 :     set32_fx( hFdCngCom->sidNoiseEst, 0, NPART );
      88        7136 :     set16_fx( &hFdCngCom->sidNoiseEstExp, 0, 1 );
      89        7136 :     set16_fx( hFdCngCom->A_cng, 0, M + 1 );
      90        7136 :     hFdCngCom->A_cng[0] = 4096 /*1.f Q12*/; /* 3Q12 */
      91        7136 :     move16();
      92             : 
      93             :     /* Set some counters and flags */
      94        7136 :     hFdCngCom->inactive_frame_counter = 0; /* Either SID or zero frames */
      95        7136 :     move16();
      96        7136 :     hFdCngCom->active_frame_counter = 0;
      97        7136 :     move16();
      98        7136 :     hFdCngCom->frame_type_previous = ACTIVE_FRAME;
      99        7136 :     move16();
     100        7136 :     hFdCngCom->flag_noisy_speech = 0;
     101        7136 :     move16();
     102        7136 :     hFdCngCom->likelihood_noisy_speech = 0;
     103        7136 :     move16();
     104        7136 :     hFdCngCom->numCoreBands = 0;
     105        7136 :     move16();
     106        7136 :     hFdCngCom->stopBand = 0;
     107        7136 :     move16();
     108        7136 :     hFdCngCom->startBand = 0;
     109        7136 :     move16();
     110        7136 :     hFdCngCom->stopFFTbin = 0;
     111        7136 :     move16();
     112        7136 :     hFdCngCom->frameSize = 0;
     113        7136 :     move16();
     114        7136 :     hFdCngCom->fftlen = 0;
     115        7136 :     move16();
     116        7136 :     hFdCngCom->seed = 0;
     117        7136 :     move16();
     118        7136 :     hFdCngCom->seed2 = 1;
     119        7136 :     move16();
     120        7136 :     hFdCngCom->seed3 = 2;
     121        7136 :     move16();
     122        7136 :     hFdCngCom->CngBitrate = -1;
     123        7136 :     move16();
     124        7136 :     hFdCngCom->olapBufferSynth_exp = 0;
     125        7136 :     move16();
     126             : 
     127             :     /* Initialize noise estimation algorithm */
     128        7136 :     set32_fx( hFdCngCom->periodog, 0, PERIODOGLEN );
     129        7136 :     mhvals( MSNUMSUBFR * MSSUBFRLEN, &( hFdCngCom->msM_win ) );
     130        7136 :     mhvals( MSSUBFRLEN, &( hFdCngCom->msM_subwin ) );
     131        7136 :     set32_fx( hFdCngCom->msPeriodogSum, 0, 2 );
     132        7136 :     hFdCngCom->msPeriodogSum_exp[0] = 0;
     133        7136 :     move16();
     134        7136 :     hFdCngCom->msPeriodogSum_exp[1] = 0;
     135        7136 :     move16();
     136        7136 :     set32_fx( hFdCngCom->msPsdSum, 0, 2 );
     137        7136 :     set16_fx( hFdCngCom->msSlope, 0, 2 );
     138        7136 :     set32_fx( hFdCngCom->msQeqInvAv, 0, 2 );
     139        7136 :     hFdCngCom->msQeqInvAv_exp[0] = 0;
     140        7136 :     move16();
     141        7136 :     hFdCngCom->msQeqInvAv_exp[1] = 0;
     142        7136 :     move16();
     143        7136 :     hFdCngCom->msFrCnt_init_counter = 0;
     144        7136 :     move16();
     145        7136 :     hFdCngCom->msFrCnt_init_thresh = 1;
     146        7136 :     move16();
     147        7136 :     hFdCngCom->init_old = 0;
     148        7136 :     move16();
     149        7136 :     hFdCngCom->offsetflag = 0;
     150        7136 :     move16();
     151        7136 :     hFdCngCom->msFrCnt = MSSUBFRLEN;
     152        7136 :     move16();
     153        7136 :     hFdCngCom->msMinBufferPtr = 0;
     154        7136 :     move16();
     155        7136 :     hFdCngCom->msAlphaCor[0] = 644245120l /*0.3f Q31*/;
     156        7136 :     move16();
     157        7136 :     hFdCngCom->msAlphaCor[1] = 644245120l /*0.3f Q31*/;
     158        7136 :     move16();
     159        7136 :     set16_fx( hFdCngCom->psize, 0, NPART );
     160             :     /* Initialize exponents */
     161        7136 :     hFdCngCom->exp_cldfb_periodog = 0;
     162        7136 :     move16();
     163             : 
     164        7136 :     hFdCngCom->coherence_fx = 16384; /* 0.5 in Q15 */
     165        7136 :     move16();
     166             : 
     167        7136 :     set32_fx( hFdCngCom->olapBufferSynth_fx, 0, FFTLEN );
     168        7136 :     set32_fx( hFdCngCom->olapBufferSynth2_fx, 0, FFTLEN );
     169        7136 :     set32_fx( hFdCngCom->exc_cng_32fx, 0, L_FRAME16k );
     170        7136 :     set16_fx( hFdCngCom->exc_cng, 0, L_FRAME16k );
     171             : 
     172        7136 :     return;
     173             : }
     174         483 : void initFdCngCom( HANDLE_FD_CNG_COM hFdCngCom, Word16 scale )
     175             : {
     176             :     /* Calculate CLDFB scaling factor */
     177             :     /* shl(i_mult2(scale, scale), 3) does not fit in 16 bit */
     178             :     /*hFdCngCom->scalingFactor = div_s(1, shl(i_mult2(scale, scale), 3));*/
     179         483 :     assert( 2048 /*1.0/(1<<4) Q15*/ < mult( scale, scale ) );
     180             :     /* Exponent invScalingFactor: -16 = -(2*7 (scale) + 2 (8.0) */
     181         483 :     hFdCngCom->invScalingFactor = shl( mult( scale, scale ), 1 );
     182         483 :     move16();
     183             :     /* Exponent scalingFactor: -15 = -(2*7 (scale) + 2 (8.0) - 1 (1.0)) */
     184         483 :     hFdCngCom->scalingFactor = div_s( 0x4000, hFdCngCom->invScalingFactor );
     185         483 :     move16();
     186             : 
     187             :     /* Initialize the overlap-add */
     188         483 :     set16_fx( hFdCngCom->timeDomainBuffer, 0, L_FRAME16k );
     189         483 :     hFdCngCom->olapBufferAna = NULL;
     190         483 :     set16_fx( hFdCngCom->olapBufferAna_fx, 0, FFTLEN );
     191             : 
     192         483 :     set16_fx( hFdCngCom->olapBufferSynth, 0, FFTLEN );
     193         483 :     hFdCngCom->olapBufferSynth2 = NULL;
     194             : 
     195             :     /* Initialize the comfort noise generation */
     196         483 :     set32_fx( hFdCngCom->fftBuffer, 0, FFTLEN );
     197         483 :     set32_fx( hFdCngCom->cngNoiseLevel, 0, FFTCLDFBLEN );
     198         483 :     set16_fx( &hFdCngCom->cngNoiseLevelExp, 0, 1 );
     199             : 
     200             :     /* Initialize quantizer */
     201         483 :     set32_fx( hFdCngCom->sidNoiseEst, 0, NPART );
     202         483 :     set16_fx( &hFdCngCom->sidNoiseEstExp, 0, 1 );
     203         483 :     set16_fx( hFdCngCom->A_cng, 0, M + 1 );
     204         483 :     hFdCngCom->A_cng[0] = 4096 /*1.f Q12*/; /* 3Q12 */
     205         483 :     move16();
     206             : 
     207             :     /* Set some counters and flags */
     208         483 :     hFdCngCom->inactive_frame_counter = 0; /* Either SID or zero frames */
     209         483 :     move16();
     210         483 :     hFdCngCom->active_frame_counter = 0;
     211         483 :     move16();
     212         483 :     hFdCngCom->frame_type_previous = ACTIVE_FRAME;
     213         483 :     move16();
     214         483 :     hFdCngCom->flag_noisy_speech = 0;
     215         483 :     move16();
     216         483 :     hFdCngCom->likelihood_noisy_speech = 0;
     217         483 :     move16();
     218         483 :     hFdCngCom->numCoreBands = 0;
     219         483 :     move16();
     220         483 :     hFdCngCom->stopBand = 0;
     221         483 :     move16();
     222         483 :     hFdCngCom->startBand = 0;
     223         483 :     move16();
     224         483 :     hFdCngCom->stopFFTbin = 0;
     225         483 :     move16();
     226         483 :     hFdCngCom->frameSize = 0;
     227         483 :     move16();
     228         483 :     hFdCngCom->fftlen = 0;
     229         483 :     move16();
     230         483 :     hFdCngCom->seed = 0;
     231         483 :     move16();
     232             :     // hFdCngCom->seed2 = 1;
     233             :     // move16();
     234             :     // hFdCngCom->seed3 = 2;
     235             :     // move16();
     236         483 :     hFdCngCom->CngBitrate = -1;
     237         483 :     move16();
     238             : 
     239             :     /* Initialize noise estimation algorithm */
     240         483 :     set32_fx( hFdCngCom->periodog, 0, PERIODOGLEN );
     241         483 :     mhvals( MSNUMSUBFR * MSSUBFRLEN, &( hFdCngCom->msM_win ) );
     242         483 :     mhvals( MSSUBFRLEN, &( hFdCngCom->msM_subwin ) );
     243         483 :     set32_fx( hFdCngCom->msPeriodogSum, 0, 2 );
     244         483 :     hFdCngCom->msPeriodogSum_exp[0] = 0;
     245         483 :     move16();
     246         483 :     hFdCngCom->msPeriodogSum_exp[1] = 0;
     247         483 :     move16();
     248         483 :     set32_fx( hFdCngCom->msPsdSum, 0, 2 );
     249         483 :     set16_fx( hFdCngCom->msSlope, 0, 2 );
     250         483 :     set32_fx( hFdCngCom->msQeqInvAv, 0, 2 );
     251         483 :     hFdCngCom->msQeqInvAv_exp[0] = 0;
     252         483 :     move16();
     253         483 :     hFdCngCom->msQeqInvAv_exp[1] = 0;
     254         483 :     move16();
     255         483 :     hFdCngCom->msFrCnt_init_counter = 0;
     256         483 :     move16();
     257         483 :     hFdCngCom->msFrCnt_init_thresh = 1;
     258         483 :     move16();
     259         483 :     hFdCngCom->init_old = 0;
     260         483 :     move16();
     261         483 :     hFdCngCom->offsetflag = 0;
     262         483 :     move16();
     263         483 :     hFdCngCom->msFrCnt = MSSUBFRLEN;
     264         483 :     move16();
     265         483 :     hFdCngCom->msMinBufferPtr = 0;
     266         483 :     move16();
     267         483 :     hFdCngCom->msAlphaCor[0] = 644245120l /*0.3f Q31*/;
     268         483 :     move16();
     269         483 :     hFdCngCom->msAlphaCor[1] = 644245120l /*0.3f Q31*/;
     270         483 :     move16();
     271         483 :     set16_fx( hFdCngCom->psize, 0, NPART );
     272             :     /* Initialize exponents */
     273         483 :     hFdCngCom->exp_cldfb_periodog = 0;
     274         483 :     move16();
     275             : 
     276         483 :     return;
     277             : }
     278             : 
     279             : /*-------------------------------------------------------------------
     280             :  * deleteFdCngCom()
     281             :  *
     282             :  * Delete an instance of type FD_CNG_COM
     283             :  *-------------------------------------------------------------------*/
     284        7619 : void deleteFdCngCom_fx( HANDLE_FD_CNG_COM *hFdCngCom ) /* i/o: Contains the variables related to the CLDFB-based CNG process */
     285             : {
     286             :     HANDLE_FD_CNG_COM hsCom;
     287        7619 :     hsCom = *hFdCngCom;
     288        7619 :     move16();
     289        7619 :     IF( hsCom != NULL )
     290             :     {
     291        7619 :         free( hsCom );
     292        7619 :         *hFdCngCom = NULL;
     293        7619 :         move16();
     294             :     }
     295        7619 : }
     296             : 
     297             : /*-------------------------------------------------------------------
     298             :  * initPartitions()
     299             :  *
     300             :  * Initialize the spectral partitioning
     301             :  *-------------------------------------------------------------------*/
     302     1173160 : void initPartitions(
     303             :     const Word16 *part_in,
     304             :     const Word16 npart_in,
     305             :     const Word16 startBand,
     306             :     const Word16 stopBand,
     307             :     Word16 *part_out,
     308             :     Word16 *npart_out,
     309             :     Word16 *midband,
     310             :     Word16 *psize,
     311             :     Word16 *psize_norm,
     312             :     Word16 *psize_norm_exp,
     313             :     Word16 *psize_inv,
     314             :     const Word16 stopBandFR )
     315             : {
     316             :     Word16 i, j, len_out, tmp16;
     317             : 
     318             : 
     319     1173160 :     IF( part_in != NULL )
     320             :     {
     321     1173160 :         len_out = 0;
     322     1173160 :         move16();
     323     1173160 :         IF( GT_16( stopBandFR, startBand ) )
     324             :         {
     325      568589 :             len_out = sub( stopBandFR, startBand );
     326    22174971 :             FOR( i = 0; i < len_out; i++ )
     327             :             {
     328    21606382 :                 part_out[i] = i;
     329    21606382 :                 move16();
     330             :             }
     331             :         }
     332    37842630 :         FOR( j = 0; j < npart_in; j++ )
     333             :         {
     334    36669498 :             IF( GE_16( part_in[j], stopBand ) )
     335             :             {
     336          28 :                 BREAK;
     337             :             }
     338    36669470 :             tmp16 = sub( part_in[j], startBand );
     339    36669470 :             test();
     340    36669470 :             if ( GE_16( part_in[j], stopBandFR ) && tmp16 >= 0 )
     341             :             {
     342    27572046 :                 part_out[len_out++] = tmp16;
     343    27572046 :                 move16();
     344             :             }
     345             :         }
     346             :     }
     347             :     ELSE
     348             :     {
     349           0 :         len_out = sub( stopBand, startBand );
     350           0 :         FOR( i = 0; i < len_out; i++ )
     351             :         {
     352           0 :             part_out[i] = i;
     353           0 :             move16();
     354             :         }
     355             :     }
     356             : 
     357     1173160 :     *npart_out = len_out;
     358     1173160 :     move16();
     359     1173160 :     getmidbands( part_out, len_out, midband, psize, psize_norm, psize_norm_exp, psize_inv );
     360     1173160 : }
     361             : 
     362             : 
     363             : /*-------------------------------------------------------------------
     364             :  * compress_range()
     365             :  *
     366             :  * Apply some dynamic range compression based on the log
     367             :  *-------------------------------------------------------------------*/
     368      170032 : void compress_range(
     369             :     Word32 *in, // Q(31 - in_exp)
     370             :     Word16 in_exp,
     371             :     Word16 *out,
     372             :     const Word16 len )
     373             : {
     374             :     Word16 i;
     375             :     Word32 in_s;
     376             :     Word32 one_s;
     377             :     Word32 in_exp32;
     378             :     Word32 L_tmp;
     379             : 
     380             : 
     381             :     /* out = log2( 1 + in ) */
     382      170032 :     IF( in_exp >= 0 )
     383             :     {
     384      146147 :         one_s = L_shr( 1073741824l /*0.5 Q31*/, in_exp ); // Q(31 - in_exp)
     385      146147 :         in_exp32 = L_shl( L_deposit_l( add( in_exp, 1 ) ), WORD32_BITS - 1 - LD_DATA_SCALE );
     386     4942167 :         FOR( i = 0; i < len; i++ )
     387             :         {
     388     4796020 :             in_s = L_add( L_shr( in[i], 1 ), one_s ); // Q(31 - in_exp)
     389     4796020 :             L_tmp = L_add( BASOP_Util_Log2( in_s ), in_exp32 );
     390     4796020 :             if ( in_s == 0 )
     391             :             {
     392       57183 :                 out[i] = 0;
     393       57183 :                 move16();
     394             :             }
     395     4796020 :             if ( in_s != 0 )
     396             :             {
     397     4738837 :                 out[i] = extract_h( L_tmp );
     398     4738837 :                 move16();
     399             :             }
     400     4796020 :             if ( out[i] == 0 )
     401             :             {
     402      171941 :                 out[i] = 1;
     403      171941 :                 move16();
     404             :             }
     405             :         }
     406             :     }
     407             :     ELSE
     408             :     {
     409       23885 :         in_exp = sub( in_exp, 1 );
     410       23885 :         in_exp32 = L_shl( L_deposit_l( 1 ), WORD32_BITS - 1 - LD_DATA_SCALE );
     411      971061 :         FOR( i = 0; i < len; i++ )
     412             :         {
     413      947176 :             L_tmp = L_add( BASOP_Util_Log2( L_add( L_shl( in[i], in_exp ), 1073741824l /*0.5 Q31*/ ) ), in_exp32 );
     414      947176 :             if ( in[i] == 0 )
     415             :             {
     416       17745 :                 out[i] = 0;
     417       17745 :                 move16();
     418             :             }
     419      947176 :             if ( in[i] != 0 )
     420             :             {
     421      929431 :                 out[i] = extract_h( L_tmp );
     422      929431 :                 move16();
     423             :             }
     424      947176 :             if ( out[i] == 0 )
     425             :             {
     426      329593 :                 out[i] = 1;
     427      329593 :                 move16();
     428             :             }
     429             :         }
     430             :     }
     431      170032 : }
     432             : 
     433             : /*-------------------------------------------------------------------
     434             :  * expand_range()
     435             :  *
     436             :  * Apply some dynamic range expansion to undo the compression
     437             :  *-------------------------------------------------------------------*/
     438        3118 : void expand_range(
     439             :     Word16 *in,  // Q15
     440             :     Word32 *out, // Q(31 - out_exp)
     441             :     Word16 *out_exp,
     442             :     const Word16 len )
     443             : {
     444             :     Word16 i;
     445             :     Word16 s;
     446             :     Word16 tmp;
     447             :     Word32 one_s, tmp32;
     448             :     Word16 maxVal;
     449             :     Word16 maxVal2;
     450             : 
     451             : 
     452        3118 :     maxVal = 0;
     453        3118 :     move16();
     454       78624 :     FOR( i = 0; i < len; i++ )
     455             :     {
     456       75506 :         maxVal = s_max( maxVal, in[i] ); // Q15
     457             :     }
     458             : 
     459        3118 :     maxVal2 = maxVal;
     460        3118 :     move16();
     461        3118 :     s = 0;
     462        3118 :     move16();
     463       41222 :     WHILE( maxVal >= 0 )
     464             :     {
     465       38104 :         maxVal = sub( maxVal, 512 /*0.015625 Q15*/ ); // Q15
     466       38104 :         s = add( s, 1 );
     467             :     }
     468        3118 :     tmp = sub( maxVal2, maxVal );
     469             : 
     470        3118 :     one_s = L_shr( 1073741824l /*0.5 Q31*/, sub( s, 1 ) ); // Q(31 - sub( s, 1 ))
     471        3118 :     tmp32 = L_shr( 726941l /*0.0003385080526823181 Q31*/, s );
     472             :     /* out = (2^(in) - 1) */
     473       78624 :     FOR( i = 0; i < len; i++ )
     474             :     {
     475       75506 :         out[i] = L_sub( BASOP_Util_InvLog2( L_deposit_h( sub( in[i], tmp ) ) ), one_s );
     476       75506 :         move32();
     477       75506 :         if ( out[i] == 0 )
     478             :         {
     479          52 :             out[i] = tmp32;
     480          52 :             move32();
     481             :         }
     482             :     }
     483        3118 :     *out_exp = s;
     484        3118 :     move16();
     485        3118 : }
     486             : 
     487      166914 : void expand_range_fx(
     488             :     Word32 *in,  // Q25
     489             :     Word32 *out, // exp:out_exp
     490             :     Word16 *out_exp,
     491             :     const Word16 len )
     492             : {
     493             :     Word16 i, tmp_e;
     494             :     Word32 maxVal, tmp32;
     495             :     Word16 maxOutExp;
     496             : 
     497      166914 :     const Word32 low_lim = 726940; /* 0.0003385080526823181f in Q31 */
     498      166914 :     move32();
     499             : 
     500             :     /* Find max possible output exponent. */
     501      166914 :     maxVal = 0;
     502      166914 :     move32();
     503     5834604 :     FOR( i = 0; i < len; i++ )
     504             :     {
     505     5667690 :         maxVal = L_max( maxVal, in[i] );
     506             :     }
     507      166914 :     tmp32 = BASOP_util_Pow2( maxVal, Q31 - Q25, &tmp_e );
     508      166914 :     maxOutExp = tmp_e;
     509      166914 :     move16();
     510             : 
     511             :     /* out = (2^(in) - 1) */
     512     5834604 :     FOR( i = 0; i < len; i++ )
     513             :     {
     514     5667690 :         tmp32 = BASOP_util_Pow2( in[i], Q31 - Q25, &tmp_e );  // 2^x
     515     5667690 :         tmp32 = L_sub( tmp32, L_shl( 1, sub( 31, tmp_e ) ) ); // 2^x - 1
     516     5667690 :         tmp32 = L_shr( tmp32, sub( maxOutExp, tmp_e ) );      // make exp same as maxExpOut
     517             : 
     518     5667690 :         out[i] = tmp32;
     519     5667690 :         move32();
     520             : 
     521     5667690 :         Word32 tmp_low_lim = L_shr( low_lim, maxOutExp );
     522     5667690 :         if ( LT_32( out[i], tmp_low_lim ) )
     523             :         {
     524       18270 :             out[i] = tmp_low_lim;
     525       18270 :             move32();
     526             :         }
     527             :     }
     528             : 
     529      166914 :     *out_exp = maxOutExp;
     530      166914 :     move16();
     531             : 
     532      166914 :     return;
     533             : }
     534             : 
     535             : /*-------------------------------------------------------------------
     536             :  * expand_range_var_e()
     537             :  *
     538             :  * Apply some dynamic range expansion to undo the compression. Similar
     539             :  * to expand_range but has variable input exponent.
     540             :  *
     541             :  *-------------------------------------------------------------------*/
     542           0 : void expand_range_var_exp(
     543             :     Word16 *in,
     544             :     Word16 in_exp,
     545             :     Word32 *out,
     546             :     Word16 *out_exp,
     547             :     const Word16 len )
     548             : {
     549             :     Word16 i, tmp_e;
     550             :     Word32 tmp32;
     551             :     Word16 maxVal, maxOutExp;
     552             : 
     553           0 :     const Word32 low_lim = 726940; /* 0.0003385080526823181f in Q31 */
     554           0 :     move32();
     555             : 
     556             :     /* Find max possible output exponent. */
     557           0 :     maxVal = 0;
     558           0 :     move16();
     559           0 :     FOR( i = 0; i < len; i++ )
     560             :     {
     561           0 :         maxVal = s_max( maxVal, in[i] );
     562             :     }
     563           0 :     tmp32 = BASOP_util_Pow2( L_deposit_h( maxVal ), in_exp, &tmp_e );
     564           0 :     maxOutExp = tmp_e;
     565           0 :     move16();
     566             : 
     567             :     /* out = (2^(in) - 1) */
     568           0 :     FOR( i = 0; i < len; i++ )
     569             :     {
     570           0 :         tmp32 = BASOP_util_Pow2( L_deposit_h( in[i] ), in_exp, &tmp_e ); // 2^x
     571           0 :         tmp32 = L_sub( tmp32, L_shl( 1, sub( 31, tmp_e ) ) );            // 2^x - 1
     572           0 :         tmp32 = L_shr( tmp32, sub( maxOutExp, tmp_e ) );                 // make exp same as maxExpOut
     573             : 
     574           0 :         out[i] = tmp32;
     575           0 :         move32();
     576             : 
     577           0 :         Word32 tmp_low_lim = L_shr( low_lim, maxOutExp );
     578           0 :         if ( LT_32( out[i], tmp_low_lim ) )
     579             :         {
     580           0 :             out[i] = tmp_low_lim;
     581           0 :             move32();
     582             :         }
     583             :     }
     584             : 
     585           0 :     *out_exp = maxOutExp;
     586           0 :     move16();
     587             : 
     588           0 :     return;
     589             : }
     590             : 
     591             : /*-------------------------------------------------------------------
     592             :  * minimum_statistics()
     593             :  *
     594             :  * Noise estimation using Minimum Statistics (MS)
     595             :  *-------------------------------------------------------------------*/
     596             : 
     597        3118 : void minimum_statistics(
     598             :     Word16 len,                    /* i  : Total number of partitions (CLDFB or FFT)                   */
     599             :     Word16 lenFFT,                 /* i  : Number of FFT partitions                                  */
     600             :     Word16 *psize,                 /* i  : Partition sizes, fractional                               */
     601             :     Word16 *msPeriodog,            /* i  : Periodogram (energies)                                    */
     602             :     Word16 *msNoiseFloor,          /* i/o: Noise floors (energies)                                   */
     603             :     Word16 *msNoiseEst,            /* i/o: Noise estimates (energies)                                */
     604             :     Word32 *msAlpha,               /* i/o: Forgetting factors                                        */
     605             :     Word16 *msPsd,                 /* i/o: Power Spectral Density (smoothed periodogram => energies) */
     606             :     Word16 *msPsdFirstMoment,      /* i/o: PSD statistics of 1st order (energy means)                */
     607             :     Word32 *msPsdSecondMoment,     /* i/o: PSD statistics of 2nd order (energy variances)            */
     608             :     Word32 *msMinBuf,              /* i/o: Buffer of minima (energies)                               */
     609             :     Word32 *msBminWin,             /* o  : Bias correction factors                                   */
     610             :     Word32 *msBminSubWin,          /* o  : Bias correction factors                                   */
     611             :     Word32 *msCurrentMin,          /* i/o: Local minima (energies)                                   */
     612             :     Word32 *msCurrentMinOut,       /* i/o: Local minima (energies)                                   */
     613             :     Word32 *msCurrentMinSubWindow, /* i/o: Local minima (energies)                                   */
     614             :     Word16 *msLocalMinFlag,        /* i  : Binary flag                                               */
     615             :     Word16 *msNewMinFlag,          /* i  : Binary flag                                               */
     616             :     Word16 *msPeriodogBuf,         /* i/o: Buffer of periodograms (energies)                         */
     617             :     Word16 *msPeriodogBufPtr,      /* i/o: Counter                                                   */
     618             :     HANDLE_FD_CNG_COM hFdCngCom    /* i/o: FD_CNG structure containing all buffers and variables */
     619             : )
     620             : {
     621             :     Word16 i, j, k, s, s1, s2, s3;
     622             :     Word16 len2;
     623             :     Word16 current_len;
     624             :     Word16 start, stop, cnt;
     625             :     Word16 totsize;
     626             :     Word16 inv_totsize;
     627             : 
     628             :     Word32 tmp, tmp0, tmp1;
     629             :     Word32 scalar, scalar2, scalar3;
     630             :     Word32 snr;
     631             :     Word32 msAlphaHatMin2;
     632             :     Word32 BminCorr;
     633             :     Word32 QeqInvAv;
     634             :     Word32 *ptr;
     635             :     Word32 *msPsdSum;
     636             :     Word32 *msPeriodogSum;
     637             : 
     638             :     Word16 tmp16, tmp16_1;
     639             :     Word16 beta;
     640             :     Word16 slope;
     641             :     Word16 QeqInv;
     642             :     Word16 scalar16;
     643             :     Word16 scalar216;
     644             :     Word16 scalar316;
     645             :     Word16 msM_win;
     646             :     Word16 msM_subwin;
     647             :     Word16 msAlphaCorAlpha;
     648             :     Word16 msAlphaCorAlpha2;
     649             :     Word16 msPeriodogSum16;
     650             :     Word16 msNoiseFloor16;
     651             : #ifndef ISSUE_1836_replace_overflow_libcom
     652             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     653             :     Flag Overflow = 0;
     654             :     move32();
     655             : #endif
     656             : #endif
     657             : 
     658        3118 :     len2 = i_mult( MSNUMSUBFR, len );
     659             : 
     660        3118 :     msM_win = hFdCngCom->msM_win;
     661        3118 :     move16();
     662        3118 :     msM_subwin = hFdCngCom->msM_subwin;
     663        3118 :     move16();
     664             : 
     665        3118 :     msAlphaCorAlpha = MSALPHACORALPHA;
     666        3118 :     move16();
     667        3118 :     msAlphaCorAlpha2 = MSALPHACORALPHA2;
     668        3118 :     move16();
     669             : 
     670        3118 :     msPsdSum = hFdCngCom->msPsdSum;
     671        3118 :     msPeriodogSum = hFdCngCom->msPeriodogSum;
     672             : 
     673             :     /* No minimum statistics at initialization */
     674        3118 :     IF( LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
     675             :     {
     676          19 :         Copy( msPeriodog, msPsd, len );            /* 6Q9 */
     677          19 :         Copy( msPeriodog, msNoiseFloor, len );     /* 6Q9 */
     678          19 :         Copy( msPeriodog, msNoiseEst, len );       /* 6Q9 */
     679          19 :         Copy( msPeriodog, msPsdFirstMoment, len ); /* 6Q9 */
     680             : 
     681          19 :         set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
     682          19 :         msPeriodogSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
     683          19 :         move32();
     684          19 :         msPsdSum[0] = msPeriodogSum[0]; /* 16Q15 */
     685          19 :         move32();
     686             : 
     687          19 :         IF( LT_16( lenFFT, len ) )
     688             :         {
     689          14 :             msPeriodogSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
     690          14 :             move32();
     691          14 :             msPsdSum[1] = msPeriodogSum[1]; /* 16Q15 */
     692          14 :             move32();
     693             :         }
     694             : 
     695             :         /* Increment frame counter at initialization */
     696             :         /* Some frames are sometimes zero at initialization => ignore them */
     697          19 :         IF( LT_16( msPeriodog[0], hFdCngCom->init_old ) )
     698             :         {
     699           5 :             set32_fx( msCurrentMinOut, 2147483647l /*1.0 Q31*/, len );       /* 16Q15 */
     700           5 :             set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );          /* 16Q15 */
     701           5 :             set32_fx( msMinBuf, 2147483647l /*1.0 Q31*/, len2 );             /* 16Q15 */
     702           5 :             set32_fx( msCurrentMinSubWindow, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
     703             : 
     704           5 :             hFdCngCom->msFrCnt_init_counter = add( hFdCngCom->msFrCnt_init_counter, 1 );
     705           5 :             move16();
     706             :         }
     707          19 :         hFdCngCom->init_old = msPeriodog[0]; /* 6Q9 */
     708          19 :         move16();
     709             :     }
     710             :     ELSE
     711             :     {
     712             :         /* Consider the FFT and CLDFB bands separately
     713             :            - first iteration for FFT bins,
     714             :            - second one for CLDFB bands in SWB mode */
     715        3099 :         cnt = 0;
     716        3099 :         move16();
     717        3099 :         start = 0;
     718        3099 :         move16();
     719        3099 :         stop = lenFFT;
     720        3099 :         move16();
     721        3099 :         totsize = sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand );
     722        9284 :         WHILE( GT_16( stop, start ) )
     723             :         {
     724        6185 :             current_len = sub( stop, start );
     725             : 
     726             :             /* Compute smoothed correction factor for PSD smoothing */
     727             : 
     728             :             /* msPeriodogSum[cnt] with format 16Q15 */
     729        6185 :             msPeriodogSum[cnt] = dotp_s_fx( msPeriodog + start, psize + start, current_len, CNG_HS );
     730        6185 :             move32();
     731             : 
     732        6185 :             IF( msPeriodogSum[cnt] == 0 )
     733             :             {
     734           0 :                 hFdCngCom->msAlphaCor[cnt] = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha );
     735           0 :                 move32();
     736             :             }
     737             :             ELSE
     738             :             {
     739             :                 /* calculate scalar with normalized msPeriodogSum[cnt], exponent -2*s1 */
     740        6185 :                 s1 = norm_l( msPeriodogSum[cnt] );
     741        6185 :                 msPeriodogSum16 = round_fx_sat( L_shl_sat( msPeriodogSum[cnt], s1 ) );
     742        6185 :                 scalar = L_mult( msPeriodogSum16, msPeriodogSum16 );
     743             : 
     744             :                 /* calculate difference, both elements in 16Q15 format, use absolute value
     745             :                    to avoid -1.0 x -1.0 multiplications later */
     746        6185 :                 scalar2 = L_abs( L_sub( msPsdSum[cnt], msPeriodogSum[cnt] ) );
     747             : 
     748        6185 :                 s2 = WORD32_BITS - 1;
     749        6185 :                 move16();
     750        6185 :                 if ( scalar2 != 0 )
     751             :                 {
     752             :                     /* use absolute value to avoid -1.0 x -1.0 multiplications */
     753        6175 :                     s2 = norm_l( scalar2 );
     754             :                 }
     755             : #ifdef ISSUE_1836_replace_overflow_libcom
     756        6185 :                 scalar216 = round_fx_sat( L_shl( scalar2, s2 ) );
     757             : #else
     758             :                 scalar216 = round_fx_o( L_shl_o( scalar2, s2, &Overflow ), &Overflow );
     759             : #endif
     760        6185 :                 scalar2 = L_mult( scalar216, scalar216 );
     761             : 
     762             :                 /* find common exponent */
     763        6185 :                 tmp16_1 = sub( s1, s2 );
     764        6185 :                 tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
     765        6185 :                 if ( tmp16_1 < 0 )
     766             :                 {
     767        5334 :                     scalar2 = L_shr( scalar2, tmp16 );
     768             :                 }
     769        6185 :                 if ( tmp16_1 > 0 )
     770             :                 {
     771         317 :                     scalar = L_shr( scalar, tmp16 );
     772             :                 }
     773             : 
     774             : 
     775             :                 /* add scalar and scalar2, avoid overflows */
     776        6185 :                 scalar = L_shr( scalar, 1 );
     777        6185 :                 scalar2 = L_shr( scalar2, 1 );
     778        6185 :                 scalar3 = L_add( scalar, scalar2 );
     779             : 
     780             :                 /* calculate division */
     781        6185 :                 scalar16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar, scalar3, &s3 );
     782        6185 :                 s3 = s_max( s3, -( WORD16_BITS - 1 ) );
     783        6185 :                 scalar16 = shl( scalar16, s3 );
     784        6185 :                 scalar16 = s_max( scalar16, MSALPHACORMAX );
     785             : 
     786        6185 :                 hFdCngCom->msAlphaCor[cnt] = L_add( Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha ),
     787             :                                                     L_mult( scalar16, msAlphaCorAlpha2 ) );
     788        6185 :                 move32();
     789             :             }
     790             : 
     791             :             /* Compute SNR */
     792             : 
     793             :             /* msPeriodogSum[cnt] with format 16Q15 */
     794        6185 :             snr = dotp_s_fx( msNoiseFloor + start, psize + start, current_len, CNG_HS );
     795             : 
     796        6185 :             IF( GT_32( L_shr( Mpy_32_16_1( msPsdSum[cnt], 18431 /*0.56246299817 Q15*/ ), 13 ), snr ) )
     797             :             {
     798           0 :                 tmp0 = BASOP_Util_Log2( msPsdSum[cnt] );
     799           0 :                 tmp1 = BASOP_Util_Log2( snr );
     800           0 :                 tmp1 = L_sub( tmp0, tmp1 );
     801           0 :                 tmp1 = Mpy_32_16_1( tmp1, MSSNREXP );
     802           0 :                 msAlphaHatMin2 = BASOP_Util_InvLog2( tmp1 );
     803             :             }
     804             :             ELSE
     805             :             {
     806        6185 :                 msAlphaHatMin2 = MSALPHAHATMIN;
     807        6185 :                 move32();
     808             :             }
     809        6185 :             scalar = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], MSALPHAMAX );
     810             : 
     811       81046 :             FOR( j = start; j < stop; j++ )
     812             :             {
     813             :                 /* Compute optimal smoothing parameter for PSD estimation */
     814       74861 :                 test();
     815       74861 :                 IF( ( scalar == 0 ) || ( msNoiseFloor[j] == 0 ) )
     816             :                 {
     817           0 :                     msAlpha[j] = msAlphaHatMin2;
     818           0 :                     move32();
     819             :                 }
     820             :                 ELSE
     821             :                 {
     822             :                     /* calculate scalar2 with normalized msNoiseFloor[j], exponent -2*s1 */
     823       74861 :                     s1 = WORD16_BITS - 1;
     824       74861 :                     move16();
     825       74861 :                     if ( msNoiseFloor[j] != 0 )
     826             :                     {
     827       74861 :                         s1 = norm_s( msNoiseFloor[j] );
     828             :                     }
     829       74861 :                     msNoiseFloor16 = shl( msNoiseFloor[j], s1 );
     830       74861 :                     scalar2 = L_mult( msNoiseFloor16, msNoiseFloor16 );
     831             : 
     832             :                     /* calculate difference, both elements in 6Q9 format, use absolute value
     833             :                        to avoid -1.0 x -1.0 multiplications later */
     834       74861 :                     scalar316 = abs_s( sub( msPsd[j], msNoiseFloor[j] ) );
     835             : 
     836       74861 :                     s2 = WORD16_BITS - 1;
     837       74861 :                     move16();
     838       74861 :                     if ( scalar316 != 0 )
     839             :                     {
     840             :                         /* use absolute value to avoid -1.0 x -1.0 multiplications */
     841       74282 :                         s2 = norm_s( scalar316 );
     842             :                     }
     843       74861 :                     scalar316 = shl( scalar316, s2 );
     844       74861 :                     scalar3 = L_mult( scalar316, scalar316 );
     845             : 
     846             :                     /* find common exponent */
     847       74861 :                     tmp16_1 = sub( s1, s2 );
     848       74861 :                     tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
     849       74861 :                     if ( tmp16_1 < 0 )
     850             :                     {
     851       33861 :                         scalar3 = L_shr( scalar3, tmp16 );
     852             :                     }
     853       74861 :                     if ( tmp16_1 > 0 )
     854             :                     {
     855       36296 :                         scalar2 = L_shr( scalar2, tmp16 );
     856             :                     }
     857             : 
     858             :                     /* add scalar2 and scalar3, avoid overflows */
     859       74861 :                     scalar2 = L_shr( scalar2, 1 );
     860       74861 :                     scalar3 = L_shr( scalar3, 1 );
     861       74861 :                     scalar3 = L_add( scalar2, scalar3 );
     862             : 
     863             :                     /* calculate division */
     864       74861 :                     tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar2, scalar3, &s3 );
     865       74861 :                     scalar2 = Mpy_32_16_1( scalar, tmp16 );
     866       74861 :                     s3 = s_max( s3, -( WORD32_BITS - 1 ) );
     867       74861 :                     scalar2 = L_shl( scalar2, s3 );
     868       74861 :                     msAlpha[j] = L_max( scalar2, msAlphaHatMin2 );
     869       74861 :                     move32();
     870             :                 }
     871             : 
     872             :                 /* Compute the PSD (smoothed periodogram) in each band */
     873       74861 :                 msPsd[j] = round_fx( L_add( Mpy_32_16_1( msAlpha[j], msPsd[j] ),
     874       74861 :                                             Mpy_32_16_1( L_sub( 2147483647l /*1.0 Q31*/, msAlpha[j] ), msPeriodog[j] ) ) );
     875       74861 :                 move16();
     876             :             }
     877        6185 :             msPsdSum[cnt] = dotp_s_fx( msPsd + start, psize + start, current_len, CNG_HS );
     878        6185 :             move32();
     879             : 
     880        6185 :             QeqInvAv = 0l /*0.0 Q31*/;
     881        6185 :             move32();
     882             : 
     883             :             /* scalar: 7Q24 format */
     884        6185 :             tmp = 1191182336l /*(float)(MSNUMSUBFR*MSSUBFRLEN)-1.0 Q24*/;
     885        6185 :             move32();
     886        6185 :             scalar = L_sub( tmp, L_mult( round_fx( tmp ), msM_win ) );
     887             : 
     888             :             /* scalar2: 4Q27 format */
     889        6185 :             tmp = 1476395008l /*(float)MSSUBFRLEN-1.0 Q27*/;
     890        6185 :             move32();
     891        6185 :             scalar2 = L_sub( tmp, L_mult( round_fx( tmp ), msM_subwin ) );
     892             : 
     893       81046 :             FOR( j = start; j < stop; j++ )
     894             :             {
     895             :                 /* Compute variance of PSD */
     896       74861 :                 tmp = L_min( msAlpha[j], MSBETAMAX_SQRT );
     897             : 
     898       74861 :                 s1 = WORD32_BITS - 1;
     899       74861 :                 move16();
     900       74861 :                 if ( tmp != 0 )
     901             :                 {
     902       74861 :                     s1 = norm_l( tmp );
     903             :                 }
     904       74861 :                 s2 = shl( s1, 1 );
     905             : 
     906       74861 :                 s2 = s_min( s2, WORD32_BITS - 1 );
     907             : 
     908             :                 /* beta: scaled by s2 */
     909             : #ifdef ISSUE_1836_replace_overflow_libcom
     910       74861 :                 tmp16 = round_fx_sat( L_shl( tmp, s1 ) );
     911             : #else
     912             :                 tmp16 = round_fx_o( L_shl_o( tmp, s1, &Overflow ), &Overflow );
     913             : #endif
     914       74861 :                 beta = mult_r( tmp16, tmp16 );
     915             : 
     916             :                 /* scalar3: scaled by s3 */
     917       74861 :                 scalar3 = L_sub( L_deposit_l( msPsd[j] ), L_deposit_l( msPsdFirstMoment[j] ) );
     918       74861 :                 s3 = norm_l( scalar3 );
     919       74861 :                 scalar3 = L_shl( scalar3, s3 );
     920             : 
     921             :                 /* msPsdFirstMoment: 6Q9   */
     922       74861 :                 tmp = L_msu( L_mult( beta, msPsdFirstMoment[j] ), beta, msPsd[j] );
     923       74861 :                 msPsdFirstMoment[j] = add( round_fx( L_shr( tmp, s2 ) ), msPsd[j] );
     924       74861 :                 move16();
     925             : 
     926             :                 /* msPsdSecondMoment: 12Q19   */
     927       74861 :                 tmp0 = L_shr( Mpy_32_16_r( msPsdSecondMoment[j], beta ), s2 );
     928       74861 :                 tmp1 = Mpy_32_32( scalar3, scalar3 );
     929       74861 :                 tmp1 = L_shr( L_sub( tmp1, L_shr( Mpy_32_16_r( tmp1, beta ), s2 ) ), sub( shl( s3, 1 ), 32 ) );
     930       74861 :                 msPsdSecondMoment[j] = L_add( tmp0, tmp1 );
     931       74861 :                 move32();
     932             : 
     933             :                 /* Compute inverse of amount of degrees of freedom */
     934       74861 :                 QeqInv = MSQEQINVMAX;
     935       74861 :                 move16();
     936             : 
     937       74861 :                 IF( msNoiseFloor[j] != 0 /*0.0 Q15*/ )
     938             :                 {
     939       74861 :                     tmp = L_mult( msNoiseFloor[j], msNoiseFloor[j] );
     940       74861 :                     tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( msPsdSecondMoment[j], tmp, &s );
     941             :                     /* consider factor of 2 */
     942       74861 :                     s = s_min( s_max( sub( s, 1 ), -( WORD16_BITS - 1 ) ), ( WORD16_BITS - 1 ) );
     943       74861 :                     if ( s < 0 )
     944             :                     {
     945       46270 :                         QeqInv = shl( tmp16, s );
     946             :                     }
     947       74861 :                     QeqInv = s_min( QeqInv, MSQEQINVMAX );
     948             :                 }
     949       74861 :                 QeqInvAv = L_add( QeqInvAv, L_mult( QeqInv, psize[j] ) );
     950             : 
     951             :                 /* Compute bias correction Bmin */
     952       74861 :                 tmp0 = Mpy_32_16_1( scalar, QeqInv );
     953       74861 :                 tmp1 = L_sub( 1073741824l /*0.5 Q31*/, L_mult( msM_win, QeqInv ) );
     954       74861 :                 tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
     955       74861 :                 msBminWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), add( s, 7 - 4 ) ) );
     956       74861 :                 move32();
     957             : 
     958       74861 :                 tmp0 = Mpy_32_16_1( scalar2, QeqInv );
     959       74861 :                 tmp1 = L_sub( 1073741824l /*0.5 Q31*/, L_mult( msM_subwin, QeqInv ) );
     960       74861 :                 tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
     961       74861 :                 msBminSubWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), s ) );
     962       74861 :                 move32();
     963             :             }
     964             : 
     965        6185 :             inv_totsize = BASOP_Util_Divide3232_uu_1616_Scale( 1, totsize, &s );
     966        6185 :             QeqInvAv = Mpy_32_16_1( QeqInvAv, inv_totsize );
     967        6185 :             QeqInvAv = L_shl( QeqInvAv, s );
     968        6185 :             hFdCngCom->msQeqInvAv[cnt] = QeqInvAv;
     969        6185 :             move32();
     970             : 
     971             :             /* New minimum? */
     972             : 
     973             :             /* exponent QeqInvAv: CNG_S, exponent MSAV: (4>>1) */
     974        6185 :             s = CNG_S + 2 * MSAV_EXP;
     975        6185 :             move16();
     976        6185 :             BminCorr = Mpy_32_16_1( Sqrt32( QeqInvAv, &s ), MSAV );
     977        6185 :             BminCorr = L_shl( BminCorr, sub( s, 1 ) );
     978             : 
     979             :             /* exponent BminCorr: 1 */
     980        6185 :             BminCorr = L_add( BminCorr, 1073741824l /*0.5 Q31*/ );
     981             : 
     982       81046 :             FOR( j = start; j < stop; j++ )
     983             :             {
     984             :                 /* exponent scalar: CNG_S+1 */
     985       74861 :                 scalar = Mpy_32_16_1( BminCorr, msPsd[j] );
     986             : 
     987             :                 /* exponent scalar2: CNG_S+1+4 */
     988       74861 :                 scalar2 = Mpy_32_32( scalar, msBminWin[j] );
     989             : 
     990       74861 :                 msNewMinFlag[j] = 0;
     991       74861 :                 move16();
     992       74861 :                 IF( LT_32( scalar2, msCurrentMin[j] ) /*0.0 Q31*/ )
     993             :                 {
     994       29387 :                     msNewMinFlag[j] = 1;
     995       29387 :                     move16();
     996             :                     /* exponent msCurrentMin[j]: CNG_S+1+4 */
     997       29387 :                     msCurrentMin[j] = scalar2;
     998       29387 :                     move32();
     999             :                     /* exponent msCurrentMinSubWindow[j]: CNG_S */
    1000             :                     BASOP_SATURATE_WARNING_OFF_EVS;
    1001             : #ifdef ISSUE_1836_replace_overflow_libcom
    1002       29387 :                     msCurrentMinSubWindow[j] = L_shl_sat( Mpy_32_32( scalar, msBminSubWin[j] ), 5 );
    1003       29387 :                     move32();
    1004             : #else
    1005             :                     msCurrentMinSubWindow[j] = L_shl_o( Mpy_32_32( scalar, msBminSubWin[j] ), 5, &Overflow );
    1006             :                     move32();
    1007             : #endif
    1008             :                     BASOP_SATURATE_WARNING_ON_EVS;
    1009             :                 }
    1010             :             }
    1011             : 
    1012             :             /* This is used later to identify local minima */
    1013        6185 :             IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1014             :             {
    1015        1897 :                 FOR( i = 0; i < 3; i++ )
    1016             :                 {
    1017        1481 :                     IF( LT_32( hFdCngCom->msQeqInvAv[cnt], L_shr( L_deposit_h( msQeqInvAv_thresh[i] ), CNG_S ) ) /*0.0 Q31*/ )
    1018             :                     {
    1019         104 :                         BREAK;
    1020             :                     }
    1021             :                 }
    1022             :                 /* format 1Q30 */
    1023         520 :                 hFdCngCom->msSlope[cnt] = msNoiseSlopeMax[i];
    1024         520 :                 move32();
    1025             :             }
    1026             : 
    1027             :             /* Consider the FFT and CLDFB bands separately */
    1028        6185 :             start = stop;
    1029        6185 :             move16();
    1030        6185 :             stop = len;
    1031        6185 :             move16();
    1032        6185 :             totsize = sub( hFdCngCom->stopBand, hFdCngCom->stopFFTbin );
    1033        6185 :             cnt = add( cnt, 1 );
    1034             :         } /*while (stop > start)*/
    1035             : 
    1036             :         /* Update minimum between sub windows */
    1037        3099 :         test();
    1038        3099 :         IF( GT_16( hFdCngCom->msFrCnt, 1 ) && LT_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1039             :         {
    1040       64810 :             FOR( j = 0; j < len; j++ )
    1041             :             {
    1042       62231 :                 if ( msNewMinFlag[j] > 0 )
    1043             :                 {
    1044       21504 :                     msLocalMinFlag[j] = 1;
    1045       21504 :                     move16();
    1046             :                 }
    1047       62231 :                 if ( LT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ )
    1048             :                 {
    1049             :                     /* msCurrentMinOut[j] scaled with CNG_S */
    1050        6243 :                     msCurrentMinOut[j] = msCurrentMinSubWindow[j];
    1051        6243 :                     move32();
    1052             :                 }
    1053             :             }
    1054             :             /* Get the current noise floor */
    1055        2579 :             Copy_Scale_sig_32_16( msCurrentMinOut, msNoiseFloor, len, -16 );
    1056             :         }
    1057             :         ELSE /* sub window complete */
    1058             :         {
    1059         520 :             IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1060             :             {
    1061             :                 /* Collect buffers */
    1062         261 :                 Copy32( msCurrentMinSubWindow, msMinBuf + len * hFdCngCom->msMinBufferPtr, len );
    1063             : 
    1064             :                 /* Compute minimum among all buffers */
    1065         261 :                 Copy32( msMinBuf, msCurrentMinOut, len );
    1066         261 :                 ptr = msMinBuf + len;
    1067        1566 :                 FOR( i = 1; i < MSNUMSUBFR; i++ )
    1068             :                 {
    1069       33000 :                     FOR( j = 0; j < len; j++ )
    1070             :                     {
    1071       31695 :                         if ( LT_32( *ptr, msCurrentMinOut[j] ) /*0.0 Q31*/ )
    1072             :                         {
    1073        8775 :                             msCurrentMinOut[j] = *ptr;
    1074        8775 :                             move32();
    1075             :                         }
    1076       31695 :                         ptr++;
    1077             :                     }
    1078             :                 }
    1079             : 
    1080             :                 /* Take over local minima */
    1081         261 :                 slope = hFdCngCom->msSlope[0];
    1082         261 :                 move16();
    1083        6600 :                 FOR( j = 0; j < len; j++ )
    1084             :                 {
    1085        6339 :                     if ( EQ_16( j, lenFFT ) )
    1086             :                     {
    1087         259 :                         slope = hFdCngCom->msSlope[1];
    1088         259 :                         move16();
    1089             :                     }
    1090        6339 :                     test();
    1091        6339 :                     test();
    1092        6339 :                     test();
    1093        6339 :                     IF( ( msLocalMinFlag[j] != 0 ) && ( msNewMinFlag[j] == 0 ) && ( LT_32( L_shr( msCurrentMinSubWindow[j], 1 ), Mpy_32_16_1( msCurrentMinOut[j], slope ) ) /*0.0 Q31*/ ) && ( GT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ ) )
    1094             :                     {
    1095         210 :                         msCurrentMinOut[j] = msCurrentMinSubWindow[j];
    1096         210 :                         move32();
    1097         210 :                         i = j;
    1098         210 :                         move16();
    1099        1470 :                         FOR( k = 0; k < MSNUMSUBFR; k++ )
    1100             :                         {
    1101        1260 :                             msMinBuf[i] = msCurrentMinOut[j];
    1102        1260 :                             move32();
    1103        1260 :                             i = add( i, len );
    1104             :                         }
    1105             :                     }
    1106             :                 }
    1107             : 
    1108             :                 /* Reset */
    1109         261 :                 set16_fx( msLocalMinFlag, 0, len );
    1110         261 :                 set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );
    1111             : 
    1112             :                 /* Get the current noise floor */
    1113         261 :                 Copy_Scale_sig_32_16( msCurrentMinOut, msNoiseFloor, len, -16 );
    1114             :             }
    1115             :         }
    1116             : 
    1117             : 
    1118             :         /* Detect sudden offsets based on the FFT bins (core bandwidth) */
    1119        3099 :         IF( GT_32( Mpy_32_16_1( msPsdSum[0], 655 /*0.02 Q15*/ ), msPeriodogSum[0] ) /*0.0 Q31*/ )
    1120             :         {
    1121           0 :             IF( hFdCngCom->offsetflag > 0 )
    1122             :             {
    1123           0 :                 Copy( msPeriodog, msPsd, len );
    1124           0 :                 FOR( j = 0; j < len; j++ )
    1125             :                 {
    1126           0 :                     msCurrentMinOut[j] = L_deposit_h( msPeriodog[j] );
    1127           0 :                     move32();
    1128             :                 }
    1129           0 :                 set32_fx( hFdCngCom->msAlphaCor, 2147483647l /*1.0 Q31*/, cnt );
    1130           0 :                 set32_fx( msAlpha, 0l /*0.0 Q31*/, len );
    1131           0 :                 Copy( msPeriodog, msPsdFirstMoment, len );
    1132           0 :                 set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
    1133             : 
    1134           0 :                 msPsdSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
    1135           0 :                 move32();
    1136           0 :                 IF( LT_16( lenFFT, len ) )
    1137             :                 {
    1138           0 :                     msPsdSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
    1139           0 :                     move32();
    1140             :                 }
    1141             :             }
    1142           0 :             hFdCngCom->offsetflag = 1;
    1143           0 :             move16();
    1144             :         }
    1145             :         ELSE
    1146             :         {
    1147        3099 :             hFdCngCom->offsetflag = 0;
    1148        3099 :             move16();
    1149             :         }
    1150             : 
    1151             : 
    1152             :         /* Increment frame counter */
    1153        3099 :         IF( EQ_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1154             :         {
    1155         261 :             hFdCngCom->msFrCnt = 1;
    1156         261 :             move16();
    1157         261 :             hFdCngCom->msMinBufferPtr = add( hFdCngCom->msMinBufferPtr, 1 );
    1158         261 :             move16();
    1159         261 :             if ( EQ_16( hFdCngCom->msMinBufferPtr, MSNUMSUBFR ) )
    1160             :             {
    1161          41 :                 hFdCngCom->msMinBufferPtr = 0;
    1162          41 :                 move16();
    1163             :             }
    1164             :         }
    1165             :         ELSE
    1166             :         {
    1167        2838 :             hFdCngCom->msFrCnt = add( hFdCngCom->msFrCnt, 1 );
    1168             :         }
    1169             : 
    1170             :         /* Smooth noise estimate during CNG phases */
    1171       77960 :         FOR( j = 0; j < len; j++ )
    1172             :         {
    1173       74861 :             msNoiseEst[j] = round_fx( L_mac( L_mult( 31130 /*0.95 Q15*/, msNoiseEst[j] ), 1638 /*0.05 Q15*/, msNoiseFloor[j] ) );
    1174       74861 :             move16();
    1175             :         }
    1176             :     }
    1177             :     /* Collect buffers */
    1178        3118 :     Copy( msPeriodog, msPeriodogBuf + len * ( *msPeriodogBufPtr ), len );
    1179             : 
    1180        3118 :     *msPeriodogBufPtr = add( *msPeriodogBufPtr, 1 );
    1181        3118 :     move16();
    1182        3118 :     if ( EQ_16( *msPeriodogBufPtr, MSBUFLEN ) )
    1183             :     {
    1184         623 :         ( *msPeriodogBufPtr ) = 0;
    1185         623 :         move16();
    1186             :     }
    1187             : 
    1188             :     /* Upper limit the noise floors with the averaged input energy */
    1189       78624 :     FOR( j = 0; j < len; j++ )
    1190             :     {
    1191       75506 :         scalar = L_mult( msPeriodogBuf[j], 6554 /*1.0/MSBUFLEN Q15*/ );
    1192             : 
    1193      377530 :         FOR( i = j + len; i < MSBUFLEN * len; i += len )
    1194             :         {
    1195      302024 :             scalar = L_mac( scalar, msPeriodogBuf[i], 6554 /*1.0/MSBUFLEN Q15*/ );
    1196             :         }
    1197       75506 :         scalar16 = round_fx( scalar );
    1198       75506 :         if ( GT_16( msNoiseEst[j], scalar16 ) /*0.0 Q15*/ )
    1199             :         {
    1200       12531 :             msNoiseEst[j] = scalar16;
    1201       12531 :             move16();
    1202             :         }
    1203             : 
    1204       75506 :         assert( msNoiseEst[j] >= 0 /*0.0 Q15*/ );
    1205             :     }
    1206        3118 : }
    1207             : 
    1208      166914 : void minimum_statistics_fx(
    1209             :     Word16 len,                    /* i  : Total number of partitions (CLDFB or FFT)                   */
    1210             :     Word16 lenFFT,                 /* i  : Number of FFT partitions                                  */
    1211             :     Word16 *psize,                 /* i  : Partition sizes, fractional                             Q9*/
    1212             :     Word16 *msPeriodog,            /* i  : Periodogram (energies)                                    */
    1213             :     Word32 *msNoiseFloor,          /* i/o: Noise floors (energies)                                Q25*/
    1214             :     Word32 *msNoiseEst,            /* i/o: Noise estimates (energies)                             Q25*/
    1215             :     Word32 *msAlpha,               /* i/o: Forgetting factors                                        */
    1216             :     Word16 *msPsd,                 /* i/o: Power Spectral Density (smoothed periodogram => energies) */
    1217             :     Word16 *msPsdFirstMoment,      /* i/o: PSD statistics of 1st order (energy means)                */
    1218             :     Word32 *msPsdSecondMoment,     /* i/o: PSD statistics of 2nd order (energy variances)            */
    1219             :     Word32 *msMinBuf,              /* i/o: Buffer of minima (energies)                               */
    1220             :     Word32 *msBminWin,             /* o  : Bias correction factors                                   */
    1221             :     Word32 *msBminSubWin,          /* o  : Bias correction factors                                   */
    1222             :     Word32 *msCurrentMin,          /* i/o: Local minima (energies)                                   */
    1223             :     Word32 *msCurrentMinOut,       /* i/o: Local minima (energies)                                   */
    1224             :     Word32 *msCurrentMinSubWindow, /* i/o: Local minima (energies)                                   */
    1225             :     Word16 *msLocalMinFlag,        /* i  : Binary flag                                               */
    1226             :     Word16 *msNewMinFlag,          /* i  : Binary flag                                               */
    1227             :     Word16 *msPeriodogBuf,         /* i/o: Buffer of periodograms (energies)                         */
    1228             :     Word16 *msPeriodogBufPtr,      /* i/o: Counter                                                   */
    1229             :     HANDLE_FD_CNG_COM hFdCngCom,   /* i/o: FD_CNG structure containing all buffers and variables */
    1230             :     const Word16 enc_dec,          /* i  : encoder/decoder indicator */
    1231             :     const Word16 element_mode      /* i  : IVAS element mode type    */
    1232             : )
    1233             : {
    1234             :     Word16 i, j, k, s, s1, s2, s3;
    1235             :     Word16 len2;
    1236             :     Word16 current_len;
    1237             :     Word16 start, stop, cnt;
    1238             :     Word16 totsize;
    1239             :     Word16 inv_totsize;
    1240             : 
    1241             :     Word32 tmp, tmp0, tmp1;
    1242             :     Word32 scalar, scalar2, scalar3;
    1243             :     Word32 snr;
    1244             :     Word32 msAlphaHatMin2;
    1245             :     Word32 BminCorr;
    1246             :     Word32 QeqInvAv;
    1247             :     Word32 *ptr;
    1248             :     Word32 *msPsdSum;
    1249             :     Word32 *msPeriodogSum;
    1250             : 
    1251             :     Word16 tmp16, tmp16_1;
    1252             :     Word16 beta;
    1253             :     Word16 slope;
    1254             :     Word16 QeqInv;
    1255             :     Word16 scalar16;
    1256             :     Word16 scalar216;
    1257             :     Word16 scalar316;
    1258             :     Word16 msM_win;
    1259             :     Word16 msM_subwin;
    1260             :     Word16 msAlphaCorAlpha;
    1261             :     Word16 msAlphaCorAlpha2;
    1262             :     Word16 msPeriodogSum16;
    1263             :     Word16 msNoiseFloor16;
    1264             : #ifndef ISSUE_1836_replace_overflow_libcom
    1265             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
    1266             :     Flag Overflow = 0;
    1267             :     move32();
    1268             : #endif
    1269             : #endif
    1270             : 
    1271             : 
    1272      166914 :     len2 = i_mult( MSNUMSUBFR, len );
    1273             : 
    1274      166914 :     msM_win = hFdCngCom->msM_win;
    1275      166914 :     move16();
    1276      166914 :     msM_subwin = hFdCngCom->msM_subwin;
    1277      166914 :     move16();
    1278             : 
    1279      166914 :     msAlphaCorAlpha = MSALPHACORALPHA;
    1280      166914 :     move16();
    1281      166914 :     msAlphaCorAlpha2 = MSALPHACORALPHA2;
    1282      166914 :     move16();
    1283             : 
    1284      166914 :     msPsdSum = hFdCngCom->msPsdSum;
    1285      166914 :     msPeriodogSum = hFdCngCom->msPeriodogSum;
    1286             : 
    1287             :     /* No minimum statistics at initialization */
    1288      166914 :     IF( LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
    1289             :     {
    1290        7037 :         Copy( msPeriodog, msPsd, len );                                    /* 6Q9 */
    1291        7037 :         Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseFloor, len, Q16 ); /* Q25 */
    1292        7037 :         Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseEst, len, Q16 );   /* Q25 */
    1293        7037 :         Copy( msPeriodog, msPsdFirstMoment, len );                         /* 6Q9 */
    1294             : 
    1295        7037 :         set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
    1296        7037 :         msPeriodogSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
    1297        7037 :         move32();
    1298        7037 :         msPsdSum[0] = msPeriodogSum[0]; /* 16Q15 */
    1299        7037 :         move32();
    1300             : 
    1301        7037 :         IF( LT_16( lenFFT, len ) )
    1302             :         {
    1303        2571 :             msPeriodogSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
    1304        2571 :             move32();
    1305        2571 :             msPsdSum[1] = msPeriodogSum[1]; /* 16Q15 */
    1306        2571 :             move32();
    1307             :         }
    1308             : 
    1309             :         /* Increment frame counter at initialization */
    1310             :         /* Some frames are sometimes zero at initialization => ignore them */
    1311        7037 :         IF( LT_16( msPeriodog[0], hFdCngCom->init_old ) )
    1312             :         {
    1313        1497 :             set32_fx( msCurrentMinOut, 2147483647l /*1.0 Q31*/, len );       /* 16Q15 */
    1314        1497 :             set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );          /* 16Q15 */
    1315        1497 :             set32_fx( msMinBuf, 2147483647l /*1.0 Q31*/, len2 );             /* 16Q15 */
    1316        1497 :             set32_fx( msCurrentMinSubWindow, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
    1317             : 
    1318        1497 :             hFdCngCom->msFrCnt_init_counter = add( hFdCngCom->msFrCnt_init_counter, 1 );
    1319        1497 :             move16();
    1320             :         }
    1321        7037 :         hFdCngCom->init_old = msPeriodog[0]; /* 6Q9 */
    1322        7037 :         move16();
    1323             :     }
    1324             :     ELSE
    1325             :     {
    1326             :         /* Consider the FFT and CLDFB bands separately
    1327             :            - first iteration for FFT bins,
    1328             :            - second one for CLDFB bands in SWB mode */
    1329      159877 :         cnt = 0;
    1330      159877 :         move16();
    1331      159877 :         start = 0;
    1332      159877 :         move16();
    1333      159877 :         stop = lenFFT;
    1334      159877 :         move16();
    1335      159877 :         totsize = sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand );
    1336      438315 :         WHILE( GT_16( stop, start ) )
    1337             :         {
    1338      278438 :             current_len = sub( stop, start );
    1339             : 
    1340             :             /* Compute smoothed correction factor for PSD smoothing */
    1341             : 
    1342             :             /* msPeriodogSum[cnt] with format 16Q15 */
    1343      278438 :             msPeriodogSum[cnt] = dotp_s_fx( msPeriodog + start, psize + start, current_len, CNG_HS );
    1344      278438 :             move32();
    1345             : 
    1346      278438 :             IF( msPeriodogSum[cnt] == 0 )
    1347             :             {
    1348           0 :                 hFdCngCom->msAlphaCor[cnt] = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha );
    1349           0 :                 move32();
    1350             :             }
    1351             :             ELSE
    1352             :             {
    1353             :                 /* calculate scalar with normalized msPeriodogSum[cnt], exponent -2*s1 */
    1354      278438 :                 s1 = norm_l( msPeriodogSum[cnt] );
    1355      278438 :                 msPeriodogSum16 = round_fx_sat( L_shl( msPeriodogSum[cnt], s1 ) );
    1356      278438 :                 scalar = L_mult( msPeriodogSum16, msPeriodogSum16 );
    1357             : 
    1358             :                 /* calculate difference, both elements in 16Q15 format, use absolute value
    1359             :                    to avoid -1.0 x -1.0 multiplications later */
    1360      278438 :                 scalar2 = L_abs( L_sub( msPsdSum[cnt], msPeriodogSum[cnt] ) );
    1361             : 
    1362      278438 :                 s2 = WORD32_BITS - 1;
    1363      278438 :                 move16();
    1364      278438 :                 if ( scalar2 != 0 )
    1365             :                 {
    1366             :                     /* use absolute value to avoid -1.0 x -1.0 multiplications */
    1367      251662 :                     s2 = norm_l( scalar2 );
    1368             :                 }
    1369             : #ifdef ISSUE_1836_replace_overflow_libcom
    1370      278438 :                 scalar216 = round_fx_sat( L_shl( scalar2, s2 ) );
    1371             : #else
    1372             :                 scalar216 = round_fx_o( L_shl_o( scalar2, s2, &Overflow ), &Overflow );
    1373             : #endif
    1374      278438 :                 scalar2 = L_mult( scalar216, scalar216 );
    1375             : 
    1376             :                 /* find common exponent */
    1377      278438 :                 tmp16_1 = sub( s1, s2 );
    1378      278438 :                 tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
    1379      278438 :                 if ( tmp16_1 < 0 )
    1380             :                 {
    1381      257512 :                     scalar2 = L_shr( scalar2, tmp16 );
    1382             :                 }
    1383      278438 :                 if ( tmp16_1 > 0 )
    1384             :                 {
    1385        8193 :                     scalar = L_shr( scalar, tmp16 );
    1386             :                 }
    1387             : 
    1388             : 
    1389             :                 /* add scalar and scalar2, avoid overflows */
    1390      278438 :                 scalar = L_shr( scalar, 1 );
    1391      278438 :                 scalar2 = L_shr( scalar2, 1 );
    1392      278438 :                 scalar3 = L_add( scalar, scalar2 );
    1393             : 
    1394             :                 /* calculate division */
    1395      278438 :                 scalar16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar, scalar3, &s3 );
    1396      278438 :                 s3 = s_max( s3, -( WORD16_BITS - 1 ) );
    1397      278438 :                 scalar16 = shl( scalar16, s3 );
    1398      278438 :                 scalar16 = s_max( scalar16, MSALPHACORMAX );
    1399             : 
    1400      278438 :                 hFdCngCom->msAlphaCor[cnt] = Madd_32_16( L_mult( scalar16, msAlphaCorAlpha2 ), hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha );
    1401      278438 :                 move32();
    1402             :             }
    1403             : 
    1404             :             /* Compute SNR */
    1405             : 
    1406             :             /* msPeriodogSum[cnt] with format 16Q15 */
    1407             :             Word16 msNoiseFloor16tmp[NPART_SHAPING];
    1408      278438 :             IF( enc_dec == ENC )
    1409             :             {
    1410      237122 :                 Copy_Scale_sig32_16( msNoiseFloor, msNoiseFloor16tmp, NPART, 0 );
    1411             :             }
    1412             :             ELSE
    1413             :             {
    1414       41316 :                 Copy_Scale_sig32_16( msNoiseFloor, msNoiseFloor16tmp, NPART_SHAPING, 0 );
    1415             :             }
    1416      278438 :             snr = dotp_s_fx( &msNoiseFloor16tmp[start], psize + start, current_len, CNG_HS );
    1417             : 
    1418      278438 :             IF( GT_32( L_shr( Mpy_32_16_1( msPsdSum[cnt], 18431 /*0.56246299817 Q15*/ ), 13 ), snr ) )
    1419             :             {
    1420           0 :                 tmp0 = BASOP_Util_Log2( msPsdSum[cnt] );
    1421           0 :                 tmp1 = BASOP_Util_Log2( snr );
    1422           0 :                 tmp1 = L_sub( tmp0, tmp1 );
    1423           0 :                 tmp1 = Mpy_32_16_1( tmp1, MSSNREXP );
    1424           0 :                 msAlphaHatMin2 = BASOP_Util_InvLog2( tmp1 );
    1425             :             }
    1426             :             ELSE
    1427             :             {
    1428      278438 :                 msAlphaHatMin2 = MSALPHAHATMIN;
    1429      278438 :                 move32();
    1430             :             }
    1431      278438 :             scalar = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], MSALPHAMAX );
    1432             : 
    1433     5611009 :             FOR( j = start; j < stop; j++ )
    1434             :             {
    1435             :                 /* Compute optimal smoothing parameter for PSD estimation */
    1436     5332571 :                 test();
    1437     5332571 :                 IF( ( scalar == 0 ) || ( msNoiseFloor[j] == 0 ) )
    1438             :                 {
    1439          83 :                     msAlpha[j] = msAlphaHatMin2;
    1440          83 :                     move32();
    1441             :                 }
    1442             :                 ELSE
    1443             :                 {
    1444             :                     /* calculate scalar2 with normalized msNoiseFloor[j], exponent -2*s1 */
    1445     5332488 :                     s1 = WORD16_BITS - 1;
    1446     5332488 :                     move16();
    1447     5332488 :                     if ( msNoiseFloor16tmp[j] != 0 )
    1448             :                     {
    1449     5332488 :                         s1 = norm_s( msNoiseFloor16tmp[j] );
    1450             :                     }
    1451     5332488 :                     msNoiseFloor16 = shl( msNoiseFloor16tmp[j], s1 );
    1452     5332488 :                     scalar2 = L_mult( msNoiseFloor16, msNoiseFloor16 );
    1453             : 
    1454             :                     /* calculate difference, both elements in 6Q9 format, use absolute value
    1455             :                        to avoid -1.0 x -1.0 multiplications later */
    1456     5332488 :                     scalar316 = abs_s( sub( msPsd[j], msNoiseFloor16tmp[j] ) );
    1457             : 
    1458     5332488 :                     s2 = WORD16_BITS - 1;
    1459     5332488 :                     move16();
    1460     5332488 :                     if ( scalar316 != 0 )
    1461             :                     {
    1462             :                         /* use absolute value to avoid -1.0 x -1.0 multiplications */
    1463     4460724 :                         s2 = norm_s( scalar316 );
    1464             :                     }
    1465     5332488 :                     scalar316 = shl( scalar316, s2 );
    1466     5332488 :                     scalar3 = L_mult( scalar316, scalar316 );
    1467             : 
    1468             :                     /* find common exponent */
    1469     5332488 :                     tmp16_1 = sub( s1, s2 );
    1470     5332488 :                     tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
    1471     5332488 :                     if ( tmp16_1 < 0 )
    1472             :                     {
    1473     4438174 :                         scalar3 = L_shr( scalar3, tmp16 );
    1474             :                     }
    1475     5332488 :                     if ( tmp16_1 > 0 )
    1476             :                     {
    1477      667063 :                         scalar2 = L_shr( scalar2, tmp16 );
    1478             :                     }
    1479             : 
    1480             :                     /* add scalar2 and scalar3, avoid overflows */
    1481     5332488 :                     scalar2 = L_shr( scalar2, 1 );
    1482     5332488 :                     scalar3 = L_shr( scalar3, 1 );
    1483     5332488 :                     scalar3 = L_add( scalar2, scalar3 );
    1484             : 
    1485             :                     /* calculate division */
    1486     5332488 :                     tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar2, scalar3, &s3 );
    1487     5332488 :                     scalar2 = Mpy_32_16_1( scalar, tmp16 );
    1488     5332488 :                     s3 = s_max( s3, -( WORD32_BITS - 1 ) );
    1489     5332488 :                     scalar2 = L_shl( scalar2, s3 );
    1490     5332488 :                     msAlpha[j] = L_max( scalar2, msAlphaHatMin2 );
    1491     5332488 :                     move32();
    1492             :                 }
    1493             : 
    1494             :                 /* Compute the PSD (smoothed periodogram) in each band */
    1495     5332571 :                 msPsd[j] = round_fx( Madd_32_16( Mpy_32_16_1( msAlpha[j], msPsd[j] ), L_sub( 2147483647l /*1.0 Q31*/, msAlpha[j] ), msPeriodog[j] ) );
    1496     5332571 :                 move16();
    1497             :             }
    1498      278438 :             msPsdSum[cnt] = dotp_s_fx( msPsd + start, psize + start, current_len, CNG_HS );
    1499      278438 :             move32();
    1500             : 
    1501      278438 :             QeqInvAv = 0l /*0.0 Q31*/;
    1502      278438 :             move32();
    1503             : 
    1504             :             /* scalar: 7Q24 format */
    1505      278438 :             tmp = 1191182336l /*(float)(MSNUMSUBFR*MSSUBFRLEN)-1.0 Q24*/;
    1506      278438 :             move32();
    1507      278438 :             scalar = L_sub( tmp, L_mult( round_fx( tmp ), msM_win ) );
    1508             : 
    1509             :             /* scalar2: 4Q27 format */
    1510      278438 :             tmp = 1476395008l /*(float)MSSUBFRLEN-1.0 Q27*/;
    1511      278438 :             move32();
    1512      278438 :             scalar2 = L_sub( tmp, L_mult( round_fx( tmp ), msM_subwin ) );
    1513             : 
    1514     5611009 :             FOR( j = start; j < stop; j++ )
    1515             :             {
    1516             :                 /* Compute variance of PSD */
    1517     5332571 :                 tmp = L_min( msAlpha[j], MSBETAMAX_SQRT );
    1518             : 
    1519     5332571 :                 s1 = WORD32_BITS - 1;
    1520     5332571 :                 move16();
    1521     5332571 :                 if ( tmp != 0 )
    1522             :                 {
    1523     5332571 :                     s1 = norm_l( tmp );
    1524             :                 }
    1525     5332571 :                 s2 = shl( s1, 1 );
    1526             : 
    1527     5332571 :                 s2 = s_min( s2, WORD32_BITS - 1 );
    1528             : 
    1529             :                 /* beta: scaled by s2 */
    1530             : #ifdef ISSUE_1836_replace_overflow_libcom
    1531     5332571 :                 tmp16 = round_fx_sat( L_shl( tmp, s1 ) );
    1532             : #else
    1533             :                 tmp16 = round_fx_o( L_shl_o( tmp, s1, &Overflow ), &Overflow );
    1534             : #endif
    1535     5332571 :                 beta = mult_r( tmp16, tmp16 );
    1536             : 
    1537             :                 /* scalar3: scaled by s3 */
    1538     5332571 :                 scalar3 = L_sub( L_deposit_l( msPsd[j] ), L_deposit_l( msPsdFirstMoment[j] ) );
    1539     5332571 :                 s3 = norm_l( scalar3 );
    1540     5332571 :                 scalar3 = L_shl( scalar3, s3 );
    1541             : 
    1542             :                 /* msPsdFirstMoment: 6Q9   */
    1543     5332571 :                 tmp = L_msu( L_mult( beta, msPsdFirstMoment[j] ), beta, msPsd[j] );
    1544     5332571 :                 msPsdFirstMoment[j] = add( round_fx( L_shr( tmp, s2 ) ), msPsd[j] );
    1545     5332571 :                 move16();
    1546             : 
    1547             :                 /* msPsdSecondMoment: 12Q19   */
    1548     5332571 :                 tmp0 = L_shr( Mpy_32_16_r( msPsdSecondMoment[j], beta ), s2 );
    1549     5332571 :                 tmp1 = Mpy_32_32( scalar3, scalar3 );
    1550     5332571 :                 tmp1 = L_shr( L_sub( tmp1, L_shr( Mpy_32_16_r( tmp1, beta ), s2 ) ), sub( shl( s3, 1 ), 32 ) );
    1551     5332571 :                 msPsdSecondMoment[j] = L_add( tmp0, tmp1 );
    1552     5332571 :                 move32();
    1553             : 
    1554             :                 /* Compute inverse of amount of degrees of freedom */
    1555     5332571 :                 QeqInv = MSQEQINVMAX;
    1556     5332571 :                 move16();
    1557             : 
    1558     5332571 :                 IF( msNoiseFloor[j] != 0 /*0.0 Q15*/ )
    1559             :                 {
    1560     5332488 :                     tmp = Mpy_32_32( msNoiseFloor[j], msNoiseFloor[j] );
    1561     5332488 :                     tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( msPsdSecondMoment[j], tmp, &s );
    1562             :                     /* consider factor of 2 */
    1563     5332488 :                     s = s_min( s_max( sub( s, 1 ), -( WORD16_BITS - 1 ) ), ( WORD16_BITS - 1 ) );
    1564     5332488 :                     if ( s < 0 )
    1565             :                     {
    1566     4710531 :                         QeqInv = shl( tmp16, s );
    1567             :                     }
    1568     5332488 :                     QeqInv = s_min( QeqInv, MSQEQINVMAX );
    1569             :                 }
    1570     5332571 :                 QeqInvAv = L_add( QeqInvAv, L_mult( QeqInv, psize[j] ) );
    1571             : 
    1572             :                 /* Compute bias correction Bmin */
    1573     5332571 :                 tmp0 = Mpy_32_16_1( scalar, QeqInv );
    1574     5332571 :                 tmp1 = L_msu( 1073741824l /*0.5 Q31*/, msM_win, QeqInv );
    1575     5332571 :                 tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
    1576     5332571 :                 msBminWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), add( s, 7 - 4 ) ) );
    1577     5332571 :                 move32();
    1578             : 
    1579     5332571 :                 tmp0 = Mpy_32_16_1( scalar2, QeqInv );
    1580     5332571 :                 tmp1 = L_msu( 1073741824l /*0.5 Q31*/, msM_subwin, QeqInv );
    1581     5332571 :                 tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
    1582     5332571 :                 msBminSubWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), s ) );
    1583     5332571 :                 move32();
    1584             :             }
    1585             : 
    1586      278438 :             inv_totsize = BASOP_Util_Divide3232_uu_1616_Scale( 1, totsize, &s );
    1587      278438 :             QeqInvAv = Mpy_32_16_1( QeqInvAv, inv_totsize );
    1588      278438 :             QeqInvAv = L_shl( QeqInvAv, s );
    1589      278438 :             hFdCngCom->msQeqInvAv[cnt] = QeqInvAv;
    1590      278438 :             move32();
    1591             : 
    1592             :             /* New minimum? */
    1593             : 
    1594             :             /* exponent QeqInvAv: CNG_S, exponent MSAV: (4>>1) */
    1595      278438 :             s = CNG_S + 2 * MSAV_EXP;
    1596      278438 :             move16();
    1597      278438 :             BminCorr = Mpy_32_16_1( Sqrt32( QeqInvAv, &s ), MSAV );
    1598      278438 :             BminCorr = L_shl( BminCorr, sub( s, 1 ) );
    1599             : 
    1600             :             /* exponent BminCorr: 1 */
    1601      278438 :             BminCorr = L_add( BminCorr, 1073741824l /*0.5 Q31*/ );
    1602             : 
    1603     5611009 :             FOR( j = start; j < stop; j++ )
    1604             :             {
    1605             :                 /* exponent scalar: CNG_S+1 */
    1606     5332571 :                 scalar = Mpy_32_16_1( BminCorr, msPsd[j] );
    1607             : 
    1608             :                 /* exponent scalar2: CNG_S+1+4 */
    1609     5332571 :                 scalar2 = Mpy_32_32( scalar, msBminWin[j] );
    1610             : 
    1611     5332571 :                 msNewMinFlag[j] = 0;
    1612     5332571 :                 move16();
    1613     5332571 :                 IF( LT_32( scalar2, msCurrentMin[j] ) /*0.0 Q31*/ )
    1614             :                 {
    1615     2041974 :                     msNewMinFlag[j] = 1;
    1616     2041974 :                     move16();
    1617             :                     /* exponent msCurrentMin[j]: CNG_S+1+4 */
    1618     2041974 :                     msCurrentMin[j] = scalar2;
    1619     2041974 :                     move32();
    1620             :                     /* exponent msCurrentMinSubWindow[j]: CNG_S */
    1621             :                     BASOP_SATURATE_WARNING_OFF_EVS;
    1622             : #ifdef ISSUE_1836_replace_overflow_libcom
    1623     2041974 :                     msCurrentMinSubWindow[j] = L_shl_sat( Mpy_32_32( scalar, msBminSubWin[j] ), 5 );
    1624             : #else
    1625             :                     msCurrentMinSubWindow[j] = L_shl_o( Mpy_32_32( scalar, msBminSubWin[j] ), 5, &Overflow );
    1626             : #endif
    1627     2041974 :                     move32();
    1628             :                     BASOP_SATURATE_WARNING_ON_EVS;
    1629             :                 }
    1630             :             }
    1631             : 
    1632             :             /* This is used later to identify local minima */
    1633      278438 :             IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1634             :             {
    1635       56238 :                 FOR( i = 0; i < 3; i++ )
    1636             :                 {
    1637       47805 :                     IF( LT_32( hFdCngCom->msQeqInvAv[cnt], L_shr( L_deposit_h( msQeqInvAv_thresh[i] ), CNG_S ) ) /*0.0 Q31*/ )
    1638             :                     {
    1639       15566 :                         BREAK;
    1640             :                     }
    1641             :                 }
    1642             :                 /* format 1Q30 */
    1643       23999 :                 hFdCngCom->msSlope[cnt] = msNoiseSlopeMax[i];
    1644       23999 :                 move32();
    1645             :             }
    1646             : 
    1647             :             /* Consider the FFT and CLDFB bands separately */
    1648      278438 :             start = stop;
    1649      278438 :             move16();
    1650      278438 :             stop = len;
    1651      278438 :             move16();
    1652      278438 :             totsize = sub( hFdCngCom->stopBand, hFdCngCom->stopFFTbin );
    1653      278438 :             cnt = add( cnt, 1 );
    1654             :         } /*while (stop > start)*/
    1655             : 
    1656             :         /* Update minimum between sub windows */
    1657      159877 :         test();
    1658      159877 :         IF( GT_16( hFdCngCom->msFrCnt, 1 ) && LT_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1659             :         {
    1660     4526489 :             FOR( j = 0; j < len; j++ )
    1661             :             {
    1662     4394318 :                 if ( msNewMinFlag[j] > 0 )
    1663             :                 {
    1664     1439464 :                     msLocalMinFlag[j] = 1;
    1665     1439464 :                     move16();
    1666             :                 }
    1667     4394318 :                 if ( LT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ )
    1668             :                 {
    1669             :                     /* msCurrentMinOut[j] scaled with CNG_S */
    1670      539035 :                     msCurrentMinOut[j] = msCurrentMinSubWindow[j];
    1671      539035 :                     move32();
    1672             :                 }
    1673             :             }
    1674             :             /* Get the current noise floor */
    1675      132171 :             Copy32( msCurrentMinOut, msNoiseFloor, len );
    1676             :         }
    1677             :         ELSE /* sub window complete */
    1678             :         {
    1679       27706 :             IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1680             :             {
    1681             :                 /* Collect buffers */
    1682       13902 :                 Copy32( msCurrentMinSubWindow, msMinBuf + len * hFdCngCom->msMinBufferPtr, len );
    1683             : 
    1684             :                 /* Compute minimum among all buffers */
    1685       13902 :                 Copy32( msMinBuf, msCurrentMinOut, len );
    1686       13902 :                 ptr = msMinBuf + len;
    1687       83412 :                 FOR( i = 1; i < MSNUMSUBFR; i++ )
    1688             :                 {
    1689     2428420 :                     FOR( j = 0; j < len; j++ )
    1690             :                     {
    1691     2358910 :                         if ( LT_32( *ptr, msCurrentMinOut[j] ) /*0.0 Q31*/ )
    1692             :                         {
    1693      538711 :                             msCurrentMinOut[j] = *ptr;
    1694      538711 :                             move32();
    1695             :                         }
    1696     2358910 :                         ptr++;
    1697             :                     }
    1698             :                 }
    1699             : 
    1700             :                 /* Take over local minima */
    1701       13902 :                 slope = hFdCngCom->msSlope[0];
    1702       13902 :                 move16();
    1703      485684 :                 FOR( j = 0; j < len; j++ )
    1704             :                 {
    1705      471782 :                     if ( EQ_16( j, lenFFT ) )
    1706             :                     {
    1707       10097 :                         slope = hFdCngCom->msSlope[1];
    1708       10097 :                         move16();
    1709             :                     }
    1710      471782 :                     test();
    1711      471782 :                     test();
    1712      471782 :                     test();
    1713      471782 :                     IF( ( msLocalMinFlag[j] != 0 ) && ( msNewMinFlag[j] == 0 ) && ( LT_32( L_shr( msCurrentMinSubWindow[j], 1 ), Mpy_32_16_1( msCurrentMinOut[j], slope ) ) /*0.0 Q31*/ ) && ( GT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ ) )
    1714             :                     {
    1715       58295 :                         msCurrentMinOut[j] = msCurrentMinSubWindow[j];
    1716       58295 :                         move32();
    1717       58295 :                         i = j;
    1718       58295 :                         move16();
    1719      408065 :                         FOR( k = 0; k < MSNUMSUBFR; k++ )
    1720             :                         {
    1721      349770 :                             msMinBuf[i] = msCurrentMinOut[j];
    1722      349770 :                             move32();
    1723      349770 :                             i = add( i, len );
    1724             :                         }
    1725             :                     }
    1726             :                 }
    1727             : 
    1728             :                 /* Reset */
    1729       13902 :                 set16_fx( msLocalMinFlag, 0, len );
    1730       13902 :                 set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );
    1731             : 
    1732             :                 /* Get the current noise floor */
    1733       13902 :                 Copy32( msCurrentMinOut, msNoiseFloor, len );
    1734             :             }
    1735             :         }
    1736             : 
    1737             : 
    1738             :         /* Detect sudden offsets based on the FFT bins (core bandwidth) */
    1739      159877 :         IF( GT_32( Mpy_32_16_1( msPsdSum[0], 655 /*0.02 Q15*/ ), msPeriodogSum[0] ) /*0.0 Q31*/ )
    1740             :         {
    1741         168 :             IF( hFdCngCom->offsetflag > 0 )
    1742             :             {
    1743          75 :                 Copy( msPeriodog, msPsd, len );
    1744        4105 :                 FOR( j = 0; j < len; j++ )
    1745             :                 {
    1746        4030 :                     msCurrentMinOut[j] = L_deposit_h( msPeriodog[j] );
    1747        4030 :                     move32();
    1748             :                 }
    1749          75 :                 set32_fx( hFdCngCom->msAlphaCor, 2147483647l /*1.0 Q31*/, cnt );
    1750          75 :                 set32_fx( msAlpha, 0l /*0.0 Q31*/, len );
    1751          75 :                 Copy( msPeriodog, msPsdFirstMoment, len );
    1752          75 :                 set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
    1753             : 
    1754          75 :                 msPsdSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
    1755          75 :                 move32();
    1756          75 :                 IF( LT_16( lenFFT, len ) )
    1757             :                 {
    1758          15 :                     msPsdSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
    1759          15 :                     move32();
    1760             :                 }
    1761             :             }
    1762         168 :             hFdCngCom->offsetflag = 1;
    1763         168 :             move16();
    1764             :         }
    1765             :         ELSE
    1766             :         {
    1767      159709 :             hFdCngCom->offsetflag = 0;
    1768      159709 :             move16();
    1769             :         }
    1770             : 
    1771             : 
    1772             :         /* Increment frame counter */
    1773      159877 :         IF( EQ_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1774             :         {
    1775       13902 :             hFdCngCom->msFrCnt = 1;
    1776       13902 :             move16();
    1777       13902 :             hFdCngCom->msMinBufferPtr = add( hFdCngCom->msMinBufferPtr, 1 );
    1778       13902 :             move16();
    1779       13902 :             if ( EQ_16( hFdCngCom->msMinBufferPtr, MSNUMSUBFR ) )
    1780             :             {
    1781        1959 :                 hFdCngCom->msMinBufferPtr = 0;
    1782        1959 :                 move16();
    1783             :             }
    1784             :         }
    1785             :         ELSE
    1786             :         {
    1787      145975 :             hFdCngCom->msFrCnt = add( hFdCngCom->msFrCnt, 1 );
    1788      145975 :             move16();
    1789             :         }
    1790             :         Word64 tmp64;
    1791             :         /* Smooth noise estimate during CNG phases */
    1792     5492448 :         FOR( j = 0; j < len; j++ )
    1793             :         {
    1794     5332571 :             tmp64 = W_add( W_mult_32_16( msNoiseEst[j], 31130 /*0.95 Q15*/ ), W_mult_32_16( msNoiseFloor[j], 1638 /*0.05 Q15*/ ) );
    1795     5332571 :             msNoiseEst[j] = W_extract_h( W_shl( tmp64, 16 ) ); // Q25
    1796     5332571 :             move32();
    1797             :         }
    1798             :     }
    1799      166914 :     IF( EQ_16( enc_dec, DEC ) && EQ_16( element_mode, IVAS_CPE_TD ) )
    1800             :     {
    1801             :         // v_multc(msNoiseEst, 1.4125f, msNoiseEst, NPART_SHAPING);
    1802           0 :         v_multc_att32( msNoiseEst, 23142, msNoiseEst, NPART_SHAPING );
    1803             :     }
    1804             :     /* Collect buffers */
    1805      166914 :     Copy( msPeriodog, msPeriodogBuf + len * ( *msPeriodogBufPtr ), len );
    1806             : 
    1807      166914 :     *msPeriodogBufPtr = add( *msPeriodogBufPtr, 1 );
    1808      166914 :     move16();
    1809      166914 :     if ( EQ_16( *msPeriodogBufPtr, MSBUFLEN ) )
    1810             :     {
    1811       32996 :         ( *msPeriodogBufPtr ) = 0;
    1812       32996 :         move16();
    1813             :     }
    1814             : 
    1815             :     /* Upper limit the noise floors with the averaged input energy */
    1816     5834604 :     FOR( j = 0; j < len; j++ )
    1817             :     {
    1818     5667690 :         scalar = L_mult( msPeriodogBuf[j], 6554 /*1.0/MSBUFLEN Q15*/ );
    1819             : 
    1820    28338450 :         FOR( i = j + len; i < MSBUFLEN * len; i += len )
    1821             :         {
    1822    22670760 :             scalar = L_mac( scalar, msPeriodogBuf[i], 6554 /*1.0/MSBUFLEN Q15*/ );
    1823             :         }
    1824     5667690 :         if ( GT_32( msNoiseEst[j], scalar ) /*0.0 Q15*/ )
    1825             :         {
    1826     1411118 :             msNoiseEst[j] = scalar;
    1827     1411118 :             move32();
    1828             :         }
    1829             : 
    1830     5667690 :         assert( msNoiseEst[j] >= 0 /*0.0 Q15*/ );
    1831             :     }
    1832      166914 : }
    1833             : /*-------------------------------------------------------------------
    1834             :  * apply_scale()
    1835             :  *
    1836             :  * Apply bitrate-dependent scale
    1837             :  *-------------------------------------------------------------------*/
    1838       31442 : void apply_scale(
    1839             :     Word32 *scale,                 /* o  : scalefactor             */
    1840             :     const Word16 bwmode,           /* i  : audio bandwidth         */
    1841             :     const Word32 bitrate,          /* i  : Bit rate                */
    1842             :     const SCALE_SETUP *scaleTable, /* i  : Scale table Q7             */
    1843             :     const Word16 scaleTableSize    /* i  : Size of scale table     */
    1844             : )
    1845             : {
    1846             :     Word16 i;
    1847             :     // PMT("Verifiy if the basop ued are ok for stereo too")
    1848      294488 :     FOR( i = 0; i < scaleTableSize; i++ )
    1849             :     {
    1850      294488 :         cast16();
    1851      294488 :         IF( s_and( (Word16) EQ_16( bwmode, (Word16) scaleTable[i].bwmode ),
    1852             :                    s_and( L_sub( bitrate, scaleTable[i].bitrateFrom ) >= 0,
    1853             :                           L_sub( bitrate, scaleTable[i].bitrateTo ) < 0 ) ) )
    1854             :         {
    1855       31442 :             BREAK;
    1856             :         }
    1857             :     }
    1858             : 
    1859             :     {
    1860       31442 :         *scale = L_add( *scale, L_deposit_h( scaleTable[i].scale ) );
    1861       31442 :         move32();
    1862             :     }
    1863       31442 : }
    1864             : 
    1865             : /*-------------------------------------------------------------------
    1866             :  * apply_scale_ind()
    1867             :  *
    1868             :  * Apply bitrate-dependent scale
    1869             :  * returns index of scaleTable
    1870             :  *-------------------------------------------------------------------*/
    1871           0 : Word16 apply_scale_ind(
    1872             :     Word32 *scale,                 /* o  : scalefactor             */
    1873             :     const Word16 bwmode,           /* i  : audio bandwidth         */
    1874             :     const Word32 bitrate,          /* i  : Bit rate                */
    1875             :     const SCALE_SETUP *scaleTable, /* i  : Scale table             */
    1876             :     const Word16 scaleTableSize    /* i  : Size of scale table     */
    1877             : )
    1878             : {
    1879             :     Word16 i;
    1880             :     // PMT("Verifiy if the basop ued are ok for stereo too")
    1881           0 :     FOR( i = 0; i < scaleTableSize; i++ )
    1882             :     {
    1883           0 :         cast16();
    1884           0 :         IF( s_and( (Word16) EQ_16( bwmode, (Word16) scaleTable[i].bwmode ),
    1885             :                    s_and( L_sub( bitrate, scaleTable[i].bitrateFrom ) >= 0,
    1886             :                           L_sub( bitrate, scaleTable[i].bitrateTo ) < 0 ) ) )
    1887             :         {
    1888           0 :             BREAK;
    1889             :         }
    1890             :     }
    1891             : 
    1892             :     {
    1893           0 :         *scale = L_add( *scale, L_deposit_h( scaleTable[i].scale ) );
    1894           0 :         move32();
    1895             :     }
    1896           0 :     return i;
    1897             : }
    1898             : 
    1899      172328 : void apply_scale_ivas_fx(
    1900             :     Word32 *scale,                 /* o  : scalefactor             */
    1901             :     const Word16 bwmode,           /* i  : audio bandwidth         */
    1902             :     const Word32 bitrate,          /* i  : Bit rate                */
    1903             :     const SCALE_SETUP *scaleTable, /* i  : Scale table Q7             */
    1904             :     const Word16 scaleTableSize,   /* i  : Size of scale table     */
    1905             :     Word16 *index )
    1906             : {
    1907             :     Word16 i;
    1908             :     // PMT("Verifiy if the basop ued are ok for stereo too")
    1909     1816827 :     FOR( i = 0; i < scaleTableSize; i++ )
    1910             :     {
    1911     1816827 :         cast16();
    1912     1816827 :         IF( s_and( (Word16) EQ_16( bwmode, (Word16) scaleTable[i].bwmode ),
    1913             :                    s_and( L_sub( bitrate, scaleTable[i].bitrateFrom ) >= 0,
    1914             :                           L_sub( bitrate, scaleTable[i].bitrateTo ) < 0 ) ) )
    1915             :         {
    1916      172328 :             BREAK;
    1917             :         }
    1918             :     }
    1919      172328 :     assert( i < scaleTableSize );
    1920             : 
    1921      172328 :     *scale = L_add( *scale, L_deposit_h( scaleTable[i].scale ) );
    1922      172328 :     move32();
    1923      172328 :     *index = i;
    1924      172328 :     move16();
    1925      172328 : }
    1926             : /*-------------------------------------------------------------------
    1927             :  * bandcombinepow()
    1928             :  *
    1929             :  * Compute the power for each partition
    1930             :  *-------------------------------------------------------------------*/
    1931      180116 : void bandcombinepow(
    1932             :     const Word32 *bandpow,    /* i  : Power for each band */
    1933             :     const Word16 exp_bandpow, /* i  : exponent of bandpow */
    1934             :     const Word16 nband,       /* i  : Number of bands */
    1935             :     Word16 *part,             /* i  : Partition upper boundaries (band indices starting from 0) */
    1936             :     const Word16 npart,       /* i  : Number of partitions */
    1937             :     const Word16 *psize_inv,  /* i  : Inverse partition sizes */
    1938             :     Word32 *partpow,          /* o  : Power for each partition */
    1939             :     Word16 *exp_partpow )
    1940             : {
    1941             : 
    1942             :     Word16 i, p;
    1943             :     Word32 temp;
    1944             :     Word16 smin, len, prev_part;
    1945             :     Word16 facTabExp[NPART_SHAPING];
    1946             : 
    1947             : 
    1948      180116 :     IF( EQ_16( nband, npart ) )
    1949             :     {
    1950           0 :         Copy32( bandpow, partpow, nband ); // Q(31 - exp_bandpow)
    1951           0 :         smin = 0;
    1952           0 :         move16();
    1953             :     }
    1954             :     ELSE
    1955             :     {
    1956             :         /* Compute the power in each partition */
    1957      180116 :         prev_part = -1;
    1958      180116 :         move16();
    1959     3870695 :         FOR( p = 0; p < npart; p++ )
    1960             :         {
    1961     3690579 :             len = sub( part[p], prev_part );
    1962     3690579 :             facTabExp[p] = getScaleFactor32( &bandpow[prev_part + 1], len );
    1963     3690579 :             move16();
    1964     3690579 :             prev_part = part[p];
    1965     3690579 :             move16();
    1966             :         }
    1967             : 
    1968      180116 :         smin = WORD32_BITS - 1;
    1969      180116 :         move16();
    1970     3870695 :         FOR( p = 0; p < npart; p++ )
    1971             :         {
    1972     3690579 :             smin = s_min( smin, facTabExp[p] );
    1973             :         }
    1974             : 
    1975      180116 :         i = 0;
    1976      180116 :         move16();
    1977     3870695 :         FOR( p = 0; p < npart; p++ )
    1978             :         {
    1979             :             /* Arithmetic averaging of power for all bins in partition */
    1980     3690579 :             temp = 0;
    1981     3690579 :             move32();
    1982    22561275 :             FOR( ; i <= part[p]; i++ )
    1983             :             {
    1984    18870696 :                 temp = L_add( temp, Mpy_32_16_1( L_shl( bandpow[i], facTabExp[p] ), psize_inv[p] ) );
    1985             :             }
    1986     3690579 :             partpow[p] = L_shr( temp, sub( facTabExp[p], smin ) );
    1987     3690579 :             move32();
    1988             :         }
    1989             :     }
    1990             : 
    1991      180116 :     *exp_partpow = sub( exp_bandpow, smin );
    1992      180116 :     move16();
    1993      180116 : }
    1994             : 
    1995             : /*-------------------------------------------------------------------
    1996             :  * scalebands()
    1997             :  *
    1998             :  * Scale partitions (with smoothing)
    1999             :  *-------------------------------------------------------------------*/
    2000        5523 : void scalebands(
    2001             :     const Word32 *partpow, /* i  : Power for each partition Qx*/
    2002             :     Word16 *part,          /* i  : Partition upper boundaries (band indices starting from 0) */
    2003             :     const Word16 npart,    /* i  : Number of partitions */
    2004             :     Word16 *midband,       /* i  : Central band of each partition */
    2005             :     const Word16 nFFTpart, /* i  : Number of FFT partitions */
    2006             :     const Word16 nband,    /* i  : Number of bands */
    2007             :     Word32 *bandpow,       /* o  : Power for each band Qx*/
    2008             :     const Word16 flag_fft_en )
    2009             : {
    2010             :     Word16 i, j, s, s1, nint, delta, delta_cmp, delta_s;
    2011             :     Word16 startBand, startPart, stopPart, stopPartM1;
    2012             :     Word32 tmp, val, partpowLD64, partpowLD64M1;
    2013             : 
    2014             : 
    2015        5523 :     j = 0;
    2016        5523 :     move16();
    2017        5523 :     delta = 0;
    2018        5523 :     move16();
    2019        5523 :     partpowLD64M1 = 0L; /* to avoid compilation warnings */
    2020        5523 :     move32();
    2021             : 
    2022             :     /* Interpolate the bin/band-wise levels from the partition levels */
    2023        5523 :     IF( EQ_16( nband, npart ) )
    2024             :     {
    2025           0 :         Copy32( partpow, bandpow, npart );
    2026             :     }
    2027             :     ELSE
    2028             :     {
    2029        5523 :         startBand = 0;
    2030        5523 :         move16();
    2031        5523 :         startPart = 0;
    2032        5523 :         move16();
    2033        5523 :         stopPart = nFFTpart;
    2034        5523 :         move16();
    2035             : 
    2036       15458 :         WHILE( startBand < nband )
    2037             :         {
    2038        9935 :             stopPartM1 = sub( stopPart, 1 );
    2039        9935 :             test();
    2040        9935 :             IF( ( flag_fft_en != 0 ) || ( GE_16( startPart, nFFTpart ) ) )
    2041             :             {
    2042             :                 /* first half partition */
    2043        9935 :                 j = startPart;
    2044        9935 :                 move16();
    2045             : 
    2046       37614 :                 FOR( i = startBand; i <= midband[j]; i++ )
    2047             :                 {
    2048       27679 :                     bandpow[i] = partpow[j];
    2049       27679 :                     move32();
    2050             :                 }
    2051        9935 :                 j = add( j, 1 );
    2052             : 
    2053             :                 /* inner partitions */
    2054        9935 :                 IF( LT_16( j, stopPart ) )
    2055             :                 {
    2056        9634 :                     partpowLD64M1 = BASOP_Util_Log2( partpow[j - 1] );
    2057             :                 }
    2058             : 
    2059             :                 /* Debug values to check this variable is set. */
    2060        9935 :                 delta = 0x4000; // 1.Q14
    2061        9935 :                 move16();
    2062        9935 :                 delta_cmp = 0x4000; // 1.Q14
    2063        9935 :                 move16();
    2064        9935 :                 s1 = 1;
    2065        9935 :                 move16();
    2066        9935 :                 s = 1;
    2067        9935 :                 move16();
    2068             : 
    2069      129040 :                 FOR( ; j < stopPart; j++ )
    2070             :                 {
    2071      119105 :                     nint = sub( midband[j], midband[j - 1] );
    2072             : 
    2073             :                     /* log-linear interpolation */
    2074      119105 :                     partpowLD64 = BASOP_Util_Log2( partpow[j] );
    2075      119105 :                     tmp = L_sub( partpowLD64, partpowLD64M1 );
    2076      119105 :                     tmp = Mpy_32_16_1( tmp, getNormReciprocalWord16( nint ) );
    2077             : 
    2078             :                     /* scale logarithmic value */
    2079      119105 :                     tmp = L_sub( tmp, DELTA_SHIFT_LD64 );
    2080      119105 :                     delta_s = DELTA_SHIFT;
    2081      119105 :                     move16();
    2082             : 
    2083      119194 :                     WHILE( tmp > 0 )
    2084             :                     {
    2085          89 :                         tmp = L_sub( tmp, 33554432l /*0.015625 Q31*/ ); // Q31
    2086          89 :                         delta_s = add( delta_s, 1 );
    2087             :                     }
    2088      119105 :                     delta_cmp = shl( 1, s_max( -15, sub( WORD16_BITS - 1, delta_s ) ) );
    2089             : 
    2090      119105 :                     tmp = BASOP_Util_InvLog2( tmp );
    2091      119105 :                     s = norm_l( tmp );
    2092      119105 :                     s1 = sub( delta_s, s );
    2093             : 
    2094      119105 :                     delta = round_fx_sat( L_shl_sat( tmp, s ) ); // Q(14+s)
    2095             :                     /* Choose scale such that the interpolation start and end point both are representable and add 1 additional bit hr. */
    2096      119105 :                     delta_s = sub( s_min( norm_l( partpow[j - 1] ), norm_l( partpow[j] ) ), 1 );
    2097      119105 :                     val = L_shl( partpow[j - 1], delta_s );
    2098     1506688 :                     FOR( ; i < midband[j]; i++ )
    2099             :                     {
    2100     1387583 :                         val = L_shl( Mpy_32_16_1( val, delta ), s1 );
    2101     1387583 :                         bandpow[i] = L_shr( val, delta_s );
    2102     1387583 :                         move32();
    2103             :                     }
    2104      119105 :                     bandpow[i++] = partpow[j];
    2105      119105 :                     move32();
    2106      119105 :                     partpowLD64M1 = partpowLD64;
    2107      119105 :                     move32();
    2108             :                 }
    2109             : 
    2110        9935 :                 IF( GT_16( shr( delta, s ), delta_cmp ) )
    2111             :                 {
    2112        2286 :                     delta = 0x4000; // 1.Q14
    2113        2286 :                     move16();
    2114        2286 :                     s1 = 1;
    2115        2286 :                     move16();
    2116             :                 }
    2117             : 
    2118             :                 /* last half partition */
    2119        9935 :                 val = partpow[stopPartM1]; // Qx
    2120        9935 :                 move32();
    2121      178989 :                 FOR( ; i <= part[stopPartM1]; i++ )
    2122             :                 {
    2123      169054 :                     val = L_shl( Mpy_32_16_1( val, delta ), s1 );
    2124      169054 :                     bandpow[i] = val; // Qx
    2125      169054 :                     move32();
    2126             :                 }
    2127             :             }
    2128        9935 :             startBand = add( part[stopPartM1], 1 );
    2129        9935 :             startPart = stopPart;
    2130        9935 :             move16();
    2131        9935 :             stopPart = npart;
    2132        9935 :             move16();
    2133             :         }
    2134             :     }
    2135        5523 : }
    2136             : 
    2137      100359 : void scalebands_fx(
    2138             :     const Word32 *partpow, /* i  : Power for each partition Qx*/
    2139             :     Word16 *part,          /* i  : Partition upper boundaries (band indices starting from 0) */
    2140             :     const Word16 npart,    /* i  : Number of partitions */
    2141             :     Word16 *midband,       /* i  : Central band of each partition */
    2142             :     const Word16 nFFTpart, /* i  : Number of FFT partitions */
    2143             :     const Word16 nband,    /* i  : Number of bands */
    2144             :     Word32 *bandpow,       /* o  : Power for each band Qx*/
    2145             :     const Word16 flag_fft_en )
    2146             : {
    2147             :     Word16 i, j, s, s1, nint, delta, delta_cmp, delta_s;
    2148             :     Word16 startBand, startPart, stopPart, stopPartM1;
    2149             :     Word32 tmp, val, partpowLD64, partpowLD64M1;
    2150             : 
    2151             : 
    2152      100359 :     j = 0;
    2153      100359 :     move16();
    2154      100359 :     delta = 0;
    2155      100359 :     move16();
    2156      100359 :     partpowLD64M1 = 0L; /* to avoid compilation warnings */
    2157      100359 :     move32();
    2158             : 
    2159             :     /* Interpolate the bin/band-wise levels from the partition levels */
    2160      100359 :     IF( EQ_16( nband, npart ) )
    2161             :     {
    2162           0 :         Copy32( partpow, bandpow, npart );
    2163             :     }
    2164             :     ELSE
    2165             :     {
    2166      100359 :         startBand = 0;
    2167      100359 :         move16();
    2168      100359 :         startPart = 0;
    2169      100359 :         move16();
    2170      100359 :         stopPart = nFFTpart;
    2171      100359 :         move16();
    2172             : 
    2173      202705 :         WHILE( LT_16( startBand, nband ) )
    2174             :         {
    2175      102346 :             stopPartM1 = sub( stopPart, 1 );
    2176      102346 :             test();
    2177      102346 :             IF( ( flag_fft_en != 0 ) || ( GE_16( startPart, nFFTpart ) ) )
    2178             :             {
    2179             :                 /* first half partition */
    2180      100365 :                 j = startPart;
    2181      100365 :                 move16();
    2182             : 
    2183      203872 :                 FOR( i = startBand; i <= midband[j]; i++ )
    2184             :                 {
    2185      103507 :                     bandpow[i] = partpow[j]; // Qx
    2186      103507 :                     move32();
    2187             :                 }
    2188      100365 :                 j = add( j, 1 );
    2189             : 
    2190             :                 /* inner partitions */
    2191      100365 :                 IF( j < stopPart )
    2192             :                 {
    2193      100152 :                     partpowLD64M1 = BASOP_Util_Log2( L_add( partpow[j - 1], DELTA_FX ) );
    2194             :                 }
    2195             : 
    2196             :                 /* Debug values to check this variable is set. */
    2197      100365 :                 delta = 0x4000; // 1.Q14
    2198      100365 :                 move16();
    2199      100365 :                 delta_cmp = 0x4000; // 1.Q14
    2200      100365 :                 move16();
    2201      100365 :                 s1 = 1;
    2202      100365 :                 move16();
    2203      100365 :                 s = 1;
    2204      100365 :                 move16();
    2205             : 
    2206     6050033 :                 FOR( ; j < stopPart; j++ )
    2207             :                 {
    2208     5949668 :                     nint = sub( midband[j], midband[j - 1] );
    2209             : 
    2210             :                     /* log-linear interpolation */
    2211     5949668 :                     IF( NE_32( partpow[j], MAX_32 ) )
    2212             :                     {
    2213     5949668 :                         partpowLD64 = BASOP_Util_Log2( L_add( partpow[j], DELTA_FX ) );
    2214             :                     }
    2215             :                     ELSE
    2216             :                     {
    2217           0 :                         partpowLD64 = BASOP_Util_Log2( partpow[j] );
    2218             :                     }
    2219     5949668 :                     tmp = L_sub( partpowLD64, partpowLD64M1 );
    2220     5949668 :                     tmp = Mpy_32_16_1( tmp, getNormReciprocalWord16( nint ) );
    2221             : 
    2222             :                     /* scale logarithmic value */
    2223     5949668 :                     tmp = L_sub( tmp, DELTA_SHIFT_LD64 );
    2224     5949668 :                     delta_s = DELTA_SHIFT;
    2225     5949668 :                     move16();
    2226             : 
    2227     6116716 :                     WHILE( tmp > 0 )
    2228             :                     {
    2229      167048 :                         tmp = L_sub( tmp, 33554432l /*0.015625 Q31*/ ); // Q31
    2230      167048 :                         delta_s = add( delta_s, 1 );
    2231             :                     }
    2232     5949668 :                     delta_cmp = shl( 1, s_max( -15, sub( WORD16_BITS - 1, delta_s ) ) );
    2233             : 
    2234     5949668 :                     tmp = BASOP_Util_InvLog2( tmp );
    2235     5949668 :                     s = norm_l( tmp );
    2236     5949668 :                     s1 = sub( delta_s, s );
    2237             : 
    2238     5949668 :                     delta = round_fx_sat( L_shl_sat( tmp, s ) ); // Q(14+s)
    2239             :                     /* Choose scale such that the interpolation start and end point both are representable and add 1 additional bit hr. */
    2240     5949668 :                     delta_s = sub( s_min( norm_l( partpow[j - 1] ), norm_l( partpow[j] ) ), 1 );
    2241     5949668 :                     val = L_shl( partpow[j - 1], delta_s );
    2242    27668142 :                     FOR( ; i < midband[j]; i++ )
    2243             :                     {
    2244    21718474 :                         val = L_shl( Mpy_32_16_1( val, delta ), s1 );
    2245    21718474 :                         bandpow[i] = L_shr( val, delta_s );
    2246    21718474 :                         move32();
    2247             :                     }
    2248     5949668 :                     bandpow[i++] = partpow[j]; // Qx
    2249     5949668 :                     move32();
    2250     5949668 :                     partpowLD64M1 = partpowLD64;
    2251     5949668 :                     move32();
    2252             :                 }
    2253             : 
    2254      100365 :                 IF( GT_16( shr( delta, s ), delta_cmp ) )
    2255             :                 {
    2256       13239 :                     delta = 0x4000; // 1.Q14
    2257       13239 :                     move16();
    2258       13239 :                     s1 = 1;
    2259       13239 :                     move16();
    2260             :                 }
    2261             : 
    2262             :                 /* last half partition */
    2263      100365 :                 val = partpow[stopPartM1]; // Qx
    2264      100365 :                 move32();
    2265      861331 :                 FOR( ; i <= part[stopPartM1]; i++ )
    2266             :                 {
    2267      760966 :                     test();
    2268      760966 :                     IF( val != 0 && delta != 0 )
    2269             :                     {
    2270      535178 :                         val = L_shl( Mpy_32_16_1( val, delta ), s1 );
    2271      535178 :                         IF( val == 0 )
    2272             :                         {
    2273        2847 :                             val = 1;
    2274        2847 :                             move32();
    2275             :                         }
    2276             :                     }
    2277             :                     ELSE
    2278             :                     {
    2279      225788 :                         val = 0;
    2280      225788 :                         move32();
    2281             :                     }
    2282      760966 :                     bandpow[i] = val; // Qx
    2283      760966 :                     move32();
    2284             :                 }
    2285             :             }
    2286      102346 :             startBand = add( part[stopPartM1], 1 );
    2287      102346 :             startPart = stopPart;
    2288      102346 :             move16();
    2289      102346 :             stopPart = npart;
    2290      102346 :             move16();
    2291             :         }
    2292             :     }
    2293      100359 : }
    2294             : 
    2295             : /*-------------------------------------------------------------------
    2296             :  * getmidbands()
    2297             :  *
    2298             :  * Get central band for each partition
    2299             :  *-------------------------------------------------------------------*/
    2300     1173160 : static void getmidbands(
    2301             :     const Word16 *part,     /* i  : Partition upper boundaries (band indices starting from 0) */
    2302             :     const Word16 npart,     /* i  : Number of partitions */
    2303             :     Word16 *midband,        /* o  : Central band of each partition */
    2304             :     Word16 *psize,          /* o  : Partition sizes */
    2305             :     Word16 *psize_norm,     /* o  : Partition sizes, fractional values */
    2306             :     Word16 *psize_norm_exp, /* o  : Exponent for fractional partition sizes */
    2307             :     Word16 *psize_inv       /* o  : Inverse of partition sizes */
    2308             : )
    2309             : {
    2310             :     Word16 j, max_psize, shift;
    2311             : #ifndef ISSUE_1836_replace_overflow_libcom
    2312             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
    2313             :     Flag Overflow = 0;
    2314             :     move32();
    2315             : #endif
    2316             : #endif
    2317             : 
    2318             : 
    2319     1173160 :     max_psize = psize[0];
    2320     1173160 :     move16();
    2321     1173160 :     /* first half partition */ move16();
    2322     1173160 :     midband[0] = part[0];
    2323     1173160 :     move16();
    2324     1173160 :     psize[0] = add( part[0], 1 );
    2325     1173160 :     move16();
    2326     1173160 :     psize_inv[0] = getNormReciprocalWord16( psize[0] );
    2327     1173160 :     move16();
    2328             :     /* inner partitions */
    2329    49178428 :     FOR( j = 1; j < npart; j++ )
    2330             :     {
    2331    48005268 :         midband[j] = shr( add( add( part[j - 1], 1 ), part[j] ), 1 );
    2332    48005268 :         move16();
    2333    48005268 :         psize[j] = sub( part[j], part[j - 1] );
    2334    48005268 :         move16();
    2335    48005268 :         psize_inv[j] = getNormReciprocalWord16( psize[j] );
    2336    48005268 :         move16();
    2337    48005268 :         if ( GT_16( psize[j], max_psize ) )
    2338             :         {
    2339    14623111 :             max_psize = psize[j];
    2340    14623111 :             move16();
    2341             :         }
    2342             :     }
    2343             : 
    2344     1173160 :     shift = 9;
    2345     1173160 :     move16();
    2346     1173160 :     *psize_norm_exp = sub( 15, shift );
    2347     1173160 :     move16();
    2348    50351588 :     FOR( j = 0; j < npart; j++ )
    2349             :     {
    2350             : #ifdef ISSUE_1836_replace_overflow_libcom
    2351    49178428 :         psize_norm[j] = shl_sat( psize[j], shift ); // Q(15 - psize_norm_exp)
    2352             : #else
    2353             :         psize_norm[j] = shl_o( psize[j], shift, &Overflow ); // Q(15 - psize_norm_exp)
    2354             : #endif
    2355    49178428 :         move16();
    2356             :     }
    2357             :     /* minimum_statistics needs fixed exponent of 6 */
    2358     1173160 :     assert( norm_s( -max_psize ) >= 9 );
    2359     1173160 : }
    2360             : 
    2361             : /*-------------------------------------------------------------------
    2362             :  * AnalysisSTFT()
    2363             :  *
    2364             :  * STFT analysis filterbank
    2365             :  *-------------------------------------------------------------------*/
    2366             : 
    2367          18 : void AnalysisSTFT(
    2368             :     const Word16 *timeDomainInput, /* i  : pointer to time signal Q(Q)*/
    2369             :     Word16 Q,
    2370             :     Word32 *fftBuffer,          /* o  : FFT bins */
    2371             :     Word16 *fftBuffer_exp,      /* i  : exponent of FFT bins */
    2372             :     HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
    2373             : )
    2374             : {
    2375             :     Word16 i, len;
    2376             :     Word16 len2;
    2377             :     const PWord16 *olapWin;
    2378             :     Word16 *olapBuffer;
    2379             : 
    2380             : 
    2381          18 :     assert( ( hFdCngCom->fftlen >> 1 ) == hFdCngCom->frameSize );
    2382             : 
    2383             :     /* pointer inititialization */
    2384          18 :     assert( hFdCngCom->olapBufferAna != NULL );
    2385          18 :     olapBuffer = hFdCngCom->olapBufferAna;
    2386          18 :     olapWin = hFdCngCom->olapWinAna;
    2387             : 
    2388             :     /* olapWin factor is scaled with one bit */
    2389          18 :     *fftBuffer_exp = 1;
    2390          18 :     move16();
    2391          18 :     len = sub( hFdCngCom->fftlen, hFdCngCom->frameSize );
    2392          18 :     assert( len <= 320 ); /* see size of olapBuffer */
    2393             : 
    2394             :     /* Window the signal */
    2395          18 :     len2 = shr( len, 1 );
    2396        2642 :     FOR( i = 0; i < len2; i++ )
    2397             :     {
    2398        2624 :         move32();
    2399        2624 :         move32();
    2400        2624 :         fftBuffer[i] = L_mult( olapBuffer[i], mult_r( olapWin[i].v.im, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
    2401        2624 :         fftBuffer[i + len2] = L_mult( olapBuffer[i + len2], mult_r( olapWin[len2 - 1 - i].v.re, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
    2402             :     }
    2403          18 :     len2 = shr( hFdCngCom->frameSize, 1 );
    2404        2642 :     FOR( i = 0; i < len2; i++ )
    2405             :     {
    2406        2624 :         move32();
    2407        2624 :         move32();
    2408        2624 :         fftBuffer[i + len] = L_mult( shr_sat( timeDomainInput[i], Q ), mult_r( olapWin[i].v.re, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
    2409        2624 :         fftBuffer[i + len + len2] = L_mult( shr_sat( timeDomainInput[i + len2], Q ), mult_r( olapWin[len2 - 1 - i].v.im, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
    2410             :     }
    2411             : 
    2412             :     /* Perform FFT */
    2413          18 :     BASOP_rfft( fftBuffer, hFdCngCom->fftlen, fftBuffer_exp, -1 );
    2414             : 
    2415        5266 :     FOR( i = 0; i < len; i++ )
    2416             :     {
    2417        5248 :         olapBuffer[i] = shr_sat( timeDomainInput[sub( hFdCngCom->frameSize, len ) + i], Q );
    2418        5248 :         move16();
    2419             :     }
    2420          18 : }
    2421             : 
    2422             : /*-------------------------------------------------------------------
    2423             :  * AnalysisSTFT_fx()
    2424             :  *
    2425             :  * STFT analysis filterbank
    2426             :  *-------------------------------------------------------------------*/
    2427       91649 : void AnalysisSTFT_fx(
    2428             :     const Word16 *timeDomainInput, // Q(Q)
    2429             :     Word16 Q,
    2430             :     Word32 *fftBuffer,          /* o  : FFT bins */
    2431             :     Word16 *fftBuffer_exp,      /* i  : exponent of FFT bins */
    2432             :     HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
    2433             : )
    2434             : {
    2435             :     Word16 i, len;
    2436             :     const Word32 *olapWin;
    2437             :     Word16 *olapBuffer;
    2438             : 
    2439       91649 :     assert( ( hFdCngCom->fftlen >> 1 ) == hFdCngCom->frameSize );
    2440             : 
    2441             :     /* pointer inititialization */
    2442       91649 :     assert( hFdCngCom->olapBufferAna != NULL );
    2443       91649 :     olapBuffer = hFdCngCom->olapBufferAna_fx;
    2444       91649 :     olapWin = hFdCngCom->olapWinAna_fx;
    2445             : 
    2446             :     /* olapWin factor is scaled with one bit */
    2447       91649 :     *fftBuffer_exp = 1;
    2448       91649 :     move16();
    2449       91649 :     len = sub( hFdCngCom->fftlen, hFdCngCom->frameSize );
    2450       91649 :     assert( len <= 320 ); /* see size of olapBuffer */
    2451             : 
    2452             :     /* Window the signal */
    2453       91649 :     Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, len );
    2454             : 
    2455    26636097 :     FOR( i = 0; i < hFdCngCom->frameSize; i++ )
    2456             :     {
    2457    26544448 :         olapBuffer[i + len] = shr_sat( timeDomainInput[i], Q ); // Values above MAX_16 seen with 10dB tests in float code
    2458    26544448 :         move16();
    2459             :     }
    2460             : 
    2461             :     /* Window the signal */
    2462       91649 :     v_L_mult_3216( olapWin, olapBuffer, fftBuffer, hFdCngCom->fftlen );
    2463             : 
    2464    53180545 :     FOR( i = 0; i < hFdCngCom->fftlen; i++ )
    2465             :     {
    2466    53088896 :         fftBuffer[i] = L_shr( fftBuffer[i], 11 );
    2467    53088896 :         move32();
    2468             :     }
    2469       91649 :     *fftBuffer_exp = WORD16_BITS + 11;
    2470       91649 :     move16();
    2471             : 
    2472             :     /* Perform FFT */
    2473       91649 :     RFFTN_fx( fftBuffer, hFdCngCom->fftSineTab_fx, hFdCngCom->fftlen, -1 );
    2474             : 
    2475             : 
    2476       91649 :     return;
    2477             : }
    2478             : 
    2479             : /*-------------------------------------------------------------------
    2480             :  * SynthesisSTFT_enc_ivas_fx()
    2481             :  *
    2482             :  * STFT synthesis filterbank
    2483             :  *-------------------------------------------------------------------*/
    2484             : 
    2485       11704 : void SynthesisSTFT_enc_ivas_fx(
    2486             :     Word32 *fftBuffer,        /* i    : pointer to FFT bins */
    2487             :     Word16 fftBufferExp,      /* i    : exponent of FFT bins */
    2488             :     Word16 *timeDomainOutput, /* o    : pointer to time domain signal */
    2489             :     Word16 *olapBuffer,       /* i/o  : pointer to overlap buffer */
    2490             :     const PWord16 *olapWin,   /* i    : pointer to overlap window */
    2491             :     Word16 tcx_transition,
    2492             :     HANDLE_FD_CNG_COM hFdCngCom, /* i/o  : pointer to FD_CNG structure containing all buffers and variables */
    2493             :     Word16 gen_exc,
    2494             :     Word16 *Q_new,             /* i  : Q of generated exc_cng */
    2495             :     const Word16 element_mode, /* i  : element mode */
    2496             :     const Word16 nchan_out     /* i  : number of output channels */
    2497             : )
    2498             : {
    2499             :     Word16 i, len, scale, tmp;
    2500             :     Word16 len2, len3, len4;
    2501             :     Word16 buf[M + 1 + L_FRAME16k];
    2502             : 
    2503             : 
    2504             :     /* Perform IFFT */
    2505       11704 :     scale = 0;
    2506       11704 :     move16();
    2507       11704 :     BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
    2508       11704 :     fftBufferExp = add( fftBufferExp, scale );
    2509       11704 :     hFdCngCom->fftBuffer_exp = fftBufferExp;
    2510       11704 :     move16();
    2511             : 
    2512       11704 :     fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
    2513             : 
    2514             :     /* Perform overlap-add */
    2515             :     /* Handle overlap in P/S domain for stereo */
    2516       11704 :     test();
    2517       11704 :     test();
    2518       11704 :     IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
    2519             :     {
    2520           0 :         Copy( olapBuffer + 3 * hFdCngCom->frameSize / 4 - ( M + 1 ), buf, hFdCngCom->frameSize + M + 1 );
    2521           0 :         set16_fx( olapBuffer, 0, hFdCngCom->fftlen );
    2522             :     }
    2523             :     ELSE
    2524             :     {
    2525       11704 :         Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
    2526       11704 :         set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
    2527             :     }
    2528       11704 :     len2 = shr( hFdCngCom->fftlen, 2 );
    2529       11704 :     len4 = shr( hFdCngCom->fftlen, 3 );
    2530       11704 :     len3 = add( len2, len4 );
    2531       11704 :     len = add( hFdCngCom->frameSize, len4 );
    2532       11704 :     IF( tcx_transition )
    2533             :     {
    2534      222810 :         FOR( i = 0; i < len; i++ )
    2535             :         {
    2536      222160 :             olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], sub( fftBufferExp, 15 ) ) ); // Q(15 - fftBufferExp)
    2537      222160 :             move16();
    2538             :         }
    2539             :     }
    2540             :     ELSE
    2541             :     {
    2542      805694 :         FOR( i = 0; i < len4; i++ )
    2543             :         {
    2544      794640 :             olapBuffer[i + 1 * len4] = add_sat( olapBuffer[i + 1 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 1 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[i].v.im ) );
    2545      794640 :             move16();
    2546      794640 :             olapBuffer[i + 2 * len4] = add_sat( olapBuffer[i + 2 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 2 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[len4 - 1 - i].v.re ) );
    2547      794640 :             move16();
    2548             :         }
    2549     1600334 :         FOR( i = len3; i < len; i++ )
    2550             :         {
    2551     1589280 :             olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], sub( fftBufferExp, 15 ) ) ); // Q(15 - fftBufferExp)
    2552     1589280 :             move16();
    2553             :         }
    2554             :     }
    2555             : 
    2556      850776 :     FOR( i = 0; i < len4; i++ )
    2557             :     {
    2558      839072 :         olapBuffer[i + 5 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 5 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[i].v.re );
    2559      839072 :         move16();
    2560      839072 :         olapBuffer[i + 6 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 6 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[len4 - 1 - i].v.im );
    2561      839072 :         move16();
    2562             :     }
    2563             : 
    2564       11704 :     len = add( len, len2 );
    2565      850776 :     FOR( i = len; i < hFdCngCom->fftlen; i++ )
    2566             :     {
    2567      839072 :         olapBuffer[i] = 0;
    2568      839072 :         move16();
    2569             :     }
    2570             : 
    2571             :     /* Get time-domain signal */
    2572     3367992 :     FOR( i = 0; i < hFdCngCom->frameSize; i++ )
    2573             :     {
    2574     3356288 :         timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
    2575     3356288 :         move16();
    2576             :     }
    2577             :     /* Generate excitation */
    2578       11704 :     test();
    2579       11704 :     test();
    2580       11704 :     IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
    2581             :     {
    2582           0 :         FOR( i = 0; i < hFdCngCom->frameSize / 2; i++ )
    2583             :         {
    2584           0 :             buf[i + ( M + 1 )] = add( buf[i + ( M + 1 )], olapBuffer[i + hFdCngCom->frameSize / 4] );
    2585           0 :             move16();
    2586             :         }
    2587             : 
    2588           0 :         FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
    2589             :         {
    2590           0 :             buf[i] = mult_r( buf[i], hFdCngCom->fftlenFac );
    2591           0 :             move16();
    2592             :         }
    2593             :     }
    2594             :     ELSE
    2595             :     {
    2596     3566960 :         FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
    2597             :         {
    2598     3555256 :             buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
    2599     3555256 :             move16();
    2600             :         }
    2601       11704 :         tmp = buf[0];
    2602       11704 :         move16();
    2603             :     }
    2604       11704 :     IF( EQ_16( gen_exc, 1 ) )
    2605             :     {
    2606             : 
    2607       11704 :         E_UTIL_f_preemph2( sub( *Q_new, 1 ), buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp );
    2608       11704 :         Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
    2609             :     }
    2610       11704 :     IF( EQ_16( gen_exc, 2 ) )
    2611             :     {
    2612           0 :         *Q_new = E_UTIL_f_preemph3( buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp, 1 );
    2613           0 :         move16();
    2614           0 :         Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
    2615             :     }
    2616       11704 : }
    2617             : 
    2618             : /*-------------------------------------------------------------------
    2619             :  * SynthesisSTFT()
    2620             :  *
    2621             :  * STFT synthesis filterbank
    2622             :  *-------------------------------------------------------------------*/
    2623             : 
    2624        1015 : void SynthesisSTFT(
    2625             :     Word32 *fftBuffer,        /* i    : pointer to FFT bins */
    2626             :     Word16 fftBufferExp,      /* i    : exponent of FFT bins */
    2627             :     Word16 *timeDomainOutput, /* o    : pointer to time domain signal Qx*/
    2628             :     Word16 *olapBuffer,       /* i/o  : pointer to overlap buffer */
    2629             :     const PWord16 *olapWin,   /* i    : pointer to overlap window */
    2630             :     Word16 tcx_transition,
    2631             :     HANDLE_FD_CNG_COM hFdCngCom, /* i/o  : pointer to FD_CNG structure containing all buffers and variables */
    2632             :     Word16 gen_exc,
    2633             :     Word16 *Q_new,
    2634             :     const Word16 element_mode, /* i  : element mode */
    2635             :     const Word16 nchan_out     /* i  : number of output channels */
    2636             : )
    2637             : {
    2638             :     Word16 i, len, scale, tmp;
    2639             :     Word16 len2, len3, len4;
    2640             :     Word16 buf[M + 1 + L_FRAME16k];
    2641             : 
    2642             : 
    2643             :     /* Perform IFFT */
    2644        1015 :     scale = 0;
    2645        1015 :     move16();
    2646        1015 :     BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
    2647        1015 :     fftBufferExp = add( fftBufferExp, scale );
    2648        1015 :     hFdCngCom->fftBuffer_exp = fftBufferExp;
    2649        1015 :     move16();
    2650             : 
    2651        1015 :     fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
    2652             : 
    2653             :     /* Perform overlap-add */
    2654             :     /* Handle overlap in P/S domain for stereo */
    2655        1015 :     IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
    2656             :     {
    2657           0 :         Copy( olapBuffer + 3 * hFdCngCom->frameSize / 4 - ( M + 1 ), buf, hFdCngCom->frameSize + M + 1 );
    2658           0 :         set16_fx( olapBuffer, 0, hFdCngCom->fftlen );
    2659             :     }
    2660             :     ELSE
    2661             :     {
    2662        1015 :         Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
    2663        1015 :         set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
    2664             :     }
    2665        1015 :     len2 = shr( hFdCngCom->fftlen, 2 );
    2666        1015 :     len4 = shr( hFdCngCom->fftlen, 3 );
    2667        1015 :     len3 = add( len2, len4 );
    2668        1015 :     len = add( hFdCngCom->frameSize, len4 );
    2669        1015 :     IF( tcx_transition )
    2670             :     {
    2671           0 :         FOR( i = 0; i < len; i++ )
    2672             :         {
    2673           0 :             olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], fftBufferExp - 15 ) ); // Q(15 - fftBufferExp)
    2674           0 :             move16();
    2675             :         }
    2676             :     }
    2677             :     ELSE
    2678             :     {
    2679       65975 :         FOR( i = 0; i < len4; i++ )
    2680             :         {
    2681       64960 :             olapBuffer[i + 1 * len4] = add_sat( olapBuffer[i + 1 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 1 * len4], fftBufferExp - 15 ) ), olapWin[i].v.im ) );
    2682       64960 :             move16();
    2683       64960 :             olapBuffer[i + 2 * len4] = add_sat( olapBuffer[i + 2 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 2 * len4], fftBufferExp - 15 ) ), olapWin[len4 - 1 - i].v.re ) );
    2684       64960 :             move16();
    2685             :         }
    2686      130935 :         FOR( i = len3; i < len; i++ )
    2687             :         {
    2688      129920 :             olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], fftBufferExp - 15 ) );
    2689             :         }
    2690             :     }
    2691             : 
    2692       65975 :     FOR( i = 0; i < len4; i++ )
    2693             :     {
    2694       64960 :         olapBuffer[i + 5 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 5 * len4], fftBufferExp - 15 ) ), olapWin[i].v.re );
    2695       64960 :         move16();
    2696       64960 :         olapBuffer[i + 6 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 6 * len4], fftBufferExp - 15 ) ), olapWin[len4 - 1 - i].v.im );
    2697       64960 :         move16();
    2698             :     }
    2699             : 
    2700        1015 :     len = add( len, len2 );
    2701       65975 :     FOR( i = len; i < hFdCngCom->fftlen; i++ )
    2702             :     {
    2703       64960 :         olapBuffer[i] = 0;
    2704       64960 :         move16();
    2705             :     }
    2706             : 
    2707             :     /* Get time-domain signal */
    2708      260855 :     FOR( i = 0; i < hFdCngCom->frameSize; i++ )
    2709             :     {
    2710      259840 :         timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
    2711      259840 :         move16();
    2712             :     }
    2713             :     /* Generate excitation */
    2714             :     {
    2715      278110 :         FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
    2716             :         {
    2717      277095 :             buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
    2718      277095 :             move16();
    2719             :         }
    2720        1015 :         tmp = buf[0];
    2721             :     }
    2722        1015 :     IF( EQ_16( gen_exc, 1 ) )
    2723             :     {
    2724             : 
    2725           0 :         E_UTIL_f_preemph2( *Q_new - 1, buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp );
    2726           0 :         Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
    2727             :     }
    2728        1015 :     IF( EQ_16( gen_exc, 2 ) )
    2729             :     {
    2730           0 :         *Q_new = E_UTIL_f_preemph3( buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp, 1 );
    2731           0 :         Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
    2732             :     }
    2733        1015 : }
    2734             : 
    2735       15676 : void SynthesisSTFT_ivas_fx(
    2736             :     Word32 *fftBuffer,        /* i    : pointer to FFT bins */
    2737             :     Word16 fftBufferExp,      /* i    : exponent of FFT bins */
    2738             :     Word16 *timeDomainOutput, /* o    : pointer to time domain signal Qx*/
    2739             :     Word16 *olapBuffer,       /* i/o  : pointer to overlap buffer */
    2740             :     const PWord16 *olapWin,   /* i    : pointer to overlap window */
    2741             :     Word16 tcx_transition,
    2742             :     HANDLE_FD_CNG_COM hFdCngCom, /* i/o  : pointer to FD_CNG structure containing all buffers and variables */
    2743             :     Word16 gen_exc,
    2744             :     Word16 *Q_new,
    2745             :     const Word16 element_mode, /* i  : element mode */
    2746             :     const Word16 nchan_out     /* i  : number of output channels */
    2747             : )
    2748             : {
    2749             :     Word16 i, len, scale, tmp, sft, exp, tmp1;
    2750             :     Word16 len2, len3, len4;
    2751             :     Word16 buf[M + 1 + L_FRAME16k];
    2752             :     Word32 L_olapBuffer[FFTLEN];
    2753             : 
    2754             : 
    2755             :     /* Perform IFFT */
    2756       15676 :     scale = 0;
    2757       15676 :     move16();
    2758       15676 :     BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
    2759       15676 :     fftBufferExp = add( fftBufferExp, scale );
    2760       15676 :     hFdCngCom->fftBuffer_exp = fftBufferExp;
    2761       15676 :     move16();
    2762             : 
    2763       15676 :     sft = getScaleFactor32( fftBuffer, hFdCngCom->fftlen );
    2764       15676 :     scale_sig32( fftBuffer, hFdCngCom->fftlen, sft );
    2765       15676 :     fftBufferExp = sub( fftBufferExp, sft );
    2766       15676 :     hFdCngCom->fftBuffer_exp = fftBufferExp;
    2767       15676 :     move16();
    2768             : 
    2769       15676 :     fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
    2770             : 
    2771             :     /* Perform overlap-add */
    2772             :     /* Handle overlap in P/S domain for stereo */
    2773       15676 :     test();
    2774       15676 :     test();
    2775       15676 :     IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
    2776             :     {
    2777           0 :         Copy( olapBuffer + 3 * hFdCngCom->frameSize / 4 - ( M + 1 ), buf, hFdCngCom->frameSize + M + 1 );
    2778           0 :         set16_fx( olapBuffer, 0, hFdCngCom->fftlen );
    2779             :     }
    2780             :     ELSE
    2781             :     {
    2782       15676 :         Copy_Scale_sig_16_32_no_sat( olapBuffer + hFdCngCom->frameSize, L_olapBuffer, hFdCngCom->frameSize, add( sub( hFdCngCom->olapBufferSynth_exp, sub( 15, hFdCngCom->fftlenShift ) ), 16 ) ); /* exp: hFdCngCom->olapBufferSynth_exp -> (15 - fftlenShift) */
    2783       15676 :         set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
    2784             :     }
    2785       15676 :     len2 = shr( hFdCngCom->fftlen, 2 );
    2786       15676 :     len4 = shr( hFdCngCom->fftlen, 3 );
    2787       15676 :     len3 = add( len2, len4 );
    2788       15676 :     len = add( hFdCngCom->frameSize, len4 );
    2789       15676 :     tmp1 = sub( fftBufferExp, 15 );
    2790       15676 :     IF( tcx_transition )
    2791             :     {
    2792      562371 :         FOR( i = 0; i < len; i++ )
    2793             :         {
    2794      560720 :             L_olapBuffer[i] = L_shl_sat( fftBuffer[i], tmp1 ); /* Q(31 - (15 - fftlenShift) ) */
    2795      560720 :             move32();
    2796             :         }
    2797             :     }
    2798             :     ELSE
    2799             :     {
    2800     1049481 :         FOR( i = 0; i < len4; i++ )
    2801             :         {
    2802     1035456 :             L_olapBuffer[i + 1 * len4] = Madd_32_16( L_olapBuffer[i + 1 * len4], L_shl_sat( fftBuffer[i + 1 * len4], tmp1 ), olapWin[i].v.im ); /* Q(31 - (15 - fftlenShift) ) */
    2803     1035456 :             move32();
    2804     1035456 :             L_olapBuffer[i + 2 * len4] = Madd_32_16( L_olapBuffer[i + 2 * len4], L_shl_sat( fftBuffer[i + 2 * len4], tmp1 ), olapWin[len4 - 1 - i].v.re ); /* Q(31 - (15 - fftlenShift) ) */
    2805     1035456 :             move32();
    2806             :         }
    2807     2084937 :         FOR( i = len3; i < len; i++ )
    2808             :         {
    2809     2070912 :             L_olapBuffer[i] = L_shl_sat( fftBuffer[i], tmp1 ); /* Q(31 - (15 - fftlenShift) ) */
    2810     2070912 :             move32();
    2811             :         }
    2812             :     }
    2813             : 
    2814     1163276 :     FOR( i = 0; i < len4; i++ )
    2815             :     {
    2816     1147600 :         L_olapBuffer[i + 5 * len4] = Mpy_32_16_1( L_shl_sat( fftBuffer[i + 5 * len4], tmp1 ), olapWin[i].v.re ); /* Q(31 - (15 - fftlenShift) ) */
    2817     1147600 :         move32();
    2818     1147600 :         L_olapBuffer[i + 6 * len4] = Mpy_32_16_1( L_shl_sat( fftBuffer[i + 6 * len4], tmp1 ), olapWin[len4 - 1 - i].v.im ); /* Q(31 - (15 - fftlenShift) ) */
    2819     1147600 :         move32();
    2820             :     }
    2821             : 
    2822       15676 :     len = add( len, len2 );
    2823     1163276 :     FOR( i = len; i < hFdCngCom->fftlen; i++ )
    2824             :     {
    2825     1147600 :         L_olapBuffer[i] = 0;
    2826     1147600 :         move32();
    2827             :     }
    2828             : 
    2829       15676 :     sft = L_norm_arr( L_olapBuffer, hFdCngCom->fftlen );
    2830       15676 :     IF( NE_16( sft, 31 ) )
    2831             :     {
    2832       14391 :         Copy_Scale_sig32_16( L_olapBuffer, olapBuffer, hFdCngCom->fftlen, sft );
    2833       14391 :         hFdCngCom->olapBufferSynth_exp = sub( sub( 15, hFdCngCom->fftlenShift ), sft );
    2834       14391 :         move16();
    2835             :     }
    2836             : 
    2837             :     /* Get time-domain signal */
    2838     4606076 :     FOR( i = 0; i < hFdCngCom->frameSize; i++ )
    2839             :     {
    2840     4590400 :         timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
    2841     4590400 :         move16();
    2842             :     }
    2843             :     /* Generate excitation */
    2844             :     {
    2845     4872568 :         FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
    2846             :         {
    2847     4856892 :             buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
    2848     4856892 :             move16();
    2849             :         }
    2850       15676 :         exp = add( hFdCngCom->olapBufferSynth_exp, hFdCngCom->fftlenShift );
    2851       15676 :         tmp = buf[0];
    2852             :     }
    2853       15676 :     IF( EQ_16( gen_exc, 1 ) )
    2854             :     {
    2855       15676 :         E_UTIL_f_preemph2( 0, buf + 1, PREEMPH_FAC, add( M, hFdCngCom->frameSize ), &tmp );
    2856       15676 :         Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 0 );
    2857       15676 :         *Q_new = sub( 15, exp );
    2858       15676 :         move16();
    2859             :     }
    2860       15676 :     IF( EQ_16( gen_exc, 2 ) )
    2861             :     {
    2862           0 :         *Q_new = E_UTIL_f_preemph3( buf + 1, PREEMPH_FAC, add( M, hFdCngCom->frameSize ), &tmp, 0 );
    2863           0 :         move16();
    2864           0 :         Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, negate( *Q_new ) );
    2865           0 :         *Q_new = sub( 15, exp );
    2866           0 :         move16();
    2867             :     }
    2868       15676 : }
    2869             : 
    2870             : /**************************************************************************************
    2871             :  * Compute some values used in the bias correction of the minimum statistics algorithm *
    2872             :  **************************************************************************************/
    2873       15238 : void mhvals(
    2874             :     const Word16 d,
    2875             :     Word16 *m /*, Word16 * h*/
    2876             : )
    2877             : {
    2878             :     Word16 i, j;
    2879       15238 :     Word16 len = SIZE_SCALE_TABLE_CN;
    2880       15238 :     move16();
    2881             : 
    2882             : 
    2883       15238 :     assert( d == 72 || d == 12 ); /* function only tested for d==72 and d==12) */
    2884       15238 :     i = 0;
    2885       15238 :     move16();
    2886      129523 :     FOR( i = 0; i < len; i++ )
    2887             :     {
    2888      129523 :         IF( LE_16( d, d_array[i] ) )
    2889             :         {
    2890       15238 :             BREAK;
    2891             :         }
    2892             :     }
    2893       15238 :     IF( EQ_16( i, len ) )
    2894             :     {
    2895           0 :         i = sub( len, 1 );
    2896           0 :         j = i;
    2897           0 :         move16();
    2898             :     }
    2899             :     ELSE
    2900             :     {
    2901       15238 :         j = sub( i, 1 );
    2902             :     }
    2903       15238 :     IF( EQ_16( d, d_array[i] ) )
    2904             :     {
    2905           0 :         *m = m_array[i];
    2906           0 :         move16();
    2907             :     }
    2908             :     ELSE
    2909             :     {
    2910             :         Word32 qi_m, qj_m, q_m, tmp1_m, tmp2_m;
    2911             :         Word16 qi_e, qj_e, q_e, tmp1_e, tmp2_e, tmp1_w16_m, tmp1_w16_e, shift;
    2912             : 
    2913             : 
    2914             :         /* d_array has exponent 15 */
    2915       15238 :         qj_e = 15;
    2916       15238 :         move16();
    2917       15238 :         qj_m = L_deposit_h( d_array[i - 1] );
    2918             : 
    2919       15238 :         qi_e = 15;
    2920       15238 :         move16();
    2921       15238 :         qi_m = L_deposit_h( d_array[i] );
    2922             : 
    2923       15238 :         q_e = 15;
    2924       15238 :         move16();
    2925       15238 :         q_m = L_deposit_h( d );
    2926             : 
    2927       15238 :         qj_m = Sqrt32( qj_m, &qj_e );
    2928       15238 :         qi_m = Sqrt32( qi_m, &qi_e );
    2929       15238 :         q_m = Sqrt32( q_m, &q_e );
    2930             : 
    2931       15238 :         tmp1_m = Mpy_32_32( qi_m, qj_m );
    2932       15238 :         tmp1_e = add( qi_e, qj_e );
    2933       15238 :         tmp1_m = L_deposit_h( BASOP_Util_Divide3232_Scale( tmp1_m, q_m, &shift ) );
    2934       15238 :         tmp1_e = sub( tmp1_e, q_e );
    2935       15238 :         tmp1_e = add( tmp1_e, shift );
    2936       15238 :         tmp1_m = BASOP_Util_Add_Mant32Exp( tmp1_m, tmp1_e, L_negate( qj_m ), qj_e, &tmp1_e );
    2937             : 
    2938       15238 :         tmp2_m = BASOP_Util_Add_Mant32Exp( qi_m, qi_e, L_negate( qj_m ), qj_e, &tmp2_e );
    2939       15238 :         tmp1_w16_m = round_fx( tmp2_m );
    2940       15238 :         tmp1_w16_e = tmp2_e;
    2941       15238 :         move16();
    2942       15238 :         BASOP_Util_Divide_MantExp( sub( m_array[j], m_array[i] ), 0, tmp1_w16_m, tmp1_w16_e, &tmp1_w16_m, &tmp1_w16_e );
    2943             : 
    2944       15238 :         tmp2_m = Mpy_32_16_1( tmp1_m, tmp1_w16_m );
    2945       15238 :         tmp2_e = add( tmp1_e, tmp1_w16_e );
    2946             : 
    2947       15238 :         tmp2_m = BASOP_Util_Add_Mant32Exp( tmp2_m, tmp2_e, L_deposit_h( m_array[i] ), 0, &tmp2_e );
    2948       15238 :         assert( tmp2_e == 0 );
    2949       15238 :         *m = extract_h( tmp2_m );
    2950       15238 :         move32();
    2951             :     }
    2952       15238 : }
    2953             : 
    2954             : /*-------------------------------------------------------------------
    2955             :  * rand_gauss()
    2956             :  *
    2957             :  * Random generator with Gaussian distribution with mean 0 and std 1
    2958             :  * Returns:
    2959             :  *   random signal format Q3.29
    2960             :  *-------------------------------------------------------------------*/
    2961    45667431 : Word32 rand_gauss( Word16 *seed )
    2962             : {
    2963             :     Word32 temp;
    2964             :     Word16 loc_seed;
    2965             : 
    2966             :     /* This unrolled version reduces the cycles from 17 to 10 */
    2967    45667431 :     loc_seed = extract_l( L_mac0( 13849, *seed, 31821 ) );
    2968    45667431 :     temp = L_deposit_l( loc_seed );
    2969             : 
    2970    45667431 :     loc_seed = extract_l( L_mac0( 13849, loc_seed, 31821 ) );
    2971    45667431 :     temp = L_msu0( temp, loc_seed, -1 );
    2972             : 
    2973    45667431 :     loc_seed = extract_l( L_mac0( 13849, loc_seed, 31821 ) );
    2974    45667431 :     temp = L_msu0( temp, loc_seed, -1 );
    2975             : 
    2976    45667431 :     *seed = loc_seed;
    2977    45667431 :     move16();
    2978    45667431 :     return L_shl( temp, WORD16_BITS - CNG_RAND_GAUSS_SHIFT );
    2979             : }
    2980             : 
    2981             : /*-------------------------------------------------------------------
    2982             :  * lpc_from_spectrum()
    2983             :  *
    2984             :  *
    2985             :  *-------------------------------------------------------------------*/
    2986             : 
    2987        6257 : void lpc_from_spectrum(
    2988             :     HANDLE_FD_CNG_COM hFdCngCom,
    2989             :     const Word16 start,      /*i  : start band*/
    2990             :     const Word16 stop,       /*i  : stop band*/
    2991             :     const Word16 preemph_fac /*i  : preemphase factor format Q1.15*/
    2992             : )
    2993             : {
    2994             :     Word16 i, s1, s2, s3, fftlen2, scale, fftlen4, fftlen8, len, step, preemph_fac2;
    2995             :     Word32 maxVal, r[32], fftBuffer[FFTLEN], *ptr, *pti, nf;
    2996             :     Word16 tmp, r_h[32], r_l[32];
    2997             :     const PWord16 *table;
    2998             : 
    2999        6257 :     Word32 *powspec = hFdCngCom->cngNoiseLevel; /*i  : pointer to noise levels format Q5.27*/
    3000        6257 :     Word16 powspec_exp = hFdCngCom->cngNoiseLevelExp;
    3001        6257 :     move16();
    3002        6257 :     Word16 fftlen = hFdCngCom->fftlen; /*i  : size of fft*/
    3003        6257 :     Word16 *A = hFdCngCom->A_cng;      /*o  : lpc coefficients format Q3.12*/
    3004        6257 :     move16();
    3005        6257 :     Word16 lpcorder = M;
    3006        6257 :     move16();
    3007             : 
    3008        6257 :     scale = 0;
    3009        6257 :     move16();
    3010        6257 :     fftlen2 = shr( fftlen, 1 );
    3011        6257 :     fftlen4 = shr( fftlen, 2 );
    3012        6257 :     fftlen8 = shr( fftlen, 3 );
    3013             : 
    3014             :     /* Power Spectrum */
    3015        6257 :     maxVal = 0;
    3016        6257 :     move32();
    3017        6257 :     len = sub( stop, start );
    3018     1839759 :     FOR( i = 0; i < len; i++ )
    3019             :     {
    3020     1833502 :         maxVal = L_max( maxVal, L_abs( powspec[i] ) );
    3021             :     }
    3022        6257 :     s1 = norm_l( maxVal );
    3023        6257 :     nf = L_shr_r_sat( 1099511680l /*1e-3f Q40*/, add( sub( powspec_exp, s1 ), 9 ) );
    3024        6257 :     ptr = fftBuffer;
    3025        6257 :     pti = fftBuffer + 1;
    3026             : 
    3027       18771 :     FOR( i = 0; i < start; i++ )
    3028             :     {
    3029       12514 :         *ptr = nf;
    3030       12514 :         move32();
    3031       12514 :         *pti = L_deposit_l( 0 );
    3032       12514 :         move32();
    3033       12514 :         ptr += 2;
    3034       12514 :         pti += 2;
    3035             :     }
    3036             : 
    3037     1839759 :     FOR( ; i < stop; i++ )
    3038             :     {
    3039     1833502 :         *ptr = L_max( nf, L_shl( powspec[i - start], s1 ) );
    3040     1833502 :         move32();
    3041     1833502 :         *pti = L_deposit_l( 0 );
    3042     1833502 :         move32();
    3043     1833502 :         ptr += 2;
    3044     1833502 :         pti += 2;
    3045             :     }
    3046             : 
    3047        6321 :     FOR( ; i < fftlen2; i++ )
    3048             :     {
    3049          64 :         *ptr = nf;
    3050          64 :         move32();
    3051          64 :         *pti = L_deposit_l( 0 );
    3052          64 :         move32();
    3053          64 :         ptr += 2;
    3054          64 :         pti += 2;
    3055             :     }
    3056             : 
    3057        6257 :     fftBuffer[1] = nf;
    3058        6257 :     move32();
    3059             : 
    3060             :     /* Pre-emphasis */
    3061             : 
    3062        6257 :     BASOP_getTables( &table, NULL, &step, fftlen4 );
    3063        6257 :     tmp = round_fx( L_shr( L_add( 0x40000000, L_mult0( preemph_fac, preemph_fac ) ), 1 ) );
    3064        6257 :     preemph_fac2 = shr( preemph_fac, 1 );
    3065        6257 :     ptr = fftBuffer;
    3066        6257 :     *ptr = Mpy_32_16_1( *ptr, sub( tmp, preemph_fac2 ) );
    3067        6257 :     move32();
    3068        6257 :     ptr += 2;
    3069      461520 :     FOR( i = 1; i < fftlen8; i++ )
    3070             :     {
    3071      455263 :         move32();
    3072      455263 :         *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r( preemph_fac2, add( shr( table[i - 1].v.re, 1 ), shr( table[i].v.re, 1 ) ) ) ) );
    3073      455263 :         ptr += 2;
    3074             :     }
    3075        6257 :     move32();
    3076        6257 :     *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r( preemph_fac2, add( shr( table[fftlen8 - 1].v.re, 1 ), shr( table[fftlen8 - 1].v.im, 1 ) ) ) ) );
    3077        6257 :     ptr += 2;
    3078      461520 :     FOR( i = 1; i < fftlen8; i++ )
    3079             :     {
    3080      455263 :         move32();
    3081      455263 :         *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r( preemph_fac2, add( shr( table[fftlen8 - i - 1].v.im, 1 ), shr( table[fftlen8 - i].v.im, 1 ) ) ) ) );
    3082      455263 :         ptr += 2;
    3083             :     }
    3084        6257 :     move32();
    3085        6257 :     *ptr = Mpy_32_16_1( *ptr, tmp );
    3086        6257 :     ptr += 2;
    3087      461520 :     FOR( i = 1; i < fftlen8; i++ )
    3088             :     {
    3089      455263 :         move32();
    3090      455263 :         *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r( preemph_fac2, add( shr( table[i - 1].v.im, 1 ), shr( table[i].v.im, 1 ) ) ) ) );
    3091      455263 :         ptr += 2;
    3092             :     }
    3093        6257 :     move32();
    3094        6257 :     *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r( preemph_fac2, add( shr( table[fftlen8 - 1].v.re, 1 ), shr( table[fftlen8 - 1].v.im, 1 ) ) ) ) );
    3095        6257 :     ptr += 2;
    3096      461520 :     FOR( i = 1; i < fftlen8; i++ )
    3097             :     {
    3098      455263 :         move32();
    3099      455263 :         *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r( preemph_fac2, add( shr( table[fftlen8 - i - 1].v.re, 1 ), shr( table[fftlen8 - i].v.re, 1 ) ) ) ) );
    3100      455263 :         ptr += 2;
    3101             :     }
    3102        6257 :     move32();
    3103        6257 :     fftBuffer[1] = Mpy_32_16_1( fftBuffer[1], add( tmp, preemph_fac2 ) );
    3104        6257 :     maxVal = 0;
    3105        6257 :     move32();
    3106     3698417 :     FOR( i = 0; i < fftlen; i++ )
    3107             :     {
    3108     3692160 :         maxVal = L_max( maxVal, L_abs( fftBuffer[i] ) );
    3109             :     }
    3110        6257 :     s2 = norm_l( maxVal );
    3111     3698417 :     FOR( i = 0; i < fftlen; i++ )
    3112             :     {
    3113     3692160 :         fftBuffer[i] = L_shl( fftBuffer[i], s2 );
    3114     3692160 :         move32();
    3115             :     }
    3116             : 
    3117             :     /* Autocorrelation */
    3118             : 
    3119        6257 :     BASOP_rfft( fftBuffer, fftlen, &scale, 1 );
    3120             : 
    3121        6257 :     s3 = getScaleFactor32( fftBuffer, add( lpcorder, 1 ) );
    3122             : 
    3123      112626 :     FOR( i = 0; i <= lpcorder; i++ )
    3124             :     {
    3125      106369 :         r[i] = L_shl( fftBuffer[i], s3 );
    3126      106369 :         move32();
    3127             :     }
    3128             : 
    3129        6257 :     r[0] = Mpy_32_32( r[0], 1074278656l /*1.0005f Q30*/ );
    3130        6257 :     move32();
    3131      106369 :     FOR( i = 1; i <= lpcorder; i++ )
    3132             :     {
    3133      100112 :         r[i] = Mpy_32_32( r[i], 1073741824l /*1.f Q30*/ );
    3134      100112 :         move32();
    3135             :     }
    3136        6257 :     s3 = getScaleFactor32( r, add( lpcorder, 1 ) );
    3137             : 
    3138      112626 :     FOR( i = 0; i <= lpcorder; i++ )
    3139             :     {
    3140      106369 :         r[i] = L_shl( r[i], s3 );
    3141      106369 :         move32();
    3142             :     }
    3143             : 
    3144      112626 :     FOR( i = 0; i <= lpcorder; i++ )
    3145             :     {
    3146      106369 :         L_Extract( r[i], &r_h[i], &r_l[i] );
    3147             :     }
    3148             : 
    3149             :     /* LPC */
    3150             : 
    3151        6257 :     E_LPC_lev_dur( r_h, r_l, A, NULL, lpcorder, NULL );
    3152        6257 : }
    3153             : 
    3154             : /*
    3155             :    msvq_decoder
    3156             : 
    3157             :     Parameters:
    3158             : 
    3159             :     cb               i  : Codebook (indexed cb[stages][levels][p]) format Q9.7
    3160             :     stages           i  : Number of stages
    3161             :     N                i  : Vector dimension
    3162             :     maxN             i  : Codebook vector dimension
    3163             :     Idx              o  : Indices
    3164             :     uq[]             i  : Quantized vector format Q9.7
    3165             : 
    3166             : 
    3167             :     Function:
    3168             :     multi stage vector dequantisation
    3169             : 
    3170             :     Returns:
    3171             :     void
    3172             : */
    3173           0 : void msvq_decoder(
    3174             :     const Word16 *const cb[], /* i  : Codebook (indexed cb[*stages][levels][p]) */
    3175             :     const Word16 stages,      /* i  : Number of stages                          */
    3176             :     const Word16 N,           /* i  : Vector dimension                          */
    3177             :     const Word16 maxN,        /* i  : Codebook vector dimension                 */
    3178             :     const Word16 Idx[],       /* i  : Indices                                   */
    3179             :     Word16 *uq                /* o  : quantized vector                          */
    3180             : )
    3181             : {
    3182             :     Word16 s, i, offset;
    3183             : 
    3184             :     // PMT("msvq_decoder Not verified")
    3185             : 
    3186           0 :     offset = i_mult( Idx[0], maxN );
    3187           0 :     FOR( i = 0; i < N; i++ )
    3188             :     {
    3189           0 :         uq[i] = cb[0][offset + i];
    3190           0 :         move16();
    3191             :     }
    3192             : 
    3193           0 :     FOR( s = 1; s < stages; s++ )
    3194             :     {
    3195           0 :         offset = i_mult( Idx[s], maxN );
    3196             : 
    3197           0 :         FOR( i = 0; i < N; i++ )
    3198             :         {
    3199           0 :             uq[i] = add( uq[i], cb[s][offset + i] );
    3200           0 :             move16();
    3201             :         }
    3202             :     }
    3203           0 : }
    3204             : /*-------------------------------------------------------------------
    3205             :  * FdCng_exc()
    3206             :  *
    3207             :  * Generate FD-CNG as LP excitation
    3208             :  *-------------------------------------------------------------------*/
    3209             : 
    3210       27380 : void FdCng_exc(
    3211             :     HANDLE_FD_CNG_COM hFdCngCom,
    3212             :     Word16 *CNG_mode,
    3213             :     Word16 L_frame,
    3214             :     Word16 *lsp_old,
    3215             :     Word16 first_CNG,
    3216             :     Word16 *lspCNG,
    3217             :     Word16 *Aq,      /* o:   LPC coeffs Q12*/
    3218             :     Word16 *lsp_new, /* o:   lsp Q15 */
    3219             :     Word16 *lsf_new, /* o:   lsf Qlog2(2.56) */
    3220             :     Word16 *exc,     /* o:   LP excitation Q12  */
    3221             :     Word16 *exc2,    /* o:   LP excitation Q12  */
    3222             :     Word16 *bwe_exc  /* o:   LP excitation for BWE Q12*/
    3223             : )
    3224             : {
    3225             :     Word16 i;
    3226             : 
    3227       27380 :     *CNG_mode = -1;
    3228       27380 :     move16();
    3229             : 
    3230      151547 :     FOR( i = 0; i < L_frame / L_SUBFR; i++ )
    3231             :     {
    3232      124167 :         Copy( hFdCngCom->A_cng, Aq + i * ( M + 1 ), M + 1 );
    3233             :     }
    3234             : 
    3235       27380 :     E_LPC_a_lsp_conversion( Aq, lsp_new, lsp_old, M );
    3236             : 
    3237       27380 :     IF( first_CNG == 0 )
    3238             :     {
    3239       10474 :         Copy( lsp_old, lspCNG, M );
    3240             :     }
    3241      465460 :     FOR( i = 0; i < M; i++ )
    3242             :     {
    3243             :         /* AR low-pass filter  */
    3244      438080 :         lspCNG[i] = mac_r( L_mult( CNG_ISF_FACT_FX, lspCNG[i] ), 32768 - CNG_ISF_FACT_FX, lsp_new[i] );
    3245      438080 :         move16(); /* Q15 (15+15+1-16) */
    3246             :     }
    3247             : 
    3248       27380 :     IF( EQ_16( L_frame, L_FRAME16k ) )
    3249             :     {
    3250       14647 :         lsp2lsf_fx( lsp_new, lsf_new, M, INT_FS_16k_FX );
    3251             :     }
    3252             :     ELSE
    3253             :     {
    3254       12733 :         E_LPC_lsp_lsf_conversion( lsp_new, lsf_new, M );
    3255             :     }
    3256       27380 :     Copy( hFdCngCom->exc_cng, exc, L_frame );
    3257       27380 :     Copy( hFdCngCom->exc_cng, exc2, L_frame );
    3258       27380 :     IF( bwe_exc != NULL )
    3259             :     {
    3260       22088 :         IF( EQ_16( L_frame, L_FRAME ) )
    3261             :         {
    3262       12733 :             interp_code_5over2_fx( exc2, bwe_exc, L_frame );
    3263             :         }
    3264             :         ELSE
    3265             :         {
    3266        9355 :             interp_code_4over2_fx( exc2, bwe_exc, L_frame );
    3267             :         }
    3268             :     }
    3269       27380 : }
    3270             : 
    3271             : /*-------------------------------------------------------------------
    3272             :  * SynthesisSTFT_fx()
    3273             :  *
    3274             :  * STFT synthesis filterbank
    3275             :  *-------------------------------------------------------------------*/
    3276             : 
    3277       59396 : void SynthesisSTFT_fx(
    3278             :     Word32 *fftBuffer,
    3279             :     /* i  : FFT bins */ // Q15
    3280             :     Word32 *timeDomainOutput,
    3281             :     Word32 *olapBuffer, // Qin
    3282             :     const Word16 *olapWin,
    3283             :     const Word16 tcx_transition,
    3284             :     HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */
    3285             :     const Word16 element_mode,   /* i  : element mode */
    3286             :     const Word16 nchan_out       /* i  : number of output channels */
    3287             : )
    3288             : {
    3289             :     Word16 i;
    3290             :     Word32 buf_fx[M + 1 + 320], tmp_fx;
    3291             : 
    3292             :     /* Perform IFFT */
    3293       59396 :     RFFTN_fx( fftBuffer, hFdCngCom->fftSineTab_fx, hFdCngCom->fftlen, 1 );
    3294             : 
    3295             :     /* Handle overlap in P/S domain for stereo */
    3296       59396 :     test();
    3297       59396 :     test();
    3298       59396 :     IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
    3299             :     {
    3300         930 :         Copy32( olapBuffer + sub( i_mult( 3, shr( hFdCngCom->frameSize, 2 ) ), ( M + 1 ) ), buf_fx, add( hFdCngCom->frameSize, M + 1 ) ); // Qin
    3301         930 :         set32_fx( olapBuffer, 0, hFdCngCom->fftlen );
    3302             :     }
    3303             :     ELSE
    3304             :     {
    3305       58466 :         Copy32( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
    3306       58466 :         set32_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize ); /*olapBuffer, fftBuffer, olapWin*/
    3307             :     }
    3308             : 
    3309       59396 :     IF( tcx_transition )
    3310             :     {
    3311           0 :         FOR( i = 0; i < ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3312             :         {
    3313           0 :             olapBuffer[i] = fftBuffer[i]; // Q15
    3314           0 :             move32();
    3315             :         }
    3316             :     }
    3317             :     ELSE
    3318             :     {
    3319     8539748 :         FOR( i = hFdCngCom->frameSize / 4; i < ( 3 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3320             :         {
    3321     8480352 :             olapBuffer[i] = L_add( olapBuffer[i], Mpy_32_16_1( fftBuffer[i], olapWin[( i - ( hFdCngCom->frameSize >> 2 ) )] ) );
    3322     8480352 :             move32();
    3323             :         }
    3324     8539748 :         FOR( ; i < ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3325             :         {
    3326     8480352 :             olapBuffer[i] = fftBuffer[i];
    3327     8480352 :             move32();
    3328             :         }
    3329             :     }
    3330     8539748 :     FOR( ; i < ( 7 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3331             :     {
    3332     8480352 :         olapBuffer[i] = Mpy_32_16_1( fftBuffer[i], olapWin[( i - ( 3 * ( hFdCngCom->frameSize >> 2 ) ) )] );
    3333     8480352 :         move32();
    3334             :     }
    3335             : 
    3336     4299572 :     FOR( ; i < hFdCngCom->fftlen; i++ )
    3337             :     {
    3338     4240176 :         olapBuffer[i] = 0;
    3339     4240176 :         move32();
    3340             :     }
    3341             : 
    3342       59396 :     Word32 fftScale = 0;
    3343       59396 :     SWITCH( hFdCngCom->fftlen )
    3344             :     {
    3345       27427 :         case 640:
    3346       27427 :             fftScale = FFT_SCALING_640;
    3347       27427 :             move32();
    3348       27427 :             BREAK;
    3349       31969 :         case 512:
    3350       31969 :             fftScale = FFT_SCALING_512;
    3351       31969 :             move32();
    3352       31969 :             BREAK;
    3353           0 :         default:
    3354           0 :             assert( !"Not supported FFT length!" );
    3355             :     }
    3356             :     /* Get time-domain signal */
    3357             :     // v_multc(olapBuffer + hFdCngCom->frameSize / 4, (float)(hFdCngCom->fftlen / 2), timeDomainOutput, hFdCngCom->frameSize);
    3358       59396 :     v_multc_fixed( olapBuffer + hFdCngCom->frameSize / 4, fftScale, timeDomainOutput, hFdCngCom->frameSize ); // Q_in - 9
    3359             :                                                                                                               /* Get excitation */
    3360       59396 :     test();
    3361       59396 :     test();
    3362       59396 :     IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
    3363             :     {
    3364      119970 :         FOR( i = 0; i < hFdCngCom->frameSize / 2; i++ )
    3365             :         {
    3366      119040 :             buf_fx[i + ( M + 1 )] = L_add( buf_fx[i + ( M + 1 )], olapBuffer[( i + ( hFdCngCom->frameSize >> 2 ) )] );
    3367      119040 :             move32();
    3368             :         }
    3369             :         // v_multc(buf, (float)(hFdCngCom->fftlen / 2), buf, M + 1 + hFdCngCom->frameSize);
    3370         930 :         v_multc_fixed( buf_fx, fftScale, buf_fx, add( M + 1, hFdCngCom->frameSize ) );
    3371             :     }
    3372             :     ELSE
    3373             :     {
    3374             :         // v_multc(olapBuffer + hFdCngCom->frameSize / 4 - (M + 1), (float)(hFdCngCom->fftlen / 2), buf, M + 1 + hFdCngCom->frameSize);
    3375       58466 :         v_multc_fixed( olapBuffer + sub( shr( hFdCngCom->frameSize, 2 ), ( M + 1 ) ), fftScale, buf_fx, add( M + 1, hFdCngCom->frameSize ) );
    3376             :     }
    3377             : 
    3378       59396 :     tmp_fx = buf_fx[0];
    3379       59396 :     move32();
    3380             :     // preemph(buf + 1, PREEMPH_FAC_FLT, M + hFdCngCom->frameSize, &tmp);
    3381       59396 :     preemph_ivas_fx( buf_fx + 1, PREEMPH_FAC, add( M, hFdCngCom->frameSize ), &tmp_fx );
    3382             :     // residu(hFdCngCom->A_cng_flt, M, buf + 1 + M, hFdCngCom->exc_cng_flt, hFdCngCom->frameSize);
    3383             : 
    3384             :     // residu_ivas_fx( hFdCngCom->A_cng, Q13, M, buf_fx + 1 + M, hFdCngCom->exc_cng_32fx, hFdCngCom->frameSize );
    3385       59396 :     residu_ivas_fx( hFdCngCom->A_cng, ( 15 - norm_s( hFdCngCom->A_cng[0] - 1 ) ), M, buf_fx + 1 + M, hFdCngCom->exc_cng_32fx, hFdCngCom->frameSize );
    3386             : 
    3387       59396 :     return;
    3388             : }
    3389             : 
    3390        4395 : void SynthesisSTFT_dirac_fx(
    3391             :     Word32 *fftBuffer,
    3392             :     /* i  : FFT bins */ // hFdCngCom->fftBuffer_exp
    3393             :     Word32 *timeDomainOutput,
    3394             :     Word32 *olapBuffer, // Q_in
    3395             :     const Word16 *olapWin,
    3396             :     const Word16 samples_out,
    3397             :     HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
    3398             : )
    3399             : {
    3400             :     Word16 i;
    3401             :     Word32 buf[M + 1 + 320], tmp;
    3402             : 
    3403             :     /* Perform IFFT */
    3404        4395 :     RFFTN_fx( fftBuffer, hFdCngCom->fftSineTab_fx, hFdCngCom->fftlen, 1 );
    3405             : 
    3406             :     /* Handle overlap in P/S domain for stereo */
    3407        4395 :     Copy32( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
    3408        4395 :     set32_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize ); /*olapBuffer, fftBuffer, olapWin*/
    3409             : 
    3410      650411 :     FOR( i = ( hFdCngCom->frameSize >> 2 ); i < ( 3 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3411             :     {
    3412      646016 :         olapBuffer[i] = L_add( olapBuffer[i], Mpy_32_16_1( fftBuffer[i], olapWin[( i - ( hFdCngCom->frameSize >> 2 ) )] ) );
    3413      646016 :         move32();
    3414             :     }
    3415      650411 :     FOR( ; i < ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3416             :     {
    3417      646016 :         olapBuffer[i] = fftBuffer[i];
    3418      646016 :         move32();
    3419             :     }
    3420             : 
    3421      650411 :     FOR( ; i < ( 7 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3422             :     {
    3423      646016 :         olapBuffer[i] = fftBuffer[i];
    3424      646016 :         move32();
    3425             :     }
    3426             : 
    3427      327403 :     FOR( ; i < hFdCngCom->fftlen; i++ )
    3428             :     {
    3429      323008 :         olapBuffer[i] = 0;
    3430      323008 :         move32();
    3431             :     }
    3432             : 
    3433        4395 :     Word32 fftScale = 0;
    3434        4395 :     move32();
    3435        4395 :     SWITCH( hFdCngCom->fftlen )
    3436             :     {
    3437        2608 :         case 640:
    3438        2608 :             fftScale = FFT_SCALING_640;
    3439        2608 :             move32();
    3440        2608 :             break;
    3441        1787 :         case 512:
    3442        1787 :             fftScale = FFT_SCALING_512;
    3443        1787 :             move32();
    3444        1787 :             break;
    3445           0 :         default:
    3446           0 :             assert( !"Not supported FFT length!" );
    3447             :     }
    3448             : 
    3449             :     /* Get time-domain signal */
    3450        4395 :     v_multc_fixed( olapBuffer + shr( hFdCngCom->frameSize, 2 ), fftScale, timeDomainOutput, samples_out ); // Q_in - 9
    3451             : 
    3452             :     /* Get excitation */
    3453        4395 :     v_multc_fixed( olapBuffer + sub( shr( hFdCngCom->frameSize, 2 ), ( M + 1 ) ), fftScale, buf, add( M + 1, hFdCngCom->frameSize ) );
    3454        4395 :     tmp = buf[0];
    3455        4395 :     move32();
    3456        4395 :     preemph_ivas_fx( buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp );
    3457             :     // residu_ivas_fx( hFdCngCom->A_cng, Q13, M, buf + 1 + M, hFdCngCom->exc_cng_32fx, hFdCngCom->frameSize );
    3458        4395 :     residu_ivas_fx( hFdCngCom->A_cng, sub( 15, norm_s( hFdCngCom->A_cng[0] - 1 ) ), M, buf + 1 + M, hFdCngCom->exc_cng_32fx, hFdCngCom->frameSize );
    3459             : 
    3460             :     /* update and window olapBuf if we have a output frame that is shorter than the default frame size...*/
    3461        4395 :     IF( LT_16( samples_out, hFdCngCom->frameSize ) )
    3462             :     {
    3463           0 :         Copy32( olapBuffer + samples_out, olapBuffer + hFdCngCom->frameSize, i_mult( 3, shr( hFdCngCom->frameSize, 2 ) ) );
    3464             :     }
    3465      650411 :     FOR( i = ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i < ( 7 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3466             :     {
    3467      646016 :         olapBuffer[i] = Mpy_32_16_1( olapBuffer[i], olapWin[( i - ( 3 * ( hFdCngCom->frameSize >> 2 ) ) )] );
    3468      646016 :         move32();
    3469             :     }
    3470             : 
    3471        4395 :     return;
    3472             : }
    3473             : 
    3474    44035272 : Word32 rand_gauss_fx(
    3475             :     Word32 *x,
    3476             :     Word16 *seed,
    3477             :     Word16 q )
    3478             : {
    3479             :     Word32 temp;
    3480             : 
    3481    44035272 :     temp = own_random( seed );
    3482    44035272 :     temp = L_add( temp, own_random( seed ) );
    3483    44035272 :     temp = L_add( temp, own_random( seed ) );
    3484    44035272 :     temp = L_shr( temp, sub( 15, q ) );
    3485             : 
    3486    44035272 :     *x = temp;
    3487    44035272 :     move32();
    3488             : 
    3489    44035272 :     return temp;
    3490             : }
    3491             : 
    3492             : /*-------------------------------------------------------------------
    3493             :  * rand_gauss_fix()
    3494             :  *
    3495             :  * Random generator with Gaussian distribution with mean 0 and std 1
    3496             :  *-------------------------------------------------------------------*/
    3497             : 
    3498    50740080 : Word16 rand_gauss_fix(
    3499             :     Word16 *x,
    3500             :     Word16 *seed )
    3501             : {
    3502             :     Word32 temp;
    3503             : 
    3504    50740080 :     temp = shr( own_random( seed ), Q2 );
    3505    50740080 :     temp = L_add( temp, shr( own_random( seed ), Q2 ) );
    3506    50740080 :     temp = L_add( temp, shr( own_random( seed ), Q2 ) );
    3507             : 
    3508    50740080 :     *x = (Word16) temp;
    3509    50740080 :     move32();
    3510             : 
    3511    50740080 :     return (Word16) temp;
    3512             : }

Generated by: LCOV version 1.14