LCOV - code coverage report
Current view: top level - lib_com - fd_cng_com_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 1474 1690 87.2 %
Date: 2025-08-23 01:22:27 Functions: 27 32 84.4 %

          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        7135 : 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        7135 :     hs = (HANDLE_FD_CNG_COM) malloc( sizeof( FD_CNG_COM ) );
      44             : 
      45        7135 :     if ( hs == NULL )
      46             :     {
      47           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD CNG COM" );
      48             :     }
      49             : 
      50        7135 :     *hFdCngCom = hs;
      51             : 
      52        7135 :     return IVAS_ERR_OK;
      53             : }
      54             : /*-------------------------------------------------------------------
      55             :  * initFdCngCom()
      56             :  *
      57             :  *
      58             :  *-------------------------------------------------------------------*/
      59             : 
      60        7132 : 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        7132 :     assert( 2048 /*1.0/(1<<4) Q15*/ < mult( scale, scale ) );
      66             :     /* Exponent invScalingFactor: -16 = -(2*7 (scale) + 2 (8.0) */
      67        7132 :     hFdCngCom->invScalingFactor = shl( mult( scale, scale ), 1 );
      68             :     /* Exponent scalingFactor: -15 = -(2*7 (scale) + 2 (8.0) - 1 (1.0)) */
      69        7132 :     hFdCngCom->scalingFactor = div_s( 0x4000, hFdCngCom->invScalingFactor );
      70             : 
      71             :     /* Initialize the overlap-add */
      72        7132 :     set16_fx( hFdCngCom->timeDomainBuffer, 0, L_FRAME16k );
      73        7132 :     hFdCngCom->olapBufferAna = NULL;
      74        7132 :     set16_fx( hFdCngCom->olapBufferAna_fx, 0, FFTLEN );
      75             : 
      76        7132 :     move16();
      77        7132 :     set16_fx( hFdCngCom->olapBufferSynth, 0, FFTLEN );
      78        7132 :     hFdCngCom->olapBufferSynth2 = NULL;
      79        7132 :     move16();
      80             : 
      81             :     /* Initialize the comfort noise generation */
      82        7132 :     set32_fx( hFdCngCom->fftBuffer, 0, FFTLEN );
      83        7132 :     set32_fx( hFdCngCom->cngNoiseLevel, 0, FFTCLDFBLEN );
      84        7132 :     set16_fx( &hFdCngCom->cngNoiseLevelExp, 0, 1 );
      85             : 
      86             :     /* Initialize quantizer */
      87        7132 :     set32_fx( hFdCngCom->sidNoiseEst, 0, NPART );
      88        7132 :     set16_fx( &hFdCngCom->sidNoiseEstExp, 0, 1 );
      89        7132 :     set16_fx( hFdCngCom->A_cng, 0, M + 1 );
      90        7132 :     hFdCngCom->A_cng[0] = 4096 /*1.f Q12*/; /* 3Q12 */
      91        7132 :     move16();
      92             : 
      93             :     /* Set some counters and flags */
      94        7132 :     hFdCngCom->inactive_frame_counter = 0; /* Either SID or zero frames */
      95        7132 :     move16();
      96        7132 :     hFdCngCom->active_frame_counter = 0;
      97        7132 :     move16();
      98        7132 :     hFdCngCom->frame_type_previous = ACTIVE_FRAME;
      99        7132 :     move16();
     100        7132 :     hFdCngCom->flag_noisy_speech = 0;
     101        7132 :     move16();
     102        7132 :     hFdCngCom->likelihood_noisy_speech = 0;
     103        7132 :     move16();
     104        7132 :     hFdCngCom->numCoreBands = 0;
     105        7132 :     move16();
     106        7132 :     hFdCngCom->stopBand = 0;
     107        7132 :     move16();
     108        7132 :     hFdCngCom->startBand = 0;
     109        7132 :     move16();
     110        7132 :     hFdCngCom->stopFFTbin = 0;
     111        7132 :     move16();
     112        7132 :     hFdCngCom->frameSize = 0;
     113        7132 :     move16();
     114        7132 :     hFdCngCom->fftlen = 0;
     115        7132 :     move16();
     116        7132 :     hFdCngCom->seed = 0;
     117        7132 :     move16();
     118        7132 :     hFdCngCom->seed2 = 1;
     119        7132 :     move16();
     120        7132 :     hFdCngCom->seed3 = 2;
     121        7132 :     move16();
     122        7132 :     hFdCngCom->CngBitrate = -1;
     123        7132 :     move16();
     124        7132 :     hFdCngCom->olapBufferSynth_exp = 0;
     125        7132 :     move16();
     126             : 
     127             :     /* Initialize noise estimation algorithm */
     128        7132 :     set32_fx( hFdCngCom->periodog, 0, PERIODOGLEN );
     129        7132 :     mhvals( MSNUMSUBFR * MSSUBFRLEN, &( hFdCngCom->msM_win ) );
     130        7132 :     mhvals( MSSUBFRLEN, &( hFdCngCom->msM_subwin ) );
     131        7132 :     set32_fx( hFdCngCom->msPeriodogSum, 0, 2 );
     132        7132 :     hFdCngCom->msPeriodogSum_exp[0] = 0;
     133        7132 :     move16();
     134        7132 :     hFdCngCom->msPeriodogSum_exp[1] = 0;
     135        7132 :     move16();
     136        7132 :     set32_fx( hFdCngCom->msPsdSum, 0, 2 );
     137        7132 :     set16_fx( hFdCngCom->msSlope, 0, 2 );
     138        7132 :     set32_fx( hFdCngCom->msQeqInvAv, 0, 2 );
     139        7132 :     hFdCngCom->msQeqInvAv_exp[0] = 0;
     140        7132 :     move16();
     141        7132 :     hFdCngCom->msQeqInvAv_exp[1] = 0;
     142        7132 :     move16();
     143        7132 :     hFdCngCom->msFrCnt_init_counter = 0;
     144        7132 :     move16();
     145        7132 :     hFdCngCom->msFrCnt_init_thresh = 1;
     146        7132 :     move16();
     147        7132 :     hFdCngCom->init_old = 0;
     148        7132 :     move16();
     149        7132 :     hFdCngCom->offsetflag = 0;
     150        7132 :     move16();
     151        7132 :     hFdCngCom->msFrCnt = MSSUBFRLEN;
     152        7132 :     move16();
     153        7132 :     hFdCngCom->msMinBufferPtr = 0;
     154        7132 :     move16();
     155        7132 :     hFdCngCom->msAlphaCor[0] = 644245120l /*0.3f Q31*/;
     156        7132 :     move16();
     157        7132 :     hFdCngCom->msAlphaCor[1] = 644245120l /*0.3f Q31*/;
     158        7132 :     move16();
     159        7132 :     set16_fx( hFdCngCom->psize, 0, NPART );
     160             :     /* Initialize exponents */
     161        7132 :     hFdCngCom->exp_cldfb_periodog = 0;
     162        7132 :     move16();
     163             : 
     164        7132 :     hFdCngCom->coherence_fx = 16384; /* 0.5 in Q15 */
     165        7132 :     move16();
     166             : 
     167        7132 :     set32_fx( hFdCngCom->olapBufferSynth_fx, 0, FFTLEN );
     168        7132 :     set32_fx( hFdCngCom->olapBufferSynth2_fx, 0, FFTLEN );
     169        7132 :     set32_fx( hFdCngCom->exc_cng_32fx, 0, L_FRAME16k );
     170        7132 :     set16_fx( hFdCngCom->exc_cng, 0, L_FRAME16k );
     171             : 
     172        7132 :     return;
     173             : }
     174           3 : 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           3 :     assert( 2048 /*1.0/(1<<4) Q15*/ < mult( scale, scale ) );
     180             :     /* Exponent invScalingFactor: -16 = -(2*7 (scale) + 2 (8.0) */
     181           3 :     hFdCngCom->invScalingFactor = shl( mult( scale, scale ), 1 );
     182           3 :     move16();
     183             :     /* Exponent scalingFactor: -15 = -(2*7 (scale) + 2 (8.0) - 1 (1.0)) */
     184           3 :     hFdCngCom->scalingFactor = div_s( 0x4000, hFdCngCom->invScalingFactor );
     185           3 :     move16();
     186             : 
     187             :     /* Initialize the overlap-add */
     188           3 :     set16_fx( hFdCngCom->timeDomainBuffer, 0, L_FRAME16k );
     189           3 :     hFdCngCom->olapBufferAna = NULL;
     190           3 :     set16_fx( hFdCngCom->olapBufferAna_fx, 0, FFTLEN );
     191             : 
     192           3 :     set16_fx( hFdCngCom->olapBufferSynth, 0, FFTLEN );
     193           3 :     hFdCngCom->olapBufferSynth2 = NULL;
     194             : 
     195             :     /* Initialize the comfort noise generation */
     196           3 :     set32_fx( hFdCngCom->fftBuffer, 0, FFTLEN );
     197           3 :     set32_fx( hFdCngCom->cngNoiseLevel, 0, FFTCLDFBLEN );
     198           3 :     set16_fx( &hFdCngCom->cngNoiseLevelExp, 0, 1 );
     199             : 
     200             :     /* Initialize quantizer */
     201           3 :     set32_fx( hFdCngCom->sidNoiseEst, 0, NPART );
     202           3 :     set16_fx( &hFdCngCom->sidNoiseEstExp, 0, 1 );
     203           3 :     set16_fx( hFdCngCom->A_cng, 0, M + 1 );
     204           3 :     hFdCngCom->A_cng[0] = 4096 /*1.f Q12*/; /* 3Q12 */
     205           3 :     move16();
     206             : 
     207             :     /* Set some counters and flags */
     208           3 :     hFdCngCom->inactive_frame_counter = 0; /* Either SID or zero frames */
     209           3 :     move16();
     210           3 :     hFdCngCom->active_frame_counter = 0;
     211           3 :     move16();
     212           3 :     hFdCngCom->frame_type_previous = ACTIVE_FRAME;
     213           3 :     move16();
     214           3 :     hFdCngCom->flag_noisy_speech = 0;
     215           3 :     move16();
     216           3 :     hFdCngCom->likelihood_noisy_speech = 0;
     217           3 :     move16();
     218           3 :     hFdCngCom->numCoreBands = 0;
     219           3 :     move16();
     220           3 :     hFdCngCom->stopBand = 0;
     221           3 :     move16();
     222           3 :     hFdCngCom->startBand = 0;
     223           3 :     move16();
     224           3 :     hFdCngCom->stopFFTbin = 0;
     225           3 :     move16();
     226           3 :     hFdCngCom->frameSize = 0;
     227           3 :     move16();
     228           3 :     hFdCngCom->fftlen = 0;
     229           3 :     move16();
     230           3 :     hFdCngCom->seed = 0;
     231           3 :     move16();
     232             :     // hFdCngCom->seed2 = 1;
     233             :     // move16();
     234             :     // hFdCngCom->seed3 = 2;
     235             :     // move16();
     236           3 :     hFdCngCom->CngBitrate = -1;
     237           3 :     move16();
     238             : 
     239             :     /* Initialize noise estimation algorithm */
     240           3 :     set32_fx( hFdCngCom->periodog, 0, PERIODOGLEN );
     241           3 :     mhvals( MSNUMSUBFR * MSSUBFRLEN, &( hFdCngCom->msM_win ) );
     242           3 :     mhvals( MSSUBFRLEN, &( hFdCngCom->msM_subwin ) );
     243           3 :     set32_fx( hFdCngCom->msPeriodogSum, 0, 2 );
     244           3 :     hFdCngCom->msPeriodogSum_exp[0] = 0;
     245           3 :     move16();
     246           3 :     hFdCngCom->msPeriodogSum_exp[1] = 0;
     247           3 :     move16();
     248           3 :     set32_fx( hFdCngCom->msPsdSum, 0, 2 );
     249           3 :     set16_fx( hFdCngCom->msSlope, 0, 2 );
     250           3 :     set32_fx( hFdCngCom->msQeqInvAv, 0, 2 );
     251           3 :     hFdCngCom->msQeqInvAv_exp[0] = 0;
     252           3 :     move16();
     253           3 :     hFdCngCom->msQeqInvAv_exp[1] = 0;
     254           3 :     move16();
     255           3 :     hFdCngCom->msFrCnt_init_counter = 0;
     256           3 :     move16();
     257           3 :     hFdCngCom->msFrCnt_init_thresh = 1;
     258           3 :     move16();
     259           3 :     hFdCngCom->init_old = 0;
     260           3 :     move16();
     261           3 :     hFdCngCom->offsetflag = 0;
     262           3 :     move16();
     263           3 :     hFdCngCom->msFrCnt = MSSUBFRLEN;
     264           3 :     move16();
     265           3 :     hFdCngCom->msMinBufferPtr = 0;
     266           3 :     move16();
     267           3 :     hFdCngCom->msAlphaCor[0] = 644245120l /*0.3f Q31*/;
     268           3 :     move16();
     269           3 :     hFdCngCom->msAlphaCor[1] = 644245120l /*0.3f Q31*/;
     270           3 :     move16();
     271           3 :     set16_fx( hFdCngCom->psize, 0, NPART );
     272             :     /* Initialize exponents */
     273           3 :     hFdCngCom->exp_cldfb_periodog = 0;
     274           3 :     move16();
     275             : 
     276           3 :     return;
     277             : }
     278             : 
     279             : /*-------------------------------------------------------------------
     280             :  * deleteFdCngCom()
     281             :  *
     282             :  * Delete an instance of type FD_CNG_COM
     283             :  *-------------------------------------------------------------------*/
     284        7135 : 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        7135 :     hsCom = *hFdCngCom;
     288        7135 :     move16();
     289        7135 :     IF( hsCom != NULL )
     290             :     {
     291        7135 :         free( hsCom );
     292        7135 :         *hFdCngCom = NULL;
     293        7135 :         move16();
     294             :     }
     295        7135 : }
     296             : 
     297             : /*-------------------------------------------------------------------
     298             :  * initPartitions()
     299             :  *
     300             :  * Initialize the spectral partitioning
     301             :  *-------------------------------------------------------------------*/
     302     1125334 : 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     1125334 :     IF( part_in != NULL )
     320             :     {
     321     1125334 :         len_out = 0;
     322     1125334 :         move16();
     323     1125334 :         IF( GT_16( stopBandFR, startBand ) )
     324             :         {
     325      562667 :             len_out = sub( stopBandFR, startBand );
     326    21944013 :             FOR( i = 0; i < len_out; i++ )
     327             :             {
     328    21381346 :                 part_out[i] = i;
     329    21381346 :                 move16();
     330             :             }
     331             :         }
     332    36570080 :         FOR( j = 0; j < npart_in; j++ )
     333             :         {
     334    35444746 :             IF( GE_16( part_in[j], stopBand ) )
     335             :             {
     336           0 :                 BREAK;
     337             :             }
     338    35444746 :             tmp16 = sub( part_in[j], startBand );
     339    35444746 :             test();
     340    35444746 :             if ( GE_16( part_in[j], stopBandFR ) && tmp16 >= 0 )
     341             :             {
     342    26442074 :                 part_out[len_out++] = tmp16;
     343    26442074 :                 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     1125334 :     *npart_out = len_out;
     358     1125334 :     move16();
     359     1125334 :     getmidbands( part_out, len_out, midband, psize, psize_norm, psize_norm_exp, psize_inv );
     360     1125334 : }
     361             : 
     362             : 
     363             : /*-------------------------------------------------------------------
     364             :  * compress_range()
     365             :  *
     366             :  * Apply some dynamic range compression based on the log
     367             :  *-------------------------------------------------------------------*/
     368       44318 : 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       44318 :     IF( in_exp >= 0 )
     383             :     {
     384       34685 :         one_s = L_shr( 1073741824l /*0.5 Q31*/, in_exp ); // Q(31 - in_exp)
     385       34685 :         in_exp32 = L_shl( L_deposit_l( add( in_exp, 1 ) ), WORD32_BITS - 1 - LD_DATA_SCALE );
     386     2163922 :         FOR( i = 0; i < len; i++ )
     387             :         {
     388     2129237 :             in_s = L_add( L_shr( in[i], 1 ), one_s ); // Q(31 - in_exp)
     389     2129237 :             L_tmp = L_add( BASOP_Util_Log2( in_s ), in_exp32 );
     390     2129237 :             if ( in_s == 0 )
     391             :             {
     392       56965 :                 out[i] = 0;
     393       56965 :                 move16();
     394             :             }
     395     2129237 :             if ( in_s != 0 )
     396             :             {
     397     2072272 :                 out[i] = extract_h( L_tmp );
     398     2072272 :                 move16();
     399             :             }
     400     2129237 :             if ( out[i] == 0 )
     401             :             {
     402      104827 :                 out[i] = 1;
     403      104827 :                 move16();
     404             :             }
     405             :         }
     406             :     }
     407             :     ELSE
     408             :     {
     409        9633 :         in_exp = sub( in_exp, 1 );
     410        9633 :         in_exp32 = L_shl( L_deposit_l( 1 ), WORD32_BITS - 1 - LD_DATA_SCALE );
     411      603086 :         FOR( i = 0; i < len; i++ )
     412             :         {
     413      593453 :             L_tmp = L_add( BASOP_Util_Log2( L_add( L_shl( in[i], in_exp ), 1073741824l /*0.5 Q31*/ ) ), in_exp32 );
     414      593453 :             if ( in[i] == 0 )
     415             :             {
     416        6960 :                 out[i] = 0;
     417        6960 :                 move16();
     418             :             }
     419      593453 :             if ( in[i] != 0 )
     420             :             {
     421      586493 :                 out[i] = extract_h( L_tmp );
     422      586493 :                 move16();
     423             :             }
     424      593453 :             if ( out[i] == 0 )
     425             :             {
     426      167614 :                 out[i] = 1;
     427      167614 :                 move16();
     428             :             }
     429             :         }
     430             :     }
     431       44318 : }
     432             : 
     433             : /*-------------------------------------------------------------------
     434             :  * expand_range()
     435             :  *
     436             :  * Apply some dynamic range expansion to undo the compression
     437             :  *-------------------------------------------------------------------*/
     438          15 : 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          15 :     maxVal = 0;
     453          15 :     move16();
     454         937 :     FOR( i = 0; i < len; i++ )
     455             :     {
     456         922 :         maxVal = s_max( maxVal, in[i] ); // Q15
     457             :     }
     458             : 
     459          15 :     maxVal2 = maxVal;
     460          15 :     move16();
     461          15 :     s = 0;
     462          15 :     move16();
     463          61 :     WHILE( maxVal >= 0 )
     464             :     {
     465          46 :         maxVal = sub( maxVal, 512 /*0.015625 Q15*/ ); // Q15
     466          46 :         s = add( s, 1 );
     467             :     }
     468          15 :     tmp = sub( maxVal2, maxVal );
     469             : 
     470          15 :     one_s = L_shr( 1073741824l /*0.5 Q31*/, sub( s, 1 ) ); // Q(31 - sub( s, 1 ))
     471          15 :     tmp32 = L_shr( 726941l /*0.0003385080526823181 Q31*/, s );
     472             :     /* out = (2^(in) - 1) */
     473         937 :     FOR( i = 0; i < len; i++ )
     474             :     {
     475         922 :         out[i] = L_sub( BASOP_Util_InvLog2( L_deposit_h( sub( in[i], tmp ) ) ), one_s );
     476         922 :         move32();
     477         922 :         if ( out[i] == 0 )
     478             :         {
     479          50 :             out[i] = tmp32;
     480          50 :             move32();
     481             :         }
     482             :     }
     483          15 :     *out_exp = s;
     484          15 :     move16();
     485          15 : }
     486             : 
     487       44303 : 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       44303 :     const Word32 low_lim = 726940; /* 0.0003385080526823181f in Q31 */
     498       44303 :     move32();
     499             : 
     500             :     /* Find max possible output exponent. */
     501       44303 :     maxVal = 0;
     502       44303 :     move32();
     503     2766071 :     FOR( i = 0; i < len; i++ )
     504             :     {
     505     2721768 :         maxVal = L_max( maxVal, in[i] );
     506             :     }
     507       44303 :     tmp32 = BASOP_util_Pow2( maxVal, Q31 - Q25, &tmp_e );
     508       44303 :     maxOutExp = tmp_e;
     509       44303 :     move16();
     510             : 
     511             :     /* out = (2^(in) - 1) */
     512     2766071 :     FOR( i = 0; i < len; i++ )
     513             :     {
     514     2721768 :         tmp32 = BASOP_util_Pow2( in[i], Q31 - Q25, &tmp_e );  // 2^x
     515     2721768 :         tmp32 = L_sub( tmp32, L_shl( 1, sub( 31, tmp_e ) ) ); // 2^x - 1
     516     2721768 :         tmp32 = L_shr( tmp32, sub( maxOutExp, tmp_e ) );      // make exp same as maxExpOut
     517             : 
     518     2721768 :         out[i] = tmp32;
     519     2721768 :         move32();
     520             : 
     521     2721768 :         Word32 tmp_low_lim = L_shr( low_lim, maxOutExp );
     522     2721768 :         if ( LT_32( out[i], tmp_low_lim ) )
     523             :         {
     524       14424 :             out[i] = tmp_low_lim;
     525       14424 :             move32();
     526             :         }
     527             :     }
     528             : 
     529       44303 :     *out_exp = maxOutExp;
     530       44303 :     move16();
     531             : 
     532       44303 :     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          15 : 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          15 :     len2 = i_mult( MSNUMSUBFR, len );
     659             : 
     660          15 :     msM_win = hFdCngCom->msM_win;
     661          15 :     move16();
     662          15 :     msM_subwin = hFdCngCom->msM_subwin;
     663          15 :     move16();
     664             : 
     665          15 :     msAlphaCorAlpha = MSALPHACORALPHA;
     666          15 :     move16();
     667          15 :     msAlphaCorAlpha2 = MSALPHACORALPHA2;
     668          15 :     move16();
     669             : 
     670          15 :     msPsdSum = hFdCngCom->msPsdSum;
     671          15 :     msPeriodogSum = hFdCngCom->msPeriodogSum;
     672             : 
     673             :     /* No minimum statistics at initialization */
     674          15 :     IF( LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
     675             :     {
     676           6 :         Copy( msPeriodog, msPsd, len );            /* 6Q9 */
     677           6 :         Copy( msPeriodog, msNoiseFloor, len );     /* 6Q9 */
     678           6 :         Copy( msPeriodog, msNoiseEst, len );       /* 6Q9 */
     679           6 :         Copy( msPeriodog, msPsdFirstMoment, len ); /* 6Q9 */
     680             : 
     681           6 :         set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
     682           6 :         msPeriodogSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
     683           6 :         move32();
     684           6 :         msPsdSum[0] = msPeriodogSum[0]; /* 16Q15 */
     685           6 :         move32();
     686             : 
     687           6 :         IF( LT_16( lenFFT, len ) )
     688             :         {
     689           0 :             msPeriodogSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
     690           0 :             move32();
     691           0 :             msPsdSum[1] = msPeriodogSum[1]; /* 16Q15 */
     692           0 :             move32();
     693             :         }
     694             : 
     695             :         /* Increment frame counter at initialization */
     696             :         /* Some frames are sometimes zero at initialization => ignore them */
     697           6 :         IF( LT_16( msPeriodog[0], hFdCngCom->init_old ) )
     698             :         {
     699           2 :             set32_fx( msCurrentMinOut, 2147483647l /*1.0 Q31*/, len );       /* 16Q15 */
     700           2 :             set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );          /* 16Q15 */
     701           2 :             set32_fx( msMinBuf, 2147483647l /*1.0 Q31*/, len2 );             /* 16Q15 */
     702           2 :             set32_fx( msCurrentMinSubWindow, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
     703             : 
     704           2 :             hFdCngCom->msFrCnt_init_counter = add( hFdCngCom->msFrCnt_init_counter, 1 );
     705           2 :             move16();
     706             :         }
     707           6 :         hFdCngCom->init_old = msPeriodog[0]; /* 6Q9 */
     708           6 :         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           9 :         cnt = 0;
     716           9 :         move16();
     717           9 :         start = 0;
     718           9 :         move16();
     719           9 :         stop = lenFFT;
     720           9 :         move16();
     721           9 :         totsize = sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand );
     722          18 :         WHILE( GT_16( stop, start ) )
     723             :         {
     724           9 :             current_len = sub( stop, start );
     725             : 
     726             :             /* Compute smoothed correction factor for PSD smoothing */
     727             : 
     728             :             /* msPeriodogSum[cnt] with format 16Q15 */
     729           9 :             msPeriodogSum[cnt] = dotp_s_fx( msPeriodog + start, psize + start, current_len, CNG_HS );
     730           9 :             move32();
     731             : 
     732           9 :             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           9 :                 s1 = norm_l( msPeriodogSum[cnt] );
     741           9 :                 msPeriodogSum16 = round_fx_sat( L_shl_sat( msPeriodogSum[cnt], s1 ) );
     742           9 :                 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           9 :                 scalar2 = L_abs( L_sub( msPsdSum[cnt], msPeriodogSum[cnt] ) );
     747             : 
     748           9 :                 s2 = WORD32_BITS - 1;
     749           9 :                 move16();
     750           9 :                 if ( scalar2 != 0 )
     751             :                 {
     752             :                     /* use absolute value to avoid -1.0 x -1.0 multiplications */
     753           9 :                     s2 = norm_l( scalar2 );
     754             :                 }
     755             : #ifdef ISSUE_1836_replace_overflow_libcom
     756           9 :                 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           9 :                 scalar2 = L_mult( scalar216, scalar216 );
     761             : 
     762             :                 /* find common exponent */
     763           9 :                 tmp16_1 = sub( s1, s2 );
     764           9 :                 tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
     765           9 :                 if ( tmp16_1 < 0 )
     766             :                 {
     767           7 :                     scalar2 = L_shr( scalar2, tmp16 );
     768             :                 }
     769           9 :                 if ( tmp16_1 > 0 )
     770             :                 {
     771           1 :                     scalar = L_shr( scalar, tmp16 );
     772             :                 }
     773             : 
     774             : 
     775             :                 /* add scalar and scalar2, avoid overflows */
     776           9 :                 scalar = L_shr( scalar, 1 );
     777           9 :                 scalar2 = L_shr( scalar2, 1 );
     778           9 :                 scalar3 = L_add( scalar, scalar2 );
     779             : 
     780             :                 /* calculate division */
     781           9 :                 scalar16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar, scalar3, &s3 );
     782           9 :                 s3 = s_max( s3, -( WORD16_BITS - 1 ) );
     783           9 :                 scalar16 = shl( scalar16, s3 );
     784           9 :                 scalar16 = s_max( scalar16, MSALPHACORMAX );
     785             : 
     786           9 :                 hFdCngCom->msAlphaCor[cnt] = L_add( Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha ),
     787             :                                                     L_mult( scalar16, msAlphaCorAlpha2 ) );
     788           9 :                 move32();
     789             :             }
     790             : 
     791             :             /* Compute SNR */
     792             : 
     793             :             /* msPeriodogSum[cnt] with format 16Q15 */
     794           9 :             snr = dotp_s_fx( msNoiseFloor + start, psize + start, current_len, CNG_HS );
     795             : 
     796           9 :             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           9 :                 msAlphaHatMin2 = MSALPHAHATMIN;
     807           9 :                 move32();
     808             :             }
     809           9 :             scalar = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], MSALPHAMAX );
     810             : 
     811         560 :             FOR( j = start; j < stop; j++ )
     812             :             {
     813             :                 /* Compute optimal smoothing parameter for PSD estimation */
     814         551 :                 test();
     815         551 :                 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         551 :                     s1 = WORD16_BITS - 1;
     824         551 :                     move16();
     825         551 :                     if ( msNoiseFloor[j] != 0 )
     826             :                     {
     827         551 :                         s1 = norm_s( msNoiseFloor[j] );
     828             :                     }
     829         551 :                     msNoiseFloor16 = shl( msNoiseFloor[j], s1 );
     830         551 :                     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         551 :                     scalar316 = abs_s( sub( msPsd[j], msNoiseFloor[j] ) );
     835             : 
     836         551 :                     s2 = WORD16_BITS - 1;
     837         551 :                     move16();
     838         551 :                     if ( scalar316 != 0 )
     839             :                     {
     840             :                         /* use absolute value to avoid -1.0 x -1.0 multiplications */
     841         397 :                         s2 = norm_s( scalar316 );
     842             :                     }
     843         551 :                     scalar316 = shl( scalar316, s2 );
     844         551 :                     scalar3 = L_mult( scalar316, scalar316 );
     845             : 
     846             :                     /* find common exponent */
     847         551 :                     tmp16_1 = sub( s1, s2 );
     848         551 :                     tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
     849         551 :                     if ( tmp16_1 < 0 )
     850             :                     {
     851         460 :                         scalar3 = L_shr( scalar3, tmp16 );
     852             :                     }
     853         551 :                     if ( tmp16_1 > 0 )
     854             :                     {
     855           3 :                         scalar2 = L_shr( scalar2, tmp16 );
     856             :                     }
     857             : 
     858             :                     /* add scalar2 and scalar3, avoid overflows */
     859         551 :                     scalar2 = L_shr( scalar2, 1 );
     860         551 :                     scalar3 = L_shr( scalar3, 1 );
     861         551 :                     scalar3 = L_add( scalar2, scalar3 );
     862             : 
     863             :                     /* calculate division */
     864         551 :                     tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar2, scalar3, &s3 );
     865         551 :                     scalar2 = Mpy_32_16_1( scalar, tmp16 );
     866         551 :                     s3 = s_max( s3, -( WORD32_BITS - 1 ) );
     867         551 :                     scalar2 = L_shl( scalar2, s3 );
     868         551 :                     msAlpha[j] = L_max( scalar2, msAlphaHatMin2 );
     869         551 :                     move32();
     870             :                 }
     871             : 
     872             :                 /* Compute the PSD (smoothed periodogram) in each band */
     873         551 :                 msPsd[j] = round_fx( L_add( Mpy_32_16_1( msAlpha[j], msPsd[j] ),
     874         551 :                                             Mpy_32_16_1( L_sub( 2147483647l /*1.0 Q31*/, msAlpha[j] ), msPeriodog[j] ) ) );
     875         551 :                 move16();
     876             :             }
     877           9 :             msPsdSum[cnt] = dotp_s_fx( msPsd + start, psize + start, current_len, CNG_HS );
     878           9 :             move32();
     879             : 
     880           9 :             QeqInvAv = 0l /*0.0 Q31*/;
     881           9 :             move32();
     882             : 
     883             :             /* scalar: 7Q24 format */
     884           9 :             tmp = 1191182336l /*(float)(MSNUMSUBFR*MSSUBFRLEN)-1.0 Q24*/;
     885           9 :             move32();
     886           9 :             scalar = L_sub( tmp, L_mult( round_fx( tmp ), msM_win ) );
     887             : 
     888             :             /* scalar2: 4Q27 format */
     889           9 :             tmp = 1476395008l /*(float)MSSUBFRLEN-1.0 Q27*/;
     890           9 :             move32();
     891           9 :             scalar2 = L_sub( tmp, L_mult( round_fx( tmp ), msM_subwin ) );
     892             : 
     893         560 :             FOR( j = start; j < stop; j++ )
     894             :             {
     895             :                 /* Compute variance of PSD */
     896         551 :                 tmp = L_min( msAlpha[j], MSBETAMAX_SQRT );
     897             : 
     898         551 :                 s1 = WORD32_BITS - 1;
     899         551 :                 move16();
     900         551 :                 if ( tmp != 0 )
     901             :                 {
     902         551 :                     s1 = norm_l( tmp );
     903             :                 }
     904         551 :                 s2 = shl( s1, 1 );
     905             : 
     906         551 :                 s2 = s_min( s2, WORD32_BITS - 1 );
     907             : 
     908             :                 /* beta: scaled by s2 */
     909             : #ifdef ISSUE_1836_replace_overflow_libcom
     910         551 :                 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         551 :                 beta = mult_r( tmp16, tmp16 );
     915             : 
     916             :                 /* scalar3: scaled by s3 */
     917         551 :                 scalar3 = L_sub( L_deposit_l( msPsd[j] ), L_deposit_l( msPsdFirstMoment[j] ) );
     918         551 :                 s3 = norm_l( scalar3 );
     919         551 :                 scalar3 = L_shl( scalar3, s3 );
     920             : 
     921             :                 /* msPsdFirstMoment: 6Q9   */
     922         551 :                 tmp = L_msu( L_mult( beta, msPsdFirstMoment[j] ), beta, msPsd[j] );
     923         551 :                 msPsdFirstMoment[j] = add( round_fx( L_shr( tmp, s2 ) ), msPsd[j] );
     924         551 :                 move16();
     925             : 
     926             :                 /* msPsdSecondMoment: 12Q19   */
     927         551 :                 tmp0 = L_shr( Mpy_32_16_r( msPsdSecondMoment[j], beta ), s2 );
     928         551 :                 tmp1 = Mpy_32_32( scalar3, scalar3 );
     929         551 :                 tmp1 = L_shr( L_sub( tmp1, L_shr( Mpy_32_16_r( tmp1, beta ), s2 ) ), sub( shl( s3, 1 ), 32 ) );
     930         551 :                 msPsdSecondMoment[j] = L_add( tmp0, tmp1 );
     931         551 :                 move32();
     932             : 
     933             :                 /* Compute inverse of amount of degrees of freedom */
     934         551 :                 QeqInv = MSQEQINVMAX;
     935         551 :                 move16();
     936             : 
     937         551 :                 IF( msNoiseFloor[j] != 0 /*0.0 Q15*/ )
     938             :                 {
     939         551 :                     tmp = L_mult( msNoiseFloor[j], msNoiseFloor[j] );
     940         551 :                     tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( msPsdSecondMoment[j], tmp, &s );
     941             :                     /* consider factor of 2 */
     942         551 :                     s = s_min( s_max( sub( s, 1 ), -( WORD16_BITS - 1 ) ), ( WORD16_BITS - 1 ) );
     943         551 :                     if ( s < 0 )
     944             :                     {
     945         494 :                         QeqInv = shl( tmp16, s );
     946             :                     }
     947         551 :                     QeqInv = s_min( QeqInv, MSQEQINVMAX );
     948             :                 }
     949         551 :                 QeqInvAv = L_add( QeqInvAv, L_mult( QeqInv, psize[j] ) );
     950             : 
     951             :                 /* Compute bias correction Bmin */
     952         551 :                 tmp0 = Mpy_32_16_1( scalar, QeqInv );
     953         551 :                 tmp1 = L_sub( 1073741824l /*0.5 Q31*/, L_mult( msM_win, QeqInv ) );
     954         551 :                 tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
     955         551 :                 msBminWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), add( s, 7 - 4 ) ) );
     956         551 :                 move32();
     957             : 
     958         551 :                 tmp0 = Mpy_32_16_1( scalar2, QeqInv );
     959         551 :                 tmp1 = L_sub( 1073741824l /*0.5 Q31*/, L_mult( msM_subwin, QeqInv ) );
     960         551 :                 tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
     961         551 :                 msBminSubWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), s ) );
     962         551 :                 move32();
     963             :             }
     964             : 
     965           9 :             inv_totsize = BASOP_Util_Divide3232_uu_1616_Scale( 1, totsize, &s );
     966           9 :             QeqInvAv = Mpy_32_16_1( QeqInvAv, inv_totsize );
     967           9 :             QeqInvAv = L_shl( QeqInvAv, s );
     968           9 :             hFdCngCom->msQeqInvAv[cnt] = QeqInvAv;
     969           9 :             move32();
     970             : 
     971             :             /* New minimum? */
     972             : 
     973             :             /* exponent QeqInvAv: CNG_S, exponent MSAV: (4>>1) */
     974           9 :             s = CNG_S + 2 * MSAV_EXP;
     975           9 :             move16();
     976           9 :             BminCorr = Mpy_32_16_1( Sqrt32( QeqInvAv, &s ), MSAV );
     977           9 :             BminCorr = L_shl( BminCorr, sub( s, 1 ) );
     978             : 
     979             :             /* exponent BminCorr: 1 */
     980           9 :             BminCorr = L_add( BminCorr, 1073741824l /*0.5 Q31*/ );
     981             : 
     982         560 :             FOR( j = start; j < stop; j++ )
     983             :             {
     984             :                 /* exponent scalar: CNG_S+1 */
     985         551 :                 scalar = Mpy_32_16_1( BminCorr, msPsd[j] );
     986             : 
     987             :                 /* exponent scalar2: CNG_S+1+4 */
     988         551 :                 scalar2 = Mpy_32_32( scalar, msBminWin[j] );
     989             : 
     990         551 :                 msNewMinFlag[j] = 0;
     991         551 :                 move16();
     992         551 :                 IF( LT_32( scalar2, msCurrentMin[j] ) /*0.0 Q31*/ )
     993             :                 {
     994         323 :                     msNewMinFlag[j] = 1;
     995         323 :                     move16();
     996             :                     /* exponent msCurrentMin[j]: CNG_S+1+4 */
     997         323 :                     msCurrentMin[j] = scalar2;
     998         323 :                     move32();
     999             :                     /* exponent msCurrentMinSubWindow[j]: CNG_S */
    1000             :                     BASOP_SATURATE_WARNING_OFF_EVS;
    1001             : #ifdef ISSUE_1836_replace_overflow_libcom
    1002         323 :                     msCurrentMinSubWindow[j] = L_shl_sat( Mpy_32_32( scalar, msBminSubWin[j] ), 5 );
    1003         323 :                     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           9 :             IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1014             :             {
    1015           7 :                 FOR( i = 0; i < 3; i++ )
    1016             :                 {
    1017           6 :                     IF( LT_32( hFdCngCom->msQeqInvAv[cnt], L_shr( L_deposit_h( msQeqInvAv_thresh[i] ), CNG_S ) ) /*0.0 Q31*/ )
    1018             :                     {
    1019           1 :                         BREAK;
    1020             :                     }
    1021             :                 }
    1022             :                 /* format 1Q30 */
    1023           2 :                 hFdCngCom->msSlope[cnt] = msNoiseSlopeMax[i];
    1024           2 :                 move32();
    1025             :             }
    1026             : 
    1027             :             /* Consider the FFT and CLDFB bands separately */
    1028           9 :             start = stop;
    1029           9 :             move16();
    1030           9 :             stop = len;
    1031           9 :             move16();
    1032           9 :             totsize = sub( hFdCngCom->stopBand, hFdCngCom->stopFFTbin );
    1033           9 :             cnt = add( cnt, 1 );
    1034             :         } /*while (stop > start)*/
    1035             : 
    1036             :         /* Update minimum between sub windows */
    1037           9 :         test();
    1038           9 :         IF( GT_16( hFdCngCom->msFrCnt, 1 ) && LT_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1039             :         {
    1040         310 :             FOR( j = 0; j < len; j++ )
    1041             :             {
    1042         305 :                 if ( msNewMinFlag[j] > 0 )
    1043             :                 {
    1044          77 :                     msLocalMinFlag[j] = 1;
    1045          77 :                     move16();
    1046             :                 }
    1047         305 :                 if ( LT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ )
    1048             :                 {
    1049             :                     /* msCurrentMinOut[j] scaled with CNG_S */
    1050          88 :                     msCurrentMinOut[j] = msCurrentMinSubWindow[j];
    1051          88 :                     move32();
    1052             :                 }
    1053             :             }
    1054             :             /* Get the current noise floor */
    1055           5 :             Copy_Scale_sig_32_16( msCurrentMinOut, msNoiseFloor, len, -16 );
    1056             :         }
    1057             :         ELSE /* sub window complete */
    1058             :         {
    1059           4 :             IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1060             :             {
    1061             :                 /* Collect buffers */
    1062           2 :                 Copy32( msCurrentMinSubWindow, msMinBuf + len * hFdCngCom->msMinBufferPtr, len );
    1063             : 
    1064             :                 /* Compute minimum among all buffers */
    1065           2 :                 Copy32( msMinBuf, msCurrentMinOut, len );
    1066           2 :                 ptr = msMinBuf + len;
    1067          12 :                 FOR( i = 1; i < MSNUMSUBFR; i++ )
    1068             :                 {
    1069         625 :                     FOR( j = 0; j < len; j++ )
    1070             :                     {
    1071         615 :                         if ( LT_32( *ptr, msCurrentMinOut[j] ) /*0.0 Q31*/ )
    1072             :                         {
    1073           0 :                             msCurrentMinOut[j] = *ptr;
    1074           0 :                             move32();
    1075             :                         }
    1076         615 :                         ptr++;
    1077             :                     }
    1078             :                 }
    1079             : 
    1080             :                 /* Take over local minima */
    1081           2 :                 slope = hFdCngCom->msSlope[0];
    1082           2 :                 move16();
    1083         125 :                 FOR( j = 0; j < len; j++ )
    1084             :                 {
    1085         123 :                     if ( EQ_16( j, lenFFT ) )
    1086             :                     {
    1087           0 :                         slope = hFdCngCom->msSlope[1];
    1088           0 :                         move16();
    1089             :                     }
    1090         123 :                     test();
    1091         123 :                     test();
    1092         123 :                     test();
    1093         123 :                     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           0 :                         msCurrentMinOut[j] = msCurrentMinSubWindow[j];
    1096           0 :                         move32();
    1097           0 :                         i = j;
    1098           0 :                         move16();
    1099           0 :                         FOR( k = 0; k < MSNUMSUBFR; k++ )
    1100             :                         {
    1101           0 :                             msMinBuf[i] = msCurrentMinOut[j];
    1102           0 :                             move32();
    1103           0 :                             i = add( i, len );
    1104             :                         }
    1105             :                     }
    1106             :                 }
    1107             : 
    1108             :                 /* Reset */
    1109           2 :                 set16_fx( msLocalMinFlag, 0, len );
    1110           2 :                 set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );
    1111             : 
    1112             :                 /* Get the current noise floor */
    1113           2 :                 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           9 :         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           9 :             hFdCngCom->offsetflag = 0;
    1148           9 :             move16();
    1149             :         }
    1150             : 
    1151             : 
    1152             :         /* Increment frame counter */
    1153           9 :         IF( EQ_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1154             :         {
    1155           2 :             hFdCngCom->msFrCnt = 1;
    1156           2 :             move16();
    1157           2 :             hFdCngCom->msMinBufferPtr = add( hFdCngCom->msMinBufferPtr, 1 );
    1158           2 :             move16();
    1159           2 :             if ( EQ_16( hFdCngCom->msMinBufferPtr, MSNUMSUBFR ) )
    1160             :             {
    1161           0 :                 hFdCngCom->msMinBufferPtr = 0;
    1162           0 :                 move16();
    1163             :             }
    1164             :         }
    1165             :         ELSE
    1166             :         {
    1167           7 :             hFdCngCom->msFrCnt = add( hFdCngCom->msFrCnt, 1 );
    1168             :         }
    1169             : 
    1170             :         /* Smooth noise estimate during CNG phases */
    1171         560 :         FOR( j = 0; j < len; j++ )
    1172             :         {
    1173         551 :             msNoiseEst[j] = round_fx( L_mac( L_mult( 31130 /*0.95 Q15*/, msNoiseEst[j] ), 1638 /*0.05 Q15*/, msNoiseFloor[j] ) );
    1174         551 :             move16();
    1175             :         }
    1176             :     }
    1177             :     /* Collect buffers */
    1178          15 :     Copy( msPeriodog, msPeriodogBuf + len * ( *msPeriodogBufPtr ), len );
    1179             : 
    1180          15 :     *msPeriodogBufPtr = add( *msPeriodogBufPtr, 1 );
    1181          15 :     move16();
    1182          15 :     if ( EQ_16( *msPeriodogBufPtr, MSBUFLEN ) )
    1183             :     {
    1184           2 :         ( *msPeriodogBufPtr ) = 0;
    1185           2 :         move16();
    1186             :     }
    1187             : 
    1188             :     /* Upper limit the noise floors with the averaged input energy */
    1189         937 :     FOR( j = 0; j < len; j++ )
    1190             :     {
    1191         922 :         scalar = L_mult( msPeriodogBuf[j], 6554 /*1.0/MSBUFLEN Q15*/ );
    1192             : 
    1193        4610 :         FOR( i = j + len; i < MSBUFLEN * len; i += len )
    1194             :         {
    1195        3688 :             scalar = L_mac( scalar, msPeriodogBuf[i], 6554 /*1.0/MSBUFLEN Q15*/ );
    1196             :         }
    1197         922 :         scalar16 = round_fx( scalar );
    1198         922 :         if ( GT_16( msNoiseEst[j], scalar16 ) /*0.0 Q15*/ )
    1199             :         {
    1200         361 :             msNoiseEst[j] = scalar16;
    1201         361 :             move16();
    1202             :         }
    1203             : 
    1204         922 :         assert( msNoiseEst[j] >= 0 /*0.0 Q15*/ );
    1205             :     }
    1206          15 : }
    1207             : 
    1208       44303 : 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       44303 :     len2 = i_mult( MSNUMSUBFR, len );
    1273             : 
    1274       44303 :     msM_win = hFdCngCom->msM_win;
    1275       44303 :     move16();
    1276       44303 :     msM_subwin = hFdCngCom->msM_subwin;
    1277       44303 :     move16();
    1278             : 
    1279       44303 :     msAlphaCorAlpha = MSALPHACORALPHA;
    1280       44303 :     move16();
    1281       44303 :     msAlphaCorAlpha2 = MSALPHACORALPHA2;
    1282       44303 :     move16();
    1283             : 
    1284       44303 :     msPsdSum = hFdCngCom->msPsdSum;
    1285       44303 :     msPeriodogSum = hFdCngCom->msPeriodogSum;
    1286             : 
    1287             :     /* No minimum statistics at initialization */
    1288       44303 :     IF( LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
    1289             :     {
    1290        3919 :         Copy( msPeriodog, msPsd, len );                                    /* 6Q9 */
    1291        3919 :         Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseFloor, len, Q16 ); /* Q25 */
    1292        3919 :         Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseEst, len, Q16 );   /* Q25 */
    1293        3919 :         Copy( msPeriodog, msPsdFirstMoment, len );                         /* 6Q9 */
    1294             : 
    1295        3919 :         set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
    1296        3919 :         msPeriodogSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
    1297        3919 :         move32();
    1298        3919 :         msPsdSum[0] = msPeriodogSum[0]; /* 16Q15 */
    1299        3919 :         move32();
    1300             : 
    1301        3919 :         IF( LT_16( lenFFT, len ) )
    1302             :         {
    1303           0 :             msPeriodogSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
    1304           0 :             move32();
    1305           0 :             msPsdSum[1] = msPeriodogSum[1]; /* 16Q15 */
    1306           0 :             move32();
    1307             :         }
    1308             : 
    1309             :         /* Increment frame counter at initialization */
    1310             :         /* Some frames are sometimes zero at initialization => ignore them */
    1311        3919 :         IF( LT_16( msPeriodog[0], hFdCngCom->init_old ) )
    1312             :         {
    1313         710 :             set32_fx( msCurrentMinOut, 2147483647l /*1.0 Q31*/, len );       /* 16Q15 */
    1314         710 :             set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );          /* 16Q15 */
    1315         710 :             set32_fx( msMinBuf, 2147483647l /*1.0 Q31*/, len2 );             /* 16Q15 */
    1316         710 :             set32_fx( msCurrentMinSubWindow, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
    1317             : 
    1318         710 :             hFdCngCom->msFrCnt_init_counter = add( hFdCngCom->msFrCnt_init_counter, 1 );
    1319         710 :             move16();
    1320             :         }
    1321        3919 :         hFdCngCom->init_old = msPeriodog[0]; /* 6Q9 */
    1322        3919 :         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       40384 :         cnt = 0;
    1330       40384 :         move16();
    1331       40384 :         start = 0;
    1332       40384 :         move16();
    1333       40384 :         stop = lenFFT;
    1334       40384 :         move16();
    1335       40384 :         totsize = sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand );
    1336       80768 :         WHILE( GT_16( stop, start ) )
    1337             :         {
    1338       40384 :             current_len = sub( stop, start );
    1339             : 
    1340             :             /* Compute smoothed correction factor for PSD smoothing */
    1341             : 
    1342             :             /* msPeriodogSum[cnt] with format 16Q15 */
    1343       40384 :             msPeriodogSum[cnt] = dotp_s_fx( msPeriodog + start, psize + start, current_len, CNG_HS );
    1344       40384 :             move32();
    1345             : 
    1346       40384 :             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       40384 :                 s1 = norm_l( msPeriodogSum[cnt] );
    1355       40384 :                 msPeriodogSum16 = round_fx_sat( L_shl( msPeriodogSum[cnt], s1 ) );
    1356       40384 :                 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       40384 :                 scalar2 = L_abs( L_sub( msPsdSum[cnt], msPeriodogSum[cnt] ) );
    1361             : 
    1362       40384 :                 s2 = WORD32_BITS - 1;
    1363       40384 :                 move16();
    1364       40384 :                 if ( scalar2 != 0 )
    1365             :                 {
    1366             :                     /* use absolute value to avoid -1.0 x -1.0 multiplications */
    1367       40128 :                     s2 = norm_l( scalar2 );
    1368             :                 }
    1369             : #ifdef ISSUE_1836_replace_overflow_libcom
    1370       40384 :                 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       40384 :                 scalar2 = L_mult( scalar216, scalar216 );
    1375             : 
    1376             :                 /* find common exponent */
    1377       40384 :                 tmp16_1 = sub( s1, s2 );
    1378       40384 :                 tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
    1379       40384 :                 if ( tmp16_1 < 0 )
    1380             :                 {
    1381       39066 :                     scalar2 = L_shr( scalar2, tmp16 );
    1382             :                 }
    1383       40384 :                 if ( tmp16_1 > 0 )
    1384             :                 {
    1385         550 :                     scalar = L_shr( scalar, tmp16 );
    1386             :                 }
    1387             : 
    1388             : 
    1389             :                 /* add scalar and scalar2, avoid overflows */
    1390       40384 :                 scalar = L_shr( scalar, 1 );
    1391       40384 :                 scalar2 = L_shr( scalar2, 1 );
    1392       40384 :                 scalar3 = L_add( scalar, scalar2 );
    1393             : 
    1394             :                 /* calculate division */
    1395       40384 :                 scalar16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar, scalar3, &s3 );
    1396       40384 :                 s3 = s_max( s3, -( WORD16_BITS - 1 ) );
    1397       40384 :                 scalar16 = shl( scalar16, s3 );
    1398       40384 :                 scalar16 = s_max( scalar16, MSALPHACORMAX );
    1399             : 
    1400       40384 :                 hFdCngCom->msAlphaCor[cnt] = Madd_32_16( L_mult( scalar16, msAlphaCorAlpha2 ), hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha );
    1401       40384 :                 move32();
    1402             :             }
    1403             : 
    1404             :             /* Compute SNR */
    1405             : 
    1406             :             /* msPeriodogSum[cnt] with format 16Q15 */
    1407             :             Word16 msNoiseFloor16tmp[NPART_SHAPING];
    1408       40384 :             IF( enc_dec == ENC )
    1409             :             {
    1410           0 :                 Copy_Scale_sig32_16( msNoiseFloor, msNoiseFloor16tmp, NPART, 0 );
    1411             :             }
    1412             :             ELSE
    1413             :             {
    1414       40384 :                 Copy_Scale_sig32_16( msNoiseFloor, msNoiseFloor16tmp, NPART_SHAPING, 0 );
    1415             :             }
    1416       40384 :             snr = dotp_s_fx( &msNoiseFloor16tmp[start], psize + start, current_len, CNG_HS );
    1417             : 
    1418       40384 :             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       40384 :                 msAlphaHatMin2 = MSALPHAHATMIN;
    1429       40384 :                 move32();
    1430             :             }
    1431       40384 :             scalar = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], MSALPHAMAX );
    1432             : 
    1433     2521709 :             FOR( j = start; j < stop; j++ )
    1434             :             {
    1435             :                 /* Compute optimal smoothing parameter for PSD estimation */
    1436     2481325 :                 test();
    1437     2481325 :                 IF( ( scalar == 0 ) || ( msNoiseFloor[j] == 0 ) )
    1438             :                 {
    1439          81 :                     msAlpha[j] = msAlphaHatMin2;
    1440          81 :                     move32();
    1441             :                 }
    1442             :                 ELSE
    1443             :                 {
    1444             :                     /* calculate scalar2 with normalized msNoiseFloor[j], exponent -2*s1 */
    1445     2481244 :                     s1 = WORD16_BITS - 1;
    1446     2481244 :                     move16();
    1447     2481244 :                     if ( msNoiseFloor16tmp[j] != 0 )
    1448             :                     {
    1449     2481244 :                         s1 = norm_s( msNoiseFloor16tmp[j] );
    1450             :                     }
    1451     2481244 :                     msNoiseFloor16 = shl( msNoiseFloor16tmp[j], s1 );
    1452     2481244 :                     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     2481244 :                     scalar316 = abs_s( sub( msPsd[j], msNoiseFloor16tmp[j] ) );
    1457             : 
    1458     2481244 :                     s2 = WORD16_BITS - 1;
    1459     2481244 :                     move16();
    1460     2481244 :                     if ( scalar316 != 0 )
    1461             :                     {
    1462             :                         /* use absolute value to avoid -1.0 x -1.0 multiplications */
    1463     2036607 :                         s2 = norm_s( scalar316 );
    1464             :                     }
    1465     2481244 :                     scalar316 = shl( scalar316, s2 );
    1466     2481244 :                     scalar3 = L_mult( scalar316, scalar316 );
    1467             : 
    1468             :                     /* find common exponent */
    1469     2481244 :                     tmp16_1 = sub( s1, s2 );
    1470     2481244 :                     tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
    1471     2481244 :                     if ( tmp16_1 < 0 )
    1472             :                     {
    1473     2176242 :                         scalar3 = L_shr( scalar3, tmp16 );
    1474             :                     }
    1475     2481244 :                     if ( tmp16_1 > 0 )
    1476             :                     {
    1477      184976 :                         scalar2 = L_shr( scalar2, tmp16 );
    1478             :                     }
    1479             : 
    1480             :                     /* add scalar2 and scalar3, avoid overflows */
    1481     2481244 :                     scalar2 = L_shr( scalar2, 1 );
    1482     2481244 :                     scalar3 = L_shr( scalar3, 1 );
    1483     2481244 :                     scalar3 = L_add( scalar2, scalar3 );
    1484             : 
    1485             :                     /* calculate division */
    1486     2481244 :                     tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar2, scalar3, &s3 );
    1487     2481244 :                     scalar2 = Mpy_32_16_1( scalar, tmp16 );
    1488     2481244 :                     s3 = s_max( s3, -( WORD32_BITS - 1 ) );
    1489     2481244 :                     scalar2 = L_shl( scalar2, s3 );
    1490     2481244 :                     msAlpha[j] = L_max( scalar2, msAlphaHatMin2 );
    1491     2481244 :                     move32();
    1492             :                 }
    1493             : 
    1494             :                 /* Compute the PSD (smoothed periodogram) in each band */
    1495     2481325 :                 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     2481325 :                 move16();
    1497             :             }
    1498       40384 :             msPsdSum[cnt] = dotp_s_fx( msPsd + start, psize + start, current_len, CNG_HS );
    1499       40384 :             move32();
    1500             : 
    1501       40384 :             QeqInvAv = 0l /*0.0 Q31*/;
    1502       40384 :             move32();
    1503             : 
    1504             :             /* scalar: 7Q24 format */
    1505       40384 :             tmp = 1191182336l /*(float)(MSNUMSUBFR*MSSUBFRLEN)-1.0 Q24*/;
    1506       40384 :             move32();
    1507       40384 :             scalar = L_sub( tmp, L_mult( round_fx( tmp ), msM_win ) );
    1508             : 
    1509             :             /* scalar2: 4Q27 format */
    1510       40384 :             tmp = 1476395008l /*(float)MSSUBFRLEN-1.0 Q27*/;
    1511       40384 :             move32();
    1512       40384 :             scalar2 = L_sub( tmp, L_mult( round_fx( tmp ), msM_subwin ) );
    1513             : 
    1514     2521709 :             FOR( j = start; j < stop; j++ )
    1515             :             {
    1516             :                 /* Compute variance of PSD */
    1517     2481325 :                 tmp = L_min( msAlpha[j], MSBETAMAX_SQRT );
    1518             : 
    1519     2481325 :                 s1 = WORD32_BITS - 1;
    1520     2481325 :                 move16();
    1521     2481325 :                 if ( tmp != 0 )
    1522             :                 {
    1523     2481325 :                     s1 = norm_l( tmp );
    1524             :                 }
    1525     2481325 :                 s2 = shl( s1, 1 );
    1526             : 
    1527     2481325 :                 s2 = s_min( s2, WORD32_BITS - 1 );
    1528             : 
    1529             :                 /* beta: scaled by s2 */
    1530             : #ifdef ISSUE_1836_replace_overflow_libcom
    1531     2481325 :                 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     2481325 :                 beta = mult_r( tmp16, tmp16 );
    1536             : 
    1537             :                 /* scalar3: scaled by s3 */
    1538     2481325 :                 scalar3 = L_sub( L_deposit_l( msPsd[j] ), L_deposit_l( msPsdFirstMoment[j] ) );
    1539     2481325 :                 s3 = norm_l( scalar3 );
    1540     2481325 :                 scalar3 = L_shl( scalar3, s3 );
    1541             : 
    1542             :                 /* msPsdFirstMoment: 6Q9   */
    1543     2481325 :                 tmp = L_msu( L_mult( beta, msPsdFirstMoment[j] ), beta, msPsd[j] );
    1544     2481325 :                 msPsdFirstMoment[j] = add( round_fx( L_shr( tmp, s2 ) ), msPsd[j] );
    1545     2481325 :                 move16();
    1546             : 
    1547             :                 /* msPsdSecondMoment: 12Q19   */
    1548     2481325 :                 tmp0 = L_shr( Mpy_32_16_r( msPsdSecondMoment[j], beta ), s2 );
    1549     2481325 :                 tmp1 = Mpy_32_32( scalar3, scalar3 );
    1550     2481325 :                 tmp1 = L_shr( L_sub( tmp1, L_shr( Mpy_32_16_r( tmp1, beta ), s2 ) ), sub( shl( s3, 1 ), 32 ) );
    1551     2481325 :                 msPsdSecondMoment[j] = L_add( tmp0, tmp1 );
    1552     2481325 :                 move32();
    1553             : 
    1554             :                 /* Compute inverse of amount of degrees of freedom */
    1555     2481325 :                 QeqInv = MSQEQINVMAX;
    1556     2481325 :                 move16();
    1557             : 
    1558     2481325 :                 IF( msNoiseFloor[j] != 0 /*0.0 Q15*/ )
    1559             :                 {
    1560     2481244 :                     tmp = Mpy_32_32( msNoiseFloor[j], msNoiseFloor[j] );
    1561     2481244 :                     tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( msPsdSecondMoment[j], tmp, &s );
    1562             :                     /* consider factor of 2 */
    1563     2481244 :                     s = s_min( s_max( sub( s, 1 ), -( WORD16_BITS - 1 ) ), ( WORD16_BITS - 1 ) );
    1564     2481244 :                     if ( s < 0 )
    1565             :                     {
    1566     2301446 :                         QeqInv = shl( tmp16, s );
    1567             :                     }
    1568     2481244 :                     QeqInv = s_min( QeqInv, MSQEQINVMAX );
    1569             :                 }
    1570     2481325 :                 QeqInvAv = L_add( QeqInvAv, L_mult( QeqInv, psize[j] ) );
    1571             : 
    1572             :                 /* Compute bias correction Bmin */
    1573     2481325 :                 tmp0 = Mpy_32_16_1( scalar, QeqInv );
    1574     2481325 :                 tmp1 = L_msu( 1073741824l /*0.5 Q31*/, msM_win, QeqInv );
    1575     2481325 :                 tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
    1576     2481325 :                 msBminWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), add( s, 7 - 4 ) ) );
    1577     2481325 :                 move32();
    1578             : 
    1579     2481325 :                 tmp0 = Mpy_32_16_1( scalar2, QeqInv );
    1580     2481325 :                 tmp1 = L_msu( 1073741824l /*0.5 Q31*/, msM_subwin, QeqInv );
    1581     2481325 :                 tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
    1582     2481325 :                 msBminSubWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), s ) );
    1583     2481325 :                 move32();
    1584             :             }
    1585             : 
    1586       40384 :             inv_totsize = BASOP_Util_Divide3232_uu_1616_Scale( 1, totsize, &s );
    1587       40384 :             QeqInvAv = Mpy_32_16_1( QeqInvAv, inv_totsize );
    1588       40384 :             QeqInvAv = L_shl( QeqInvAv, s );
    1589       40384 :             hFdCngCom->msQeqInvAv[cnt] = QeqInvAv;
    1590       40384 :             move32();
    1591             : 
    1592             :             /* New minimum? */
    1593             : 
    1594             :             /* exponent QeqInvAv: CNG_S, exponent MSAV: (4>>1) */
    1595       40384 :             s = CNG_S + 2 * MSAV_EXP;
    1596       40384 :             move16();
    1597       40384 :             BminCorr = Mpy_32_16_1( Sqrt32( QeqInvAv, &s ), MSAV );
    1598       40384 :             BminCorr = L_shl( BminCorr, sub( s, 1 ) );
    1599             : 
    1600             :             /* exponent BminCorr: 1 */
    1601       40384 :             BminCorr = L_add( BminCorr, 1073741824l /*0.5 Q31*/ );
    1602             : 
    1603     2521709 :             FOR( j = start; j < stop; j++ )
    1604             :             {
    1605             :                 /* exponent scalar: CNG_S+1 */
    1606     2481325 :                 scalar = Mpy_32_16_1( BminCorr, msPsd[j] );
    1607             : 
    1608             :                 /* exponent scalar2: CNG_S+1+4 */
    1609     2481325 :                 scalar2 = Mpy_32_32( scalar, msBminWin[j] );
    1610             : 
    1611     2481325 :                 msNewMinFlag[j] = 0;
    1612     2481325 :                 move16();
    1613     2481325 :                 IF( LT_32( scalar2, msCurrentMin[j] ) /*0.0 Q31*/ )
    1614             :                 {
    1615      873470 :                     msNewMinFlag[j] = 1;
    1616      873470 :                     move16();
    1617             :                     /* exponent msCurrentMin[j]: CNG_S+1+4 */
    1618      873470 :                     msCurrentMin[j] = scalar2;
    1619      873470 :                     move32();
    1620             :                     /* exponent msCurrentMinSubWindow[j]: CNG_S */
    1621             :                     BASOP_SATURATE_WARNING_OFF_EVS;
    1622             : #ifdef ISSUE_1836_replace_overflow_libcom
    1623      873470 :                     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      873470 :                     move32();
    1628             :                     BASOP_SATURATE_WARNING_ON_EVS;
    1629             :                 }
    1630             :             }
    1631             : 
    1632             :             /* This is used later to identify local minima */
    1633       40384 :             IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1634             :             {
    1635        9691 :                 FOR( i = 0; i < 3; i++ )
    1636             :                 {
    1637        8325 :                     IF( LT_32( hFdCngCom->msQeqInvAv[cnt], L_shr( L_deposit_h( msQeqInvAv_thresh[i] ), CNG_S ) ) /*0.0 Q31*/ )
    1638             :                     {
    1639        2360 :                         BREAK;
    1640             :                     }
    1641             :                 }
    1642             :                 /* format 1Q30 */
    1643        3726 :                 hFdCngCom->msSlope[cnt] = msNoiseSlopeMax[i];
    1644        3726 :                 move32();
    1645             :             }
    1646             : 
    1647             :             /* Consider the FFT and CLDFB bands separately */
    1648       40384 :             start = stop;
    1649       40384 :             move16();
    1650       40384 :             stop = len;
    1651       40384 :             move16();
    1652       40384 :             totsize = sub( hFdCngCom->stopBand, hFdCngCom->stopFFTbin );
    1653       40384 :             cnt = add( cnt, 1 );
    1654             :         } /*while (stop > start)*/
    1655             : 
    1656             :         /* Update minimum between sub windows */
    1657       40384 :         test();
    1658       40384 :         IF( GT_16( hFdCngCom->msFrCnt, 1 ) && LT_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1659             :         {
    1660     2061564 :             FOR( j = 0; j < len; j++ )
    1661             :             {
    1662     2028549 :                 if ( msNewMinFlag[j] > 0 )
    1663             :                 {
    1664      576430 :                     msLocalMinFlag[j] = 1;
    1665      576430 :                     move16();
    1666             :                 }
    1667     2028549 :                 if ( LT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ )
    1668             :                 {
    1669             :                     /* msCurrentMinOut[j] scaled with CNG_S */
    1670      185799 :                     msCurrentMinOut[j] = msCurrentMinSubWindow[j];
    1671      185799 :                     move32();
    1672             :                 }
    1673             :             }
    1674             :             /* Get the current noise floor */
    1675       33015 :             Copy32( msCurrentMinOut, msNoiseFloor, len );
    1676             :         }
    1677             :         ELSE /* sub window complete */
    1678             :         {
    1679        7369 :             IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1680             :             {
    1681             :                 /* Collect buffers */
    1682        3726 :                 Copy32( msCurrentMinSubWindow, msMinBuf + len * hFdCngCom->msMinBufferPtr, len );
    1683             : 
    1684             :                 /* Compute minimum among all buffers */
    1685        3726 :                 Copy32( msMinBuf, msCurrentMinOut, len );
    1686        3726 :                 ptr = msMinBuf + len;
    1687       22356 :                 FOR( i = 1; i < MSNUMSUBFR; i++ )
    1688             :                 {
    1689     1163280 :                     FOR( j = 0; j < len; j++ )
    1690             :                     {
    1691     1144650 :                         if ( LT_32( *ptr, msCurrentMinOut[j] ) /*0.0 Q31*/ )
    1692             :                         {
    1693      220175 :                             msCurrentMinOut[j] = *ptr;
    1694      220175 :                             move32();
    1695             :                         }
    1696     1144650 :                         ptr++;
    1697             :                     }
    1698             :                 }
    1699             : 
    1700             :                 /* Take over local minima */
    1701        3726 :                 slope = hFdCngCom->msSlope[0];
    1702        3726 :                 move16();
    1703      232656 :                 FOR( j = 0; j < len; j++ )
    1704             :                 {
    1705      228930 :                     if ( EQ_16( j, lenFFT ) )
    1706             :                     {
    1707           0 :                         slope = hFdCngCom->msSlope[1];
    1708           0 :                         move16();
    1709             :                     }
    1710      228930 :                     test();
    1711      228930 :                     test();
    1712      228930 :                     test();
    1713      228930 :                     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       27545 :                         msCurrentMinOut[j] = msCurrentMinSubWindow[j];
    1716       27545 :                         move32();
    1717       27545 :                         i = j;
    1718       27545 :                         move16();
    1719      192815 :                         FOR( k = 0; k < MSNUMSUBFR; k++ )
    1720             :                         {
    1721      165270 :                             msMinBuf[i] = msCurrentMinOut[j];
    1722      165270 :                             move32();
    1723      165270 :                             i = add( i, len );
    1724             :                         }
    1725             :                     }
    1726             :                 }
    1727             : 
    1728             :                 /* Reset */
    1729        3726 :                 set16_fx( msLocalMinFlag, 0, len );
    1730        3726 :                 set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );
    1731             : 
    1732             :                 /* Get the current noise floor */
    1733        3726 :                 Copy32( msCurrentMinOut, msNoiseFloor, len );
    1734             :             }
    1735             :         }
    1736             : 
    1737             : 
    1738             :         /* Detect sudden offsets based on the FFT bins (core bandwidth) */
    1739       40384 :         IF( GT_32( Mpy_32_16_1( msPsdSum[0], 655 /*0.02 Q15*/ ), msPeriodogSum[0] ) /*0.0 Q31*/ )
    1740             :         {
    1741         131 :             IF( hFdCngCom->offsetflag > 0 )
    1742             :             {
    1743          59 :                 Copy( msPeriodog, msPsd, len );
    1744        3676 :                 FOR( j = 0; j < len; j++ )
    1745             :                 {
    1746        3617 :                     msCurrentMinOut[j] = L_deposit_h( msPeriodog[j] );
    1747        3617 :                     move32();
    1748             :                 }
    1749          59 :                 set32_fx( hFdCngCom->msAlphaCor, 2147483647l /*1.0 Q31*/, cnt );
    1750          59 :                 set32_fx( msAlpha, 0l /*0.0 Q31*/, len );
    1751          59 :                 Copy( msPeriodog, msPsdFirstMoment, len );
    1752          59 :                 set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
    1753             : 
    1754          59 :                 msPsdSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
    1755          59 :                 move32();
    1756          59 :                 IF( LT_16( lenFFT, len ) )
    1757             :                 {
    1758           0 :                     msPsdSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
    1759           0 :                     move32();
    1760             :                 }
    1761             :             }
    1762         131 :             hFdCngCom->offsetflag = 1;
    1763         131 :             move16();
    1764             :         }
    1765             :         ELSE
    1766             :         {
    1767       40253 :             hFdCngCom->offsetflag = 0;
    1768       40253 :             move16();
    1769             :         }
    1770             : 
    1771             : 
    1772             :         /* Increment frame counter */
    1773       40384 :         IF( EQ_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
    1774             :         {
    1775        3726 :             hFdCngCom->msFrCnt = 1;
    1776        3726 :             move16();
    1777        3726 :             hFdCngCom->msMinBufferPtr = add( hFdCngCom->msMinBufferPtr, 1 );
    1778        3726 :             move16();
    1779        3726 :             if ( EQ_16( hFdCngCom->msMinBufferPtr, MSNUMSUBFR ) )
    1780             :             {
    1781         419 :                 hFdCngCom->msMinBufferPtr = 0;
    1782         419 :                 move16();
    1783             :             }
    1784             :         }
    1785             :         ELSE
    1786             :         {
    1787       36658 :             hFdCngCom->msFrCnt = add( hFdCngCom->msFrCnt, 1 );
    1788       36658 :             move16();
    1789             :         }
    1790             :         Word64 tmp64;
    1791             :         /* Smooth noise estimate during CNG phases */
    1792     2521709 :         FOR( j = 0; j < len; j++ )
    1793             :         {
    1794     2481325 :             tmp64 = W_add( W_mult_32_16( msNoiseEst[j], 31130 /*0.95 Q15*/ ), W_mult_32_16( msNoiseFloor[j], 1638 /*0.05 Q15*/ ) );
    1795     2481325 :             msNoiseEst[j] = W_extract_h( W_shl( tmp64, 16 ) ); // Q25
    1796     2481325 :             move32();
    1797             :         }
    1798             :     }
    1799       44303 :     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       44303 :     Copy( msPeriodog, msPeriodogBuf + len * ( *msPeriodogBufPtr ), len );
    1806             : 
    1807       44303 :     *msPeriodogBufPtr = add( *msPeriodogBufPtr, 1 );
    1808       44303 :     move16();
    1809       44303 :     if ( EQ_16( *msPeriodogBufPtr, MSBUFLEN ) )
    1810             :     {
    1811        8487 :         ( *msPeriodogBufPtr ) = 0;
    1812        8487 :         move16();
    1813             :     }
    1814             : 
    1815             :     /* Upper limit the noise floors with the averaged input energy */
    1816     2766071 :     FOR( j = 0; j < len; j++ )
    1817             :     {
    1818     2721768 :         scalar = L_mult( msPeriodogBuf[j], 6554 /*1.0/MSBUFLEN Q15*/ );
    1819             : 
    1820    13608840 :         FOR( i = j + len; i < MSBUFLEN * len; i += len )
    1821             :         {
    1822    10887072 :             scalar = L_mac( scalar, msPeriodogBuf[i], 6554 /*1.0/MSBUFLEN Q15*/ );
    1823             :         }
    1824     2721768 :         if ( GT_32( msNoiseEst[j], scalar ) /*0.0 Q15*/ )
    1825             :         {
    1826      706186 :             msNoiseEst[j] = scalar;
    1827      706186 :             move32();
    1828             :         }
    1829             : 
    1830     2721768 :         assert( msNoiseEst[j] >= 0 /*0.0 Q15*/ );
    1831             :     }
    1832       44303 : }
    1833             : /*-------------------------------------------------------------------
    1834             :  * apply_scale()
    1835             :  *
    1836             :  * Apply bitrate-dependent scale
    1837             :  *-------------------------------------------------------------------*/
    1838           0 : 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           0 :     FOR( i = 0; i < scaleTableSize; i++ )
    1849             :     {
    1850           0 :         cast16();
    1851           0 :         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           0 :             BREAK;
    1856             :         }
    1857             :     }
    1858             : 
    1859             :     {
    1860           0 :         *scale = L_add( *scale, L_deposit_h( scaleTable[i].scale ) );
    1861           0 :         move32();
    1862             :     }
    1863           0 : }
    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      169445 : 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     1789847 :     FOR( i = 0; i < scaleTableSize; i++ )
    1910             :     {
    1911     1789847 :         cast16();
    1912     1789847 :         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      169445 :             BREAK;
    1917             :         }
    1918             :     }
    1919      169445 :     assert( i < scaleTableSize );
    1920             : 
    1921      169445 :     *scale = L_add( *scale, L_deposit_h( scaleTable[i].scale ) );
    1922      169445 :     move32();
    1923      169445 :     *index = i;
    1924      169445 :     move16();
    1925      169445 : }
    1926             : /*-------------------------------------------------------------------
    1927             :  * bandcombinepow()
    1928             :  *
    1929             :  * Compute the power for each partition
    1930             :  *-------------------------------------------------------------------*/
    1931       53576 : 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       53576 :     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       53576 :         prev_part = -1;
    1958       53576 :         move16();
    1959     3189996 :         FOR( p = 0; p < npart; p++ )
    1960             :         {
    1961     3136420 :             len = sub( part[p], prev_part );
    1962     3136420 :             facTabExp[p] = getScaleFactor32( &bandpow[prev_part + 1], len );
    1963     3136420 :             move16();
    1964     3136420 :             prev_part = part[p];
    1965     3136420 :             move16();
    1966             :         }
    1967             : 
    1968       53576 :         smin = WORD32_BITS - 1;
    1969       53576 :         move16();
    1970     3189996 :         FOR( p = 0; p < npart; p++ )
    1971             :         {
    1972     3136420 :             smin = s_min( smin, facTabExp[p] );
    1973             :         }
    1974             : 
    1975       53576 :         i = 0;
    1976       53576 :         move16();
    1977     3189996 :         FOR( p = 0; p < npart; p++ )
    1978             :         {
    1979             :             /* Arithmetic averaging of power for all bins in partition */
    1980     3136420 :             temp = 0;
    1981     3136420 :             move32();
    1982    18653844 :             FOR( ; i <= part[p]; i++ )
    1983             :             {
    1984    15517424 :                 temp = L_add( temp, Mpy_32_16_1( L_shl( bandpow[i], facTabExp[p] ), psize_inv[p] ) );
    1985             :             }
    1986     3136420 :             partpow[p] = L_shr( temp, sub( facTabExp[p], smin ) );
    1987     3136420 :             move32();
    1988             :         }
    1989             :     }
    1990             : 
    1991       53576 :     *exp_partpow = sub( exp_bandpow, smin );
    1992       53576 :     move16();
    1993       53576 : }
    1994             : 
    1995             : /*-------------------------------------------------------------------
    1996             :  * scalebands()
    1997             :  *
    1998             :  * Scale partitions (with smoothing)
    1999             :  *-------------------------------------------------------------------*/
    2000        3082 : 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        3082 :     j = 0;
    2016        3082 :     move16();
    2017        3082 :     delta = 0;
    2018        3082 :     move16();
    2019        3082 :     partpowLD64M1 = 0L; /* to avoid compilation warnings */
    2020        3082 :     move32();
    2021             : 
    2022             :     /* Interpolate the bin/band-wise levels from the partition levels */
    2023        3082 :     IF( EQ_16( nband, npart ) )
    2024             :     {
    2025           0 :         Copy32( partpow, bandpow, npart );
    2026             :     }
    2027             :     ELSE
    2028             :     {
    2029        3082 :         startBand = 0;
    2030        3082 :         move16();
    2031        3082 :         startPart = 0;
    2032        3082 :         move16();
    2033        3082 :         stopPart = nFFTpart;
    2034        3082 :         move16();
    2035             : 
    2036        8624 :         WHILE( startBand < nband )
    2037             :         {
    2038        5542 :             stopPartM1 = sub( stopPart, 1 );
    2039        5542 :             test();
    2040        5542 :             IF( ( flag_fft_en != 0 ) || ( GE_16( startPart, nFFTpart ) ) )
    2041             :             {
    2042             :                 /* first half partition */
    2043        5542 :                 j = startPart;
    2044        5542 :                 move16();
    2045             : 
    2046       21063 :                 FOR( i = startBand; i <= midband[j]; i++ )
    2047             :                 {
    2048       15521 :                     bandpow[i] = partpow[j];
    2049       15521 :                     move32();
    2050             :                 }
    2051        5542 :                 j = add( j, 1 );
    2052             : 
    2053             :                 /* inner partitions */
    2054        5542 :                 IF( LT_16( j, stopPart ) )
    2055             :                 {
    2056        5394 :                     partpowLD64M1 = BASOP_Util_Log2( partpow[j - 1] );
    2057             :                 }
    2058             : 
    2059             :                 /* Debug values to check this variable is set. */
    2060        5542 :                 delta = 0x4000; // 1.Q14
    2061        5542 :                 move16();
    2062        5542 :                 delta_cmp = 0x4000; // 1.Q14
    2063        5542 :                 move16();
    2064        5542 :                 s1 = 1;
    2065        5542 :                 move16();
    2066        5542 :                 s = 1;
    2067        5542 :                 move16();
    2068             : 
    2069       72263 :                 FOR( ; j < stopPart; j++ )
    2070             :                 {
    2071       66721 :                     nint = sub( midband[j], midband[j - 1] );
    2072             : 
    2073             :                     /* log-linear interpolation */
    2074       66721 :                     partpowLD64 = BASOP_Util_Log2( partpow[j] );
    2075       66721 :                     tmp = L_sub( partpowLD64, partpowLD64M1 );
    2076       66721 :                     tmp = Mpy_32_16_1( tmp, getNormReciprocalWord16( nint ) );
    2077             : 
    2078             :                     /* scale logarithmic value */
    2079       66721 :                     tmp = L_sub( tmp, DELTA_SHIFT_LD64 );
    2080       66721 :                     delta_s = DELTA_SHIFT;
    2081       66721 :                     move16();
    2082             : 
    2083       66748 :                     WHILE( tmp > 0 )
    2084             :                     {
    2085          27 :                         tmp = L_sub( tmp, 33554432l /*0.015625 Q31*/ ); // Q31
    2086          27 :                         delta_s = add( delta_s, 1 );
    2087             :                     }
    2088       66721 :                     delta_cmp = shl( 1, s_max( -15, sub( WORD16_BITS - 1, delta_s ) ) );
    2089             : 
    2090       66721 :                     tmp = BASOP_Util_InvLog2( tmp );
    2091       66721 :                     s = norm_l( tmp );
    2092       66721 :                     s1 = sub( delta_s, s );
    2093             : 
    2094       66721 :                     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       66721 :                     delta_s = sub( s_min( norm_l( partpow[j - 1] ), norm_l( partpow[j] ) ), 1 );
    2097       66721 :                     val = L_shl( partpow[j - 1], delta_s );
    2098      845595 :                     FOR( ; i < midband[j]; i++ )
    2099             :                     {
    2100      778874 :                         val = L_shl( Mpy_32_16_1( val, delta ), s1 );
    2101      778874 :                         bandpow[i] = L_shr( val, delta_s );
    2102      778874 :                         move32();
    2103             :                     }
    2104       66721 :                     bandpow[i++] = partpow[j];
    2105       66721 :                     move32();
    2106       66721 :                     partpowLD64M1 = partpowLD64;
    2107       66721 :                     move32();
    2108             :                 }
    2109             : 
    2110        5542 :                 IF( GT_16( shr( delta, s ), delta_cmp ) )
    2111             :                 {
    2112        1385 :                     delta = 0x4000; // 1.Q14
    2113        1385 :                     move16();
    2114        1385 :                     s1 = 1;
    2115        1385 :                     move16();
    2116             :                 }
    2117             : 
    2118             :                 /* last half partition */
    2119        5542 :                 val = partpow[stopPartM1]; // Qx
    2120        5542 :                 move32();
    2121      101031 :                 FOR( ; i <= part[stopPartM1]; i++ )
    2122             :                 {
    2123       95489 :                     val = L_shl( Mpy_32_16_1( val, delta ), s1 );
    2124       95489 :                     bandpow[i] = val; // Qx
    2125       95489 :                     move32();
    2126             :                 }
    2127             :             }
    2128        5542 :             startBand = add( part[stopPartM1], 1 );
    2129        5542 :             startPart = stopPart;
    2130        5542 :             move16();
    2131        5542 :             stopPart = npart;
    2132        5542 :             move16();
    2133             :         }
    2134             :     }
    2135        3082 : }
    2136             : 
    2137       98774 : 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       98774 :     j = 0;
    2153       98774 :     move16();
    2154       98774 :     delta = 0;
    2155       98774 :     move16();
    2156       98774 :     partpowLD64M1 = 0L; /* to avoid compilation warnings */
    2157       98774 :     move32();
    2158             : 
    2159             :     /* Interpolate the bin/band-wise levels from the partition levels */
    2160       98774 :     IF( EQ_16( nband, npart ) )
    2161             :     {
    2162           0 :         Copy32( partpow, bandpow, npart );
    2163             :     }
    2164             :     ELSE
    2165             :     {
    2166       98774 :         startBand = 0;
    2167       98774 :         move16();
    2168       98774 :         startPart = 0;
    2169       98774 :         move16();
    2170       98774 :         stopPart = nFFTpart;
    2171       98774 :         move16();
    2172             : 
    2173      199565 :         WHILE( LT_16( startBand, nband ) )
    2174             :         {
    2175      100791 :             stopPartM1 = sub( stopPart, 1 );
    2176      100791 :             test();
    2177      100791 :             IF( ( flag_fft_en != 0 ) || ( GE_16( startPart, nFFTpart ) ) )
    2178             :             {
    2179             :                 /* first half partition */
    2180       98796 :                 j = startPart;
    2181       98796 :                 move16();
    2182             : 
    2183      200838 :                 FOR( i = startBand; i <= midband[j]; i++ )
    2184             :                 {
    2185      102042 :                     bandpow[i] = partpow[j]; // Qx
    2186      102042 :                     move32();
    2187             :                 }
    2188       98796 :                 j = add( j, 1 );
    2189             : 
    2190             :                 /* inner partitions */
    2191       98796 :                 IF( j < stopPart )
    2192             :                 {
    2193       98571 :                     partpowLD64M1 = BASOP_Util_Log2( L_add( partpow[j - 1], DELTA_FX ) );
    2194             :                 }
    2195             : 
    2196             :                 /* Debug values to check this variable is set. */
    2197       98796 :                 delta = 0x4000; // 1.Q14
    2198       98796 :                 move16();
    2199       98796 :                 delta_cmp = 0x4000; // 1.Q14
    2200       98796 :                 move16();
    2201       98796 :                 s1 = 1;
    2202       98796 :                 move16();
    2203       98796 :                 s = 1;
    2204       98796 :                 move16();
    2205             : 
    2206     5951032 :                 FOR( ; j < stopPart; j++ )
    2207             :                 {
    2208     5852236 :                     nint = sub( midband[j], midband[j - 1] );
    2209             : 
    2210             :                     /* log-linear interpolation */
    2211     5852236 :                     IF( NE_32( partpow[j], MAX_32 ) )
    2212             :                     {
    2213     5852236 :                         partpowLD64 = BASOP_Util_Log2( L_add( partpow[j], DELTA_FX ) );
    2214             :                     }
    2215             :                     ELSE
    2216             :                     {
    2217           0 :                         partpowLD64 = BASOP_Util_Log2( partpow[j] );
    2218             :                     }
    2219     5852236 :                     tmp = L_sub( partpowLD64, partpowLD64M1 );
    2220     5852236 :                     tmp = Mpy_32_16_1( tmp, getNormReciprocalWord16( nint ) );
    2221             : 
    2222             :                     /* scale logarithmic value */
    2223     5852236 :                     tmp = L_sub( tmp, DELTA_SHIFT_LD64 );
    2224     5852236 :                     delta_s = DELTA_SHIFT;
    2225     5852236 :                     move16();
    2226             : 
    2227     6013731 :                     WHILE( tmp > 0 )
    2228             :                     {
    2229      161495 :                         tmp = L_sub( tmp, 33554432l /*0.015625 Q31*/ ); // Q31
    2230      161495 :                         delta_s = add( delta_s, 1 );
    2231             :                     }
    2232     5852236 :                     delta_cmp = shl( 1, s_max( -15, sub( WORD16_BITS - 1, delta_s ) ) );
    2233             : 
    2234     5852236 :                     tmp = BASOP_Util_InvLog2( tmp );
    2235     5852236 :                     s = norm_l( tmp );
    2236     5852236 :                     s1 = sub( delta_s, s );
    2237             : 
    2238     5852236 :                     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     5852236 :                     delta_s = sub( s_min( norm_l( partpow[j - 1] ), norm_l( partpow[j] ) ), 1 );
    2241     5852236 :                     val = L_shl( partpow[j - 1], delta_s );
    2242    27176469 :                     FOR( ; i < midband[j]; i++ )
    2243             :                     {
    2244    21324233 :                         val = L_shl( Mpy_32_16_1( val, delta ), s1 );
    2245    21324233 :                         bandpow[i] = L_shr( val, delta_s );
    2246    21324233 :                         move32();
    2247             :                     }
    2248     5852236 :                     bandpow[i++] = partpow[j]; // Qx
    2249     5852236 :                     move32();
    2250     5852236 :                     partpowLD64M1 = partpowLD64;
    2251     5852236 :                     move32();
    2252             :                 }
    2253             : 
    2254       98796 :                 IF( GT_16( shr( delta, s ), delta_cmp ) )
    2255             :                 {
    2256       11512 :                     delta = 0x4000; // 1.Q14
    2257       11512 :                     move16();
    2258       11512 :                     s1 = 1;
    2259       11512 :                     move16();
    2260             :                 }
    2261             : 
    2262             :                 /* last half partition */
    2263       98796 :                 val = partpow[stopPartM1]; // Qx
    2264       98796 :                 move32();
    2265      851852 :                 FOR( ; i <= part[stopPartM1]; i++ )
    2266             :                 {
    2267      753056 :                     test();
    2268      753056 :                     IF( val != 0 && delta != 0 )
    2269             :                     {
    2270      528422 :                         val = L_shl( Mpy_32_16_1( val, delta ), s1 );
    2271      528422 :                         IF( val == 0 )
    2272             :                         {
    2273        2941 :                             val = 1;
    2274        2941 :                             move32();
    2275             :                         }
    2276             :                     }
    2277             :                     ELSE
    2278             :                     {
    2279      224634 :                         val = 0;
    2280      224634 :                         move32();
    2281             :                     }
    2282      753056 :                     bandpow[i] = val; // Qx
    2283      753056 :                     move32();
    2284             :                 }
    2285             :             }
    2286      100791 :             startBand = add( part[stopPartM1], 1 );
    2287      100791 :             startPart = stopPart;
    2288      100791 :             move16();
    2289      100791 :             stopPart = npart;
    2290      100791 :             move16();
    2291             :         }
    2292             :     }
    2293       98774 : }
    2294             : 
    2295             : /*-------------------------------------------------------------------
    2296             :  * getmidbands()
    2297             :  *
    2298             :  * Get central band for each partition
    2299             :  *-------------------------------------------------------------------*/
    2300     1125334 : 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     1125334 :     max_psize = psize[0];
    2320     1125334 :     move16();
    2321     1125334 :     /* first half partition */ move16();
    2322     1125334 :     midband[0] = part[0];
    2323     1125334 :     move16();
    2324     1125334 :     psize[0] = add( part[0], 1 );
    2325     1125334 :     move16();
    2326     1125334 :     psize_inv[0] = getNormReciprocalWord16( psize[0] );
    2327     1125334 :     move16();
    2328             :     /* inner partitions */
    2329    47823420 :     FOR( j = 1; j < npart; j++ )
    2330             :     {
    2331    46698086 :         midband[j] = shr( add( add( part[j - 1], 1 ), part[j] ), 1 );
    2332    46698086 :         move16();
    2333    46698086 :         psize[j] = sub( part[j], part[j - 1] );
    2334    46698086 :         move16();
    2335    46698086 :         psize_inv[j] = getNormReciprocalWord16( psize[j] );
    2336    46698086 :         move16();
    2337    46698086 :         if ( GT_16( psize[j], max_psize ) )
    2338             :         {
    2339    14062356 :             max_psize = psize[j];
    2340    14062356 :             move16();
    2341             :         }
    2342             :     }
    2343             : 
    2344     1125334 :     shift = 9;
    2345     1125334 :     move16();
    2346     1125334 :     *psize_norm_exp = sub( 15, shift );
    2347     1125334 :     move16();
    2348    48948754 :     FOR( j = 0; j < npart; j++ )
    2349             :     {
    2350             : #ifdef ISSUE_1836_replace_overflow_libcom
    2351    47823420 :         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    47823420 :         move16();
    2356             :     }
    2357             :     /* minimum_statistics needs fixed exponent of 6 */
    2358     1125334 :     assert( norm_s( -max_psize ) >= 9 );
    2359     1125334 : }
    2360             : 
    2361             : /*-------------------------------------------------------------------
    2362             :  * AnalysisSTFT()
    2363             :  *
    2364             :  * STFT analysis filterbank
    2365             :  *-------------------------------------------------------------------*/
    2366             : 
    2367          15 : 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          15 :     assert( ( hFdCngCom->fftlen >> 1 ) == hFdCngCom->frameSize );
    2382             : 
    2383             :     /* pointer inititialization */
    2384          15 :     assert( hFdCngCom->olapBufferAna != NULL );
    2385          15 :     olapBuffer = hFdCngCom->olapBufferAna;
    2386          15 :     olapWin = hFdCngCom->olapWinAna;
    2387             : 
    2388             :     /* olapWin factor is scaled with one bit */
    2389          15 :     *fftBuffer_exp = 1;
    2390          15 :     move16();
    2391          15 :     len = sub( hFdCngCom->fftlen, hFdCngCom->frameSize );
    2392          15 :     assert( len <= 320 ); /* see size of olapBuffer */
    2393             : 
    2394             :     /* Window the signal */
    2395          15 :     len2 = shr( len, 1 );
    2396        2191 :     FOR( i = 0; i < len2; i++ )
    2397             :     {
    2398        2176 :         move32();
    2399        2176 :         move32();
    2400        2176 :         fftBuffer[i] = L_mult( olapBuffer[i], mult_r( olapWin[i].v.im, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
    2401        2176 :         fftBuffer[i + len2] = L_mult( olapBuffer[i + len2], mult_r( olapWin[len2 - 1 - i].v.re, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
    2402             :     }
    2403          15 :     len2 = shr( hFdCngCom->frameSize, 1 );
    2404        2191 :     FOR( i = 0; i < len2; i++ )
    2405             :     {
    2406        2176 :         move32();
    2407        2176 :         move32();
    2408        2176 :         fftBuffer[i + len] = L_mult( shr_sat( timeDomainInput[i], Q ), mult_r( olapWin[i].v.re, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
    2409        2176 :         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          15 :     BASOP_rfft( fftBuffer, hFdCngCom->fftlen, fftBuffer_exp, -1 );
    2414             : 
    2415        4367 :     FOR( i = 0; i < len; i++ )
    2416             :     {
    2417        4352 :         olapBuffer[i] = shr_sat( timeDomainInput[sub( hFdCngCom->frameSize, len ) + i], Q );
    2418        4352 :         move16();
    2419             :     }
    2420          15 : }
    2421             : 
    2422             : /*-------------------------------------------------------------------
    2423             :  * AnalysisSTFT_fx()
    2424             :  *
    2425             :  * STFT analysis filterbank
    2426             :  *-------------------------------------------------------------------*/
    2427       90653 : 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       90653 :     assert( ( hFdCngCom->fftlen >> 1 ) == hFdCngCom->frameSize );
    2440             : 
    2441             :     /* pointer inititialization */
    2442       90653 :     assert( hFdCngCom->olapBufferAna != NULL );
    2443       90653 :     olapBuffer = hFdCngCom->olapBufferAna_fx;
    2444       90653 :     olapWin = hFdCngCom->olapWinAna_fx;
    2445             : 
    2446             :     /* olapWin factor is scaled with one bit */
    2447       90653 :     *fftBuffer_exp = 1;
    2448       90653 :     move16();
    2449       90653 :     len = sub( hFdCngCom->fftlen, hFdCngCom->frameSize );
    2450       90653 :     assert( len <= 320 ); /* see size of olapBuffer */
    2451             : 
    2452             :     /* Window the signal */
    2453       90653 :     Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, len );
    2454             : 
    2455    26324445 :     FOR( i = 0; i < hFdCngCom->frameSize; i++ )
    2456             :     {
    2457    26233792 :         olapBuffer[i + len] = shr_sat( timeDomainInput[i], Q ); // Values above MAX_16 seen with 10dB tests in float code
    2458    26233792 :         move16();
    2459             :     }
    2460             : 
    2461             :     /* Window the signal */
    2462       90653 :     v_L_mult_3216( olapWin, olapBuffer, fftBuffer, hFdCngCom->fftlen );
    2463             : 
    2464    52558237 :     FOR( i = 0; i < hFdCngCom->fftlen; i++ )
    2465             :     {
    2466    52467584 :         fftBuffer[i] = L_shr( fftBuffer[i], 11 );
    2467    52467584 :         move32();
    2468             :     }
    2469       90653 :     *fftBuffer_exp = WORD16_BITS + 11;
    2470       90653 :     move16();
    2471             : 
    2472             :     /* Perform FFT */
    2473       90653 :     RFFTN_fx( fftBuffer, hFdCngCom->fftSineTab_fx, hFdCngCom->fftlen, -1 );
    2474             : 
    2475             : 
    2476       90653 :     return;
    2477             : }
    2478             : 
    2479             : /*-------------------------------------------------------------------
    2480             :  * SynthesisSTFT_enc_ivas_fx()
    2481             :  *
    2482             :  * STFT synthesis filterbank
    2483             :  *-------------------------------------------------------------------*/
    2484             : 
    2485           0 : 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           0 :     scale = 0;
    2506           0 :     move16();
    2507           0 :     BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
    2508           0 :     fftBufferExp = add( fftBufferExp, scale );
    2509           0 :     hFdCngCom->fftBuffer_exp = fftBufferExp;
    2510           0 :     move16();
    2511             : 
    2512           0 :     fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
    2513             : 
    2514             :     /* Perform overlap-add */
    2515             :     /* Handle overlap in P/S domain for stereo */
    2516           0 :     test();
    2517           0 :     test();
    2518           0 :     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           0 :         Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
    2526           0 :         set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
    2527             :     }
    2528           0 :     len2 = shr( hFdCngCom->fftlen, 2 );
    2529           0 :     len4 = shr( hFdCngCom->fftlen, 3 );
    2530           0 :     len3 = add( len2, len4 );
    2531           0 :     len = add( hFdCngCom->frameSize, len4 );
    2532           0 :     IF( tcx_transition )
    2533             :     {
    2534           0 :         FOR( i = 0; i < len; i++ )
    2535             :         {
    2536           0 :             olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], sub( fftBufferExp, 15 ) ) ); // Q(15 - fftBufferExp)
    2537           0 :             move16();
    2538             :         }
    2539             :     }
    2540             :     ELSE
    2541             :     {
    2542           0 :         FOR( i = 0; i < len4; i++ )
    2543             :         {
    2544           0 :             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           0 :             move16();
    2546           0 :             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           0 :             move16();
    2548             :         }
    2549           0 :         FOR( i = len3; i < len; i++ )
    2550             :         {
    2551           0 :             olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], sub( fftBufferExp, 15 ) ) ); // Q(15 - fftBufferExp)
    2552           0 :             move16();
    2553             :         }
    2554             :     }
    2555             : 
    2556           0 :     FOR( i = 0; i < len4; i++ )
    2557             :     {
    2558           0 :         olapBuffer[i + 5 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 5 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[i].v.re );
    2559           0 :         move16();
    2560           0 :         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           0 :         move16();
    2562             :     }
    2563             : 
    2564           0 :     len = add( len, len2 );
    2565           0 :     FOR( i = len; i < hFdCngCom->fftlen; i++ )
    2566             :     {
    2567           0 :         olapBuffer[i] = 0;
    2568           0 :         move16();
    2569             :     }
    2570             : 
    2571             :     /* Get time-domain signal */
    2572           0 :     FOR( i = 0; i < hFdCngCom->frameSize; i++ )
    2573             :     {
    2574           0 :         timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
    2575           0 :         move16();
    2576             :     }
    2577             :     /* Generate excitation */
    2578           0 :     test();
    2579           0 :     test();
    2580           0 :     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           0 :         FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
    2597             :         {
    2598           0 :             buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
    2599           0 :             move16();
    2600             :         }
    2601           0 :         tmp = buf[0];
    2602           0 :         move16();
    2603             :     }
    2604           0 :     IF( EQ_16( gen_exc, 1 ) )
    2605             :     {
    2606             : 
    2607           0 :         E_UTIL_f_preemph2( sub( *Q_new, 1 ), buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp );
    2608           0 :         Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
    2609             :     }
    2610           0 :     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           0 : }
    2617             : 
    2618             : /*-------------------------------------------------------------------
    2619             :  * SynthesisSTFT()
    2620             :  *
    2621             :  * STFT synthesis filterbank
    2622             :  *-------------------------------------------------------------------*/
    2623             : 
    2624        1021 : 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        1021 :     scale = 0;
    2645        1021 :     move16();
    2646        1021 :     BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
    2647        1021 :     fftBufferExp = add( fftBufferExp, scale );
    2648        1021 :     hFdCngCom->fftBuffer_exp = fftBufferExp;
    2649        1021 :     move16();
    2650             : 
    2651        1021 :     fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
    2652             : 
    2653             :     /* Perform overlap-add */
    2654             :     /* Handle overlap in P/S domain for stereo */
    2655        1021 :     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        1021 :         Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
    2663        1021 :         set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
    2664             :     }
    2665        1021 :     len2 = shr( hFdCngCom->fftlen, 2 );
    2666        1021 :     len4 = shr( hFdCngCom->fftlen, 3 );
    2667        1021 :     len3 = add( len2, len4 );
    2668        1021 :     len = add( hFdCngCom->frameSize, len4 );
    2669        1021 :     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       66365 :         FOR( i = 0; i < len4; i++ )
    2680             :         {
    2681       65344 :             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       65344 :             move16();
    2683       65344 :             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       65344 :             move16();
    2685             :         }
    2686      131709 :         FOR( i = len3; i < len; i++ )
    2687             :         {
    2688      130688 :             olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], fftBufferExp - 15 ) );
    2689             :         }
    2690             :     }
    2691             : 
    2692       66365 :     FOR( i = 0; i < len4; i++ )
    2693             :     {
    2694       65344 :         olapBuffer[i + 5 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 5 * len4], fftBufferExp - 15 ) ), olapWin[i].v.re );
    2695       65344 :         move16();
    2696       65344 :         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       65344 :         move16();
    2698             :     }
    2699             : 
    2700        1021 :     len = add( len, len2 );
    2701       66365 :     FOR( i = len; i < hFdCngCom->fftlen; i++ )
    2702             :     {
    2703       65344 :         olapBuffer[i] = 0;
    2704       65344 :         move16();
    2705             :     }
    2706             : 
    2707             :     /* Get time-domain signal */
    2708      262397 :     FOR( i = 0; i < hFdCngCom->frameSize; i++ )
    2709             :     {
    2710      261376 :         timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
    2711      261376 :         move16();
    2712             :     }
    2713             :     /* Generate excitation */
    2714             :     {
    2715      279754 :         FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
    2716             :         {
    2717      278733 :             buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
    2718      278733 :             move16();
    2719             :         }
    2720        1021 :         tmp = buf[0];
    2721             :     }
    2722        1021 :     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        1021 :     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        1021 : }
    2734             : 
    2735       18381 : 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       18381 :     scale = 0;
    2757       18381 :     move16();
    2758       18381 :     BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
    2759       18381 :     fftBufferExp = add( fftBufferExp, scale );
    2760       18381 :     hFdCngCom->fftBuffer_exp = fftBufferExp;
    2761       18381 :     move16();
    2762             : 
    2763       18381 :     sft = getScaleFactor32( fftBuffer, hFdCngCom->fftlen );
    2764       18381 :     scale_sig32( fftBuffer, hFdCngCom->fftlen, sft );
    2765       18381 :     fftBufferExp = sub( fftBufferExp, sft );
    2766       18381 :     hFdCngCom->fftBuffer_exp = fftBufferExp;
    2767       18381 :     move16();
    2768             : 
    2769       18381 :     fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
    2770             : 
    2771             :     /* Perform overlap-add */
    2772             :     /* Handle overlap in P/S domain for stereo */
    2773       18381 :     test();
    2774       18381 :     test();
    2775       18381 :     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       18381 :         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       18381 :         set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
    2784             :     }
    2785       18381 :     len2 = shr( hFdCngCom->fftlen, 2 );
    2786       18381 :     len4 = shr( hFdCngCom->fftlen, 3 );
    2787       18381 :     len3 = add( len2, len4 );
    2788       18381 :     len = add( hFdCngCom->frameSize, len4 );
    2789       18381 :     tmp1 = sub( fftBufferExp, 15 );
    2790       18381 :     IF( tcx_transition )
    2791             :     {
    2792      607052 :         FOR( i = 0; i < len; i++ )
    2793             :         {
    2794      605280 :             L_olapBuffer[i] = L_shl_sat( fftBuffer[i], tmp1 ); /* Q(31 - (15 - fftlenShift) ) */
    2795      605280 :             move32();
    2796             :         }
    2797             :     }
    2798             :     ELSE
    2799             :     {
    2800     1256417 :         FOR( i = 0; i < len4; i++ )
    2801             :         {
    2802     1239808 :             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     1239808 :             move32();
    2804     1239808 :             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     1239808 :             move32();
    2806             :         }
    2807     2496225 :         FOR( i = len3; i < len; i++ )
    2808             :         {
    2809     2479616 :             L_olapBuffer[i] = L_shl_sat( fftBuffer[i], tmp1 ); /* Q(31 - (15 - fftlenShift) ) */
    2810     2479616 :             move32();
    2811             :         }
    2812             :     }
    2813             : 
    2814     1379245 :     FOR( i = 0; i < len4; i++ )
    2815             :     {
    2816     1360864 :         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     1360864 :         move32();
    2818     1360864 :         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     1360864 :         move32();
    2820             :     }
    2821             : 
    2822       18381 :     len = add( len, len2 );
    2823     1379245 :     FOR( i = len; i < hFdCngCom->fftlen; i++ )
    2824             :     {
    2825     1360864 :         L_olapBuffer[i] = 0;
    2826     1360864 :         move32();
    2827             :     }
    2828             : 
    2829       18381 :     sft = L_norm_arr( L_olapBuffer, hFdCngCom->fftlen );
    2830       18381 :     IF( NE_16( sft, 31 ) )
    2831             :     {
    2832       17096 :         Copy_Scale_sig32_16( L_olapBuffer, olapBuffer, hFdCngCom->fftlen, sft );
    2833       17096 :         hFdCngCom->olapBufferSynth_exp = sub( sub( 15, hFdCngCom->fftlenShift ), sft );
    2834       17096 :         move16();
    2835             :     }
    2836             : 
    2837             :     /* Get time-domain signal */
    2838     5461837 :     FOR( i = 0; i < hFdCngCom->frameSize; i++ )
    2839             :     {
    2840     5443456 :         timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
    2841     5443456 :         move16();
    2842             :     }
    2843             :     /* Generate excitation */
    2844             :     {
    2845     5774314 :         FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
    2846             :         {
    2847     5755933 :             buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
    2848     5755933 :             move16();
    2849             :         }
    2850       18381 :         exp = add( hFdCngCom->olapBufferSynth_exp, hFdCngCom->fftlenShift );
    2851       18381 :         tmp = buf[0];
    2852             :     }
    2853       18381 :     IF( EQ_16( gen_exc, 1 ) )
    2854             :     {
    2855       18381 :         E_UTIL_f_preemph2( 0, buf + 1, PREEMPH_FAC, add( M, hFdCngCom->frameSize ), &tmp );
    2856       18381 :         Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 0 );
    2857       18381 :         *Q_new = sub( 15, exp );
    2858       18381 :         move16();
    2859             :     }
    2860       18381 :     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       18381 : }
    2869             : 
    2870             : /**************************************************************************************
    2871             :  * Compute some values used in the bias correction of the minimum statistics algorithm *
    2872             :  **************************************************************************************/
    2873       14270 : void mhvals(
    2874             :     const Word16 d,
    2875             :     Word16 *m /*, Word16 * h*/
    2876             : )
    2877             : {
    2878             :     Word16 i, j;
    2879       14270 :     Word16 len = SIZE_SCALE_TABLE_CN;
    2880       14270 :     move16();
    2881             : 
    2882             : 
    2883       14270 :     assert( d == 72 || d == 12 ); /* function only tested for d==72 and d==12) */
    2884       14270 :     i = 0;
    2885       14270 :     move16();
    2886      121295 :     FOR( i = 0; i < len; i++ )
    2887             :     {
    2888      121295 :         IF( LE_16( d, d_array[i] ) )
    2889             :         {
    2890       14270 :             BREAK;
    2891             :         }
    2892             :     }
    2893       14270 :     IF( EQ_16( i, len ) )
    2894             :     {
    2895           0 :         i = sub( len, 1 );
    2896           0 :         j = i;
    2897           0 :         move16();
    2898             :     }
    2899             :     ELSE
    2900             :     {
    2901       14270 :         j = sub( i, 1 );
    2902             :     }
    2903       14270 :     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       14270 :         qj_e = 15;
    2916       14270 :         move16();
    2917       14270 :         qj_m = L_deposit_h( d_array[i - 1] );
    2918             : 
    2919       14270 :         qi_e = 15;
    2920       14270 :         move16();
    2921       14270 :         qi_m = L_deposit_h( d_array[i] );
    2922             : 
    2923       14270 :         q_e = 15;
    2924       14270 :         move16();
    2925       14270 :         q_m = L_deposit_h( d );
    2926             : 
    2927       14270 :         qj_m = Sqrt32( qj_m, &qj_e );
    2928       14270 :         qi_m = Sqrt32( qi_m, &qi_e );
    2929       14270 :         q_m = Sqrt32( q_m, &q_e );
    2930             : 
    2931       14270 :         tmp1_m = Mpy_32_32( qi_m, qj_m );
    2932       14270 :         tmp1_e = add( qi_e, qj_e );
    2933       14270 :         tmp1_m = L_deposit_h( BASOP_Util_Divide3232_Scale( tmp1_m, q_m, &shift ) );
    2934       14270 :         tmp1_e = sub( tmp1_e, q_e );
    2935       14270 :         tmp1_e = add( tmp1_e, shift );
    2936       14270 :         tmp1_m = BASOP_Util_Add_Mant32Exp( tmp1_m, tmp1_e, L_negate( qj_m ), qj_e, &tmp1_e );
    2937             : 
    2938       14270 :         tmp2_m = BASOP_Util_Add_Mant32Exp( qi_m, qi_e, L_negate( qj_m ), qj_e, &tmp2_e );
    2939       14270 :         tmp1_w16_m = round_fx( tmp2_m );
    2940       14270 :         tmp1_w16_e = tmp2_e;
    2941       14270 :         move16();
    2942       14270 :         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       14270 :         tmp2_m = Mpy_32_16_1( tmp1_m, tmp1_w16_m );
    2945       14270 :         tmp2_e = add( tmp1_e, tmp1_w16_e );
    2946             : 
    2947       14270 :         tmp2_m = BASOP_Util_Add_Mant32Exp( tmp2_m, tmp2_e, L_deposit_h( m_array[i] ), 0, &tmp2_e );
    2948       14270 :         assert( tmp2_e == 0 );
    2949       14270 :         *m = extract_h( tmp2_m );
    2950       14270 :         move32();
    2951             :     }
    2952       14270 : }
    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    40372388 : 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    40372388 :     loc_seed = extract_l( L_mac0( 13849, *seed, 31821 ) );
    2968    40372388 :     temp = L_deposit_l( loc_seed );
    2969             : 
    2970    40372388 :     loc_seed = extract_l( L_mac0( 13849, loc_seed, 31821 ) );
    2971    40372388 :     temp = L_msu0( temp, loc_seed, -1 );
    2972             : 
    2973    40372388 :     loc_seed = extract_l( L_mac0( 13849, loc_seed, 31821 ) );
    2974    40372388 :     temp = L_msu0( temp, loc_seed, -1 );
    2975             : 
    2976    40372388 :     *seed = loc_seed;
    2977    40372388 :     move16();
    2978    40372388 :     return L_shl( temp, WORD16_BITS - CNG_RAND_GAUSS_SHIFT );
    2979             : }
    2980             : 
    2981             : /*-------------------------------------------------------------------
    2982             :  * lpc_from_spectrum()
    2983             :  *
    2984             :  *
    2985             :  *-------------------------------------------------------------------*/
    2986             : 
    2987        3802 : 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        3802 :     Word32 *powspec = hFdCngCom->cngNoiseLevel; /*i  : pointer to noise levels format Q5.27*/
    3000        3802 :     Word16 powspec_exp = hFdCngCom->cngNoiseLevelExp;
    3001        3802 :     move16();
    3002        3802 :     Word16 fftlen = hFdCngCom->fftlen; /*i  : size of fft*/
    3003        3802 :     Word16 *A = hFdCngCom->A_cng;      /*o  : lpc coefficients format Q3.12*/
    3004        3802 :     move16();
    3005        3802 :     Word16 lpcorder = M;
    3006        3802 :     move16();
    3007             : 
    3008        3802 :     scale = 0;
    3009        3802 :     move16();
    3010        3802 :     fftlen2 = shr( fftlen, 1 );
    3011        3802 :     fftlen4 = shr( fftlen, 2 );
    3012        3802 :     fftlen8 = shr( fftlen, 3 );
    3013             : 
    3014             :     /* Power Spectrum */
    3015        3802 :     maxVal = 0;
    3016        3802 :     move32();
    3017        3802 :     len = sub( stop, start );
    3018     1121574 :     FOR( i = 0; i < len; i++ )
    3019             :     {
    3020     1117772 :         maxVal = L_max( maxVal, L_abs( powspec[i] ) );
    3021             :     }
    3022        3802 :     s1 = norm_l( maxVal );
    3023        3802 :     nf = L_shr_r_sat( 1099511680l /*1e-3f Q40*/, add( sub( powspec_exp, s1 ), 9 ) );
    3024        3802 :     ptr = fftBuffer;
    3025        3802 :     pti = fftBuffer + 1;
    3026             : 
    3027       11406 :     FOR( i = 0; i < start; i++ )
    3028             :     {
    3029        7604 :         *ptr = nf;
    3030        7604 :         move32();
    3031        7604 :         *pti = L_deposit_l( 0 );
    3032        7604 :         move32();
    3033        7604 :         ptr += 2;
    3034        7604 :         pti += 2;
    3035             :     }
    3036             : 
    3037     1121574 :     FOR( ; i < stop; i++ )
    3038             :     {
    3039     1117772 :         *ptr = L_max( nf, L_shl( powspec[i - start], s1 ) );
    3040     1117772 :         move32();
    3041     1117772 :         *pti = L_deposit_l( 0 );
    3042     1117772 :         move32();
    3043     1117772 :         ptr += 2;
    3044     1117772 :         pti += 2;
    3045             :     }
    3046             : 
    3047        3994 :     FOR( ; i < fftlen2; i++ )
    3048             :     {
    3049         192 :         *ptr = nf;
    3050         192 :         move32();
    3051         192 :         *pti = L_deposit_l( 0 );
    3052         192 :         move32();
    3053         192 :         ptr += 2;
    3054         192 :         pti += 2;
    3055             :     }
    3056             : 
    3057        3802 :     fftBuffer[1] = nf;
    3058        3802 :     move32();
    3059             : 
    3060             :     /* Pre-emphasis */
    3061             : 
    3062        3802 :     BASOP_getTables( &table, NULL, &step, fftlen4 );
    3063        3802 :     tmp = round_fx( L_shr( L_add( 0x40000000, L_mult0( preemph_fac, preemph_fac ) ), 1 ) );
    3064        3802 :     preemph_fac2 = shr( preemph_fac, 1 );
    3065        3802 :     ptr = fftBuffer;
    3066        3802 :     *ptr = Mpy_32_16_1( *ptr, sub( tmp, preemph_fac2 ) );
    3067        3802 :     move32();
    3068        3802 :     ptr += 2;
    3069      281392 :     FOR( i = 1; i < fftlen8; i++ )
    3070             :     {
    3071      277590 :         move32();
    3072      277590 :         *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      277590 :         ptr += 2;
    3074             :     }
    3075        3802 :     move32();
    3076        3802 :     *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        3802 :     ptr += 2;
    3078      281392 :     FOR( i = 1; i < fftlen8; i++ )
    3079             :     {
    3080      277590 :         move32();
    3081      277590 :         *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      277590 :         ptr += 2;
    3083             :     }
    3084        3802 :     move32();
    3085        3802 :     *ptr = Mpy_32_16_1( *ptr, tmp );
    3086        3802 :     ptr += 2;
    3087      281392 :     FOR( i = 1; i < fftlen8; i++ )
    3088             :     {
    3089      277590 :         move32();
    3090      277590 :         *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      277590 :         ptr += 2;
    3092             :     }
    3093        3802 :     move32();
    3094        3802 :     *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        3802 :     ptr += 2;
    3096      281392 :     FOR( i = 1; i < fftlen8; i++ )
    3097             :     {
    3098      277590 :         move32();
    3099      277590 :         *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      277590 :         ptr += 2;
    3101             :     }
    3102        3802 :     move32();
    3103        3802 :     fftBuffer[1] = Mpy_32_16_1( fftBuffer[1], add( tmp, preemph_fac2 ) );
    3104        3802 :     maxVal = 0;
    3105        3802 :     move32();
    3106     2254938 :     FOR( i = 0; i < fftlen; i++ )
    3107             :     {
    3108     2251136 :         maxVal = L_max( maxVal, L_abs( fftBuffer[i] ) );
    3109             :     }
    3110        3802 :     s2 = norm_l( maxVal );
    3111     2254938 :     FOR( i = 0; i < fftlen; i++ )
    3112             :     {
    3113     2251136 :         fftBuffer[i] = L_shl( fftBuffer[i], s2 );
    3114     2251136 :         move32();
    3115             :     }
    3116             : 
    3117             :     /* Autocorrelation */
    3118             : 
    3119        3802 :     BASOP_rfft( fftBuffer, fftlen, &scale, 1 );
    3120             : 
    3121        3802 :     s3 = getScaleFactor32( fftBuffer, add( lpcorder, 1 ) );
    3122             : 
    3123       68436 :     FOR( i = 0; i <= lpcorder; i++ )
    3124             :     {
    3125       64634 :         r[i] = L_shl( fftBuffer[i], s3 );
    3126       64634 :         move32();
    3127             :     }
    3128             : 
    3129        3802 :     r[0] = Mpy_32_32( r[0], 1074278656l /*1.0005f Q30*/ );
    3130        3802 :     move32();
    3131       64634 :     FOR( i = 1; i <= lpcorder; i++ )
    3132             :     {
    3133       60832 :         r[i] = Mpy_32_32( r[i], 1073741824l /*1.f Q30*/ );
    3134       60832 :         move32();
    3135             :     }
    3136        3802 :     s3 = getScaleFactor32( r, add( lpcorder, 1 ) );
    3137             : 
    3138       68436 :     FOR( i = 0; i <= lpcorder; i++ )
    3139             :     {
    3140       64634 :         r[i] = L_shl( r[i], s3 );
    3141       64634 :         move32();
    3142             :     }
    3143             : 
    3144       68436 :     FOR( i = 0; i <= lpcorder; i++ )
    3145             :     {
    3146       64634 :         L_Extract( r[i], &r_h[i], &r_l[i] );
    3147             :     }
    3148             : 
    3149             :     /* LPC */
    3150             : 
    3151        3802 :     E_LPC_lev_dur( r_h, r_l, A, NULL, lpcorder, NULL );
    3152        3802 : }
    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       18381 : 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       18381 :     *CNG_mode = -1;
    3228       18381 :     move16();
    3229             : 
    3230      103435 :     FOR( i = 0; i < L_frame / L_SUBFR; i++ )
    3231             :     {
    3232       85054 :         Copy( hFdCngCom->A_cng, Aq + i * ( M + 1 ), M + 1 );
    3233             :     }
    3234             : 
    3235       18381 :     E_LPC_a_lsp_conversion( Aq, lsp_new, lsp_old, M );
    3236             : 
    3237       18381 :     IF( first_CNG == 0 )
    3238             :     {
    3239        7447 :         Copy( lsp_old, lspCNG, M );
    3240             :     }
    3241      312477 :     FOR( i = 0; i < M; i++ )
    3242             :     {
    3243             :         /* AR low-pass filter  */
    3244      294096 :         lspCNG[i] = mac_r( L_mult( CNG_ISF_FACT_FX, lspCNG[i] ), 32768 - CNG_ISF_FACT_FX, lsp_new[i] );
    3245      294096 :         move16(); /* Q15 (15+15+1-16) */
    3246             :     }
    3247             : 
    3248       18381 :     IF( EQ_16( L_frame, L_FRAME16k ) )
    3249             :     {
    3250       11530 :         lsp2lsf_fx( lsp_new, lsf_new, M, INT_FS_16k_FX );
    3251             :     }
    3252             :     ELSE
    3253             :     {
    3254        6851 :         E_LPC_lsp_lsf_conversion( lsp_new, lsf_new, M );
    3255             :     }
    3256       18381 :     Copy( hFdCngCom->exc_cng, exc, L_frame );
    3257       18381 :     Copy( hFdCngCom->exc_cng, exc2, L_frame );
    3258       18381 :     IF( bwe_exc != NULL )
    3259             :     {
    3260       11158 :         IF( EQ_16( L_frame, L_FRAME ) )
    3261             :         {
    3262        6851 :             interp_code_5over2_fx( exc2, bwe_exc, L_frame );
    3263             :         }
    3264             :         ELSE
    3265             :         {
    3266        4307 :             interp_code_4over2_fx( exc2, bwe_exc, L_frame );
    3267             :         }
    3268             :     }
    3269       18381 : }
    3270             : 
    3271             : /*-------------------------------------------------------------------
    3272             :  * SynthesisSTFT_fx()
    3273             :  *
    3274             :  * STFT synthesis filterbank
    3275             :  *-------------------------------------------------------------------*/
    3276             : 
    3277       59265 : 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       59265 :     RFFTN_fx( fftBuffer, hFdCngCom->fftSineTab_fx, hFdCngCom->fftlen, 1 );
    3294             : 
    3295             :     /* Handle overlap in P/S domain for stereo */
    3296       59265 :     test();
    3297       59265 :     test();
    3298       59265 :     IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
    3299             :     {
    3300         890 :         Copy32( olapBuffer + sub( i_mult( 3, shr( hFdCngCom->frameSize, 2 ) ), ( M + 1 ) ), buf_fx, add( hFdCngCom->frameSize, M + 1 ) ); // Qin
    3301         890 :         set32_fx( olapBuffer, 0, hFdCngCom->fftlen );
    3302             :     }
    3303             :     ELSE
    3304             :     {
    3305       58375 :         Copy32( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
    3306       58375 :         set32_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize ); /*olapBuffer, fftBuffer, olapWin*/
    3307             :     }
    3308             : 
    3309       59265 :     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     8522689 :         FOR( i = hFdCngCom->frameSize / 4; i < ( 3 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3320             :         {
    3321     8463424 :             olapBuffer[i] = L_add( olapBuffer[i], Mpy_32_16_1( fftBuffer[i], olapWin[( i - ( hFdCngCom->frameSize >> 2 ) )] ) );
    3322     8463424 :             move32();
    3323             :         }
    3324     8522689 :         FOR( ; i < ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3325             :         {
    3326     8463424 :             olapBuffer[i] = fftBuffer[i];
    3327     8463424 :             move32();
    3328             :         }
    3329             :     }
    3330     8522689 :     FOR( ; i < ( 7 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
    3331             :     {
    3332     8463424 :         olapBuffer[i] = Mpy_32_16_1( fftBuffer[i], olapWin[( i - ( 3 * ( hFdCngCom->frameSize >> 2 ) ) )] );
    3333     8463424 :         move32();
    3334             :     }
    3335             : 
    3336     4290977 :     FOR( ; i < hFdCngCom->fftlen; i++ )
    3337             :     {
    3338     4231712 :         olapBuffer[i] = 0;
    3339     4231712 :         move32();
    3340             :     }
    3341             : 
    3342       59265 :     Word32 fftScale = 0;
    3343       59265 :     SWITCH( hFdCngCom->fftlen )
    3344             :     {
    3345       27422 :         case 640:
    3346       27422 :             fftScale = FFT_SCALING_640;
    3347       27422 :             move32();
    3348       27422 :             BREAK;
    3349       31843 :         case 512:
    3350       31843 :             fftScale = FFT_SCALING_512;
    3351       31843 :             move32();
    3352       31843 :             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       59265 :     v_multc_fixed( olapBuffer + hFdCngCom->frameSize / 4, fftScale, timeDomainOutput, hFdCngCom->frameSize ); // Q_in - 9
    3359             :                                                                                                               /* Get excitation */
    3360       59265 :     test();
    3361       59265 :     test();
    3362       59265 :     IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
    3363             :     {
    3364      114810 :         FOR( i = 0; i < hFdCngCom->frameSize / 2; i++ )
    3365             :         {
    3366      113920 :             buf_fx[i + ( M + 1 )] = L_add( buf_fx[i + ( M + 1 )], olapBuffer[( i + ( hFdCngCom->frameSize >> 2 ) )] );
    3367      113920 :             move32();
    3368             :         }
    3369             :         // v_multc(buf, (float)(hFdCngCom->fftlen / 2), buf, M + 1 + hFdCngCom->frameSize);
    3370         890 :         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       58375 :         v_multc_fixed( olapBuffer + sub( shr( hFdCngCom->frameSize, 2 ), ( M + 1 ) ), fftScale, buf_fx, add( M + 1, hFdCngCom->frameSize ) );
    3376             :     }
    3377             : 
    3378       59265 :     tmp_fx = buf_fx[0];
    3379       59265 :     move32();
    3380             :     // preemph(buf + 1, PREEMPH_FAC_FLT, M + hFdCngCom->frameSize, &tmp);
    3381       59265 :     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       59265 :     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       59265 :     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    46665862 : Word32 rand_gauss_fx(
    3475             :     Word32 *x,
    3476             :     Word16 *seed,
    3477             :     Word16 q )
    3478             : {
    3479             :     Word32 temp;
    3480             : 
    3481    46665862 :     temp = own_random( seed );
    3482    46665862 :     temp = L_add( temp, own_random( seed ) );
    3483    46665862 :     temp = L_add( temp, own_random( seed ) );
    3484    46665862 :     temp = L_shr( temp, sub( 15, q ) );
    3485             : 
    3486    46665862 :     *x = temp;
    3487    46665862 :     move32();
    3488             : 
    3489    46665862 :     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    50857104 : Word16 rand_gauss_fix(
    3499             :     Word16 *x,
    3500             :     Word16 *seed )
    3501             : {
    3502             :     Word32 temp;
    3503             : 
    3504    50857104 :     temp = shr( own_random( seed ), Q2 );
    3505    50857104 :     temp = L_add( temp, shr( own_random( seed ), Q2 ) );
    3506    50857104 :     temp = L_add( temp, shr( own_random( seed ), Q2 ) );
    3507             : 
    3508    50857104 :     *x = (Word16) temp;
    3509    50857104 :     move32();
    3510             : 
    3511    50857104 :     return (Word16) temp;
    3512             : }

Generated by: LCOV version 1.14