LCOV - code coverage report
Current view: top level - lib_com - fd_cng_com_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 1533 1654 92.7 %
Date: 2025-05-03 01:55:50 Functions: 28 31 90.3 %

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

Generated by: LCOV version 1.14