LCOV - code coverage report
Current view: top level - lib_dec - FEC_HQ_phase_ecu_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ da9cc8ead0679b4682d329fdff98cf1616159273 Lines: 1370 2578 53.1 %
Date: 2025-10-13 22:24:20 Functions: 22 36 61.1 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <stdint.h>
       6             : #include "options.h" /* Compilation switches                   */
       7             : #include "rom_dec.h" /* Static table prototypes                */
       8             : #include "rom_com.h" /* Static table prototypes                */
       9             : #include "prot_fx.h"
      10             : #include "basop_util.h"
      11             : #include "ivas_prot_fx.h"
      12             : 
      13             : /*---------------------------------------------------------------------*
      14             :  * Local constants
      15             :  *---------------------------------------------------------------------*/
      16             : 
      17             : #define FEC_MAX                512
      18             : #define FEC_NB_PULSE_MAX       20
      19             : #define FEC_FFT_MAX_SIZE       512
      20             : #define FEC_DCIM_FILT_SIZE_MAX 60
      21             : 
      22             : #define ENV_STAB_DEC_THR 16384 /* Q15 st->env_stab based threshold for hq-ecu technology decision */
      23             : 
      24             : #define PHASE_DITH_fx              25736 /* 2*pi in Q12 */
      25             : #define DELTA_CORR                 6     /* Tuning parameter - defining range for phase correction around peak */
      26             : #define THRESH_TR_DB_FX            10
      27             : #define THRESH_TR_LIN_BY2_FX       ( 10 / 2 ) /* 10.0^(THRESH_TR_DB_FX/10.0)/2. Divided by 2 to facilitate fixed-point implementation. */
      28             : #define MAX_INCREASE_GRPPOW_FX     0          /* max. amplification in case of transients (in dB scale) */
      29             : #define MAX_INCREASE_GRPPOW_LIN_FX 32767      /* in Q15-- 10.0^(MAX_INCREASE_GRPPOW_FX/10.0)  (in linear scale) */
      30             : 
      31             : #define PHASE_DITH_SCALE_SHIFT 16 /* The number of bit shift equivalent to multiply by PHASE_DITH_SCALE */
      32             : 
      33             : #define BURST_PHDITH_THRESH     ( 4 - 1 ) /* speech start phase dither with <burst_phdith_thresh> losses in a row */
      34             : #define BURST_PHDITH_RAMPUP_LEN 2         /* speech ramp up degree of phase dither over a length of <burst_phdith_rampup_len> frames */
      35             : #define BURST_ATT_THRESH        ( 3 - 1 ) /* speech start attenuate with <burst_att_thresh> losses in a row */
      36             : #define ATT_PER_FRAME           4         /* speech attenuation in dB */
      37             : #define BETA_MUTE_THR           10        /* time threshold to start beta-noise attenuation */
      38             : 
      39             : #define LGW32K 7
      40             : #define LGW16K 6
      41             : #define LGW48K LGW32K + 1 /* Use the same frequency groups as for SWB + 1 */
      42             : 
      43             : #define LTRANALOG32K          8
      44             : #define LTRANALOG16K          7
      45             : #define PFIND_SENS_FX         31785 /* 0.97 in Q15 */
      46             : #define CMPLMNT_PFIND_SENS_FX 983   /* (1.0 - pfind_sen) in Q15 */
      47             : 
      48             : #define DELTA_CORR_F0_INT        2         /* Constant controls the bin range where Jacobsen is used */
      49             : #define L_PROT_NS                32000000L /* Prototype frame length in nanoseconds (32 ms) */
      50             : #define PH_ECU_CORR_LIMIT_Q15    27853     /* 0.85 in Q15 */
      51             : #define PH_ECU_N_LIMIT           56        /* fec_alg analysis frame limit for IVAS Phase ECU activation */
      52             : #define CMPLMNT_ST_PFIND_SENS_FX 2293      /* (1.0 - st_pfind_sen) in Q15 */
      53             : 
      54             : #define FEC_HQ_ECU_POINT5 ( 0x4000 ) /* 0.5 in Q15. Prefix with FEC_HQ namespace to avoid naming conflict. */
      55             : #define FEC_HQ_ECU_ROOT2  ( 0x5a83 ) /* sqrt(2) in Q14 */
      56             : #define FEC_HQ_HAMM_A0    17695      /* 0.54 in Q15 */
      57             : #define FEC_HQ_HAMM_A1    15073      /* 0.46 in Q15 */
      58             : #define FEC_HQ_WIN_A0     FEC_HQ_HAMM_A0
      59             : #define FEC_HQ_WIN_A1     FEC_HQ_HAMM_A1
      60             : 
      61             : static Word16 sqrt2ndOrder( const Word16 );
      62             : 
      63             : static void windowing( const Word16 *, Word16 *, const Word16 *, const Word16, const Word16 );
      64             : static void windowing_ROM_optimized( const Word16 *, Word16 *, const Word16, const Word16, const Word16 );
      65             : static void fft_spec2_fx( const Word16[], Word32[], const Word16 );
      66             : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
      67             : static void trans_ana_fx( const Word16 *, Word16 *, Word16 *, Word16 *, const Word16, const Word16, const Word16, const Word16, const Word16, Word16 *, Word16 *, Word16 *, Word16 * );
      68             : #else
      69             : static void trans_ana_fx( const Word16 *, Word16 *, Word16 *, Word16 *, const Word16, const Word16, const Word16, const Word16, Word16 *, Word16 *, Word16 *, Word16 * );
      70             : #endif
      71             : static void peakfinder_fx( const Word16 *, const Word16, Word16 *, Word16 *, const Word16 );
      72             : static Word16 imax_fx( const Word16 *, const Word16 );
      73             : static void spec_ana_fx( const Word16 *prevsynth, Word16 *plocs, Word32 *plocsi, Word16 *num_plocs, Word16 *X_sav, const Word16 output_frame, const Word16 bwidth_fx, Word16 *Q );
      74             : static void subst_spec_fx( const Word16 *, const Word32 *, Word16 *, const Word16, Word16 *, const Word16 *, const Word16, const Word16 *, const Word16, Word16 *, const Word16 *, const Word16 *, Word16, const Word16 * );
      75             : static Word16 rand_phase_fx( const Word16 seed, Word16 *sin_F, Word16 *cos_F );
      76             : 
      77             : /*------------------------------------------------------------------*
      78             :  * rand_phase()
      79             :  *
      80             :  * randomized phase in form of sin and cos components
      81             :  *------------------------------------------------------------------*/
      82      115272 : static Word16 rand_phase_fx( const Word16 seed, Word16 *sin_F /*Q15*/, Word16 *cos_F /*Q15*/ )
      83             : {
      84      115272 :     const Word16 *sincos = sincos_t_ext_fx + 128; // Q15
      85      115272 :     Word16 seed2 = own_random2_fx( seed );
      86      115272 :     Word16 seed2_shift = shr( seed2, 8 );
      87             : 
      88      115272 :     *sin_F = negate( *( sincos + seed2_shift ) ); // Q15
      89      115272 :     move16();
      90      115272 :     if ( s_and( seed2, 0x40 ) != 0 )
      91             :     {
      92       57586 :         *sin_F = *( sincos + seed2_shift );
      93       57586 :         move16();
      94             :     }
      95             : 
      96      115272 :     *cos_F = negate( *( sincos - seed2_shift ) ); // Q15
      97      115272 :     move16();
      98      115272 :     if ( s_and( seed2, 0x80 ) != 0 )
      99             :     {
     100       57665 :         *cos_F = *( sincos - seed2_shift );
     101       57665 :         move16();
     102             :     }
     103             : 
     104      115272 :     return seed2;
     105             : }
     106             : 
     107             : /*! r: The location, relative to the middle of the 3 given data point, of the maximum. (Q15)*/
     108         886 : static Word16 ivas_imax2_jacobsen_mag_fx(
     109             :     const Word16 *y_re, /* i  : The 3 given data points. real part order -1 0 1 Qx                       */
     110             :     const Word16 *y_im  /* i  : The 3 given data points. imag part order  1 0 -1 (from FFT) Qx          */
     111             : )
     112             : {
     113             :     Word16 posi; // Q15
     114             :     const Word16 *pY;
     115             :     Word16 y_m1_re, y_0_re, y_p1_re;
     116             :     Word16 y_m1_im, y_0_im, y_p1_im;
     117             :     Word32 N_re, N_im;
     118             :     Word32 D_re, D_im;
     119             :     Word16 tmp, tmp_e;
     120             :     Word32 numer, denom;
     121             :     Word64 tmp_64_n, tmp_64_d;
     122             : 
     123             :     /* Jacobsen estimates peak offset relative y_0 using
     124             :      *                 X_m1 - X_p1
     125             :      *  d = REAL ( ------------------- ) * c_jacob
     126             :      *              2*X_0 - X_m1 -Xp1
     127             :      *
     128             :      *  Where c_jacob is a window  dependent constant
     129             :      */
     130             : #define C_JACOB_FX 18765 /*  % assume 0.1875 hammrect window 'symmetric' */ /*Q14*/
     131             : 
     132             :     /* Get the bin parameters into variables */
     133         886 :     pY = y_re;
     134         886 :     y_m1_re = *pY++;
     135         886 :     move16();
     136         886 :     y_0_re = *pY++;
     137         886 :     move16();
     138         886 :     y_p1_re = *pY++;
     139         886 :     move16();
     140             : 
     141             :     /* Same for imaginary parts - note reverse order from FFT */
     142         886 :     pY = y_im;
     143         886 :     y_p1_im = *pY++;
     144         886 :     move16();
     145         886 :     y_0_im = *pY++;
     146         886 :     move16();
     147         886 :     y_m1_im = *pY++;
     148         886 :     move16();
     149             : 
     150             :     /* prepare numerator real and imaginary parts*/
     151         886 :     N_re = L_sub( y_m1_re, y_p1_re );
     152         886 :     N_im = L_sub( y_m1_im, y_p1_im );
     153             : 
     154             :     /* prepare denominator real and imaginary parts */
     155             : 
     156         886 :     D_re = L_sub( L_sub( L_shl( y_0_re, 1 ), y_m1_re ), y_p1_re );
     157         886 :     D_im = L_sub( L_sub( L_shl( y_0_im, 1 ), y_m1_im ), y_p1_im );
     158             : 
     159             :     /* REAL part of complex division  */
     160         886 :     tmp_64_n = W_mac_32_32( W_mult_32_32( N_re, D_re ), N_im, D_im );
     161         886 :     tmp_64_d = W_mac_32_32( W_mult_32_32( D_re, D_re ), D_im, D_im );
     162         886 :     tmp_e = s_min( W_norm( tmp_64_n ), W_norm( tmp_64_d ) );
     163         886 :     numer = W_extract_h( W_shl( tmp_64_n, tmp_e ) );
     164         886 :     denom = W_extract_h( W_shl( tmp_64_d, tmp_e ) );
     165             : 
     166         886 :     test();
     167         886 :     IF( numer != 0 && denom != 0 )
     168             :     {
     169         886 :         tmp = BASOP_Util_Divide3232_Scale( numer, denom, &tmp_e );
     170         886 :         tmp = shl_sat( tmp, tmp_e );                     // Q15
     171         886 :         posi = shl_sat( mult_r( tmp, C_JACOB_FX ), Q1 ); // Q15
     172             :     }
     173             :     ELSE
     174             :     {
     175           0 :         posi = 0; /* flat top,  division is not possible choose center freq */
     176           0 :         move16();
     177             :     }
     178             : 
     179         886 :     return posi;
     180             : }
     181             : 
     182             : /*-----------------------------------------------------------------------------
     183             :  * fft_spec2_fx()
     184             :  *
     185             :  * Square magnitude of fft spectrum
     186             :  *----------------------------------------------------------------------------*/
     187         162 : static void fft_spec2_fx(
     188             :     const Word16 x[], /* i : Input vector: complex spectrum Q0*/
     189             :     Word32 xMagSq[],  /* o : Magnitude square spectrum Q0*/
     190             :     const Word16 N    /* i : Input vector length */
     191             : )
     192             : {
     193             :     Word16 i, l;
     194             :     const Word16 *pRe, *pIm;
     195             :     Word32 *pMagSq, acc;
     196             : 
     197             :     /* Magnitude at 0. */
     198         162 :     pMagSq = &xMagSq[0];
     199         162 :     pRe = &x[0];
     200         162 :     *pMagSq++ = L_mult0( *pRe, *pRe );
     201         162 :     move32();
     202         162 :     pRe++; /* Non-fractional multiply gives subsequent group power accumulation a bit headroom. */
     203             : 
     204             :     /* From 1 to (N/2 - 1). */
     205         162 :     l = sub( shr( N, 1 ), 1 ); /* N/2 - 1. */
     206         162 :     pIm = &x[N];
     207         162 :     pIm--;
     208       51072 :     FOR( i = 0; i < l; i++ )
     209             :     {
     210       50910 :         acc = L_mult0( *pRe, *pRe );
     211       50910 :         pRe++; /* Non-fractional mode multiply. */
     212       50910 :         *pMagSq++ = L_mac0( acc, *pIm, *pIm );
     213       50910 :         pIm--;
     214       50910 :         move32();
     215             :     }
     216             : 
     217             :     /* The magnitude square at N/2 */
     218         162 :     *pMagSq = L_mult0( *pRe, *pRe );
     219         162 :     move32();
     220         162 :     return;
     221             : }
     222             : 
     223             : /*-----------------------------------------------------------------------------
     224             :  * trans_ana_fx()
     225             :  *
     226             :  * Transient analysis
     227             :  *----------------------------------------------------------------------------*/
     228         132 : static void trans_ana_fx(
     229             :     const Word16 *xfp,            /* i  : Input signal                                       Q0  */
     230             :     Word16 *mag_chg,              /* o  : Magnitude modification                             Q15 */
     231             :     Word16 *ph_dith,              /* o  : Phase dither, 2*PI is not included (Q15, i.e., between 0.0 and 1.0) */
     232             :     Word16 *mag_chg_1st,          /* i/o: per band magnitude modifier for transients         Q15 */
     233             :     const Word16 output_frame,    /* i  : Frame length                                           */
     234             :     const Word16 time_offs,       /* i  : Time offset (integral multiple of output_frame)        */
     235             :     const Word16 est_mus_content, /* i  : 0.0=speech_like ... 1.0=Music    (==st->env_stab )     */
     236             :     const Word16 last_fec,        /* i  : signal that previous frame was concealed with fec_alg  */
     237             : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
     238             :     const Word16 element_mode, /* i :  element_mode req to handle EVS_MONO specific BE path  */
     239             : #endif
     240             :     Word16 *alpha,     /* o  : Magnitude modification factors for fade to average     */
     241             :     Word16 *beta,      /* o  : Magnitude modification factors for fade to average     */
     242             :     Word16 *beta_mute, /* o  : Factor for long-term mute Q15                              */
     243             :     Word16 *Xavg       /* o  : Frequency group average gain to fade to                */
     244             : )
     245             : {
     246             :     const Word16 *w_hamm, *pFftTbl;
     247             :     Word16 att_val, attDegreeFrames;
     248             :     Word16 xfp_left[L_TRANA48k], xfp_right[L_TRANA48k];
     249             :     Word32 magSqLeft[L_TRANA48k / 2 + 1], magSqRight[L_TRANA48k / 2 + 1];
     250             :     Word32 *pLeft, *pRight, *pGrPowLeft, *pGrPowRight;
     251             :     Word32 gr_pow_left[LGW_MAX], gr_pow_right[LGW_MAX];
     252             :     const Word16 *pXfp, *pGw;
     253             :     Word16 Ltrana, Ltrana_2, Lprot, three4thLength, LtranaLogMinus1, Lgw, i, k, l, burst_len;
     254             :     Word16 man, expo;
     255         132 :     Word16 att_always = 0; /* fixed attenuation per frequency group if set to  1 */
     256             :     Word16 oneOverFrame, roundEstMusContent, tmp16, headroom, lowerEdge;
     257         132 :     Word16 burst_phdith_thresh = BURST_PHDITH_THRESH; /*speech settings */
     258         132 :     Word16 burst_att_thresh = BURST_ATT_THRESH;
     259         132 :     Word16 att_per_frame = ATT_PER_FRAME;
     260         132 :     Word16 burst_phdith_rampup_len = BURST_PHDITH_RAMPUP_LEN;
     261             :     Word16 tr_dec[LGW_MAX];
     262             :     UWord16 lsb;
     263             :     Word32 acc;
     264             : 
     265         132 :     Lgw = 0;
     266         132 :     move16();
     267         132 :     LtranaLogMinus1 = 0;
     268         132 :     move16();
     269             : 
     270         132 :     move16(); // att_always
     271         132 :     move16(); // burst_phdith_thresh
     272         132 :     move16(); // burst_att_thresh
     273         132 :     move16(); // att_per_frame
     274         132 :     move16(); // burst_phdith_rampup_len
     275             : 
     276         132 :     pFftTbl = NULL;
     277             : 
     278             :     /* Initialisation to prevent warnings */
     279         132 :     oneOverFrame = 102; /* 1/320 in Q15 */
     280         132 :     move16();
     281         132 :     w_hamm = w_hamm16k_2_fx;
     282         132 :     move16();
     283         132 :     Lprot = 512;
     284         132 :     move16();
     285             : 
     286             :     /* check burst error */
     287         132 :     IF( EQ_16( output_frame, L_FRAME48k ) ) /* output_frame = (sampling frequency)/50 */
     288             :     {
     289         103 :         oneOverFrame = 34; /* 1/960 in Q15 */
     290         103 :         move16();
     291         103 :         w_hamm = w_hamm48k_2_fx;
     292         103 :         move16();
     293         103 :         Lgw = LGW48K;
     294         103 :         move16();
     295         103 :         Lprot = 1536; /* (2*output_frame)*1024/1280; */
     296         103 :         move16();
     297             :     }
     298          29 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
     299             :     {
     300          29 :         oneOverFrame = 51; /* 1/640 in Q15 */
     301          29 :         move16();
     302          29 :         w_hamm = w_hamm32k_2_fx;
     303          29 :         Lgw = LGW32K;
     304          29 :         move16();
     305          29 :         Lprot = 1024;
     306          29 :         move16();
     307          29 :         pFftTbl = FFT_W128; /* Table for 256 real input radix-2 FFT */
     308          29 :         LtranaLogMinus1 = LTRANALOG32K - 1;
     309          29 :         move16();
     310             :     }
     311             :     ELSE
     312             :     {
     313           0 :         oneOverFrame = 102; /* 1/320 in Q15 */
     314           0 :         move16();
     315           0 :         w_hamm = w_hamm16k_2_fx;
     316           0 :         Lgw = LGW16K;
     317           0 :         move16();
     318           0 :         Lprot = 512;
     319           0 :         move16();
     320           0 :         pFftTbl = FFT_W64; /* Table for 128 real input radix-2 FFT */
     321           0 :         LtranaLogMinus1 = LTRANALOG16K - 1;
     322           0 :         move16();
     323             :     }
     324         132 :     burst_len = add( mult_r( time_offs, oneOverFrame ), 1 );
     325             : 
     326         132 :     *ph_dith = 0;
     327         132 :     move16(); /*  typical pattern is 2*pi*[0  0 .25 .50 .75 1.0 1.0 1.0 ..] */
     328             : 
     329         132 :     IF( GE_16( output_frame, L_FRAME32k ) ) /*currently est_mus_content only calculated for SWB and FB */
     330             :     {
     331         132 :         roundEstMusContent = 0;
     332         132 :         move16();
     333         132 :         if ( GE_16( est_mus_content, FEC_HQ_ECU_POINT5 ) ) /* est_mus_content is in [0.0, 1.0]. */
     334             :         {
     335         131 :             roundEstMusContent = 1;
     336         131 :             move16();
     337             :         }
     338             : 
     339             :         /* softly shift attenuation just a bit later  for estimated "stable" music_content */
     340         132 :         burst_phdith_thresh = add( BURST_PHDITH_THRESH, roundEstMusContent );
     341         132 :         burst_att_thresh = add( BURST_ATT_THRESH, roundEstMusContent );
     342         132 :         att_per_frame = sub( ATT_PER_FRAME, roundEstMusContent ); /* only slighty less att for music */
     343             :     }
     344             :     ELSE
     345             :     {
     346             :         /* lock to music-like stable envelope  setting for now */
     347           0 :         burst_phdith_thresh = add( BURST_PHDITH_THRESH, 1 ); /* in Q0 */
     348           0 :         burst_att_thresh = add( BURST_ATT_THRESH, 1 );       /* in Q0 */
     349           0 :         att_per_frame = sub( ATT_PER_FRAME, 1 );             /* in Q0 */
     350             :     }
     351             : 
     352         132 :     IF( GT_16( burst_len, burst_phdith_thresh ) )
     353             :     {
     354             :         /* increase degree of dither */
     355             : #if BURST_PHDITH_RAMPUP_LEN != 2
     356             : #error The implementation of phase_dith=min(1.0, (burst_len - burst_phdith_thresh)/burst_phdith_rampup_len)) is incorrect
     357             : #endif
     358          72 :         *ph_dith = 32767; /* 1.0 in Q15. N.B. 2*PI is not included. */
     359          72 :         move16();
     360          72 :         tmp16 = sub( burst_len, burst_phdith_thresh );
     361          72 :         if ( LT_16( tmp16, burst_phdith_rampup_len ) )
     362             :         {
     363           2 :             *ph_dith = 16384; /* 0.5 in Q15. N.B. 2*PI is not included. */
     364           2 :             move16();
     365             :         }
     366             :     }
     367             : 
     368         132 :     attDegreeFrames = 0;
     369         132 :     move16();
     370         132 :     IF( GT_16( burst_len, burst_att_thresh ) )
     371             :     {
     372          74 :         att_always = 1;
     373          74 :         move16();
     374             :         /* increase degree of attenuation */
     375             : 
     376             :         /* N.B. To facilitate the subsequent 10^(-att_degree/20) implementation
     377             :          * so as to use direct table-lookup,
     378             :          * (burstLen - burst_att_thresh) is NOT multiplied by "att_per_frame". */
     379          74 :         attDegreeFrames = sub( burst_len, burst_att_thresh ); /* Not multiplied by att_per_frqme! */
     380             :         /* Furthermore, in order to minimize the size of the lookup-table required to
     381             :          * implement 10^(-att_degree/10), hard limit attDegreeFrames to (30% of 50)=15.
     382             :          * If attDegreeFrames is greater than 15, it means there are more than 15 successive
     383             :          * bad frames. In this case, no matter what to do, the sound quality will be bad.
     384             :          */
     385          74 :         if ( GT_16( attDegreeFrames, OFF_FRAMES_LIMIT ) )
     386             :         {
     387          14 :             attDegreeFrames = OFF_FRAMES_LIMIT; /* Hard limit the no. of frames */
     388          14 :             move16();
     389             :         }
     390             :     }
     391             : 
     392         132 :     Ltrana = shr( Lprot, 2 );
     393         132 :     Ltrana_2 = shr( Ltrana, 1 );
     394             : 
     395         132 :     test();
     396         132 :     test();
     397         132 :     IF( LE_16( burst_len, 1 ) || ( EQ_16( burst_len, 2 ) && last_fec != 0 ) )
     398             :     {
     399             : 
     400          54 :         set16_fx( alpha, 32767, LGW_MAX );
     401          54 :         set16_fx( beta, 0, LGW_MAX );
     402          54 :         *beta_mute = BETA_MUTE_FAC_INI;
     403          54 :         move16();
     404             : 
     405             :         /* Apply Hamming window */
     406          54 :         windowing( xfp, xfp_left, w_hamm, 0, Ltrana_2 ); /* 1st quarter */
     407          54 :         three4thLength = sub( Lprot, Ltrana );
     408          54 :         pXfp = xfp + three4thLength;
     409          54 :         windowing( pXfp, xfp_right, w_hamm, 0, Ltrana_2 ); /* 4th quarter */
     410             : 
     411             :         /* spectrum */
     412          54 :         IF( EQ_16( output_frame, L_FRAME48k ) )
     413             :         {
     414          25 :             fft3_fx( xfp_left, xfp_left, Ltrana );
     415          25 :             fft3_fx( xfp_right, xfp_right, Ltrana );
     416             :         }
     417             :         ELSE
     418             :         {
     419          29 :             r_fft_fx_lc( pFftTbl, Ltrana, Ltrana_2, LtranaLogMinus1, xfp_left, xfp_left, 1 );
     420          29 :             r_fft_fx_lc( pFftTbl, Ltrana, Ltrana_2, LtranaLogMinus1, xfp_right, xfp_right, 1 );
     421             :         }
     422             : 
     423             :         /* square representation */
     424          54 :         fft_spec2_fx( xfp_left, magSqLeft, Ltrana );
     425          54 :         fft_spec2_fx( xfp_right, magSqRight, Ltrana );
     426             : 
     427             :         /* band powers in frequency groups
     428             :          * exclude bin at PI from calculation */
     429          54 :         magSqLeft[Ltrana_2] = L_deposit_l( 0 );
     430          54 :         move32();
     431          54 :         magSqRight[Ltrana_2] = L_deposit_l( 0 );
     432          54 :         move32();
     433             :     }
     434             : 
     435         132 :     pGrPowLeft = &gr_pow_left[0];
     436         132 :     pGrPowRight = &gr_pow_right[0];
     437         132 :     pGw = gw;
     438        1159 :     FOR( k = 0; k < Lgw; k++ )
     439             :     {
     440        1027 :         test();
     441        1027 :         test();
     442        1027 :         IF( LE_16( burst_len, 1 ) || ( EQ_16( burst_len, 2 ) && last_fec != 0 ) )
     443             :         {
     444         403 :             lowerEdge = *pGw++;
     445         403 :             move16();
     446         403 :             l = sub( *pGw, lowerEdge );
     447         403 :             headroom = GR_POW_HEADROOM[k]; /* Number of bits to scale down preventing from saturation in accumulation.*/
     448         403 :             move16();
     449         403 :             pLeft = magSqLeft + lowerEdge;
     450         403 :             pRight = magSqRight + lowerEdge;
     451         403 :             *pGrPowLeft = L_deposit_l( 0 );
     452         403 :             move32();
     453         403 :             *pGrPowRight = L_deposit_l( 0 );
     454         403 :             move32();
     455        8861 :             FOR( i = 0; i < l; i++ )
     456             :             {
     457        8458 :                 acc = L_shr( *pLeft++, headroom ); /* Scale down to prevent from saturation. */
     458        8458 :                 *pGrPowLeft = L_add( *pGrPowLeft, acc );
     459        8458 :                 move32();
     460        8458 :                 acc = L_shr( *pRight++, headroom );
     461        8458 :                 *pGrPowRight = L_add( *pGrPowRight, acc );
     462        8458 :                 move32();
     463             :             }
     464             : 
     465             :             /*Xavg[k] = sqrt(0.5f*(gr_pow_left[k]+gr_pow_right[k])/(float)(gw[k+1]-gw[k]));*/
     466         403 :             acc = L_shr( L_add( *pGrPowLeft, *pGrPowRight ), 1 );
     467         403 :             acc = Mult_32_16( acc, gw_len_inv_fx[k] ); /* -headroom */
     468             : 
     469         403 :             acc = Sqrt_l( acc, &expo ); /* -headroom+31+expo */
     470             : 
     471         403 :             expo = sub( add( expo, 31 ), headroom );
     472         403 :             if ( EQ_16( s_and( expo, 1 ), 1 ) )
     473             :             {
     474         295 :                 acc = Mult_32_16( acc, 23170 ); /* 1/sqrt(2) in Q15 */
     475             :             }
     476         403 :             expo = shr( expo, 1 );
     477         403 :             Xavg[k] = round_fx( L_shl( acc, sub( sub( 16, expo ), 2 ) ) ); /* Q0, additional right shift by 2 to account for that Xavg is
     478             :                                                                               calculated using lenght N/4 fft but is applied on a fft of length N */
     479         403 :             move16();
     480             : 
     481             :             /*dither phase in case of transient */
     482             :             /* separate transition detection and application of forced burst dithering */
     483         403 :             tr_dec[k] = 0;
     484         403 :             move16();
     485         403 :             Mpy_32_16_ss( *pGrPowLeft, THRESH_TR_LIN_BY2_FX, &acc, &lsb ); /* To facilitate fixed-point implementation, divide threshold by 2. */
     486         403 :             acc = L_or( L_shl_sat( acc, 16 ), L_and( 0xffffL, lsb ) );     /* Equivalent to concatenate acc and lsb, and then down shift by 16 bits. */
     487         403 :             if ( GT_32( *pGrPowRight, acc ) )                              /* gr_pow_right > thres_tr_lin*gr_pow_left */
     488             :             {
     489          12 :                 tr_dec[k] = 1;
     490          12 :                 move16();
     491             :             }
     492         403 :             Mpy_32_16_ss( *pGrPowRight, THRESH_TR_LIN_BY2_FX, &acc, &lsb );
     493         403 :             acc = L_or( L_shl_sat( acc, 16 ), L_and( 0xffffL, lsb ) ); /* Equivalent to concatenate acc and lsb, and then down shift by 16 bits. */
     494         403 :             if ( GT_32( *pGrPowLeft, acc ) )                           /* gr_pow_left > thres_tr_lin*gr_pow_right */
     495             :             {
     496          10 :                 tr_dec[k] = 1;
     497          10 :                 move16();
     498             :             }
     499             : 
     500             :             /* magnitude modification */
     501         403 :             IF( add( tr_dec[k], att_always ) != 0 )
     502             :             {
     503             : 
     504             : #if MAX_INCREASE_GRPPOW_FX != 0
     505             : #error trans_ana_fx-- The following implementation is incorrect
     506             : #endif
     507          22 :                 att_val = 32767;
     508          22 :                 move16();
     509          22 :                 IF( *pGrPowRight > 0 )
     510             :                 {
     511          17 :                     IF( LT_32( *pGrPowRight, *pGrPowLeft ) ) /* i.e., (gr_pow_right/gr_pow_left) < 1.0 */
     512             :                     {
     513             :                         /* Compute sqrt(grp_pow_chg), where grp_pow_chg = gr_pow_right/gr_pow_left. */
     514           5 :                         tmp16 = ratio( *pGrPowRight, *pGrPowLeft, &expo ); /* tmp16 in Q14 */
     515           5 :                         expo = sub( expo, ( 15 - 14 ) );                   /* Now, tmp16 is considered in Q15 */
     516           5 :                         i = norm_s( tmp16 );
     517           5 :                         man = shl( tmp16, i ); /* Mandatory normalization before sqrtNthOrder(). */
     518           5 :                         expo = add( expo, i );
     519           5 :                         man = sqrt2ndOrder( man );
     520           5 :                         if ( s_and( expo, 1 ) != 0 ) /* Check even or odd. */
     521             :                         {
     522           4 :                             man = mult_r( man, FEC_HQ_ECU_ROOT2 );
     523             :                         }
     524           5 :                         expo = shr( expo, 1 );      /* Divided by 2-- square root operation. */
     525           5 :                         att_val = shr( man, expo ); /* Denormalize the mantissa back to Q15. */
     526             :                     }
     527             :                     /* ELSE do nothing because (gr_pow_right/gr_pow_left) >= 1.0 (i.e.,
     528             :                      * max_increase_grppow_lin) */
     529             :                 }
     530             : 
     531          22 :                 mag_chg_1st[k] = att_val;
     532          22 :                 move16();
     533          22 :                 mag_chg[k] = att_val;
     534          22 :                 move16();
     535             :             }
     536             :             ELSE
     537             :             {
     538         381 :                 mag_chg_1st[k] = 32767;
     539         381 :                 move16();
     540         381 :                 mag_chg[k] = 32767;
     541         381 :                 move16(); /* Set to 1.0 in Q15 */
     542             :             }
     543             :         }
     544             :         ELSE
     545             :         {
     546             :             /* Since attDegreeFrames is discrete (integer) and hard limited to OFF_FRAMES_LIMIT,
     547             :              * it is much easier to implement 10^(-att_degree/20.0) by a simply direct
     548             :              * table-lookup. Also, att_per_frame is discrete as well and can be
     549             :              * either ATT_PER_FRAME-1 or ATT_PER_FRAME and nothing else. This
     550             :              * means only 2 tables of size=(OFF_FRAMES_LIMIT+1) each are required.
     551             :              * To take square root into account, it is divided by 20 instead of 10. */
     552         624 :             IF( EQ_16( att_per_frame, ATT_PER_FRAME ) ) /* Select the corresponding lookup-table. */
     553             :             {
     554           0 :                 att_val = POW_ATT_TABLE0[attDegreeFrames]; /* 10^(-attDegreeFrames*(ATT_PER_FRAME)/20) */
     555           0 :                 move16();
     556             :             }
     557             :             ELSE
     558             :             {
     559         624 :                 att_val = POW_ATT_TABLE1[attDegreeFrames]; /* 10^(-attDegreeFrames*(ATT_PER_FRAME - 1)/20) */
     560         624 :                 move16();
     561             :             }
     562         624 :             mag_chg[k] = mult_r( mag_chg_1st[k], att_val ); /* Q15 */
     563         624 :             move16();
     564             : 
     565             : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
     566         624 :             IF( NE_16( element_mode, EVS_MONO ) )
     567             :             {
     568         624 :                 IF( EQ_16( k, 0 ) && GT_16( burst_len, BETA_MUTE_THR ) ) /* beta_mute final long term attenuation adjusted only once per frame in the first sub-band, Ref   Eq(184) in 26.447 */
     569             :                 {
     570          60 :                     *beta_mute = shr( *beta_mute, 1 );
     571          60 :                     move16();
     572             :                 }
     573             :             }
     574             :             ELSE
     575             :             {
     576           0 :                 IF( GT_16( burst_len, BETA_MUTE_THR ) ) /* legacy incorrect(too fast) EVS_MONO operation, still kept for BE.  To be updated after EVS CR, ref Eq (184) in 26.447 */
     577             :                 {
     578           0 :                     *beta_mute = shr( *beta_mute, 1 );
     579           0 :                     move16();
     580             :                 }
     581             :             }
     582             : #else
     583             :             IF( GT_16( burst_len, BETA_MUTE_THR ) )
     584             :             {
     585             :                 *beta_mute = shr( *beta_mute, 1 );
     586             :                 move16();
     587             :             }
     588             : #endif
     589         624 :             alpha[k] = mag_chg[k];
     590         624 :             move16();
     591             :             /*beta[k] = sqrt(1.0f - SQR(alpha[k])) * *beta_mute;*/
     592         624 :             acc = L_sub( 1073741824, L_mult0( alpha[k], alpha[k] ) );
     593         624 :             acc = Sqrt_l( acc, &expo );
     594         624 :             expo = add( 30, add( 31, expo ) );
     595         624 :             if ( EQ_16( s_and( expo, 1 ), 1 ) )
     596             :             {
     597         624 :                 acc = Mult_32_16( acc, 23170 ); /* 1/sqrt(2) in Q15 */
     598             :             }
     599         624 :             expo = shr( expo, 1 );
     600         624 :             beta[k] = mult_r( *beta_mute, round_fx( L_shl( acc, sub( 31, expo ) ) ) );
     601         624 :             move16();
     602             : 
     603         624 :             IF( GE_16( k, LGW32K - 1 ) )
     604             :             {
     605         156 :                 beta[k] = mult_r( beta[k], 3277 ); /* 0.1 in Q15 */
     606         156 :                 move16();
     607             :             }
     608         468 :             ELSE IF( GE_16( k, LGW16K - 1 ) )
     609             :             {
     610          78 :                 beta[k] = mult_r( beta[k], 16384 ); /* 0.5 in Q15 */
     611          78 :                 move16();
     612             :             }
     613             :         }
     614        1027 :         pGrPowLeft++;
     615        1027 :         pGrPowRight++;
     616             :     }
     617             : 
     618         132 :     return;
     619             : }
     620             : 
     621             : /*-----------------------------------------------------------------------------
     622             :  * peakfinder_fx()
     623             :  *
     624             :  * Peak-picking algorithm
     625             :  *----------------------------------------------------------------------------*/
     626          54 : static void ivas_peakfinder_fx(
     627             :     const Word16 *x0,      /* i : vector from which the maxima will be found                    */
     628             :     const Word16 len0,     /* i : length of input vector                                        */
     629             :     Word16 *plocs,         /* o : the indices of the identified peaks in x0                  Q0 */
     630             :     Word16 *cInd,          /* o : number of identified peaks                                 Q0 */
     631             :     const Word16 sel,      /* i : The amount above surrounding data for a peak to be identified */
     632             :     const Word16 endpoints /* i  : Flag to include endpoints in peak search                       */
     633             : )
     634             : {
     635             :     const Word16 *pX0;
     636             :     Word16 minMag, tempMag, leftMin;
     637             :     Word16 dx0[L_PROT48k_2], x[L_PROT48k_2 + 1], peakMag[MAX_PLOCS];
     638             :     Word16 *pDx0, *pDx01, *pX;
     639             :     Word16 i, len, tempLoc, foundPeak, ii, xInd, tmp16, threshold, xAt0, xAt1, xAt2;
     640             :     Word16 len0Minus1, len0Minus2, lenMinus1;
     641             :     Word16 indarr[L_PROT48k_2 + 1], peakLoc[MAX_PLOCS];
     642             :     Word16 *pInd;
     643             : 
     644          54 :     tempLoc = 0;
     645          54 :     move16();
     646             : 
     647             :     /* Find derivative */
     648          54 :     len0Minus1 = sub( len0, 1 );
     649          54 :     pX0 = x0 + 1;
     650          54 :     Vr_subt( pX0, x0, dx0, len0Minus1 );
     651             : 
     652       34102 :     FOR( i = 0; i < len0Minus1; i++ )
     653             :     {
     654       34048 :         if ( dx0[i] == 0 )
     655             :         {
     656        7663 :             dx0[i] = -1;
     657        7663 :             move16();
     658             :         }
     659             :     }
     660             : 
     661             :     /* Find where the derivative changes sign
     662             :        Include endpoints in potential peaks and valleys */
     663          54 :     pX = x;
     664          54 :     pX0 = x0;
     665          54 :     pInd = indarr;
     666          54 :     pDx01 = dx0;
     667          54 :     pDx0 = pDx01 + 1;
     668          54 :     len = 0;
     669          54 :     move16();
     670          54 :     IF( endpoints )
     671             :     {
     672          54 :         *pX++ = *pX0++;
     673          54 :         move16();
     674          54 :         *pInd++ = 0;
     675          54 :         move16();
     676          54 :         len = 2;
     677          54 :         move16();
     678             :     }
     679          54 :     len0Minus2 = sub( len0, 2 );
     680             : 
     681       34048 :     FOR( i = 0; i < len0Minus2; i++ )
     682             :     {
     683       33994 :         IF( s_xor( *pDx01++, *pDx0++ ) < 0 ) /* Detect sign change. */
     684             :         {
     685       15438 :             *pInd++ = add( i, 1 );
     686       15438 :             move16();
     687       15438 :             *pX++ = *pX0;
     688       15438 :             move16();
     689       15438 :             len = add( len, 1 );
     690             :         }
     691       33994 :         pX0++;
     692             :     }
     693          54 :     IF( endpoints )
     694             :     {
     695          54 :         *pInd = len0Minus1;
     696          54 :         move16();
     697          54 :         *pX = *pX0;
     698          54 :         move16();
     699             :     }
     700             :     /* x[] only has the peaks, valleys, and endpoints */
     701          54 :     minimum_fx( x, len, &minMag );
     702             : 
     703          54 :     pInd = indarr;
     704          54 :     test();
     705          54 :     test();
     706          54 :     IF( GT_16( len, 2 ) || ( !endpoints && ( len > 0 ) ) )
     707             :     {
     708             :         /* Set initial parameters for loop */
     709          54 :         tempMag = minMag;
     710          54 :         move16();
     711          54 :         foundPeak = 0;
     712          54 :         move16();
     713          54 :         leftMin = minMag;
     714          54 :         move16();
     715          54 :         threshold = add( leftMin, sel );
     716             : 
     717          54 :         IF( len > 0 )
     718             :         {
     719             :             /* Deal with first point a little differently since tacked it on
     720             :                Calculate the sign of the derivative since we took the first point
     721             :                on it does not necessarily alternate like the rest. */
     722             : 
     723             :             /* The first point is larger or equal to the second */
     724          54 :             pX = x;
     725          54 :             xAt0 = *pX++;
     726          54 :             move16();
     727          54 :             xAt1 = *pX++;
     728          54 :             move16();
     729          54 :             xAt2 = *pX--; /* After decrement, pX points to x[1]. */
     730          54 :             move16();
     731          54 :             IF( GE_16( xAt0, xAt1 ) )
     732             :             {
     733          10 :                 ii = -1;
     734          10 :                 move16();
     735          10 :                 IF( GE_16( xAt1, xAt2 ) ) /* x[1] is not extremum -> overwrite with x[0] */
     736             :                 {
     737           0 :                     *pX = xAt0; /* x[1] = x[0] */
     738           0 :                     move16();
     739           0 :                     tmp16 = *pInd++;
     740           0 :                     move16();
     741           0 :                     *pInd++ = tmp16; /* ind[1] = ind[0] */
     742           0 :                     move16();
     743           0 :                     len = sub( len, 1 );
     744             :                 }
     745          10 :                 pX--; /* After decrement, pX points to x[0]. */
     746             :             }
     747             :             ELSE /* First point is smaller than the second */
     748             :             {
     749          44 :                 ii = 0;
     750          44 :                 move16();
     751          44 :                 IF( LT_16( xAt1, xAt2 ) ) /* x[1] is not extremum -> overwrite with x[0] */
     752             :                 {
     753           0 :                     *pX = xAt0; /* x[1] = x[0] */
     754           0 :                     move16();
     755           0 :                     tmp16 = *pInd++;
     756           0 :                     move16();
     757           0 :                     *pInd++ = tmp16; /* ind[1] = ind[0] */
     758           0 :                     move16();
     759           0 :                     len = sub( len, 1 );
     760             :                 }
     761             :             }
     762          54 :             pX--; /* After decrement, pX points to either x[-1] or x[0]. */
     763             :         }
     764             :         ELSE
     765             :         {
     766             :             // PMTE ()
     767           0 :             ii = -1; /* First point is a peak */
     768           0 :             move16();
     769           0 :             IF( GE_16( len, 2 ) )
     770             :             {
     771           0 :                 if ( GE_16( x[1], x[0] ) )
     772             :                 {
     773           0 :                     ii = 0; /* First point is a valley, skip it */
     774           0 :                     move16();
     775             :                 }
     776             :             }
     777             :         }
     778          54 :         *cInd = 0;
     779          54 :         move16();
     780             :         /*Loop through extrema which should be peaks and then valleys*/
     781          54 :         lenMinus1 = sub( len, 1 );
     782             :         FOR( ;; )
     783             :         {
     784        7793 :             ii = add( ii, 1 ); /* This is a peak */
     785             : 
     786             :             /* Make sure we don't iterate past the length of our vector */
     787        7793 :             IF( GE_16( ii, lenMinus1 ) )
     788             :             {
     789          54 :                 BREAK;
     790             :             }
     791             : 
     792             :             /*Reset peak finding if we had a peak and the next peak is bigger
     793             :               than the last or the left min was small enough to reset.*/
     794        7739 :             IF( foundPeak > 0 )
     795             :             {
     796         890 :                 tempMag = minMag;
     797         890 :                 move16();
     798         890 :                 foundPeak = 0;
     799         890 :                 move16();
     800             :             }
     801             : 
     802             :             /* Found new peak that was larger than temp mag and selectivity larger
     803             :                than the minimum to its left. */
     804        7739 :             IF( GT_16( *( ++pX ), tempMag ) )
     805             :             {
     806        7660 :                 IF( GT_16( *pX, threshold ) ) /* threshold = leftMin + sel */
     807             :                 {
     808         987 :                     tempLoc = ii;
     809         987 :                     move16();
     810         987 :                     tempMag = *pX;
     811         987 :                     move16();
     812             :                 }
     813             :             }
     814             : 
     815        7739 :             ii = add( ii, 1 ); /* Move onto the valley */
     816        7739 :             pX++;
     817             : 
     818             :             /* Come down at least sel from peak */
     819        7739 :             IF( foundPeak == 0 )
     820             :             {
     821        7739 :                 IF( GT_16( tempMag, add( sel, *pX ) ) )
     822             :                 {
     823         890 :                     foundPeak = 1; /* We have found a peak */
     824         890 :                     move16();
     825         890 :                     leftMin = *pX;
     826         890 :                     move16();
     827         890 :                     threshold = add( leftMin, sel );
     828         890 :                     peakLoc[*cInd] = tempLoc; /* Add peak to index */
     829         890 :                     move16();
     830         890 :                     peakMag[*cInd] = tempMag;
     831         890 :                     move16();
     832         890 :                     *cInd = add( *cInd, 1 );
     833         890 :                     move16();
     834             :                 }
     835             :             }
     836        7739 :             IF( foundPeak == 0 ) /* The above IF-block has not found the peak yet. */
     837             :             {
     838        6849 :                 IF( LT_16( *pX, leftMin ) ) /* New left minimum */
     839             :                 {
     840         746 :                     leftMin = *pX;
     841         746 :                     move16();
     842         746 :                     threshold = add( leftMin, sel );
     843             :                 }
     844             :             }
     845             :         }
     846             : 
     847             :         /* Check end point */
     848          54 :         IF( GT_16( x[lenMinus1], tempMag ) )
     849             :         {
     850          38 :             IF( GT_16( x[lenMinus1], threshold ) ) /* threshold = leftMin + sel */
     851             :             {
     852           0 :                 peakLoc[*cInd] = lenMinus1;
     853           0 :                 move16();
     854           0 :                 peakMag[*cInd] = x[lenMinus1];
     855           0 :                 move16();
     856           0 :                 *cInd = add( *cInd, 1 );
     857           0 :                 move16();
     858           0 :                 foundPeak = 1;
     859           0 :                 move16();
     860             :             }
     861             :         }
     862          54 :         IF( foundPeak == 0 ) /* Check if we still need to add the last point */
     863             :         {
     864          54 :             IF( GT_16( tempMag, minMag ) )
     865             :             {
     866           0 :                 peakLoc[*cInd] = tempLoc;
     867           0 :                 move16();
     868           0 :                 peakMag[*cInd] = tempMag;
     869           0 :                 move16();
     870           0 :                 *cInd = add( *cInd, 1 );
     871           0 :                 move16();
     872             :             }
     873             :         }
     874             : 
     875             :         /* Create output */
     876         944 :         FOR( i = 0; i < *cInd; i++ )
     877             :         {
     878         890 :             plocs[i] = *( indarr + peakLoc[i] );
     879         890 :             move16();
     880             :         }
     881             :     }
     882             :     ELSE /* This is a monotone function where an endpoint is the only peak */
     883             :     {
     884           0 :         IF( endpoints )
     885             :         {
     886           0 :             xInd = 1;
     887           0 :             move16();
     888           0 :             if ( GT_16( x[0], x[1] ) )
     889             :             {
     890           0 :                 xInd = 0;
     891           0 :                 move16();
     892             :             }
     893             : 
     894           0 :             peakMag[0] = x[xInd];
     895           0 :             move16();
     896           0 :             IF( GT_16( peakMag[0], add( minMag, sel ) ) )
     897             :             {
     898           0 :                 plocs[0] = *( indarr + xInd );
     899           0 :                 move16();
     900           0 :                 *cInd = 1;
     901           0 :                 move16();
     902             :             }
     903             :             ELSE
     904             :             {
     905           0 :                 *cInd = 0;
     906           0 :                 move16();
     907             :             }
     908             :         }
     909             :         ELSE
     910             :         { /* Input constant or all zeros -- no peaks found */
     911           0 :             *cInd = 0;
     912           0 :             move16();
     913             :         }
     914             :     }
     915          54 : }
     916             : 
     917           0 : static void peakfinder_fx(
     918             :     const Word16 *x0,  /* i : vector from which the maxima will be found                    */
     919             :     const Word16 len0, /* i : length of input vector                                        */
     920             :     Word16 *plocs,     /* o : the indices of the identified peaks in x0                  Q0 */
     921             :     Word16 *cInd,      /* o : number of identified peaks                                 Q0 */
     922             :     const Word16 sel   /* i : The amount above surrounding data for a peak to be identified */
     923             : )
     924             : {
     925             :     const Word16 *pX0;
     926             :     Word16 minMag, tempMag, leftMin;
     927             :     Word16 dx0[L_PROT48k_2], x[L_PROT48k_2 + 1], peakMag[MAX_PLOCS];
     928             :     Word16 *pDx0, *pDx01, *pX;
     929             :     Word16 i, len, tempLoc, foundPeak, ii, xInd, tmp16, threshold, xAt0, xAt1, xAt2;
     930             :     Word16 len0Minus1, len0Minus2, lenMinus1;
     931             :     Word16 indarr[L_PROT48k_2 + 1], peakLoc[MAX_PLOCS];
     932             :     Word16 *pInd;
     933             : 
     934           0 :     tempLoc = 0;
     935           0 :     move16();
     936             : 
     937             :     /* Find derivative */
     938           0 :     len0Minus1 = sub( len0, 1 );
     939           0 :     pX0 = x0 + 1;
     940           0 :     Vr_subt( pX0, x0, dx0, len0Minus1 );
     941             : 
     942           0 :     FOR( i = 0; i < len0Minus1; i++ )
     943             :     {
     944           0 :         if ( dx0[i] == 0 )
     945             :         {
     946           0 :             dx0[i] = -1;
     947           0 :             move16();
     948             :         }
     949             :     }
     950             : 
     951             :     /* Find where the derivative changes sign
     952             :        Include endpoints in potential peaks and valleys */
     953           0 :     pX = x;
     954           0 :     pX0 = x0;
     955           0 :     pInd = indarr;
     956           0 :     pDx01 = dx0;
     957           0 :     pDx0 = pDx01 + 1;
     958             :     {
     959           0 :         *pX++ = *pX0++;
     960           0 :         move16();
     961           0 :         *pInd++ = 0;
     962           0 :         move16();
     963           0 :         len = 2;
     964           0 :         move16();
     965             :     }
     966           0 :     len0Minus2 = sub( len0, 2 );
     967             : 
     968           0 :     FOR( i = 0; i < len0Minus2; i++ )
     969             :     {
     970           0 :         IF( s_xor( *pDx01++, *pDx0++ ) < 0 ) /* Detect sign change. */
     971             :         {
     972           0 :             *pInd++ = add( i, 1 );
     973           0 :             move16();
     974           0 :             *pX++ = *pX0;
     975           0 :             move16();
     976           0 :             len = add( len, 1 );
     977             :         }
     978           0 :         pX0++;
     979             :     }
     980             :     {
     981           0 :         *pInd = len0Minus1;
     982           0 :         move16();
     983           0 :         *pX = *pX0;
     984           0 :         move16();
     985             :     }
     986             :     /* x[] only has the peaks, valleys, and endpoints */
     987           0 :     minimum_fx( x, len, &minMag );
     988             : 
     989           0 :     pInd = indarr;
     990           0 :     IF( GT_16( len, 2 ) )
     991             :     {
     992             :         /* Set initial parameters for loop */
     993           0 :         tempMag = minMag;
     994           0 :         move16();
     995           0 :         foundPeak = 0;
     996           0 :         move16();
     997           0 :         leftMin = minMag;
     998           0 :         move16();
     999           0 :         threshold = add( leftMin, sel );
    1000             : 
    1001             :         {
    1002             :             /* Deal with first point a little differently since tacked it on
    1003             :                Calculate the sign of the derivative since we took the first point
    1004             :                on it does not necessarily alternate like the rest. */
    1005             : 
    1006             :             /* The first point is larger or equal to the second */
    1007           0 :             pX = x;
    1008           0 :             xAt0 = *pX++;
    1009           0 :             move16();
    1010           0 :             xAt1 = *pX++;
    1011           0 :             move16();
    1012           0 :             xAt2 = *pX--; /* After decrement, pX points to x[1]. */
    1013           0 :             move16();
    1014           0 :             IF( GE_16( xAt0, xAt1 ) )
    1015             :             {
    1016           0 :                 ii = -1;
    1017           0 :                 move16();
    1018           0 :                 IF( GE_16( xAt1, xAt2 ) ) /* x[1] is not extremum -> overwrite with x[0] */
    1019             :                 {
    1020           0 :                     *pX = xAt0; /* x[1] = x[0] */
    1021           0 :                     move16();
    1022           0 :                     tmp16 = *pInd++;
    1023           0 :                     move16();
    1024           0 :                     *pInd++ = tmp16; /* ind[1] = ind[0] */
    1025           0 :                     move16();
    1026           0 :                     len = sub( len, 1 );
    1027             :                 }
    1028           0 :                 pX--; /* After decrement, pX points to x[0]. */
    1029             :             }
    1030             :             ELSE /* First point is smaller than the second */
    1031             :             {
    1032           0 :                 ii = 0;
    1033           0 :                 move16();
    1034           0 :                 IF( LT_16( xAt1, xAt2 ) ) /* x[1] is not extremum -> overwrite with x[0] */
    1035             :                 {
    1036           0 :                     *pX = xAt0; /* x[1] = x[0] */
    1037           0 :                     move16();
    1038           0 :                     tmp16 = *pInd++;
    1039           0 :                     move16();
    1040           0 :                     *pInd++ = tmp16; /* ind[1] = ind[0] */
    1041           0 :                     move16();
    1042           0 :                     len = sub( len, 1 );
    1043             :                 }
    1044             :             }
    1045           0 :             pX--; /* After decrement, pX points to either x[-1] or x[0]. */
    1046             :         }
    1047           0 :         *cInd = 0;
    1048           0 :         move16();
    1049             :         /*Loop through extrema which should be peaks and then valleys*/
    1050           0 :         lenMinus1 = sub( len, 1 );
    1051             :         FOR( ;; )
    1052             :         {
    1053           0 :             ii = add( ii, 1 ); /* This is a peak */
    1054             : 
    1055             :             /* Make sure we don't iterate past the length of our vector */
    1056           0 :             IF( GE_16( ii, lenMinus1 ) )
    1057             :             {
    1058           0 :                 BREAK;
    1059             :             }
    1060             : 
    1061             :             /*Reset peak finding if we had a peak and the next peak is bigger
    1062             :               than the last or the left min was small enough to reset.*/
    1063           0 :             IF( foundPeak > 0 )
    1064             :             {
    1065           0 :                 tempMag = minMag;
    1066           0 :                 move16();
    1067           0 :                 foundPeak = 0;
    1068           0 :                 move16();
    1069             :             }
    1070             : 
    1071             :             /* Found new peak that was larger than temp mag and selectivity larger
    1072             :                than the minimum to its left. */
    1073           0 :             IF( GT_16( *( ++pX ), tempMag ) )
    1074             :             {
    1075           0 :                 IF( GT_16( *pX, threshold ) ) /* threshold = leftMin + sel */
    1076             :                 {
    1077           0 :                     tempLoc = ii;
    1078           0 :                     move16();
    1079           0 :                     tempMag = *pX;
    1080           0 :                     move16();
    1081             :                 }
    1082             :             }
    1083             : 
    1084           0 :             ii = add( ii, 1 ); /* Move onto the valley */
    1085           0 :             pX++;
    1086             : 
    1087             :             /* Come down at least sel from peak */
    1088           0 :             IF( foundPeak == 0 )
    1089             :             {
    1090           0 :                 IF( GT_16( tempMag, add( sel, *pX ) ) )
    1091             :                 {
    1092           0 :                     foundPeak = 1; /* We have found a peak */
    1093           0 :                     move16();
    1094           0 :                     leftMin = *pX;
    1095           0 :                     move16();
    1096           0 :                     threshold = add( leftMin, sel );
    1097           0 :                     peakLoc[*cInd] = tempLoc; /* Add peak to index */
    1098           0 :                     move16();
    1099           0 :                     peakMag[*cInd] = tempMag;
    1100           0 :                     move16();
    1101           0 :                     *cInd = add( *cInd, 1 );
    1102           0 :                     move16();
    1103             :                 }
    1104             :             }
    1105           0 :             IF( foundPeak == 0 ) /* The above IF-block has not found the peak yet. */
    1106             :             {
    1107           0 :                 IF( LT_16( *pX, leftMin ) ) /* New left minimum */
    1108             :                 {
    1109           0 :                     leftMin = *pX;
    1110           0 :                     move16();
    1111           0 :                     threshold = add( leftMin, sel );
    1112             :                 }
    1113             :             }
    1114             :         }
    1115             : 
    1116             :         /* Check end point */
    1117           0 :         IF( GT_16( x[lenMinus1], tempMag ) )
    1118             :         {
    1119           0 :             IF( GT_16( x[lenMinus1], threshold ) ) /* threshold = leftMin + sel */
    1120             :             {
    1121           0 :                 peakLoc[*cInd] = lenMinus1;
    1122           0 :                 move16();
    1123           0 :                 peakMag[*cInd] = x[lenMinus1];
    1124           0 :                 move16();
    1125           0 :                 *cInd = add( *cInd, 1 );
    1126           0 :                 foundPeak = 1;
    1127           0 :                 move16();
    1128             :             }
    1129             :         }
    1130           0 :         IF( foundPeak == 0 ) /* Check if we still need to add the last point */
    1131             :         {
    1132           0 :             IF( GT_16( tempMag, minMag ) )
    1133             :             {
    1134           0 :                 peakLoc[*cInd] = tempLoc;
    1135           0 :                 move16();
    1136           0 :                 peakMag[*cInd] = tempMag;
    1137           0 :                 move16();
    1138           0 :                 *cInd = add( *cInd, 1 );
    1139           0 :                 move16();
    1140             :             }
    1141             :         }
    1142             : 
    1143             :         /* Create output */
    1144           0 :         FOR( i = 0; i < *cInd; i++ )
    1145             :         {
    1146           0 :             plocs[i] = *( indarr + peakLoc[i] );
    1147           0 :             move16();
    1148             :         }
    1149             :     }
    1150             :     ELSE /* This is a monotone function where an endpoint is the only peak */
    1151             :     {
    1152             :         {
    1153           0 :             xInd = 1;
    1154           0 :             move16();
    1155           0 :             if ( GT_16( x[0], x[1] ) )
    1156             :             {
    1157           0 :                 xInd = 0;
    1158           0 :                 move16();
    1159             :             }
    1160             : 
    1161           0 :             peakMag[0] = x[xInd];
    1162           0 :             move16();
    1163           0 :             IF( GT_16( peakMag[0], add( minMag, sel ) ) )
    1164             :             {
    1165           0 :                 plocs[0] = *( indarr + xInd );
    1166           0 :                 move16();
    1167           0 :                 *cInd = 1;
    1168           0 :                 move16();
    1169             :             }
    1170             :             ELSE
    1171             :             {
    1172           0 :                 *cInd = 0;
    1173           0 :                 move16();
    1174             :             }
    1175             :         }
    1176             :     }
    1177           0 : }
    1178             : 
    1179             : /*-----------------------------------------------------------------------------
    1180             :  * imax_fx()
    1181             :  *
    1182             :  * Get interpolated maximum position
    1183             :  *-----------------------------------------------------------------------------*/
    1184           0 : static Word16 imax_fx(                      /* o: The location, relative to the middle of the 3 given data point, of the maximum. (Q15) */
    1185             :                        const Word16 *y,     /* i: The 3 given data points. */
    1186             :                        const Word16 special /* i: -1 = left edge special case, 0 = normal, +1 = right edge special case */
    1187             : )
    1188             : {
    1189             :     Word16 posi;
    1190             :     Word16 y1, y2, y3, man, expo, edge;
    1191             :     const Word16 *pY;
    1192             :     Word32 numer, denom, sign, acc, y3_y1;
    1193             :     /* Seek the extremum of the parabola P(x) defined by 3 consecutive points
    1194             :        so that P([-1 0 1]) = [y1 y2 y3] */
    1195           0 :     pY = y;
    1196           0 :     y1 = *pY++, y2 = *pY++, y3 = *pY;
    1197           0 :     move16();
    1198           0 :     move16();
    1199           0 :     move16();
    1200             : 
    1201             :     /* The extremum value:
    1202             :      *   y2i = -0.125f * SQR(y3_y1) / (y1+y3-2*y2)+y2
    1203             :      * is not computed. Alternatively, the derivative of the parabola evaluated at y=0,
    1204             :      * dP/dy|y=0, is used to determine whether the extremum is maximum or not.
    1205             :      */
    1206             : 
    1207             :     /* Compute the extremum location: posi = (y3 - y1)/(4*y2 - 2*y1 - 2*y3). */
    1208           0 :     y3_y1 = L_sub( y3, y1 );
    1209           0 :     acc = L_shl( y2, 1 );         /* N.B. y2 is multiplied by 2 not 4. */
    1210           0 :     acc = L_sub( acc, y1 );       /* N.B. Y1 is not multiplied by 2. */
    1211           0 :     denom = L_sub( acc, y3 );     /* N.B. Y3 is not multiplied by 2. */
    1212           0 :     sign = L_xor( y3_y1, denom ); /* Preserve the sign since div_s() only takes positive arguments. */
    1213           0 :     numer = L_abs( y3_y1 );
    1214           0 :     denom = L_abs( denom );
    1215           0 :     IF( numer == 0 )
    1216             :     {
    1217           0 :         return 0;
    1218             :     }
    1219           0 :     IF( denom == 0 )
    1220             :     {
    1221           0 :         return 0;
    1222             :     }
    1223             :     /* Although the output of ratio() is in Q14, adding the missing factor of 2 (See above)
    1224             :      * in the denominator, the output is now considered to be in Q15. */
    1225           0 :     man = ratio( numer, denom, &expo ); /* The mantissa is considered in Q15 */
    1226           0 :     posi = shr_sat( man, expo );        /* in Q15 (Due to saturation, it is automatically bound inside [-1.0,1.0].) */
    1227           0 :     if ( sign < 0 )                     /* Restore the sign. */
    1228             :     {
    1229           0 :         posi = negate( posi );
    1230             :     }
    1231             : 
    1232             :     /* For both edges (left and right), the extremum found above may be minimum.
    1233             :      * It needs to reject the minimum. */
    1234           0 :     IF( special != 0 ) /* Either edge specical case. */
    1235             :     {
    1236           0 :         edge = 0x7fff; /* 1 in Q15 for the right edge special case */
    1237           0 :         move16();
    1238           0 :         if ( special < 0 )
    1239             :         {
    1240           0 :             edge = 0; /* Left edge special case */
    1241           0 :             move16();
    1242             :         }
    1243             : 
    1244             :         /* The derivative (slope) of the interpolating parabola = 2*A*y + B,
    1245             :          *   where A = (y3 + y1)/2 - y2
    1246             :          *     and B = (y3 - y1)/2.
    1247             :          * Therefore, the slope at y=0 is simply B. Use this slope to determine
    1248             :          * if the parabola is concave upward or downward.
    1249             :          */
    1250           0 :         IF( posi > 0 ) /* The extremum is in between the middle and the right given data points. */
    1251             :         {
    1252           0 :             IF( LE_16( y3, y1 ) ) /* Check the slope at y=0, i.e., at the middle given data point. */
    1253             :             {
    1254           0 :                 posi = edge; /* minimum case */
    1255           0 :                 move16();
    1256             :             }
    1257             :             ELSE
    1258             :             {
    1259           0 :                 posi = sub( 0x7fff, posi ); /* maximum case */
    1260             :             }
    1261             :         }
    1262             :         ELSE /* The extremum is in between the left and the middle given data points. */
    1263             :         {
    1264           0 :             IF( GE_16( y3, y1 ) )
    1265             :             {
    1266           0 :                 posi = edge; /* minimum case */
    1267           0 :                 move16();
    1268             :             }
    1269             :             ELSE
    1270             :             {
    1271           0 :                 posi = add( 0x7fff, posi ); /* maximum case */
    1272             :             }
    1273             :         }
    1274             :     }
    1275           0 :     return posi; /* Q15. The position either left or right relative to the index of the middle of the 3 given data points. */
    1276             : }
    1277             : 
    1278             : /*-----------------------------------------------------------------------------
    1279             :  * spec_ana_fx()
    1280             :  *
    1281             :  * Spectral analysis
    1282             :  *-----------------------------------------------------------------------------*/
    1283             : 
    1284          54 : static void ivas_spec_ana_fx(
    1285             :     const Word16 *prevsynth,   /* i : Input signal                                         */
    1286             :     Word16 *plocs,             /* o : The indicies of the identified peaks             Q0  */
    1287             :     Word32 *plocsi,            /* o : Interpolated positions of the identified peaks   Q16 */
    1288             :     Word16 *num_plocs,         /* o : Number of identified peaks                       Q0  */
    1289             :     Word16 *X_sav,             /* o : Stored fft spectrum                                  */
    1290             :     const Word16 output_frame, /* i : Frame length                                     Q0  */
    1291             :     const Word16 bwidth_fx,    /* i : Encoded bandwidth index                          Q0  */
    1292             :     Word16 *Q,                 /* o : Q value of the fft spectrum                          */
    1293             :     const Word16 element_mode, /* i  : IVAS element mode                               */
    1294             :     Word16 *noise_fac,         /* o  : for few peaks zeroing valleys decision making   Q15*/
    1295             :     const Word16 pcorr )
    1296             : {
    1297          54 :     Word16 Lprot, LprotLog2Minus1 = 0, hamm_len2 = 0, Lprot2, Lprot2_1, m, n;
    1298          54 :     const Word16 *pFftTbl = NULL;
    1299             :     Word16 xfp[L_PROT48k];
    1300             :     Word32 magSq[L_PROT48k / 2 + 1], *pMagSq;
    1301             :     Word16 *pXfp, *pXfp1, *pXsav, *pPlocs;
    1302             :     Word16 Xmax, Xmin, sel, man, expo, expoBy2;
    1303             :     Word16 sinTblOffset, rectLength, fraction, special;
    1304             :     Word32 *pPlocsi;
    1305             :     Word32 acc;
    1306             :     Word16 stop_band_start;
    1307             :     Word16 stop_band_length;
    1308          54 :     const Word16 *w_hamm = NULL;
    1309             :     Word16 window_corr, window_corr_step;
    1310             :     Word16 currPlocs, endPlocs, nJacob, k, i;
    1311             :     Word32 sig, noise, st_point, end_point;
    1312             :     Word32 xfp_32[3]; // Q + 16
    1313             : 
    1314          54 :     move16();    // LprotLog2Minus1
    1315          54 :     move16();    // hamm_len2
    1316          54 :     Lprot = 512; /* 1536=(2*output_frame)*1024/1280; */
    1317          54 :     move16();
    1318             : 
    1319          54 :     sinTblOffset = 0;
    1320          54 :     move16();
    1321             : 
    1322          54 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    1323             :     {
    1324          25 :         Lprot = L_PROT48k; /* 1536=(2*output_frame)*1024/1280; */
    1325          25 :         move16();
    1326          25 :         hamm_len2 = L_PROT_HAMM_LEN2_48k; /* half Hamming window = 288 */
    1327          25 :         move16();
    1328          25 :         w_hamm = w_hamm_sana48k_2_fx;
    1329             :     }
    1330          29 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    1331             :     {
    1332          29 :         Lprot = L_PROT32k; /* 1024 */
    1333          29 :         move16();
    1334          29 :         sinTblOffset = 4;
    1335          29 :         move16();
    1336          29 :         hamm_len2 = L_PROT_HAMM_LEN2_32k; /* half Hamming window = 192 */
    1337          29 :         move16();
    1338          29 :         pFftTbl = FFT_W512;  /* Table for 1024-point real input FFT */
    1339          29 :         LprotLog2Minus1 = 9; /* FFT stages for complex input FFT */
    1340          29 :         move16();
    1341          29 :         w_hamm = w_hamm_sana32k_2_fx;
    1342             :     }
    1343             :     ELSE
    1344             :     {
    1345           0 :         Lprot = 512;
    1346           0 :         move16();
    1347           0 :         sinTblOffset = 8;
    1348           0 :         move16();
    1349           0 :         hamm_len2 = L_PROT_HAMM_LEN2_16k; /* half Hamming window = 96 */
    1350           0 :         move16();
    1351           0 :         pFftTbl = FFT_W256;  /* Table for 512-point real input FFT */
    1352           0 :         LprotLog2Minus1 = 8; /* FFT stages for complex input FFT */
    1353           0 :         move16();
    1354           0 :         w_hamm = w_hamm_sana16k_2_fx;
    1355             :     }
    1356             : 
    1357          54 :     Lprot2 = shr( Lprot, 1 );
    1358          54 :     Lprot2_1 = add( Lprot2, 1 );
    1359          54 :     rectLength = sub( Lprot, shl( hamm_len2, 1 ) ); /* The length of the rectangular portion of the Hamming-Rectangular window. */
    1360             : 
    1361          54 :     *Q = s_max( 0, sub( Exp16Array( Lprot, prevsynth ), 1 ) );
    1362          54 :     move16();
    1363          54 :     Copy_Scale_sig( prevsynth, xfp, Lprot, *Q );
    1364             : 
    1365             : 
    1366          54 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    1367             :     {
    1368             :         /* Apply hamming-rect window */
    1369          25 :         IF( element_mode == EVS_MONO )
    1370             :         {
    1371           0 :             windowing( xfp, xfp, w_hamm_sana48k_2_fx, rectLength, hamm_len2 );
    1372             :         }
    1373             :         ELSE
    1374             :         {
    1375             :             // PMTE()
    1376          25 :             window_corr = w_hamm[0];
    1377          25 :             move16();
    1378          25 :             window_corr_step = idiv1616( w_hamm[0], hamm_len2 );
    1379        7225 :             FOR( i = 0; i < hamm_len2; i++ )
    1380             :             {
    1381        7200 :                 xfp[i] = mult_r( shl( prevsynth[i], *Q ), sub( w_hamm[i], window_corr ) );
    1382        7200 :                 move16();
    1383        7200 :                 xfp[Lprot - i - 1] = mult_r( shl( prevsynth[Lprot - i - 1], *Q ), sub( w_hamm[i], window_corr ) );
    1384        7200 :                 move16();
    1385        7200 :                 window_corr = sub( window_corr, window_corr_step );
    1386             :             }
    1387             :         }
    1388             :         /* Spectrum */
    1389          25 :         fft3_fx( xfp, xfp, Lprot );
    1390             :     }
    1391             :     ELSE
    1392             :     {
    1393          29 :         IF( element_mode == EVS_MONO )
    1394             :         {
    1395             :             /* Apply hamming-rect window */
    1396           0 :             windowing_ROM_optimized( xfp, xfp, sinTblOffset, rectLength, hamm_len2 );
    1397             :         }
    1398             :         ELSE
    1399             :         {
    1400             :             // PMTE()
    1401          29 :             window_corr = w_hamm[0];
    1402          29 :             move16();
    1403          29 :             window_corr_step = idiv1616( w_hamm[0], hamm_len2 );
    1404        5597 :             FOR( i = 0; i < hamm_len2; i++ )
    1405             :             {
    1406        5568 :                 xfp[i] = mult_r( shl( prevsynth[i], *Q ), sub( w_hamm[i], window_corr ) );
    1407        5568 :                 move16();
    1408        5568 :                 xfp[Lprot - i - 1] = mult_r( shl( prevsynth[Lprot - i - 1], *Q ), sub( w_hamm[i], window_corr ) );
    1409        5568 :                 move16();
    1410        5568 :                 window_corr = sub( window_corr, window_corr_step );
    1411             :             }
    1412             :         }
    1413             :         /* Spectrum */
    1414          29 :         r_fft_fx_lc( pFftTbl, Lprot, Lprot2, LprotLog2Minus1, xfp, xfp, 1 );
    1415             :     }
    1416             : 
    1417             :     /* Apply zeroing of non-coded FFT spectrum */
    1418          54 :     IF( GT_16( output_frame, inner_frame_tbl[bwidth_fx] ) )
    1419             :     {
    1420          11 :         stop_band_start = shl( 128, bwidth_fx );
    1421          11 :         stop_band_length = sub( Lprot, shl( stop_band_start, 1 ) );
    1422          11 :         stop_band_start = add( stop_band_start, 1 );
    1423          11 :         set16_fx( xfp + stop_band_start, 0, stop_band_length );
    1424             :     }
    1425             : 
    1426          54 :     pXfp = xfp;
    1427          54 :     pXsav = X_sav;
    1428             : 
    1429       68150 :     FOR( m = 0; m < Lprot; m++ )
    1430             :     {
    1431       68096 :         *pXsav++ = *pXfp++;
    1432       68096 :         move16();
    1433             :     }
    1434             : 
    1435             :     /* Magnitude representation */
    1436          54 :     fft_spec2_fx( xfp, magSq, Lprot );
    1437             : 
    1438             :     /* Compute xfp[m] = sqrt(magSq[m]) */
    1439          54 :     pXfp = xfp;
    1440          54 :     pMagSq = magSq;
    1441       34156 :     FOR( m = 0; m < Lprot2_1; m++ )
    1442             :     {
    1443       34102 :         IF( *pMagSq == 0 )
    1444             :         {
    1445        5526 :             *pXfp++ = extract_l( *pMagSq++ ); /* magSq[] is zero */
    1446        5526 :             move16();
    1447             :         }
    1448             :         ELSE
    1449             :         {
    1450       28576 :             expo = norm_l( *pMagSq );                    /* exponent */
    1451       28576 :             man = extract_h( L_shl( *pMagSq++, expo ) ); /* mantissa */
    1452       28576 :             man = sqrt2ndOrder( man );
    1453       28576 :             expoBy2 = shr( expo, 1 );   /* Divided by 2-- square root operation. */
    1454       28576 :             IF( s_and( expo, 1 ) == 0 ) /* Check even or odd. */
    1455             :             {
    1456       15599 :                 man = mult_r( man, FEC_HQ_ECU_ROOT2 ); /* FEC_HQ_ECU_ROOT2 is sqrt(2) in Q14 */
    1457       15599 :                 expoBy2 = sub( expoBy2, 1 );
    1458             :             }
    1459       28576 :             *pXfp++ = shr_sat( man, expoBy2 );
    1460       28576 :             move16(); /* Denormalize the mantissa back to Q0. */
    1461             :         }
    1462             :     }
    1463             : 
    1464             :     /* Find maximum and minimum. */
    1465          54 :     maximum_fx( xfp, Lprot2_1, &Xmax );
    1466          54 :     minimum_fx( xfp, Lprot2_1, &Xmin );
    1467          54 :     IF( element_mode == EVS_MONO )
    1468             :     {
    1469           0 :         sel = mult_r( sub( Xmax, Xmin ), CMPLMNT_PFIND_SENS_FX );
    1470             :     }
    1471             :     ELSE
    1472             :     {
    1473          54 :         sel = mult_r( sub( Xmax, Xmin ), CMPLMNT_ST_PFIND_SENS_FX );
    1474             :     }
    1475          54 :     ivas_peakfinder_fx( xfp, Lprot2_1, plocs, num_plocs, sel, TRUE );
    1476             : 
    1477             : 
    1478             :     /* Currently not the pitch correlation but some LF correlation */
    1479          54 :     if ( element_mode != EVS_MONO && *num_plocs > 50 && pcorr < 19661 /* 0.6f in Q15 */ )
    1480             :     {
    1481           0 :         *num_plocs = 0;
    1482           0 :         move16();
    1483             :     }
    1484             : 
    1485          54 :     IF( element_mode == EVS_MONO )
    1486             :     {
    1487             : 
    1488             :         /* Refine peaks */
    1489           0 :         pPlocsi = plocsi;
    1490           0 :         pPlocs = plocs;
    1491           0 :         n = sub( *num_plocs, 1 ); /* -1 so as to exclude the very last peak. */
    1492             :         /* Special case-- The very 1st peak if it is at 0 index position */
    1493           0 :         IF( *pPlocs == 0 ) /* Only the very 1st peak is possible the peak at 0 index position. */
    1494             :         {
    1495           0 :             fraction = imax_fx( xfp, -1 );  /* -1 signifies special left edge case. */
    1496           0 :             acc = L_deposit_h( *pPlocs++ ); /* N.B., (*pPlocs) must be zero here. */
    1497           0 :             *pPlocsi++ = L_mac( acc, fraction, 1 );
    1498           0 :             move32();        /* in Q16 */
    1499           0 :             n = sub( n, 1 ); /* This special case is taken care of-- one less to go */
    1500             :         }
    1501             :         /* All peaks except the very last peak but including the very 1st one if it has not been taken care of. */
    1502           0 :         pXfp1 = xfp - 1;
    1503           0 :         FOR( m = 0; m < n; m++ ) /* Loop through up to the last but one peak. (The last one is excluded.) */
    1504             :         {
    1505           0 :             pXfp = pXfp1 + *pPlocs;
    1506           0 :             fraction = imax_fx( pXfp, 0 ); /* in Q15 */
    1507           0 :             acc = L_deposit_h( *pPlocs++ );
    1508           0 :             *pPlocsi++ = L_mac( acc, fraction, 1 );
    1509           0 :             move32(); /* in Q16. Append the fractional part to the integral part. */
    1510             :         }
    1511           0 :         IF( n >= 0 )
    1512             :         {
    1513             :             /* Special case-- The very last peak */
    1514           0 :             pXfp = pXfp1 + *pPlocs;
    1515           0 :             IF( EQ_16( *pPlocs, Lprot2 ) ) /* Only the very last peak is possible the peak at Lprot2 index position. */
    1516             :             {
    1517           0 :                 pXfp--;      /* Special case needs extra decrement */
    1518           0 :                 special = 1; /* Signify special right edge case. */
    1519           0 :                 move16();
    1520             :             }
    1521             :             ELSE
    1522             :             {
    1523           0 :                 special = 0;
    1524           0 :                 move16();
    1525             :             }
    1526           0 :             fraction = imax_fx( pXfp, special ); /* in Q15 */
    1527           0 :             acc = L_deposit_h( *pPlocs );
    1528           0 :             *pPlocsi = L_mac( acc, fraction, 1 );
    1529           0 :             move32(); /* in Q16. Append the fractional part to the integral part. */
    1530             :         }
    1531             :     }
    1532             :     ELSE
    1533             :     {
    1534          54 :         Lprot2 = shr( Lprot, 1 );
    1535          54 :         Lprot2_1 = add( Lprot2, 1 );
    1536             : 
    1537             :         /* Refine peaks */
    1538          54 :         pPlocsi = plocsi;
    1539          54 :         pPlocs = plocs;
    1540          54 :         n = *num_plocs; /* number of peaks to process */
    1541          54 :         move16();
    1542             : 
    1543             :         /* Special case-- The very 1st peak if it is at 0 index position (DC) */
    1544             :         /* With DELTA_CORR_F0_INT == 2 one needs to handle both *pPlocs==0 and *pPlocs==1 */
    1545             :         // IF( n > 0 && *pPlocs == 0 ) /* Very 1st peak position possible to have a peak at 0/DC index position. */
    1546          54 :         test();
    1547          54 :         IF( n > 0 && *pPlocs == 0 ) /* Very 1st peak position possible to have a peak at 0/DC index position. */
    1548             :         {
    1549           0 :             Copy_Scale_sig_16_32_no_sat( &xfp[*pPlocs], xfp_32, 3, Q15 );           // Q + 15
    1550           0 :             acc = L_deposit_h( *pPlocs );                                           // Q16
    1551           0 :             *pPlocsi++ = L_add( acc, L_shl( imax_pos_fx( xfp_32 ) /* Q15 */, 1 ) ); // Q16
    1552           0 :             move32();
    1553           0 :             pPlocs++;
    1554           0 :             n = sub( n, 1 );
    1555             :         }
    1556             : 
    1557          54 :         test();
    1558          54 :         IF( n > 0 && EQ_16( *pPlocs, 1 ) ) /* Also 2nd peak position uses DC which makes jacobsen unsuitable. */
    1559             :         {
    1560           4 :             Copy_Scale_sig_16_32_no_sat( &xfp[*pPlocs - 1], xfp_32, 3, Q15 );       // Q + 15
    1561           4 :             acc = L_deposit_h( sub( *pPlocs, 1 ) );                                 // Q16
    1562           4 :             *pPlocsi++ = L_add( acc, L_shl( imax_pos_fx( xfp_32 ) /* Q15 */, 1 ) ); // Q16
    1563           4 :             move32();
    1564           4 :             currPlocs = *pPlocs++; // Q16
    1565           4 :             move16();
    1566           4 :             n = sub( n, 1 );
    1567             :         }
    1568             : 
    1569             :         /* All remaining peaks except the very last two possible integer positions */
    1570          54 :         currPlocs = *pPlocs++;
    1571          54 :         move16();
    1572          54 :         endPlocs = sub( Lprot2_1, DELTA_CORR_F0_INT ); /* last *pPlocs position for Jacobsen */
    1573             : 
    1574             :         /* precompute number of turns based on endpoint integer location  and make into  a proper for loop */
    1575          54 :         IF( n > 0 )
    1576             :         {
    1577          54 :             nJacob = n;
    1578          54 :             move16();
    1579          54 :             if ( sub( endPlocs, plocs[*num_plocs - 1] ) <= 0 )
    1580             :             {
    1581           0 :                 nJacob = sub( nJacob, 1 );
    1582             :             }
    1583             : 
    1584         940 :             FOR( k = 0; k < nJacob; k++ )
    1585             :             {
    1586         886 :                 fraction = ivas_imax2_jacobsen_mag_fx( &( X_sav[currPlocs - 1] ), &( X_sav[Lprot - 1 - currPlocs] ) ); /* in Q15 */
    1587         886 :                 acc = L_deposit_h( currPlocs );                                                                        // Q16
    1588         886 :                 *pPlocsi++ = L_mac( acc, fraction, 1 );                                                                // Q16
    1589         886 :                 move32();
    1590         886 :                 currPlocs = *pPlocs++; // Q16
    1591         886 :                 move16();
    1592             :             }
    1593          54 :             n = sub( n, nJacob );
    1594             :         }
    1595             : 
    1596             :         /* At this point there should at most two plocs left to process */
    1597             :         /* the position before fs/2 and fs/2 both use the same magnitude points */
    1598          54 :         IF( n > 0 )
    1599             :         {
    1600             :             /* [ . . .            .  .  .  . ]   Lprot/2+1 positions  */
    1601             :             /*   |                   |     |           */
    1602             :             /*   0         (Lprot/2-2)     (Lprot/2)   */
    1603             : 
    1604           0 :             IF( EQ_16( currPlocs, ( sub( Lprot2_1, DELTA_CORR_F0_INT ) ) ) ) /* Also 2nd last peak position uses fs/2  which makes jacobsen less suitable. */
    1605             :             {
    1606           0 :                 Copy_Scale_sig_16_32_no_sat( &xfp[currPlocs - 1], xfp_32, 3, Q15 );     // Q + 15
    1607           0 :                 acc = L_deposit_h( sub( currPlocs, 1 ) );                               // Q16
    1608           0 :                 *pPlocsi++ = L_add( acc, L_shl( imax_pos_fx( xfp_32 ) /* Q15 */, 1 ) ); // Q16
    1609           0 :                 move32();
    1610           0 :                 currPlocs = *pPlocs++; // Q16
    1611           0 :                 move16();
    1612           0 :                 n = sub( n, 1 );
    1613             :             }
    1614             : 
    1615             :             /* Here the only remaining point would be a  fs/2 plocs */
    1616             :             /*    pXfp = xfp + sub(Lprot2,1); already set just a reminder where it
    1617             :              * whould point */
    1618           0 :             IF( n > 0 ) /* fs/2 which makes special case . */
    1619             :             {
    1620           0 :                 Copy_Scale_sig_16_32_no_sat( &xfp[currPlocs - 2], xfp_32, 3, Q15 );     // Q + 15
    1621           0 :                 acc = L_deposit_h( sub( currPlocs, 2 ) );                               // Q16
    1622           0 :                 *pPlocsi++ = L_add( acc, L_shl( imax_pos_fx( xfp_32 ) /* Q15 */, 1 ) ); // Q16
    1623           0 :                 move32();
    1624           0 :                 currPlocs = *pPlocs++; // Q16
    1625           0 :                 move16();
    1626           0 :                 n = sub( n, 1 );
    1627             :             }
    1628             :         }
    1629             : 
    1630             :         /* For few peaks decide noise floor attenuation */
    1631          54 :         test();
    1632          54 :         IF( LT_16( *num_plocs, 3 ) && *num_plocs > 0 )
    1633             :         {
    1634           3 :             sig = L_add( sum16_32_fx( xfp, Lprot2_1 ), 1 );
    1635             : 
    1636             :             /*excluding peaks and neighboring bins*/
    1637           9 :             FOR( i = 0; i < *num_plocs; i++ )
    1638             :             {
    1639           6 :                 st_point = s_max( 0, sub( plocs[i], DELTA_CORR ) );
    1640           6 :                 end_point = s_min( sub( Lprot2_1, 1 ), add( plocs[i], DELTA_CORR ) );
    1641           6 :                 set16_fx( &xfp[st_point], 0, extract_l( L_add( L_sub( end_point, st_point ), 1 ) ) );
    1642             :             }
    1643           3 :             noise = L_add( sum16_32_fx( xfp, Lprot2_1 ), 1 );
    1644             : 
    1645           3 :             IF( LT_32( noise, Mpy_32_32( 64424509 /* 0.03 in Q31 */, sig ) ) )
    1646             :             {
    1647           0 :                 *noise_fac = 16384; /* 0.5f in Q15 */
    1648           0 :                 move16();
    1649             :             }
    1650             :             ELSE
    1651             :             {
    1652           3 :                 *noise_fac = 32767; /* 1.0f in Q15 */
    1653           3 :                 move16();
    1654             :             }
    1655             :         }
    1656             :     }
    1657          54 : }
    1658             : 
    1659           0 : static void spec_ana_fx(
    1660             :     const Word16 *prevsynth,   /* i : Input signal                                         */
    1661             :     Word16 *plocs,             /* o : The indicies of the identified peaks             Q0  */
    1662             :     Word32 *plocsi,            /* o : Interpolated positions of the identified peaks   Q16 */
    1663             :     Word16 *num_plocs,         /* o : Number of identified peaks                       Q0  */
    1664             :     Word16 *X_sav,             /* o : Stored fft spectrum                                  */
    1665             :     const Word16 output_frame, /* i : Frame length                                     Q0  */
    1666             :     const Word16 bwidth_fx,    /* i : Encoded bandwidth index                          Q0  */
    1667             :     Word16 *Q                  /* o : Q value of the fft spectrum                          */
    1668             : )
    1669             : {
    1670             :     Word16 Lprot, LprotLog2Minus1, hamm_len2, Lprot2, Lprot2_1, m, n;
    1671           0 :     const Word16 *pFftTbl = NULL;
    1672             :     Word16 xfp[L_PROT48k];
    1673             :     Word32 magSq[L_PROT48k / 2 + 1], *pMagSq;
    1674             :     Word16 *pXfp, *pXfp1, *pXsav, *pPlocs;
    1675             :     Word16 Xmax, Xmin, sel, man, expo, expoBy2;
    1676             :     Word16 sinTblOffset, rectLength, fraction, special;
    1677             :     Word32 *pPlocsi;
    1678             :     Word32 acc;
    1679             :     Word16 stop_band_start;
    1680             :     Word16 stop_band_length;
    1681             : 
    1682           0 :     LprotLog2Minus1 = 0;
    1683           0 :     hamm_len2 = 0;
    1684           0 :     move16();    // LprotLog2Minus1
    1685           0 :     move16();    // hamm_len2
    1686           0 :     Lprot = 512; /* 1536=(2*output_frame)*1024/1280; */
    1687           0 :     move16();
    1688             : 
    1689           0 :     sinTblOffset = 0;
    1690           0 :     move16();
    1691             : 
    1692           0 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    1693             :     {
    1694           0 :         Lprot = L_PROT48k; /* 1536=(2*output_frame)*1024/1280; */
    1695           0 :         move16();
    1696           0 :         hamm_len2 = L_PROT_HAMM_LEN2_48k; /* half Hamming window = 288 */
    1697           0 :         move16();
    1698             :     }
    1699           0 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    1700             :     {
    1701           0 :         Lprot = L_PROT32k; /* 1024 */
    1702           0 :         move16();
    1703           0 :         sinTblOffset = 4;
    1704           0 :         move16();
    1705           0 :         hamm_len2 = L_PROT_HAMM_LEN2_32k; /* half Hamming window = 192 */
    1706           0 :         move16();
    1707           0 :         pFftTbl = FFT_W512;  /* Table for 1024-point real input FFT */
    1708           0 :         LprotLog2Minus1 = 9; /* FFT stages for complex input FFT */
    1709           0 :         move16();
    1710             :     }
    1711             :     ELSE
    1712             :     {
    1713           0 :         Lprot = 512;
    1714           0 :         move16();
    1715           0 :         sinTblOffset = 8;
    1716           0 :         move16();
    1717           0 :         hamm_len2 = L_PROT_HAMM_LEN2_16k; /* half Hamming window = 96 */
    1718           0 :         move16();
    1719           0 :         pFftTbl = FFT_W256;  /* Table for 512-point real input FFT */
    1720           0 :         LprotLog2Minus1 = 8; /* FFT stages for complex input FFT */
    1721           0 :         move16();
    1722             :     }
    1723             : 
    1724           0 :     Lprot2 = shr( Lprot, 1 );
    1725           0 :     Lprot2_1 = add( Lprot2, 1 );
    1726           0 :     rectLength = sub( Lprot, shl( hamm_len2, 1 ) ); /* The length of the rectangular portion of the Hamming-Rectangular window. */
    1727             : 
    1728           0 :     *Q = s_max( 0, sub( Exp16Array( Lprot, prevsynth ), 1 ) );
    1729           0 :     move16();
    1730           0 :     Copy_Scale_sig( prevsynth, xfp, Lprot, *Q );
    1731             : 
    1732           0 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    1733             :     {
    1734             :         /* Apply hamming-rect window */
    1735             :         {
    1736           0 :             windowing( xfp, xfp, w_hamm_sana48k_2_fx, rectLength, hamm_len2 );
    1737             :         }
    1738             :         /* Spectrum */
    1739           0 :         fft3_fx( xfp, xfp, Lprot );
    1740             :     }
    1741             :     ELSE
    1742             :     {
    1743             :         {
    1744             :             /* Apply hamming-rect window */
    1745           0 :             windowing_ROM_optimized( xfp, xfp, sinTblOffset, rectLength, hamm_len2 );
    1746             :         }
    1747             :         /* Spectrum */
    1748           0 :         r_fft_fx_lc( pFftTbl, Lprot, Lprot2, LprotLog2Minus1, xfp, xfp, 1 );
    1749             :     }
    1750             : 
    1751             :     /* Apply zeroing of non-coded FFT spectrum */
    1752           0 :     IF( GT_16( output_frame, inner_frame_tbl[bwidth_fx] ) )
    1753             :     {
    1754           0 :         stop_band_start = shl( 128, bwidth_fx );
    1755           0 :         stop_band_length = sub( Lprot, shl( stop_band_start, 1 ) );
    1756           0 :         stop_band_start = add( stop_band_start, 1 );
    1757           0 :         set16_fx( xfp + stop_band_start, 0, stop_band_length );
    1758             :     }
    1759             : 
    1760           0 :     pXfp = xfp;
    1761           0 :     pXsav = X_sav;
    1762           0 :     FOR( m = 0; m < Lprot; m++ )
    1763             :     {
    1764           0 :         *pXsav++ = *pXfp++;
    1765           0 :         move16();
    1766             :     }
    1767             : 
    1768             :     /* Magnitude representation */
    1769           0 :     fft_spec2_fx( xfp, magSq, Lprot );
    1770             : 
    1771             :     /* Compute xfp[m] = sqrt(magSq[m]) */
    1772           0 :     pXfp = xfp;
    1773           0 :     pMagSq = magSq;
    1774           0 :     FOR( m = 0; m < Lprot2_1; m++ )
    1775             :     {
    1776           0 :         IF( *pMagSq == 0 )
    1777             :         {
    1778           0 :             *pXfp++ = extract_l( *pMagSq++ ); /* magSq[] is zero */
    1779             :         }
    1780             :         ELSE
    1781             :         {
    1782           0 :             expo = norm_l( *pMagSq );                    /* exponent */
    1783           0 :             man = extract_h( L_shl( *pMagSq++, expo ) ); /* mantissa */
    1784           0 :             man = sqrt2ndOrder( man );
    1785           0 :             expoBy2 = shr( expo, 1 );   /* Divided by 2-- square root operation. */
    1786           0 :             IF( s_and( expo, 1 ) == 0 ) /* Check even or odd. */
    1787             :             {
    1788           0 :                 man = mult_r( man, FEC_HQ_ECU_ROOT2 ); /* FEC_HQ_ECU_ROOT2 is sqrt(2) in Q14 */
    1789           0 :                 expoBy2 = sub( expoBy2, 1 );
    1790             :             }
    1791           0 :             *pXfp++ = shr_sat( man, expoBy2 );
    1792           0 :             move16(); /* Denormalize the mantissa back to Q0. */
    1793             :         }
    1794             :     }
    1795             : 
    1796             :     /* Find maximum and minimum. */
    1797           0 :     maximum_fx( xfp, Lprot2_1, &Xmax );
    1798           0 :     minimum_fx( xfp, Lprot2_1, &Xmin );
    1799             :     {
    1800           0 :         sel = mult_r( sub( Xmax, Xmin ), CMPLMNT_PFIND_SENS_FX );
    1801             :     }
    1802           0 :     peakfinder_fx( xfp, Lprot2_1, plocs, num_plocs, sel );
    1803             : 
    1804             : 
    1805             :     {
    1806             : 
    1807             :         /* Refine peaks */
    1808           0 :         pPlocsi = plocsi;
    1809           0 :         pPlocs = plocs;
    1810           0 :         n = sub( *num_plocs, 1 ); /* -1 so as to exclude the very last peak. */
    1811             :         /* Special case-- The very 1st peak if it is at 0 index position */
    1812           0 :         IF( *pPlocs == 0 ) /* Only the very 1st peak is possible the peak at 0 index position. */
    1813             :         {
    1814           0 :             fraction = imax_fx( xfp, -1 );  /* -1 signifies special left edge case. */
    1815           0 :             acc = L_deposit_h( *pPlocs++ ); /* N.B., (*pPlocs) must be zero here. */
    1816           0 :             *pPlocsi++ = L_mac( acc, fraction, 1 );
    1817           0 :             move32();        /* in Q16 */
    1818           0 :             n = sub( n, 1 ); /* This special case is taken care of-- one less to go */
    1819             :         }
    1820             :         /* All peaks except the very last peak but including the very 1st one if it has not been taken care of. */
    1821           0 :         pXfp1 = xfp - 1;
    1822           0 :         FOR( m = 0; m < n; m++ ) /* Loop through up to the last but one peak. (The last one is excluded.) */
    1823             :         {
    1824           0 :             pXfp = pXfp1 + *pPlocs;
    1825           0 :             fraction = imax_fx( pXfp, 0 ); /* in Q15 */
    1826           0 :             acc = L_deposit_h( *pPlocs++ );
    1827           0 :             *pPlocsi++ = L_mac( acc, fraction, 1 );
    1828           0 :             move32(); /* in Q16. Append the fractional part to the integral part. */
    1829             :         }
    1830           0 :         IF( n >= 0 )
    1831             :         {
    1832             :             /* Special case-- The very last peak */
    1833           0 :             pXfp = pXfp1 + *pPlocs;
    1834           0 :             IF( EQ_16( *pPlocs, Lprot2 ) ) /* Only the very last peak is possible the peak at Lprot2 index position. */
    1835             :             {
    1836           0 :                 pXfp--;      /* Special case needs extra decrement */
    1837           0 :                 special = 1; /* Signify special right edge case. */
    1838           0 :                 move16();
    1839             :             }
    1840             :             ELSE
    1841             :             {
    1842           0 :                 special = 0;
    1843           0 :                 move16();
    1844             :             }
    1845           0 :             fraction = imax_fx( pXfp, special ); /* in Q15 */
    1846           0 :             acc = L_deposit_h( *pPlocs );
    1847           0 :             *pPlocsi = L_mac( acc, fraction, 1 );
    1848           0 :             move32(); /* in Q16. Append the fractional part to the integral part. */
    1849             :         }
    1850             :     }
    1851           0 : }
    1852             : 
    1853             : /*-------------------------------------------------------------------*
    1854             :  * subst_spec_fx()
    1855             :  *
    1856             :  * Substitution spectrum calculation
    1857             :  *-------------------------------------------------------------------*/
    1858             : 
    1859         132 : static void ivas_subst_spec_fx(
    1860             :     const Word16 *plocs,           /* i   : The indices of the identified peaks                Q0  */
    1861             :     const Word32 *plocsi,          /* i   : Interpolated positions of the identified peaks     Q16 */
    1862             :     Word16 *num_plocs,             /* i/o : Number of identified peaks                         Q0  */
    1863             :     const Word16 time_offs,        /* i   : Time offset                                        Q0  */
    1864             :     Word16 *X,                     /* i/o : FFT spectrum                                           */
    1865             :     const Word16 *mag_chg,         /* i   : Magnitude modification                             Q15 */
    1866             :     const Word16 ph_dith,          /* i   : Phase dither, 2*PI is not included. (Q15, i.e., between 0.0 and 1.0) */
    1867             :     const Word16 *is_trans,        /* i   : Transient flags (either 0 or 1)                        */
    1868             :     const Word16 output_frame,     /* i   : Frame length                                       Q0  */
    1869             :     Word16 *seed,                  /* i/o : Random seed                                            */
    1870             :     const Word16 *alpha,           /* i   : Magnitude modification factors for fade to average Q15 */
    1871             :     const Word16 *beta,            /* i   : Magnitude modification factors for fade to average Q15 */
    1872             :     Word16 beta_mute,              /* i   : Factor for long-term mute                          Q15 */
    1873             :     const Word16 *Xavg,            /* i   : Frequency group averages to fade to                Q0  */
    1874             :     const Word16 element_mode,     /* i  : IVAS element mode                                  */
    1875             :     const Word16 ph_ecu_lookahead, /* i  : Phase ECU lookahead                                */
    1876             :     const Word16 noise_fac         /* i  : noise factor                                      Q15 */
    1877             : )
    1878             : {
    1879             :     Word16 Xph_short;
    1880             :     Word32 corr_phase[MAX_PLOCS], Xph;
    1881             :     Word32 *pCorrPhase;
    1882             :     Word16 cos_F, sin_F, tmp;
    1883             :     Word16 Lprot, m, i, e, im_ind, delta_corr_up, delta_corr_dn, delta_tmp;
    1884             :     Word32 tmp1;
    1885             :     Word16 j, re, im, *pReX, *pImX, lastPeak, lprotBy2Minus1, segmentLen;
    1886             :     Word16 pkLocation_1, pkLocation, pkLocation1;
    1887             :     const Word16 *pPlocs;
    1888             :     const Word32 *pPlocsi;
    1889             :     Word32 acc;
    1890             :     Word16 Lecu;
    1891             :     Word16 Lprot_inv;
    1892             :     Word16 k;
    1893             :     Word16 tmp2;
    1894             :     Word16 alpha_local;
    1895             :     Word16 beta_local;
    1896             :     Word16 expo;
    1897             :     Word16 one_peak_flag_mask;
    1898             :     Word16 mag_chg_local; /*for peak attenuation in burst */
    1899             : 
    1900         132 :     Lprot = 512;
    1901         132 :     move16();
    1902         132 :     Lprot_inv = 8192;
    1903         132 :     move16();
    1904         132 :     Lecu = shl( output_frame, 1 );
    1905             : 
    1906         132 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    1907             :     {
    1908         103 :         Lprot = L_PROT48k; /* 1536=(2*output_frame)*1024/1280; */
    1909         103 :         move16();
    1910         103 :         Lprot_inv = 2731; /* Q22 */
    1911         103 :         move16();
    1912             :     }
    1913          29 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    1914             :     {
    1915          29 :         Lprot = L_PROT32k; /* 1024 */
    1916          29 :         move16();
    1917          29 :         Lprot_inv = 4096; /* Q22 */
    1918          29 :         move16();
    1919             :     }
    1920             :     ELSE
    1921             :     {
    1922           0 :         Lprot = 512;
    1923           0 :         move16();
    1924           0 :         Lprot_inv = 8192; /* Q22 */
    1925           0 :         move16();
    1926             :     }
    1927             : 
    1928             :     /* Correction phase of the identified peaks */
    1929         132 :     IF( s_or( is_trans[0], is_trans[1] ) != 0 )
    1930             :     {
    1931           4 :         *num_plocs = 0;
    1932           4 :         move16();
    1933             :     }
    1934             :     ELSE
    1935             :     {
    1936             :         // tmp = NS2SA(output_frame*50,PH_ECU_ALDO_OLP2_NS-PH_ECU_LOOKAHEAD_NS);
    1937         128 :         tmp = NS2SA_FX2( L_mult0( output_frame, 50 ), PH_ECU_ALDO_OLP2_NS );
    1938         128 :         move16();
    1939         128 :         tmp = sub( tmp, ph_ecu_lookahead );
    1940         128 :         tmp = add( tmp, sub( Lecu, shr( sub( Lecu, Lprot ), 1 ) ) );
    1941         128 :         tmp = sub( tmp, shr( output_frame, 1 ) );
    1942         128 :         tmp1 = L_mac0( L_mult0( tmp, Lprot_inv ), time_offs, Lprot_inv ); /* Q22 */
    1943             : 
    1944         128 :         pPlocsi = plocsi;
    1945         128 :         pCorrPhase = corr_phase;
    1946        5637 :         FOR( m = 0; m < *num_plocs; m++ )
    1947             :         {
    1948        5509 :             acc = L_shl( Mpy_32_32( *pPlocsi++, tmp1 ), 9 ); /* 16+22+9-31 = 16*/
    1949        5509 :             *pCorrPhase++ = acc;                             /* in Q16. 2*PI is not included. */
    1950        5509 :             move32();
    1951             :         }
    1952             :     }
    1953         132 :     one_peak_flag_mask = 32767 /* 1.0f in Q15 */; /* all ones mask -> keep  */
    1954         132 :     move16();
    1955         132 :     IF( element_mode != EVS_MONO )
    1956             :     {
    1957         132 :         test();
    1958         132 :         if ( ( *num_plocs > 0 ) && ( sub( *num_plocs, 3 ) < 0 ) )
    1959             :         {
    1960           3 :             one_peak_flag_mask = noise_fac; /* all zeroes  mask -> zero  */
    1961           3 :             move16();
    1962             :         }
    1963         132 :         IF( *num_plocs == 0 )
    1964             :         {
    1965           4 :             X[0] = 0; /* reset DC if there are no  peaks */
    1966           4 :             move16();
    1967           4 :             X[Lprot / 2] = 0; /* also reset fs/2 if there are no peaks */
    1968           4 :             move16();
    1969             :         }
    1970             :     }
    1971         132 :     lprotBy2Minus1 = sub( shr( Lprot, 1 ), 1 );
    1972         132 :     i = 1;
    1973         132 :     move16();
    1974         132 :     k = 0;
    1975         132 :     move16();
    1976         132 :     im_ind = sub( Lprot, 1 );
    1977         132 :     move16();
    1978         132 :     pReX = X + i;
    1979         132 :     pImX = X + im_ind;
    1980         132 :     pPlocs = plocs;
    1981         132 :     pCorrPhase = corr_phase;
    1982         132 :     pkLocation = *pPlocs; /* N.B. No post-increment */
    1983         132 :     move16();
    1984         132 :     pkLocation1 = *pPlocs++;
    1985         132 :     move16();
    1986         132 :     lastPeak = sub( *num_plocs, 1 );
    1987        5641 :     FOR( m = 0; m < *num_plocs; m++ )
    1988             :     {
    1989        5509 :         delta_corr_dn = DELTA_CORR;
    1990        5509 :         move16();
    1991        5509 :         delta_corr_up = DELTA_CORR;
    1992        5509 :         move16();
    1993             : 
    1994        5509 :         pkLocation_1 = pkLocation; /* plocs[m - 1] */
    1995        5509 :         move16();
    1996        5509 :         pkLocation = pkLocation1; /* plocs[m] */
    1997        5509 :         move16();
    1998        5509 :         pkLocation1 = *pPlocs++; /* plocs[m + 1] */
    1999        5509 :         move16();
    2000        5509 :         IF( m > 0 )
    2001             :         {
    2002        5381 :             delta_tmp = shr( sub( sub( pkLocation, pkLocation_1 ), 1 ), 1 );
    2003        5381 :             if ( LT_16( delta_tmp, DELTA_CORR ) )
    2004             :             {
    2005        4626 :                 delta_corr_dn = delta_tmp;
    2006        4626 :                 move16();
    2007             :             }
    2008             :         }
    2009             : 
    2010        5509 :         IF( LT_16( m, lastPeak ) )
    2011             :         {
    2012        5381 :             delta_tmp = shr( sub( sub( pkLocation1, pkLocation ), 1 ), 1 );
    2013        5381 :             if ( LT_16( delta_tmp, DELTA_CORR ) )
    2014             :             {
    2015        4626 :                 delta_corr_up = delta_tmp;
    2016        4626 :                 move16();
    2017             :             }
    2018             :         }
    2019             : 
    2020             :         /* Input Xph */
    2021        5509 :         segmentLen = sub( sub( pkLocation, delta_corr_dn ), i );
    2022             :         /* i = add(i, segmentLen); */
    2023       14047 :         FOR( j = 0; j < segmentLen; j++ )
    2024             :         {
    2025        8538 :             *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2026             : 
    2027        8538 :             re = *pReX;
    2028        8538 :             move16();
    2029        8538 :             im = *pImX;
    2030        8538 :             move16();
    2031        8538 :             IF( element_mode == EVS_MONO )
    2032             :             {
    2033           0 :                 tmp = sub( mult_r( re, cos_F ), mult_r( im, sin_F ) );
    2034           0 :                 im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
    2035             :             }
    2036             :             ELSE
    2037             :             {
    2038        8538 :                 tmp = mult_r( one_peak_flag_mask, sub( mult_r( re, cos_F ), mult_r( im, sin_F ) ) );
    2039        8538 :                 im = mult_r( one_peak_flag_mask, add( mult_r( re, sin_F ), mult_r( im, cos_F ) ) );
    2040             :             }
    2041        8538 :             IF( LT_16( alpha[k], 32766 ) )
    2042             :             {
    2043        5180 :                 *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2044        5180 :                 move16();
    2045        5180 :                 tmp2 = mult_r( beta[k], Xavg[k] );
    2046        5180 :                 *pReX++ = add( mult_r( alpha[k], tmp ), mult_r( tmp2, cos_F ) );
    2047        5180 :                 move16();
    2048        5180 :                 *pImX-- = add( mult_r( alpha[k], im ), mult_r( tmp2, sin_F ) );
    2049        5180 :                 move16();
    2050             :             }
    2051             :             ELSE
    2052             :             {
    2053        3358 :                 *pReX++ = mult_r( mag_chg[k], tmp );
    2054        3358 :                 move16();
    2055        3358 :                 *pImX-- = mult_r( mag_chg[k], im );
    2056        3358 :                 move16();
    2057             :             }
    2058        8538 :             i = add( i, 1 );
    2059        8538 :             if ( GE_16( i, ivas_gwlpr[k + 1] ) )
    2060             :             {
    2061          70 :                 k = add( k, 1 );
    2062             :             }
    2063             :         }
    2064             : 
    2065        5509 :         e = add( pkLocation, delta_corr_up );
    2066        5509 :         if ( GT_16( e, lprotBy2Minus1 ) )
    2067             :         {
    2068           0 :             e = lprotBy2Minus1;
    2069           0 :             move16();
    2070             :         }
    2071             : 
    2072        5509 :         Xph = *pCorrPhase;
    2073        5509 :         move32();
    2074        5509 :         Xph_short = s_and( extract_l( L_shr( Xph, 16 - 10 ) ), 0x3ff ); /* 10 bits precision after radix point */
    2075        5509 :         IF( GE_16( Xph_short, 512 ) )
    2076             :         {
    2077        2761 :             sin_F = negate( sincos_t_ext_fx[Xph_short - 512] );
    2078        2761 :             IF( LT_16( Xph_short, 768 ) )
    2079             :             {
    2080        1405 :                 cos_F = negate( sincos_t_ext_fx[Xph_short - ( 512 - 256 )] );
    2081             :             }
    2082             :             ELSE
    2083             :             {
    2084        1356 :                 cos_F = sincos_t_ext_fx[-Xph_short + ( 1024 + 256 )];
    2085        1356 :                 move16();
    2086             :             }
    2087             :         }
    2088             :         ELSE
    2089             :         {
    2090        2748 :             sin_F = sincos_t_ext_fx[Xph_short];
    2091        2748 :             move16();
    2092        2748 :             IF( LT_16( Xph_short, 256 ) )
    2093             :             {
    2094        1420 :                 cos_F = sincos_t_ext_fx[Xph_short + 256];
    2095        1420 :                 move16();
    2096             :             }
    2097             :             ELSE
    2098             :             {
    2099        1328 :                 cos_F = negate( sincos_t_ext_fx[-Xph_short + ( 256 + 512 )] );
    2100             :             }
    2101             :         }
    2102             : 
    2103        5509 :         segmentLen = add( sub( e, i ), 1 );
    2104             :         /* i = add(i, segmentLen); */
    2105       40815 :         FOR( j = 0; j < segmentLen; j++ )
    2106             :         {
    2107       35306 :             mag_chg_local = mag_chg[k];
    2108       35306 :             move16();
    2109       35306 :             IF( ph_dith != 0 )
    2110             :             {
    2111       25812 :                 Xph = *pCorrPhase; /* in Q16. 2*PI is not included. */
    2112       25812 :                 move32();
    2113       25812 :                 Random( seed );                 /* in Q0 */
    2114       25812 :                 acc = L_mult( *seed, ph_dith ); /* N.B. ph_dith[i] is in Q15, i.e., in between 0 and 1.0 (2*PI not included) */
    2115       25812 :                 acc = L_shr( acc, PHASE_DITH_SCALE_SHIFT );
    2116       25812 :                 Xph = L_add( Xph, acc ); /* in Q16. */
    2117             : 
    2118       25812 :                 IF( ph_dith > 0 ) /* up to 6 dB additional att of peaks in non_transient longer bursts, (when  peak phase is randomized ) */
    2119             :                 {
    2120             :                     /* mag_chg_local *= 0.5 + (1.0 - ph_dith[i])/2 where 0.5~= sqrt((float)pow(10.0,-6/10.0)) and ph_dith=0..1.0--> scale=1.0 ...5 */
    2121       25812 :                     mag_chg_local = mult_r( mag_chg_local, sub( 32767, shr( ph_dith, 1 ) ) );
    2122             :                 }
    2123       25812 :                 Xph_short = s_and( extract_l( L_shr( Xph, 16 - 10 ) ), 0x3ff );
    2124       25812 :                 IF( GE_16( Xph_short, 512 ) )
    2125             :                 {
    2126       12722 :                     sin_F = negate( sincos_t_ext_fx[Xph_short - 512] );
    2127       12722 :                     IF( LT_16( Xph_short, 768 ) )
    2128             :                     {
    2129        6328 :                         cos_F = negate( sincos_t_ext_fx[Xph_short - ( 512 - 256 )] );
    2130             :                     }
    2131             :                     ELSE
    2132             :                     {
    2133        6394 :                         cos_F = sincos_t_ext_fx[-Xph_short + ( 1024 + 256 )];
    2134        6394 :                         move16();
    2135             :                     }
    2136             :                 }
    2137             :                 ELSE
    2138             :                 {
    2139       13090 :                     sin_F = sincos_t_ext_fx[Xph_short];
    2140       13090 :                     move16();
    2141       13090 :                     IF( LT_16( Xph_short, 256 ) )
    2142             :                     {
    2143        6521 :                         cos_F = sincos_t_ext_fx[Xph_short + 256];
    2144        6521 :                         move16();
    2145             :                     }
    2146             :                     ELSE
    2147             :                     {
    2148        6569 :                         cos_F = negate( sincos_t_ext_fx[-Xph_short + ( 256 + 512 )] );
    2149             :                     }
    2150             :                 }
    2151             :             }
    2152             : 
    2153       35306 :             re = *pReX;
    2154       35306 :             move16();
    2155       35306 :             im = *pImX;
    2156       35306 :             move16();
    2157       35306 :             tmp = sub_sat( mult_r( re, cos_F ), mult_r( im, sin_F ) );
    2158       35306 :             im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
    2159       35306 :             IF( LT_16( alpha[k], 32766 ) )
    2160             :             {
    2161       26529 :                 alpha_local = mag_chg_local;
    2162       26529 :                 move16();
    2163             : 
    2164       26529 :                 acc = L_sub( 1073741824L, L_mult0( alpha_local, alpha_local ) );
    2165       26529 :                 acc = Sqrt_l( acc, &expo );
    2166       26529 :                 expo = add( 30, add( 31, expo ) );
    2167       26529 :                 if ( EQ_16( s_and( expo, 1 ), 1 ) )
    2168             :                 {
    2169       26529 :                     acc = Mult_32_16( acc, 23170 ); /* 1/sqrt(2) in Q15 */
    2170             :                 }
    2171       26529 :                 expo = shr( expo, 1 );
    2172       26529 :                 beta_local = mult_r( beta_mute, round_fx( L_shl( acc, sub( 31, expo ) ) ) );
    2173             : 
    2174       26529 :                 IF( GE_16( k, LGW32K - 1 ) )
    2175             :                 {
    2176       10138 :                     beta_local = mult_r( beta_local, 3277 ); /* 0.1 in Q15 */
    2177             :                 }
    2178       16391 :                 ELSE IF( GE_16( k, LGW16K - 1 ) )
    2179             :                 {
    2180        8325 :                     beta_local = mult_r( beta_local, 16384 ); /* 0.5 in Q15 */
    2181             :                 }
    2182             : 
    2183       26529 :                 *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2184       26529 :                 move16();
    2185       26529 :                 tmp2 = mult_r( beta_local, Xavg[k] );
    2186       26529 :                 *pReX++ = add( mult_r( alpha_local, tmp ), mult_r( tmp2, cos_F ) );
    2187       26529 :                 move16();
    2188       26529 :                 *pImX-- = add( mult_r( alpha_local, im ), mult_r( tmp2, sin_F ) );
    2189       26529 :                 move16();
    2190             :             }
    2191             :             ELSE
    2192             :             {
    2193        8777 :                 *pReX++ = mult_r( mag_chg_local, tmp );
    2194        8777 :                 move16();
    2195        8777 :                 *pImX-- = mult_r( mag_chg_local, im );
    2196        8777 :                 move16();
    2197             :             }
    2198             : 
    2199       35306 :             i = add( i, 1 );
    2200       35306 :             if ( GE_16( i, ivas_gwlpr[k + 1] ) )
    2201             :             {
    2202         637 :                 k = add( k, 1 );
    2203             :             }
    2204             :         }
    2205        5509 :         pCorrPhase++;
    2206             :     }
    2207             : 
    2208         132 :     segmentLen = sub( shr( Lprot, 1 ), i );
    2209       50108 :     FOR( j = 0; j < segmentLen; j++ )
    2210             :     {
    2211       49976 :         *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2212       49976 :         move16();
    2213             : 
    2214       49976 :         re = *pReX;
    2215       49976 :         move16();
    2216       49976 :         im = *pImX;
    2217       49976 :         move16();
    2218             : 
    2219             : 
    2220       49976 :         IF( element_mode == EVS_MONO )
    2221             :         {
    2222           0 :             tmp = sub( mult_r( re, cos_F ), mult_r( im, sin_F ) );
    2223           0 :             im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
    2224             :         }
    2225             :         ELSE
    2226             :         {
    2227       49976 :             tmp = mult_r( one_peak_flag_mask, sub( mult_r( re, cos_F ), mult_r( im, sin_F ) ) );
    2228       49976 :             im = mult_r( one_peak_flag_mask, add( mult_r( re, sin_F ), mult_r( im, cos_F ) ) );
    2229             :         }
    2230       49976 :         IF( LT_16( alpha[k], 32766 ) )
    2231             :         {
    2232       25049 :             *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2233       25049 :             move16();
    2234       25049 :             tmp2 = mult_r( beta[k], Xavg[k] );
    2235       25049 :             *pReX++ = add( mult_r( alpha[k], tmp ), mult_r( tmp2, cos_F ) );
    2236       25049 :             move16();
    2237       25049 :             *pImX-- = add( mult_r( alpha[k], im ), mult_r( tmp2, sin_F ) );
    2238       25049 :             move16();
    2239             :         }
    2240             :         ELSE
    2241             :         {
    2242       24927 :             *pReX++ = mult_r( mag_chg[k], tmp );
    2243       24927 :             move16();
    2244       24927 :             *pImX-- = mult_r( mag_chg[k], im );
    2245       24927 :             move16();
    2246             :         }
    2247             : 
    2248       49976 :         i = add( i, 1 );
    2249       49976 :         if ( GE_16( i, ivas_gwlpr[k + 1] ) )
    2250             :         {
    2251         320 :             k = add( k, 1 );
    2252             :         }
    2253             :     }
    2254         132 : }
    2255             : 
    2256           0 : static void subst_spec_fx(
    2257             :     const Word16 *plocs,       /* i   : The indices of the identified peaks                Q0  */
    2258             :     const Word32 *plocsi,      /* i   : Interpolated positions of the identified peaks     Q16 */
    2259             :     Word16 *num_plocs,         /* i/o : Number of identified peaks                         Q0  */
    2260             :     const Word16 time_offs,    /* i   : Time offset                                        Q0  */
    2261             :     Word16 *X,                 /* i/o : FFT spectrum                                           */
    2262             :     const Word16 *mag_chg,     /* i   : Magnitude modification                             Q15 */
    2263             :     const Word16 ph_dith,      /* i   : Phase dither, 2*PI is not included. (Q15, i.e., between 0.0 and 1.0) */
    2264             :     const Word16 *is_trans,    /* i   : Transient flags (either 0 or 1)                        */
    2265             :     const Word16 output_frame, /* i   : Frame length                                       Q0  */
    2266             :     Word16 *seed,              /* i/o : Random seed                                            */
    2267             :     const Word16 *alpha,       /* i   : Magnitude modification factors for fade to average Q15 */
    2268             :     const Word16 *beta,        /* i   : Magnitude modification factors for fade to average Q15 */
    2269             :     Word16 beta_mute,          /* i   : Factor for long-term mute                          Q15 */
    2270             :     const Word16 *Xavg         /* i   : Frequency group averages to fade to                Q0  */
    2271             : )
    2272             : {
    2273             :     Word16 Xph_short;
    2274             :     Word32 corr_phase[MAX_PLOCS], Xph;
    2275             :     Word32 *pCorrPhase;
    2276             :     Word16 cos_F, sin_F, tmp;
    2277             :     Word16 Lprot, m, i, e, im_ind, delta_corr_up, delta_corr_dn, delta_tmp;
    2278             :     UWord16 lsb;
    2279             :     Word16 j, re, im, *pReX, *pImX, lastPeak, lprotBy2Minus1, segmentLen;
    2280             :     Word16 pkLocation_1, pkLocation, pkLocation1;
    2281             :     const Word16 *pPlocs;
    2282             :     const Word32 *pPlocsi;
    2283             :     Word32 acc;
    2284             :     Word16 Lecu;
    2285             :     Word16 Lprot_inv;
    2286             :     Word16 k;
    2287             :     Word16 tmp2;
    2288             :     Word16 alpha_local;
    2289             :     Word16 beta_local;
    2290             :     Word16 expo;
    2291             :     Word16 mag_chg_local; /*for peak attenuation in burst */
    2292             : 
    2293           0 :     Lprot = 512;
    2294           0 :     move16();
    2295           0 :     Lprot_inv = 8192;
    2296           0 :     move16();
    2297           0 :     Lecu = shl( output_frame, 1 );
    2298             : 
    2299           0 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    2300             :     {
    2301           0 :         Lprot = L_PROT48k; /* 1536=(2*output_frame)*1024/1280; */
    2302           0 :         move16();
    2303           0 :         Lprot_inv = 2731; /* Q22 */
    2304           0 :         move16();
    2305             :     }
    2306           0 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    2307             :     {
    2308           0 :         Lprot = L_PROT32k; /* 1024 */
    2309           0 :         move16();
    2310           0 :         Lprot_inv = 4096; /* Q22 */
    2311           0 :         move16();
    2312             :     }
    2313             :     ELSE
    2314             :     {
    2315           0 :         Lprot = 512;
    2316           0 :         move16();
    2317           0 :         Lprot_inv = 8192; /* Q22 */
    2318           0 :         move16();
    2319             :     }
    2320             : 
    2321             :     /* Correction phase of the identified peaks */
    2322           0 :     IF( s_or( is_trans[0], is_trans[1] ) != 0 )
    2323             :     {
    2324           0 :         *num_plocs = 0;
    2325           0 :         move16();
    2326             :     }
    2327             :     ELSE
    2328             :     {
    2329           0 :         tmp = NS2SA_FX2( L_mult0( output_frame, 50 ), PH_ECU_ALDO_OLP2_NS - PH_ECU_LOOKAHEAD_NS );
    2330           0 :         move16();
    2331           0 :         tmp = add( tmp, sub( Lecu, shr( sub( Lecu, Lprot ), 1 ) ) );
    2332           0 :         tmp = sub( tmp, shr( output_frame, 1 ) );
    2333             : #ifdef FIX_1179_USAN_PHASEECU
    2334           0 :         tmp = add_sat( tmp, time_offs );
    2335             : #else
    2336             :         tmp = add( tmp, time_offs );
    2337             : #endif
    2338           0 :         tmp = round_fx( L_shl( L_mult0( tmp, Lprot_inv ), 4 ) ); /* 0+22+4-16=10 */
    2339             : 
    2340           0 :         pPlocsi = plocsi;
    2341           0 :         pCorrPhase = corr_phase;
    2342           0 :         FOR( m = 0; m < *num_plocs; m++ )
    2343             :         {
    2344           0 :             Mpy_32_16_ss( *pPlocsi++, tmp, &acc, &lsb ); /* plocsi[] in Q16, tmp in Q10 and tmp does not include 2*PI. */
    2345           0 :             acc = L_add( L_shl( acc, 5 ), lshr( lsb, 11 ) );
    2346           0 :             *pCorrPhase++ = acc; /* in Q16. 2*PI is not included. */
    2347           0 :             move32();
    2348             :         }
    2349             :     }
    2350           0 :     lprotBy2Minus1 = sub( shr( Lprot, 1 ), 1 );
    2351           0 :     i = 1;
    2352           0 :     move16();
    2353           0 :     k = 0;
    2354           0 :     move16();
    2355           0 :     im_ind = sub( Lprot, 1 );
    2356           0 :     move16();
    2357           0 :     pReX = X + i;
    2358           0 :     pImX = X + im_ind;
    2359           0 :     pPlocs = plocs;
    2360           0 :     pCorrPhase = corr_phase;
    2361           0 :     pkLocation = *pPlocs; /* N.B. No post-increment */
    2362           0 :     move16();
    2363           0 :     pkLocation1 = *pPlocs++;
    2364           0 :     move16();
    2365           0 :     lastPeak = sub( *num_plocs, 1 );
    2366           0 :     FOR( m = 0; m < *num_plocs; m++ )
    2367             :     {
    2368           0 :         delta_corr_dn = DELTA_CORR;
    2369           0 :         move16();
    2370           0 :         delta_corr_up = DELTA_CORR;
    2371           0 :         move16();
    2372             : 
    2373           0 :         pkLocation_1 = pkLocation; /* plocs[m - 1] */
    2374           0 :         move16();
    2375           0 :         pkLocation = pkLocation1; /* plocs[m] */
    2376           0 :         move16();
    2377           0 :         pkLocation1 = *pPlocs++; /* plocs[m + 1] */
    2378           0 :         move16();
    2379           0 :         IF( m > 0 )
    2380             :         {
    2381           0 :             delta_tmp = shr( sub( sub( pkLocation, pkLocation_1 ), 1 ), 1 );
    2382           0 :             if ( LT_16( delta_tmp, DELTA_CORR ) )
    2383             :             {
    2384           0 :                 delta_corr_dn = delta_tmp;
    2385           0 :                 move16();
    2386             :             }
    2387             :         }
    2388             : 
    2389           0 :         IF( LT_16( m, lastPeak ) )
    2390             :         {
    2391           0 :             delta_tmp = shr( sub( sub( pkLocation1, pkLocation ), 1 ), 1 );
    2392           0 :             if ( LT_16( delta_tmp, DELTA_CORR ) )
    2393             :             {
    2394           0 :                 delta_corr_up = delta_tmp;
    2395           0 :                 move16();
    2396             :             }
    2397             :         }
    2398             : 
    2399             :         /* Input Xph */
    2400           0 :         segmentLen = sub( sub( pkLocation, delta_corr_dn ), i );
    2401             :         /* i = add(i, segmentLen); */
    2402           0 :         FOR( j = 0; j < segmentLen; j++ )
    2403             :         {
    2404           0 :             *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2405             : 
    2406           0 :             re = *pReX;
    2407           0 :             move16();
    2408           0 :             im = *pImX;
    2409           0 :             move16();
    2410             :             {
    2411           0 :                 tmp = sub( mult_r( re, cos_F ), mult_r( im, sin_F ) );
    2412           0 :                 im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
    2413             :             }
    2414           0 :             IF( LT_16( alpha[k], 32766 ) )
    2415             :             {
    2416           0 :                 *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2417           0 :                 move16();
    2418           0 :                 tmp2 = mult_r( beta[k], Xavg[k] );
    2419           0 :                 *pReX++ = add( mult_r( alpha[k], tmp ), mult_r( tmp2, cos_F ) );
    2420           0 :                 move16();
    2421           0 :                 *pImX-- = add( mult_r( alpha[k], im ), mult_r( tmp2, sin_F ) );
    2422           0 :                 move16();
    2423             :             }
    2424             :             ELSE
    2425             :             {
    2426           0 :                 *pReX++ = mult_r( mag_chg[k], tmp );
    2427           0 :                 move16();
    2428           0 :                 *pImX-- = mult_r( mag_chg[k], im );
    2429           0 :                 move16();
    2430             :             }
    2431           0 :             i = add( i, 1 );
    2432           0 :             if ( GE_16( i, ivas_gwlpr[k + 1] ) )
    2433             :             {
    2434           0 :                 k = add( k, 1 );
    2435             :             }
    2436             :         }
    2437             : 
    2438           0 :         e = add( pkLocation, delta_corr_up );
    2439           0 :         if ( GT_16( e, lprotBy2Minus1 ) )
    2440             :         {
    2441           0 :             e = lprotBy2Minus1;
    2442           0 :             move16();
    2443             :         }
    2444             : 
    2445           0 :         Xph = *pCorrPhase;
    2446           0 :         move32();
    2447           0 :         Xph_short = s_and( extract_l( L_shr( Xph, 16 - 10 ) ), 0x3ff ); /* 10 bits precision after radix point */
    2448           0 :         IF( GE_16( Xph_short, 512 ) )
    2449             :         {
    2450           0 :             sin_F = negate( sincos_t_ext_fx[Xph_short - 512] );
    2451           0 :             IF( LT_16( Xph_short, 768 ) )
    2452             :             {
    2453           0 :                 cos_F = negate( sincos_t_ext_fx[Xph_short - ( 512 - 256 )] );
    2454             :             }
    2455             :             ELSE
    2456             :             {
    2457           0 :                 cos_F = sincos_t_ext_fx[-Xph_short + ( 1024 + 256 )];
    2458           0 :                 move16();
    2459             :             }
    2460             :         }
    2461             :         ELSE
    2462             :         {
    2463           0 :             sin_F = sincos_t_ext_fx[Xph_short];
    2464           0 :             move16();
    2465           0 :             IF( LT_16( Xph_short, 256 ) )
    2466             :             {
    2467           0 :                 cos_F = sincos_t_ext_fx[Xph_short + 256];
    2468           0 :                 move16();
    2469             :             }
    2470             :             ELSE
    2471             :             {
    2472           0 :                 cos_F = negate( sincos_t_ext_fx[-Xph_short + ( 256 + 512 )] );
    2473             :             }
    2474             :         }
    2475             : 
    2476           0 :         segmentLen = add( sub( e, i ), 1 );
    2477             :         /* i = add(i, segmentLen); */
    2478           0 :         FOR( j = 0; j < segmentLen; j++ )
    2479             :         {
    2480           0 :             mag_chg_local = mag_chg[k];
    2481           0 :             move16();
    2482           0 :             IF( ph_dith != 0 )
    2483             :             {
    2484           0 :                 Xph = *pCorrPhase; /* in Q16. 2*PI is not included. */
    2485           0 :                 move32();
    2486           0 :                 Random( seed );                 /* in Q0 */
    2487           0 :                 acc = L_mult( *seed, ph_dith ); /* N.B. ph_dith[i] is in Q15, i.e., in between 0 and 1.0 (2*PI not included) */
    2488           0 :                 acc = L_shr( acc, PHASE_DITH_SCALE_SHIFT );
    2489           0 :                 Xph = L_add( Xph, acc ); /* in Q16. */
    2490             : 
    2491           0 :                 IF( ph_dith > 0 ) /* up to 6 dB additional att of peaks in non_transient longer bursts, (when  peak phase is randomized ) */
    2492             :                 {
    2493             :                     /* mag_chg_local *= 0.5 + (1.0 - ph_dith[i])/2 where 0.5~= sqrt((float)pow(10.0,-6/10.0)) and ph_dith=0..1.0--> scale=1.0 ...5 */
    2494           0 :                     mag_chg_local = mult_r( mag_chg_local, sub( 32767, shr( ph_dith, 1 ) ) );
    2495             :                 }
    2496           0 :                 Xph_short = s_and( extract_l( L_shr( Xph, 16 - 10 ) ), 0x3ff );
    2497           0 :                 IF( GE_16( Xph_short, 512 ) )
    2498             :                 {
    2499           0 :                     sin_F = negate( sincos_t_ext_fx[Xph_short - 512] );
    2500           0 :                     IF( LT_16( Xph_short, 768 ) )
    2501             :                     {
    2502           0 :                         cos_F = negate( sincos_t_ext_fx[Xph_short - ( 512 - 256 )] );
    2503             :                     }
    2504             :                     ELSE
    2505             :                     {
    2506           0 :                         cos_F = sincos_t_ext_fx[-Xph_short + ( 1024 + 256 )];
    2507           0 :                         move16();
    2508             :                     }
    2509             :                 }
    2510             :                 ELSE
    2511             :                 {
    2512           0 :                     sin_F = sincos_t_ext_fx[Xph_short];
    2513           0 :                     move16();
    2514           0 :                     IF( LT_16( Xph_short, 256 ) )
    2515             :                     {
    2516           0 :                         cos_F = sincos_t_ext_fx[Xph_short + 256];
    2517           0 :                         move16();
    2518             :                     }
    2519             :                     ELSE
    2520             :                     {
    2521           0 :                         cos_F = negate( sincos_t_ext_fx[-Xph_short + ( 256 + 512 )] );
    2522             :                     }
    2523             :                 }
    2524             :             }
    2525             : 
    2526           0 :             re = *pReX;
    2527           0 :             move16();
    2528           0 :             im = *pImX;
    2529           0 :             move16();
    2530             :             {
    2531           0 :                 tmp = sub_sat( mult_r( re, cos_F ), mult_r( im, sin_F ) );
    2532           0 :                 im = add_sat( mult_r( re, sin_F ), mult_r( im, cos_F ) );
    2533             :             }
    2534           0 :             IF( LT_16( alpha[k], 32766 ) )
    2535             :             {
    2536           0 :                 alpha_local = mag_chg_local;
    2537           0 :                 move16();
    2538             : 
    2539           0 :                 acc = L_sub( 1073741824L, L_mult0( alpha_local, alpha_local ) );
    2540           0 :                 acc = Sqrt_l( acc, &expo );
    2541           0 :                 expo = add( 30, add( 31, expo ) );
    2542           0 :                 if ( EQ_16( s_and( expo, 1 ), 1 ) )
    2543             :                 {
    2544           0 :                     acc = Mult_32_16( acc, 23170 ); /* 1/sqrt(2) in Q15 */
    2545             :                 }
    2546           0 :                 expo = shr( expo, 1 );
    2547           0 :                 beta_local = mult_r( beta_mute, round_fx( L_shl( acc, sub( 31, expo ) ) ) );
    2548             : 
    2549           0 :                 IF( GE_16( k, LGW32K - 1 ) )
    2550             :                 {
    2551           0 :                     beta_local = mult_r( beta_local, 3277 ); /* 0.1 in Q15 */
    2552             :                 }
    2553           0 :                 ELSE IF( GE_16( k, LGW16K - 1 ) )
    2554             :                 {
    2555           0 :                     beta_local = mult_r( beta_local, 16384 ); /* 0.5 in Q15 */
    2556             :                 }
    2557             : 
    2558           0 :                 *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2559           0 :                 move16();
    2560           0 :                 tmp2 = mult_r( beta_local, Xavg[k] );
    2561           0 :                 *pReX++ = add( mult_r( alpha_local, tmp ), mult_r( tmp2, cos_F ) );
    2562           0 :                 move16();
    2563           0 :                 *pImX-- = add( mult_r( alpha_local, im ), mult_r( tmp2, sin_F ) );
    2564           0 :                 move16();
    2565             :             }
    2566             :             ELSE
    2567             :             {
    2568           0 :                 *pReX++ = mult_r( mag_chg_local, tmp );
    2569           0 :                 move16();
    2570           0 :                 *pImX-- = mult_r( mag_chg_local, im );
    2571           0 :                 move16();
    2572             :             }
    2573             : 
    2574           0 :             i = add( i, 1 );
    2575           0 :             if ( GE_16( i, ivas_gwlpr[k + 1] ) )
    2576             :             {
    2577           0 :                 k = add( k, 1 );
    2578             :             }
    2579             :         }
    2580           0 :         pCorrPhase++;
    2581             :     }
    2582             : 
    2583           0 :     segmentLen = sub( shr( Lprot, 1 ), i );
    2584           0 :     FOR( j = 0; j < segmentLen; j++ )
    2585             :     {
    2586           0 :         *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2587           0 :         move16();
    2588             : 
    2589           0 :         re = *pReX;
    2590           0 :         move16();
    2591           0 :         im = *pImX;
    2592           0 :         move16();
    2593           0 :         tmp = sub( mult_r( re, cos_F ), mult_r( im, sin_F ) );
    2594           0 :         im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
    2595           0 :         IF( LT_16( alpha[k], 32766 ) )
    2596             :         {
    2597           0 :             *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
    2598           0 :             move16();
    2599           0 :             tmp2 = mult_r( beta[k], Xavg[k] );
    2600           0 :             *pReX++ = add( mult_r( alpha[k], tmp ), mult_r( tmp2, cos_F ) );
    2601           0 :             move16();
    2602           0 :             *pImX-- = add( mult_r( alpha[k], im ), mult_r( tmp2, sin_F ) );
    2603           0 :             move16();
    2604             :         }
    2605             :         ELSE
    2606             :         {
    2607           0 :             *pReX++ = mult_r( mag_chg[k], tmp );
    2608           0 :             move16();
    2609           0 :             *pImX-- = mult_r( mag_chg[k], im );
    2610           0 :             move16();
    2611             :         }
    2612             : 
    2613           0 :         i = add( i, 1 );
    2614           0 :         if ( GE_16( i, ivas_gwlpr[k + 1] ) )
    2615             :         {
    2616           0 :             k = add( k, 1 );
    2617             :         }
    2618             :     }
    2619           0 : }
    2620             : 
    2621             : /*--------------------------------------------------------------------------
    2622             :  *  rec_wtda()
    2623             :  *
    2624             :  *  Windowing and TDA of reconstructed frame
    2625             :  *--------------------------------------------------------------------------*/
    2626             : 
    2627         132 : static void ivas_rec_wtda_fx(
    2628             :     Word16 *X,                 /* i  : FFT spectrum                          */
    2629             :     Word32 *ecu_rec,           /* o  : Reconstructed frame in tda domain     */
    2630             :     const Word16 output_frame, /* i  : Frame length                          */
    2631             :     const Word16 Lprot,        /* i  : Prototype frame length                */
    2632             :     const Word16 old_dec[270], /* i  : end of last decoded for OLA before tda and itda */
    2633             :     const Word16 element_mode, /* i  : IVAS element mode                   */
    2634             :     const Word16 *num_p,       /* i  : Number of peaks Q0                     */
    2635             :     const Word16 *plocs        /* i  : Peak locations Q0                      */
    2636             : )
    2637             : {
    2638             :     Word16 timesh;
    2639             :     Word16 Qin;
    2640             :     Word16 xf_len;
    2641             :     Word16 i, idx;
    2642             :     Word16 *p_ecu;
    2643             :     Word16 g;
    2644             :     Word16 tbl_delta;
    2645             :     Word16 xsubst_[2 * L_FRAME48k];
    2646             :     const Word16 *w_hamm;
    2647             :     Word16 *pX_start, *pX_end;
    2648             :     Word16 tmp, tmp_e;
    2649             :     Word16 hamm_len2;
    2650             :     Word16 *pNew;
    2651             :     const Word16 *pOldW, *pNewW;
    2652             :     Word16 xfwin[NS2SA( L_FRAME48k * FRAMES_PER_SEC, N_ZERO_MDCT_NS - ( 2 * FRAME_SIZE_NS - L_PROT_NS ) / 2 )];
    2653             :     const Word16 *pOld;
    2654             :     Word16 copy_len;
    2655             :     Word16 ola_len;
    2656             : 
    2657         132 :     copy_len = NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), ( 2 * FRAME_SIZE_NS - L_PROT_NS ) / 2 ); /* prototype fill on each side of xsubst to fill MDCT Frame */
    2658         132 :     move16();
    2659         132 :     ola_len = NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS - ( 2 * FRAME_SIZE_NS - L_PROT_NS ) / 2 ); /* remaining lengt of LA_ZEROS to overlap add decoded with xsubst */
    2660         132 :     move16();
    2661             : 
    2662         132 :     xf_len = 26;
    2663         132 :     move16();
    2664         132 :     tbl_delta = 10082; /* Q12 */
    2665         132 :     move16();
    2666         132 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    2667             :     {
    2668         103 :         w_hamm = w_hamm_sana48k_2_fx;
    2669         103 :         hamm_len2 = L_PROT_HAMM_LEN2_48k;
    2670         103 :         move16();
    2671         103 :         xf_len = 78;
    2672         103 :         move16();
    2673         103 :         tbl_delta = 3361; /* Q12 */
    2674         103 :         move16();
    2675             :     }
    2676          29 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    2677             :     {
    2678          29 :         w_hamm = w_hamm_sana32k_2_fx;
    2679          29 :         hamm_len2 = L_PROT_HAMM_LEN2_32k;
    2680          29 :         move16();
    2681          29 :         xf_len = 52;
    2682          29 :         move16();
    2683          29 :         tbl_delta = 5041; /* Q12 */
    2684          29 :         move16();
    2685             :     }
    2686             :     ELSE
    2687             :     {
    2688           0 :         w_hamm = w_hamm_sana16k_2_fx;
    2689           0 :         hamm_len2 = L_PROT_HAMM_LEN2_16k;
    2690           0 :         move16();
    2691             :     }
    2692             : 
    2693         132 :     test();
    2694         132 :     test();
    2695         132 :     IF( element_mode != EVS_MONO && *num_p > 0 && GT_16( plocs[0], 3 ) )
    2696             :     {
    2697             :         /* Perform inverse windowing of hammrect */
    2698          26 :         pX_start = X;
    2699          26 :         pX_end = X + sub( Lprot, 1 );
    2700        6074 :         FOR( i = 0; i < hamm_len2; i++ )
    2701             :         {
    2702        6048 :             tmp_e = 0;
    2703        6048 :             tmp = BASOP_Util_Divide1616_Scale( ONE_IN_Q14, *w_hamm, &tmp_e );
    2704        6048 :             tmp = shl( tmp, 1 );
    2705        6048 :             tmp = shr( tmp, sub( 4, tmp_e ) );                  // Q11
    2706        6048 :             *pX_start = shl_sat( mult_r( *pX_start, tmp ), 4 ); // Qin
    2707        6048 :             move16();
    2708        6048 :             *pX_end = shl_sat( mult_r( *pX_end, tmp ), 4 ); // Qin
    2709        6048 :             move16();
    2710        6048 :             pX_start++;
    2711        6048 :             pX_end--;
    2712        6048 :             w_hamm++;
    2713             :         }
    2714             :     }
    2715             : 
    2716             :     /* extract reconstructed frame with aldo window */
    2717         132 :     timesh = sub( NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS ), shr( sub( shl( output_frame, 1 ), Lprot ), 1 ) );
    2718             : 
    2719         132 :     set16_fx( xsubst_, 0, add( sub( shl( output_frame, 1 ), Lprot ), timesh ) );
    2720         132 :     Copy( X, xsubst_ + add( sub( shl( output_frame, 1 ), Lprot ), timesh ), sub( Lprot, timesh ) );
    2721             : 
    2722             :     /* Copy and OLA look ahead zero part of MDCT window from decoded signal  */
    2723         132 :     IF( element_mode != EVS_MONO )
    2724             :     {
    2725         132 :         Copy( old_dec, xsubst_ + NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS ), copy_len ); /* also need to scale to Q0 ?? */
    2726         132 :         pOld = old_dec + copy_len;
    2727         132 :         pNew = xsubst_ + add( copy_len, NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS ) );
    2728         132 :         tmp = div_s( 1, shl( ola_len, 1 ) );                    // Q15
    2729         132 :         tmp = round_fx( L_shl( L_mult( tmp, EVS_PI_FX ), 2 ) ); // Q15
    2730         132 :         sinq_fx( tmp, 0, ola_len, xfwin );
    2731         132 :         v_mult16_fixed( xfwin, xfwin, xfwin, ola_len ); /* xfwin = sin^2 of 0..pi/4 */
    2732         132 :         pOldW = xfwin + sub( ola_len, 1 );
    2733         132 :         pNewW = xfwin;
    2734        9674 :         FOR( i = 0; i < ola_len; i++ )
    2735             :         {
    2736        9542 :             *pNew = add( mult_r( *pOld, *pOldW ), mult_r( *pNew, *pNewW ) );
    2737        9542 :             move16();
    2738        9542 :             pOld += 1;
    2739        9542 :             pNew += 1;
    2740        9542 :             pOldW -= 1;
    2741        9542 :             pNewW += 1;
    2742             :         }
    2743             :     }
    2744             :     ELSE
    2745             :     {
    2746             :         /* Smoothen onset of ECU frame */
    2747           0 :         p_ecu = xsubst_ + add( sub( shl( output_frame, 1 ), Lprot ), timesh );
    2748           0 :         FOR( i = 0; i < xf_len; ( i++, p_ecu++ ) )
    2749             :         {
    2750           0 :             idx = extract_l( L_shr( L_mult0( i, tbl_delta ), 12 ) ); // Q0
    2751           0 :             g = sincos_t_fx[idx];                                    // Q15
    2752           0 :             move16();
    2753           0 :             g = mult( g, g ); // Q15
    2754           0 :             *p_ecu = mult( g, ( *p_ecu ) );
    2755           0 :             move16();
    2756           0 :             p_ecu++;
    2757             :         }
    2758             :     }
    2759             : 
    2760             :     /* Apply TDA and windowing to ECU frame */
    2761         132 :     Qin = 0;
    2762         132 :     move16();
    2763         132 :     wtda_fx( xsubst_ + output_frame, &Qin, ecu_rec, NULL, 0, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */
    2764             :              output_frame );
    2765             : 
    2766         132 :     return;
    2767             : }
    2768             : 
    2769           0 : static void rec_wtda_fx(
    2770             :     Word16 *X,                 /* i  : FFT spectrum                          */
    2771             :     Word32 *ecu_rec,           /* o  : Reconstructed frame in tda domain     */
    2772             :     const Word16 output_frame, /* i  : Frame length                          */
    2773             :     const Word16 Lprot,        /* i  : Prototype frame length                */
    2774             :     const Word32 fs )
    2775             : {
    2776             :     Word16 l, Lprot2, timesh;
    2777             :     Word16 rec_buf[3 * L_FRAME48k];
    2778             :     Word16 *xsubst_, *out_ptr;
    2779             :     Word16 Qin;
    2780             :     Word16 xf_len;
    2781             :     Word16 i, idx;
    2782             :     Word16 *p_ecu;
    2783             :     Word16 g;
    2784             :     Word16 tbl_delta;
    2785             : 
    2786             :     // PMTE()
    2787           0 :     xsubst_ = rec_buf + output_frame;
    2788           0 :     Lprot2 = shr( Lprot, 1 );
    2789             : 
    2790             :     /* Initialize to WB constants */
    2791           0 :     xf_len = 26;
    2792           0 :     move16();
    2793           0 :     tbl_delta = 10082; /* Q12 */
    2794           0 :     move16();
    2795           0 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    2796             :     {
    2797           0 :         xf_len = 78;
    2798           0 :         move16();
    2799           0 :         tbl_delta = 3361; /* Q12 */
    2800           0 :         move16();
    2801             :     }
    2802           0 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    2803             :     {
    2804           0 :         xf_len = 52;
    2805           0 :         move16();
    2806           0 :         tbl_delta = 5041; /* Q12 */
    2807           0 :         move16();
    2808             :     }
    2809             : 
    2810             :     /* extract reconstructed frame with aldo window */
    2811           0 :     l = sub( output_frame, Lprot2 );
    2812           0 :     set16_fx( xsubst_, 0, l );
    2813           0 :     Copy( X, xsubst_ + l, Lprot );
    2814           0 :     set16_fx( xsubst_ + add( output_frame, Lprot2 ), 0, l );
    2815             : 
    2816             :     /* Smoothen onset of ECU frame */
    2817           0 :     p_ecu = xsubst_ + sub( output_frame, Lprot2 );
    2818           0 :     FOR( i = 0; i < xf_len; i++ )
    2819             :     {
    2820           0 :         idx = extract_l( L_shr( L_mult0( i, tbl_delta ), 12 ) );
    2821           0 :         g = sincos_t_fx[idx];
    2822           0 :         move16();
    2823           0 :         g = mult( g, g );
    2824           0 :         *p_ecu = mult( g, ( *p_ecu ) );
    2825           0 :         move16();
    2826           0 :         p_ecu++;
    2827             :     }
    2828             : 
    2829           0 :     timesh = NS2SA_FX2( fs, 10000000L - PH_ECU_ALDO_OLP2_NS );
    2830           0 :     move16();
    2831             : 
    2832           0 :     set16_fx( rec_buf, 0, output_frame );
    2833           0 :     Qin = 0;
    2834           0 :     move16();
    2835           0 :     out_ptr = rec_buf + sub( shl( output_frame, 1 ), timesh );
    2836           0 :     wtda_fx( out_ptr, &Qin, ecu_rec, NULL, 0, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */
    2837             :              output_frame );
    2838           0 :     return;
    2839             : }
    2840             : 
    2841             : /*--------------------------------------------------------------------------
    2842             :  *  rec_frame_fx()
    2843             :  *
    2844             :  *  Frame reconstruction
    2845             :  *--------------------------------------------------------------------------*/
    2846             : 
    2847         132 : static void ivas_rec_frame_fx(
    2848             :     Word16 *X,                 /* i  : FFT spectrum */
    2849             :     Word32 *ecu_rec,           /* o  : Reconstructed frame in tda domain */
    2850             :     const Word16 output_frame, /* i  : Frame length */
    2851             :     const Word16 Q,
    2852             :     const Word16 *old_dec,     /* i  : end of last decoded for OLA before tda and itda */
    2853             :     const Word16 element_mode, /* i  : IVAS element mode                     */
    2854             :     const Word16 *num_p,       /* i  : Number of peaks                       */
    2855             :     const Word16 *plocs        /* i  : Peak locations                        */
    2856             : )
    2857             : {
    2858             :     const Word16 *pFftTbl;
    2859             :     Word16 Lprot, lprotLog2Minus1;
    2860             : 
    2861             :     /* Initialize to WB constants */
    2862         132 :     Lprot = 512;
    2863         132 :     move16();
    2864         132 :     lprotLog2Minus1 = 9 - 1;
    2865         132 :     move16();
    2866         132 :     pFftTbl = FFT_W256; /* Table for 512-point real input FFT */
    2867         132 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    2868             :     {
    2869         103 :         Lprot = L_PROT48k; /* 1536 = (2*output_frame)*1024/1280 */
    2870         103 :         move16();
    2871             :     }
    2872          29 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    2873             :     {
    2874          29 :         Lprot = L_PROT32k; /* 1024 */
    2875          29 :         move16();
    2876          29 :         lprotLog2Minus1 = 10 - 1;
    2877          29 :         move16();
    2878          29 :         pFftTbl = FFT_W512; /* Table for 1024-point real input FFT */
    2879             :     }
    2880             : 
    2881             :     /* extend spectrum and IDFT */
    2882         132 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    2883             :     {
    2884         103 :         ifft3_fx( X, X, Lprot );
    2885             :     }
    2886             :     ELSE
    2887             :     {
    2888          29 :         r_fft_fx_lc( pFftTbl, Lprot, shr( Lprot, 1 ), lprotLog2Minus1, X, X, 0 ); /* Inverse FFT */
    2889             :     }
    2890         132 :     Scale_sig( X, Lprot, -Q );
    2891             : 
    2892         132 :     ivas_rec_wtda_fx( X, ecu_rec, output_frame, Lprot, old_dec, element_mode, num_p, plocs );
    2893             : 
    2894         132 :     return;
    2895             : }
    2896             : 
    2897           0 : static void rec_frame_fx(
    2898             :     Word16 *X,                 /* i  : FFT spectrum */
    2899             :     Word32 *ecu_rec,           /* o  : Reconstructed frame in tda domain */
    2900             :     const Word16 output_frame, /* i  : Frame length */
    2901             :     const Word16 Q )
    2902             : {
    2903             :     const Word16 *pFftTbl;
    2904             :     Word16 Lprot, lprotLog2Minus1;
    2905             :     Word32 fs;
    2906             : 
    2907           0 :     fs = L_mult0( output_frame, 50 );
    2908             : 
    2909             :     /* Initialize to WB constants */
    2910           0 :     Lprot = 512;
    2911           0 :     move16();
    2912           0 :     lprotLog2Minus1 = 9 - 1;
    2913           0 :     move16();
    2914           0 :     pFftTbl = FFT_W256; /* Table for 512-point real input FFT */
    2915           0 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    2916             :     {
    2917           0 :         Lprot = L_PROT48k; /* 1536 = (2*output_frame)*1024/1280 */
    2918           0 :         move16();
    2919             :     }
    2920           0 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    2921             :     {
    2922           0 :         Lprot = L_PROT32k; /* 1024 */
    2923           0 :         move16();
    2924           0 :         lprotLog2Minus1 = 10 - 1;
    2925           0 :         move16();
    2926           0 :         pFftTbl = FFT_W512; /* Table for 1024-point real input FFT */
    2927             :     }
    2928             : 
    2929             :     /* extend spectrum and IDFT */
    2930           0 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    2931             :     {
    2932           0 :         ifft3_fx( X, X, Lprot );
    2933             :     }
    2934             :     ELSE
    2935             :     {
    2936           0 :         r_fft_fx_lc( pFftTbl, Lprot, shr( Lprot, 1 ), lprotLog2Minus1, X, X, 0 ); /* Inverse FFT */
    2937             :     }
    2938           0 :     Scale_sig( X, Lprot, -Q );
    2939             : 
    2940           0 :     rec_wtda_fx( X, ecu_rec, output_frame, Lprot, fs );
    2941             : 
    2942           0 :     return;
    2943             : }
    2944             : 
    2945           0 : static Word32 mult_32_32_q( const Word32 a, const Word32 b, const Word16 q )
    2946             : {
    2947             :     Word32 hi;
    2948             :     UWord32 lo;
    2949           0 :     Mpy_32_32_ss( a, b, &hi, &lo );
    2950             : 
    2951           0 :     return L_or( L_shl_sat( hi, sub( 32 - 1, q ) ), L_lshr( (Word32) lo, add( q, 1 ) ) );
    2952             : }
    2953             : 
    2954         133 : static void fir_dwn_fx(
    2955             :     const Word16 x[],       /* i  : input vector Q(x_Q)                       */
    2956             :     const Word16 h[],       /* i  : impulse response of the FIR filter Q(h_Q)  */
    2957             :     const Word16 h_Q,       /* H's Q                                          */
    2958             :     Word16 y[],             /* o  : output vector (result of filtering) Q~    */
    2959             :     const Word16 L,         /* i  : input vector size                         */
    2960             :     const Word16 K,         /* i  : order of the FIR filter (K+1 coefs.)      */
    2961             :     const Word16 decimation /* i  : decimation                                */
    2962             : )
    2963             : {
    2964             :     Word32 s;
    2965             :     Word16 i, j;
    2966             :     const Word16 *ptr_h, *ptr_x;
    2967             :     Word16 *ptr_y;
    2968             :     Word16 Kdiv2;
    2969             :     Word16 centering;
    2970             :     Word16 tmp;
    2971             : 
    2972         133 :     centering = sub( 16, h_Q );
    2973         133 :     Kdiv2 = shr( K, 1 );
    2974             : 
    2975         133 :     ptr_y = y;
    2976             :     /* do the filtering */
    2977         798 :     FOR( i = Kdiv2; i < K; i += decimation )
    2978             :     {
    2979         665 :         s = L_deposit_l( 0 );
    2980         665 :         ptr_h = h + 1;
    2981         665 :         ptr_x = x + sub( i, 1 );
    2982             : 
    2983       26495 :         FOR( j = 1; j <= i; j++ )
    2984             :         {
    2985       25830 :             s = L_mac0_sat( s, *ptr_h++, *ptr_x-- ); // Q(h_Q) + Q(x_q)
    2986             :         }
    2987             : 
    2988         665 :         *ptr_y++ = extract_h( L_shl_sat( s, centering ) );
    2989         665 :         move16();
    2990             :     }
    2991       41363 :     FOR( i = K; i < L; i += decimation )
    2992             :     {
    2993       41230 :         s = L_deposit_l( 0 );
    2994       41230 :         ptr_h = h + 1;
    2995       41230 :         ptr_x = x + sub( i, 1 );
    2996       41230 :         move16();
    2997             : 
    2998     2329030 :         FOR( j = 1; j <= K; j++ )
    2999             :         {
    3000     2287800 :             s = L_mac0_sat( s, *ptr_h++, *ptr_x-- ); // Q(h_Q) + Q(x_q)
    3001             :         }
    3002             : 
    3003       41230 :         *ptr_y++ = extract_h( L_shl_sat( s, centering ) );
    3004       41230 :         move16();
    3005             :     }
    3006         133 :     tmp = add( L, Kdiv2 );
    3007         798 :     FOR( i = i; i < tmp; i += decimation )
    3008             :     {
    3009         665 :         s = L_deposit_l( 0 );
    3010         665 :         ptr_h = h + add( sub( i, L ), 1 );
    3011         665 :         move16();
    3012         665 :         ptr_x = x + sub( L, 1 );
    3013         665 :         move16();
    3014             : 
    3015       30185 :         FOR( j = i - L + 1; j <= K; j++ )
    3016             :         {
    3017       29520 :             s = L_mac0_sat( s, *ptr_h++, *ptr_x-- );
    3018             :         }
    3019             : 
    3020         665 :         *ptr_y++ = extract_h( L_shl_sat( s, centering ) );
    3021         665 :         move16();
    3022             :     }
    3023             : 
    3024         133 :     return;
    3025             : }
    3026             : 
    3027             : /*--------------------------------------------------------------------------
    3028             :  *  fec_ecu_pitch()
    3029             :  *
    3030             :  *  Pitch/correlation analysis and adaptive analysis frame length calculation
    3031             :  *--------------------------------------------------------------------------*/
    3032             : 
    3033         133 : static void fec_ecu_pitch_ivas_fx(
    3034             :     const Word16 *prevsynth_fx, /*Q15 16 */
    3035             :     Word16 *prevsynth_LP_fx,    /* Q15 16 */
    3036             :     const Word16 L,
    3037             :     Word16 *N,
    3038             :     Word16 *min_corr_fx, /* Q15 16 */
    3039             :     Word16 *decimatefator,
    3040             :     const Word16 HqVoicing )
    3041             : {
    3042             : 
    3043             :     Word16 i, filt_size;
    3044             :     Word16 QAsr, Ryy, cb_start, tmpQLP;
    3045             :     Word32 Ryytmp;
    3046             :     Word32 accA, accB, accBisqrt, accC, accCisqrt;
    3047             :     Word16 delay_ind, k;
    3048             :     const Word16 *Asr_LP_fx;
    3049             :     Word16 *ptr_LP, *ptr_LP2, *ptr_LP3, *ptr_LP4;
    3050             :     Word16 cb_end;
    3051             :     Word16 Lmul2, Lon20mul6, Lon20mul28, Lon20mul33, Lon20mul34;
    3052             : 
    3053             : 
    3054         133 :     SWITCH( L )
    3055             :     {
    3056         103 :         case L_FRAME48k:
    3057         103 :             *decimatefator = 6;
    3058         103 :             move16();
    3059         103 :             filt_size = 60;
    3060         103 :             move16();
    3061         103 :             Asr_LP_fx = Asr_LP48_fx;
    3062         103 :             QAsr = 17;
    3063         103 :             move16();
    3064         103 :             Lon20mul6 = 48;
    3065         103 :             move16();
    3066         103 :             Lon20mul28 = 224;
    3067         103 :             move16();
    3068         103 :             Lon20mul33 = 264;
    3069         103 :             move16();
    3070         103 :             Lon20mul34 = 272;
    3071         103 :             move16();
    3072         103 :             Lmul2 = 1920;
    3073         103 :             move16();
    3074         103 :             BREAK;
    3075             : 
    3076          30 :         case L_FRAME32k:
    3077          30 :             *decimatefator = 4;
    3078          30 :             move16();
    3079          30 :             filt_size = 40;
    3080          30 :             move16();
    3081          30 :             Asr_LP_fx = Asr_LP32_fx;
    3082          30 :             QAsr = 15;
    3083          30 :             move16();
    3084          30 :             Lon20mul6 = 48;
    3085          30 :             move16();
    3086          30 :             Lon20mul28 = 224;
    3087          30 :             move16();
    3088          30 :             Lon20mul33 = 264;
    3089          30 :             move16();
    3090          30 :             Lon20mul34 = 272;
    3091          30 :             move16();
    3092          30 :             Lmul2 = 1280;
    3093          30 :             move16();
    3094          30 :             BREAK;
    3095             : 
    3096           0 :         case L_FRAME16k:
    3097           0 :             *decimatefator = 2;
    3098           0 :             move16();
    3099           0 :             filt_size = 20;
    3100           0 :             move16();
    3101           0 :             Asr_LP_fx = Asr_LP16_fx;
    3102           0 :             QAsr = 15;
    3103           0 :             move16();
    3104           0 :             Lon20mul6 = 48;
    3105           0 :             move16();
    3106           0 :             Lon20mul28 = 224;
    3107           0 :             move16();
    3108           0 :             Lon20mul33 = 264;
    3109           0 :             move16();
    3110           0 :             Lon20mul34 = 272;
    3111           0 :             move16();
    3112           0 :             Lmul2 = 640;
    3113           0 :             move16();
    3114           0 :             BREAK;
    3115             : 
    3116           0 :         default:
    3117           0 :             *decimatefator = 2;
    3118           0 :             move16();
    3119           0 :             filt_size = 40;
    3120           0 :             move16();
    3121           0 :             Asr_LP_fx = Asr_LP16_fx;
    3122           0 :             QAsr = 15;
    3123           0 :             move16();
    3124           0 :             Lon20mul6 = 48;
    3125           0 :             move16();
    3126           0 :             Lon20mul28 = 224;
    3127           0 :             move16();
    3128           0 :             Lon20mul33 = 264;
    3129           0 :             move16();
    3130           0 :             Lon20mul34 = 272;
    3131           0 :             move16();
    3132           0 :             Lmul2 = 320;
    3133           0 :             move16();
    3134           0 :             BREAK;
    3135             :     }
    3136             : 
    3137             : 
    3138             :     /* Resampling to work at 8Khz */
    3139         133 :     fir_dwn_fx( prevsynth_fx, Asr_LP_fx, QAsr, prevsynth_LP_fx, Lmul2, filt_size, *decimatefator ); /* resampling without delay */
    3140             : 
    3141             : 
    3142         133 :     tmpQLP = Find_Max_Norm16( prevsynth_LP_fx, 320 );
    3143         133 :     Scale_sig( prevsynth_LP_fx, 320, sub( tmpQLP, 3 ) ); /* to avoid over scaling */
    3144             : 
    3145             : 
    3146             :     /* Correlation analysis */
    3147         133 :     *min_corr_fx = 0;
    3148         133 :     move16();
    3149         133 :     accC = L_deposit_l( 0 );
    3150             : 
    3151         133 :     ptr_LP = prevsynth_LP_fx + Lon20mul34;
    3152        6517 :     FOR( k = 0; k < Lon20mul6; k++ )
    3153             :     {
    3154        6384 :         accC = L_mac0( accC, *ptr_LP, *ptr_LP );
    3155        6384 :         ptr_LP++;
    3156             :     }
    3157             : 
    3158             : 
    3159         133 :     IF( EQ_16( HqVoicing, 1 ) )
    3160             :     {
    3161           0 :         cb_start = 0;
    3162           0 :         move16();
    3163           0 :         cb_end = Lon20mul33;
    3164           0 :         move16();
    3165             :     }
    3166             :     ELSE
    3167             :     {
    3168         133 :         cb_start = 0;
    3169         133 :         move16();
    3170         133 :         cb_end = Lon20mul28;
    3171         133 :         move16();
    3172             :     }
    3173             : 
    3174         133 :     accB = 0;
    3175         133 :     move16();
    3176         133 :     delay_ind = cb_start;
    3177         133 :     move16();
    3178             : 
    3179       22002 :     FOR( i = cb_start; i < cb_end; i++ ) /* cb_end = 35 let 6 ms min of loop size */
    3180             :     {
    3181       21911 :         accA = 0;
    3182       21911 :         move16();
    3183       21911 :         IF( EQ_16( i, cb_start ) )
    3184             :         {
    3185         133 :             accB = 0;
    3186         133 :             move16();
    3187         133 :             ptr_LP = prevsynth_LP_fx;
    3188         133 :             ptr_LP2 = prevsynth_LP_fx + Lon20mul34;
    3189        6517 :             FOR( k = 0; k < Lon20mul6; k++ )
    3190             :             {
    3191        6384 :                 accA = L_mac0( accA, *ptr_LP, *ptr_LP2 );
    3192        6384 :                 accB = L_mac0( accB, *ptr_LP, *ptr_LP );
    3193        6384 :                 ptr_LP++;
    3194        6384 :                 ptr_LP2++;
    3195             :             }
    3196             :         }
    3197             :         ELSE
    3198             :         {
    3199             : 
    3200             : 
    3201       21778 :             accB = L_mac0( L_msu0( accB, prevsynth_LP_fx[i - 1], prevsynth_LP_fx[i - 1] ), prevsynth_LP_fx[i + Lon20mul6 - 1], prevsynth_LP_fx[i + Lon20mul6 - 1] ); /* tmpQLP-5  */
    3202             : 
    3203             : 
    3204       21778 :             ptr_LP3 = prevsynth_LP_fx + i;
    3205       21778 :             ptr_LP4 = prevsynth_LP_fx + Lon20mul34;
    3206             : 
    3207     1067122 :             FOR( k = 0; k < Lon20mul6; k++ )
    3208             :             {
    3209     1045344 :                 accA = L_mac0( accA, *ptr_LP3, *ptr_LP4 ); /*2* tmpQLP-5  */
    3210     1045344 :                 ptr_LP3++;
    3211     1045344 :                 ptr_LP4++;
    3212             :             }
    3213             :         }
    3214             : 
    3215             :         /*accB*/
    3216             :         /*accC*/
    3217             :         /*accA Q 6-2*tmpQLP*/
    3218             : 
    3219       21911 :         accBisqrt = Isqrt( accB ); /* Q31 - 3 +  tmpQLP */
    3220       21911 :         accCisqrt = Isqrt( accC ); /* Q31 - 3 +  tmpQLP*/
    3221             : 
    3222             : 
    3223       21911 :         Ryytmp = L_shl_sat( Mult_32_32( accA, accCisqrt ), Q15 );            /*Q   6 -2*tmpQLP +  Q31 - 3 +  tmpQLP -16 -3 +tmpQLP      = Q15*/
    3224       21911 :         Ryy = extract_h( L_shl_sat( Mult_32_32( Ryytmp, accBisqrt ), 16 ) ); /*Q15 + Q31 - 3 +  tmpQLP -15 + 3- tmpQLP = Q31*/
    3225             : 
    3226       21911 :         IF( GT_16( Ryy, *min_corr_fx ) )
    3227             :         {
    3228         856 :             *min_corr_fx = Ryy;
    3229         856 :             move16();
    3230         856 :             delay_ind = i;
    3231         856 :             move16();
    3232             :         }
    3233             : 
    3234       21911 :         test();
    3235       21911 :         IF( HqVoicing == 0 && GT_16( *min_corr_fx, 31130 ) )
    3236             :         {
    3237          42 :             BREAK;
    3238             :         }
    3239             :     }
    3240             : 
    3241         133 :     *N = sub( Lon20mul34, delay_ind );
    3242         133 :     move16();
    3243             : 
    3244         133 :     Scale_sig( prevsynth_LP_fx, 320, negate( sub( tmpQLP, 3 ) ) );
    3245         133 :     return;
    3246             : }
    3247             : 
    3248           0 : static void fec_ecu_pitch_fx(
    3249             :     const Word16 *prevsynth_fx, /*Q15 16 */
    3250             :     Word16 *prevsynth_LP_fx,    /* Q15 16 */
    3251             :     const Word16 L,
    3252             :     Word16 *N,
    3253             :     Word16 *min_corr_fx, /* Q15 16 */
    3254             :     Word16 *decimatefator,
    3255             :     const Word16 HqVoicing )
    3256             : {
    3257             : 
    3258             :     Word16 i, filt_size;
    3259             :     Word16 QAsr, Ryy, cb_start, tmpQLP;
    3260             :     Word32 Ryytmp;
    3261             :     Word32 accA, accB, accBisqrt, accC, accCisqrt;
    3262             :     Word16 delay_ind, k;
    3263             :     const Word16 *Asr_LP_fx;
    3264             :     Word16 *ptr_LP, *ptr_LP2, *ptr_LP3, *ptr_LP4;
    3265             :     Word16 cb_end;
    3266             :     Word16 Lmul2, Lon20mul6, Lon20mul28, Lon20mul33, Lon20mul34;
    3267             : 
    3268             : 
    3269           0 :     SWITCH( L )
    3270             :     {
    3271           0 :         case L_FRAME48k:
    3272           0 :             *decimatefator = 6;
    3273           0 :             move16();
    3274           0 :             filt_size = 60;
    3275           0 :             move16();
    3276           0 :             Asr_LP_fx = Asr_LP48_fx;
    3277           0 :             QAsr = 17;
    3278           0 :             move16();
    3279           0 :             Lon20mul6 = 48;
    3280           0 :             move16();
    3281           0 :             Lon20mul28 = 224;
    3282           0 :             move16();
    3283           0 :             Lon20mul33 = 264;
    3284           0 :             move16();
    3285           0 :             Lon20mul34 = 272;
    3286           0 :             move16();
    3287           0 :             Lmul2 = 1920;
    3288           0 :             move16();
    3289           0 :             BREAK;
    3290             : 
    3291           0 :         case L_FRAME32k:
    3292           0 :             *decimatefator = 4;
    3293           0 :             move16();
    3294           0 :             filt_size = 40;
    3295           0 :             move16();
    3296           0 :             Asr_LP_fx = Asr_LP32_fx;
    3297           0 :             QAsr = 15;
    3298           0 :             move16();
    3299           0 :             Lon20mul6 = 48;
    3300           0 :             move16();
    3301           0 :             Lon20mul28 = 224;
    3302           0 :             move16();
    3303           0 :             Lon20mul33 = 264;
    3304           0 :             move16();
    3305           0 :             Lon20mul34 = 272;
    3306           0 :             move16();
    3307           0 :             Lmul2 = 1280;
    3308           0 :             move16();
    3309           0 :             BREAK;
    3310             : 
    3311           0 :         case L_FRAME16k:
    3312           0 :             *decimatefator = 2;
    3313           0 :             move16();
    3314           0 :             filt_size = 20;
    3315           0 :             move16();
    3316           0 :             Asr_LP_fx = Asr_LP16_fx;
    3317           0 :             QAsr = 15;
    3318           0 :             move16();
    3319           0 :             Lon20mul6 = 48;
    3320           0 :             move16();
    3321           0 :             Lon20mul28 = 224;
    3322           0 :             move16();
    3323           0 :             Lon20mul33 = 264;
    3324           0 :             move16();
    3325           0 :             Lon20mul34 = 272;
    3326           0 :             move16();
    3327           0 :             Lmul2 = 640;
    3328           0 :             move16();
    3329           0 :             BREAK;
    3330             : 
    3331           0 :         default:
    3332           0 :             *decimatefator = 2;
    3333           0 :             move16();
    3334           0 :             filt_size = 40;
    3335           0 :             move16();
    3336           0 :             Asr_LP_fx = Asr_LP16_fx;
    3337           0 :             QAsr = 15;
    3338           0 :             move16();
    3339           0 :             Lon20mul6 = 48;
    3340           0 :             move16();
    3341           0 :             Lon20mul28 = 224;
    3342           0 :             move16();
    3343           0 :             Lon20mul33 = 264;
    3344           0 :             move16();
    3345           0 :             Lon20mul34 = 272;
    3346           0 :             move16();
    3347           0 :             Lmul2 = 320;
    3348           0 :             move16();
    3349           0 :             BREAK;
    3350             :     }
    3351             : 
    3352             : 
    3353             :     /* Resampling to work at 8Khz */
    3354           0 :     fir_dwn_fx( prevsynth_fx, Asr_LP_fx, QAsr, prevsynth_LP_fx, Lmul2, filt_size, *decimatefator ); /* resampling without delay */
    3355             : 
    3356             : 
    3357           0 :     tmpQLP = Find_Max_Norm16( prevsynth_LP_fx, 320 );
    3358           0 :     Scale_sig( prevsynth_LP_fx, 320, sub( tmpQLP, 3 ) ); /* to avoid over scaling */
    3359             : 
    3360             : 
    3361             :     /* Correlation analysis */
    3362           0 :     *min_corr_fx = 0;
    3363           0 :     move16();
    3364           0 :     accC = L_deposit_l( 0 );
    3365             : 
    3366           0 :     ptr_LP = prevsynth_LP_fx + Lon20mul34;
    3367           0 :     FOR( k = 0; k < Lon20mul6; k++ )
    3368             :     {
    3369           0 :         accC = L_mac0( accC, *ptr_LP, *ptr_LP );
    3370           0 :         ptr_LP++;
    3371             :     }
    3372             : 
    3373             : 
    3374           0 :     IF( EQ_16( HqVoicing, 1 ) )
    3375             :     {
    3376           0 :         cb_start = 0;
    3377           0 :         move16();
    3378           0 :         cb_end = Lon20mul33;
    3379           0 :         move16();
    3380             :     }
    3381             :     ELSE
    3382             :     {
    3383           0 :         cb_start = 0;
    3384           0 :         move16();
    3385           0 :         cb_end = Lon20mul28;
    3386           0 :         move16();
    3387             :     }
    3388             : 
    3389           0 :     accB = 0;
    3390           0 :     move16();
    3391           0 :     delay_ind = cb_start;
    3392           0 :     move16();
    3393             : 
    3394           0 :     FOR( i = cb_start; i < cb_end; i++ ) /* cb_end = 35 let 6 ms min of loop size */
    3395             :     {
    3396           0 :         accA = 0;
    3397           0 :         move16();
    3398           0 :         IF( EQ_16( i, cb_start ) )
    3399             :         {
    3400           0 :             accB = 0;
    3401           0 :             move16();
    3402           0 :             ptr_LP = prevsynth_LP_fx;
    3403           0 :             ptr_LP2 = prevsynth_LP_fx + Lon20mul34;
    3404           0 :             FOR( k = 0; k < Lon20mul6; k++ )
    3405             :             {
    3406           0 :                 accA = L_mac0( accA, *ptr_LP, *ptr_LP2 );
    3407           0 :                 accB = L_mac0( accB, *ptr_LP, *ptr_LP );
    3408           0 :                 ptr_LP++;
    3409           0 :                 ptr_LP2++;
    3410             :             }
    3411             :         }
    3412             :         ELSE
    3413             :         {
    3414             : 
    3415             : 
    3416           0 :             accB = L_mac0( L_msu0( accB, prevsynth_LP_fx[i - 1], prevsynth_LP_fx[i - 1] ), prevsynth_LP_fx[i + Lon20mul6 - 1], prevsynth_LP_fx[i + Lon20mul6 - 1] ); /* tmpQLP-5  */
    3417             : 
    3418             : 
    3419           0 :             ptr_LP3 = prevsynth_LP_fx + i;
    3420           0 :             ptr_LP4 = prevsynth_LP_fx + Lon20mul34;
    3421             : 
    3422           0 :             FOR( k = 0; k < Lon20mul6; k++ )
    3423             :             {
    3424           0 :                 accA = L_mac0( accA, *ptr_LP3, *ptr_LP4 ); /*2* tmpQLP-5  */
    3425           0 :                 ptr_LP3++;
    3426           0 :                 ptr_LP4++;
    3427             :             }
    3428             :         }
    3429             : 
    3430             :         /*accB*/
    3431             :         /*accC*/
    3432             :         /*accA Q 6-2*tmpQLP*/
    3433             : 
    3434           0 :         accBisqrt = Isqrt( accB ); /* Q31 - 3 +  tmpQLP */
    3435           0 :         accCisqrt = Isqrt( accC ); /* Q31 - 3 +  tmpQLP*/
    3436             : 
    3437             : 
    3438           0 :         Ryytmp = mult_32_32_q( accA, accCisqrt, sub( 16 + 3, tmpQLP ) );   /*Q   6 -2*tmpQLP +  Q31 - 3 +  tmpQLP -16 -3 +tmpQLP      = Q15*/
    3439           0 :         Ryytmp = mult_32_32_q( Ryytmp, accBisqrt, add( 15 - 3, tmpQLP ) ); /*Q15 + Q31 - 3 +  tmpQLP -15 + 3- tmpQLP = Q31*/
    3440           0 :         Ryy = extract_h( Ryytmp );                                         /* Q15 */
    3441             : 
    3442             : 
    3443           0 :         IF( GT_16( Ryy, *min_corr_fx ) )
    3444             :         {
    3445           0 :             *min_corr_fx = Ryy;
    3446           0 :             move16();
    3447           0 :             delay_ind = i;
    3448           0 :             move16();
    3449             :         }
    3450             : 
    3451           0 :         test();
    3452           0 :         IF( HqVoicing == 0 && GT_16( *min_corr_fx, 31130 ) )
    3453             :         {
    3454           0 :             BREAK;
    3455             :         }
    3456             :     }
    3457             : 
    3458           0 :     *N = sub( Lon20mul34, delay_ind );
    3459           0 :     move16();
    3460             : 
    3461           0 :     Scale_sig( prevsynth_LP_fx, 320, negate( sub( tmpQLP, 3 ) ) );
    3462           0 :     return;
    3463             : }
    3464             : 
    3465           8 : static void sin_cos_est_fx( Word32 phi, Word16 *cosfreq, Word16 *sinfreq )
    3466             : {
    3467             : 
    3468             : 
    3469             :     /* i phi : normalized frequency beteween 0 and Pi (nyquist) in Q30 */
    3470             :     /* o  cosfreq & sinfreq : cos(phi) and sin (phi) in Q15 */
    3471             : 
    3472             :     Word16 i;
    3473             :     Word32 delta;
    3474             :     Word32 imin;
    3475             :     Word16 sinb, cosb;
    3476             :     Word32 sinv, cosv, tmp;
    3477             : 
    3478           8 :     i = 0;
    3479           8 :     move16();
    3480         540 :     FOR( imin = 0; imin < phi; imin += 4392264 )
    3481             :     {
    3482         532 :         i = add( i, 1 );
    3483             :     }
    3484             : 
    3485           8 :     delta = L_sub( phi, imin ); /*Q30 */
    3486           8 :     sinb = sincos_t_rad3_fx[i];
    3487           8 :     move16(); /*Q15 */
    3488           8 :     cosb = sincos_t_rad3_fx[384 - i];
    3489           8 :     move16(); /*Q15 */
    3490             : 
    3491             :     /*sinv = sin(phi) = sinb*cos(delta)+cosb*sin(delta) */
    3492             :     /*cosv = cos(phi) = cosb*cos(delta)-sinb*sin(delta) */
    3493             :     /*sin(delta) is approximated by delta for very small delta; cos(delta) is approximated by 1 */
    3494           8 :     tmp = L_shl( Mult_32_16( delta, cosb ), 1 ); /*Q31 */
    3495           8 :     sinv = L_add( L_deposit_h( sinb ), tmp );
    3496           8 :     tmp = L_shl( Mult_32_16( delta, sinb ), 1 ); /*Q31 */
    3497           8 :     cosv = L_sub_sat( L_deposit_h( cosb ), tmp );
    3498           8 :     *sinfreq = round_fx_sat( sinv );
    3499           8 :     move16();
    3500           8 :     *cosfreq = round_fx_sat( cosv );
    3501           8 :     move16();
    3502             : 
    3503           8 :     return;
    3504             : }
    3505             : 
    3506          32 : static Word16 abs_iter_fx( Word16 re /*Qx*/, Word16 im /*Qx*/, Word16 N )
    3507             : {
    3508             :     Word16 A, tmp, L_tmp1, L_tmp2;
    3509             :     Word16 i, exp;
    3510             : 
    3511             :     /*const Word16 cor[10] =  { 23170,      20724,      20106,      19950,      19911,      19902,      19899,      19899,    19899,      19898}; */
    3512             : 
    3513          32 :     exp = norm_s( re );
    3514          32 :     exp = s_min( exp, norm_s( im ) );
    3515          32 :     exp = sub( exp, 2 );
    3516             : 
    3517          32 :     re = shl( re, exp );
    3518          32 :     im = shl( im, exp );
    3519             : 
    3520             : 
    3521          32 :     IF( im < 0 )
    3522             :     {
    3523          13 :         im = negate( im );
    3524             :     }
    3525             :     ELSE
    3526             :     {
    3527          19 :         re = negate( re );
    3528             :     }
    3529          32 :     tmp = re;
    3530          32 :     move16();
    3531          32 :     re = im;
    3532          32 :     move16();
    3533          32 :     im = tmp;
    3534          32 :     move16();
    3535             : 
    3536             : 
    3537         192 :     FOR( i = 0; i < N; i++ )
    3538             :     {
    3539         160 :         L_tmp1 = shr( im, i );
    3540         160 :         L_tmp2 = shr( re, i );
    3541         160 :         IF( im < 0 )
    3542             :         {
    3543          83 :             L_tmp1 = negate( L_tmp1 );
    3544             :         }
    3545             :         ELSE
    3546             :         {
    3547          77 :             L_tmp2 = negate( L_tmp2 );
    3548             :         }
    3549         160 :         re = add( re, L_tmp1 );
    3550         160 :         im = add( im, L_tmp2 );
    3551             :     }
    3552          32 :     i = s_min( sub( i, 1 ), 9 );
    3553          32 :     tmp = abs_s( re );
    3554             :     /*A = round_fx(L_shr(L_mult(tmp, cor[i]), exp)); //this can be ommited, if we don't need the exact abs value */
    3555          32 :     A = shr_sat( tmp, exp );
    3556          32 :     return A;
    3557             : }
    3558             : /*--------------------------------------------------------------------------
    3559             :  *  fec_ecu_dft()
    3560             :  *
    3561             :  *  DFT analysis on adaptive frame length. Analysis frame stretched to
    3562             :  *  next power of 2 using linear interpolation.
    3563             :  *--------------------------------------------------------------------------*/
    3564             : 
    3565           1 : static void ivas_fec_ecu_dft_fx(
    3566             :     const Word16 *prevsynth_LP, /*Qin */
    3567             :     const Word16 N,
    3568             :     Word16 *Tfr,        /*Qout */
    3569             :     Word16 *Tfi,        /*Qout */
    3570             :     Word32 *sum_Tf_abs, /*Qout; */
    3571             :     Word16 *Tf_abs,     /*Qout */
    3572             :     Word16 *Nfft,
    3573             :     Word16 *exp,              /*Qout = Qin+exp */
    3574             :     const Word16 element_mode /* i  : IVAS element mode */
    3575             : )
    3576             : {
    3577             :     Word32 L_tmp, Tmp, Tfr32[512], Tfi32[512], fac, *Pt1, *Pt2;
    3578             :     Word16 i, tmp, tmp_short, N_LP, target[2 * L_FRAME48k], Tfr16[FEC_FFT_MAX_SIZE], *pt1, *pt2, *pt3, Lon20;
    3579             :     Word16 tmp_loop;
    3580             :     Word16 alignment_point;
    3581             : 
    3582           1 :     Lon20 = 8;
    3583           1 :     move16();
    3584           1 :     IF( element_mode == EVS_MONO )
    3585             :     {
    3586           0 :         alignment_point = sub( shl( 160, 1 ), i_mult( 3, Lon20 ) );
    3587             :     }
    3588             :     ELSE
    3589             :     {
    3590           1 :         alignment_point = shl( 160, 1 );
    3591             :     }
    3592           1 :     tmp = sub( alignment_point, N );
    3593           1 :     Copy( &prevsynth_LP[tmp], target, N );
    3594             : 
    3595             :     /* DFT  */
    3596             : 
    3597           1 :     L_tmp = L_deposit_l( N );
    3598          10 :     FOR( tmp = 0; L_tmp <= 16384; tmp++ )
    3599             :     {
    3600           9 :         L_tmp = L_shl( L_tmp, 1 );
    3601             :     }
    3602           1 :     *Nfft = shl( 1, sub( 15, tmp ) );
    3603           1 :     move16();
    3604             : 
    3605           1 :     set32_fx( Tfr32, 0, *Nfft );
    3606           1 :     set32_fx( Tfi32, 0, *Nfft );
    3607           1 :     Tfr16[0] = target[0];
    3608           1 :     move16();
    3609           1 :     Tfr16[*Nfft - 1] = target[N - 1];
    3610           1 :     move16();
    3611             : 
    3612           1 :     IF( EQ_16( *Nfft, N ) )
    3613             :     {
    3614           0 :         Copy( &target[1], &Tfr16[1], sub( *Nfft, 2 ) );
    3615             :     }
    3616             :     ELSE
    3617             :     {
    3618             : 
    3619           1 :         tmp = div_s( sub( N, 1 ), sub( *Nfft, 1 ) );
    3620           1 :         Tmp = L_deposit_l( tmp );
    3621           1 :         fac = L_add( Tmp, 0 );
    3622           1 :         tmp_loop = sub( *Nfft, 1 );
    3623          63 :         FOR( i = 1; i < tmp_loop; i++ ) /* interpolation for FFT */
    3624             :         {
    3625          62 :             tmp_short = extract_l( L_shr( Tmp, 15 ) );
    3626          62 :             tmp = extract_l( L_msu( Tmp, tmp_short, 16384 ) );
    3627          62 :             L_tmp = L_mult( sub_sat( target[tmp_short + 1], target[tmp_short] ), tmp ); /*Qin+16 */
    3628          62 :             Tfr16[i] = add_sat( target[tmp_short], round_fx_sat( L_tmp ) );
    3629          62 :             move16(); /*Qin */
    3630          62 :             Tmp = L_add( Tmp, fac );
    3631             :         }
    3632             :     }
    3633             : 
    3634             : 
    3635             :     /*to avoid overflow in DoRTFTn_fx() */
    3636           1 :     tmp = Exp16Array( *Nfft, Tfr16 );
    3637           1 :     *exp = add( tmp, add( 2, norm_s( *Nfft ) ) );
    3638           1 :     move16();
    3639           1 :     Copy_Scale_sig_16_32_no_sat( Tfr16, Tfr32, *Nfft, *exp ); /*Qin+exp; */
    3640           1 :     *exp = s_min( *exp, 15 );
    3641             : 
    3642           1 :     DoRTFTn_fx( Tfr32, Tfi32, *Nfft );
    3643           1 :     N_LP = shr( *Nfft, 1 );
    3644             : 
    3645             : 
    3646           1 :     L_tmp = L_deposit_l( 0 );
    3647             : 
    3648           1 :     pt1 = Tfr;
    3649           1 :     pt2 = Tfi;
    3650           1 :     pt3 = Tf_abs;
    3651           1 :     Pt1 = Tfr32;
    3652           1 :     Pt2 = Tfi32;
    3653          33 :     FOR( i = 0; i < N_LP; i++ )
    3654             :     {
    3655          32 :         *pt1 = extract_h( *Pt1 ); /*Qin+exp-16 */
    3656          32 :         move16();
    3657          32 :         *pt2 = extract_h( *Pt2 ); /*Qin+exp-16 */
    3658          32 :         move16();
    3659          32 :         *pt3 = abs_iter_fx( Tfr[i], Tfi[i], 5 );
    3660          32 :         move16();                         /*Qin+exp-16 */
    3661          32 :         L_tmp = L_mac0( L_tmp, *pt3, 1 ); /*Qin+exp-16 */
    3662          32 :         pt1++;
    3663          32 :         pt2++;
    3664          32 :         pt3++;
    3665          32 :         Pt1++;
    3666          32 :         Pt2++;
    3667             :     }
    3668           1 :     *sum_Tf_abs = L_tmp;
    3669           1 :     move32();
    3670           1 :     *exp = sub( *exp, 16 );
    3671           1 :     move16();
    3672           1 :     return;
    3673             : }
    3674             : 
    3675           0 : static void fec_ecu_dft_fx(
    3676             :     const Word16 *prevsynth_LP, /*Qin */
    3677             :     const Word16 N,
    3678             :     Word16 *Tfr,        /*Qout */
    3679             :     Word16 *Tfi,        /*Qout */
    3680             :     Word32 *sum_Tf_abs, /*Qout; */
    3681             :     Word16 *Tf_abs,     /*Qout */
    3682             :     Word16 *Nfft,
    3683             :     Word16 *exp /*Qout = Qin+exp */
    3684             : )
    3685             : {
    3686             :     Word32 L_tmp, Tmp, Tfr32[512], Tfi32[512], fac, *Pt1, *Pt2;
    3687             :     Word16 i, tmp, tmp_short, N_LP, target[2 * L_FRAME48k], Tfr16[FEC_FFT_MAX_SIZE], *pt1, *pt2, *pt3;
    3688             :     Word16 tmp_loop;
    3689           0 :     tmp = sub( 296, N );
    3690           0 :     Copy( &prevsynth_LP[tmp], target, N );
    3691             : 
    3692             : 
    3693             :     /* DFT  */
    3694             : 
    3695           0 :     L_tmp = L_deposit_l( N );
    3696           0 :     FOR( tmp = 0; L_tmp <= 16384; tmp++ )
    3697             :     {
    3698           0 :         L_tmp = L_shl( L_tmp, 1 );
    3699             :     }
    3700           0 :     *Nfft = shl( 1, sub( 15, tmp ) );
    3701           0 :     move16();
    3702             : 
    3703             : 
    3704           0 :     set32_fx( Tfr32, 0, *Nfft );
    3705           0 :     set32_fx( Tfi32, 0, *Nfft );
    3706           0 :     Tfr16[0] = target[0];
    3707           0 :     move16();
    3708           0 :     Tfr16[*Nfft - 1] = target[N - 1];
    3709           0 :     move16();
    3710             : 
    3711           0 :     IF( EQ_16( *Nfft, N ) )
    3712             :     {
    3713           0 :         Copy( &target[1], &Tfr16[1], sub( *Nfft, 2 ) );
    3714             :     }
    3715             :     ELSE
    3716             :     {
    3717             : 
    3718           0 :         tmp = div_s( sub( N, 1 ), sub( *Nfft, 1 ) );
    3719           0 :         Tmp = L_deposit_l( tmp );
    3720           0 :         fac = L_add( Tmp, 0 );
    3721           0 :         tmp_loop = sub( *Nfft, 1 );
    3722           0 :         FOR( i = 1; i < tmp_loop; i++ ) /* interpolation for FFT */
    3723             :         {
    3724           0 :             tmp_short = extract_l( L_shr( Tmp, 15 ) );
    3725           0 :             tmp = extract_l( L_msu( Tmp, tmp_short, 16384 ) );
    3726           0 :             L_tmp = L_mult( sub_sat( target[tmp_short + 1], target[tmp_short] ), tmp ); /*Qin+16 */
    3727           0 :             Tfr16[i] = add_sat( target[tmp_short], round_fx_sat( L_tmp ) );
    3728           0 :             move16(); /*Qin */
    3729           0 :             Tmp = L_add( Tmp, fac );
    3730             :         }
    3731             :     }
    3732             : 
    3733             : 
    3734             :     /*to avoid overflow in DoRTFTn_fx() */
    3735           0 :     tmp = Exp16Array( *Nfft, Tfr16 );
    3736           0 :     *exp = add( tmp, add( 2, norm_s( *Nfft ) ) );
    3737           0 :     move16();
    3738             :     {
    3739           0 :         Word16 loctmp = *exp;
    3740           0 :         move16();
    3741           0 :         loctmp = s_min( 15, loctmp );
    3742           0 :         Copy_Scale_sig_16_32_DEPREC( Tfr16, Tfr32, *Nfft, loctmp ); /*Qin+exp; */ /*Even with limiting loctmp, if Copy_Scale_sig_16_32_no_sat() is used, can lead to 1 difference */
    3743             :     }
    3744             : 
    3745           0 :     DoRTFTn_fx( Tfr32, Tfi32, *Nfft );
    3746           0 :     N_LP = shr( *Nfft, 1 );
    3747             : 
    3748             : 
    3749           0 :     L_tmp = L_deposit_l( 0 );
    3750             : 
    3751           0 :     pt1 = Tfr;
    3752           0 :     pt2 = Tfi;
    3753           0 :     pt3 = Tf_abs;
    3754           0 :     Pt1 = Tfr32;
    3755           0 :     Pt2 = Tfi32;
    3756           0 :     FOR( i = 0; i < N_LP; i++ )
    3757             :     {
    3758           0 :         *pt1 = extract_h( *Pt1 ); /*Qin+exp-16 */
    3759           0 :         move16();
    3760           0 :         *pt2 = extract_h( *Pt2 ); /*Qin+exp-16 */
    3761           0 :         move16();
    3762           0 :         *pt3 = abs_iter_fx( Tfr[i], Tfi[i], 5 );
    3763           0 :         move16();                         /*Qin+exp-16 */
    3764           0 :         L_tmp = L_mac0( L_tmp, *pt3, 1 ); /*Qin+exp-16 */
    3765           0 :         pt1++;
    3766           0 :         pt2++;
    3767           0 :         pt3++;
    3768           0 :         Pt1++;
    3769           0 :         Pt2++;
    3770             :     }
    3771           0 :     *sum_Tf_abs = L_tmp;
    3772           0 :     move32();
    3773           0 :     *exp = sub( *exp, 16 );
    3774           0 :     move16();
    3775           0 :     return;
    3776             : }
    3777             : 
    3778           8 : static void singenerator_fx(
    3779             :     const Word16 L,       /* i  : size of output */
    3780             :     const Word16 cosfreq, /* i  : cosine of 1-sample dephasing at the given frequency Q15*/
    3781             :     const Word16 sinfreq, /* i  : sine   of 1-sample dephasing at the given frequency Q15*/
    3782             :     const Word16 a_re,
    3783             :     /* i  : real part of complex spectral coefficient at the given frequency */ /*Qin */
    3784             :     const Word16 a_im,
    3785             :     /* i  : imag part of complex spectral coefficient at the given frequency */ /*Qin */
    3786             :     Word32 xx[] /* o  : output vector */                                        /*Qin+16 */
    3787             : )
    3788             : {
    3789             : 
    3790             :     Word32 *ptr, L_C0, L_S0, L_C1, L_S1;
    3791             :     Word16 C0, S0, C1, S1;
    3792             :     Word16 i;
    3793             : 
    3794           8 :     L_S0 = L_deposit_l( 0 );    /*prevent warning*/
    3795           8 :     L_C0 = L_deposit_h( a_re ); /*Qin+16 */
    3796           8 :     S0 = a_im;
    3797           8 :     move16();
    3798             : 
    3799           8 :     ptr = xx;
    3800             : 
    3801           8 :     *ptr = L_add_sat( *ptr, L_C0 );
    3802           8 :     move32();
    3803           8 :     ptr++;
    3804             : 
    3805        5120 :     FOR( i = 0; i < L / 2 - 1; i++ )
    3806             :     {
    3807        5112 :         C0 = extract_h( L_C0 );            /*Qin */
    3808        5112 :         L_C1 = L_mult( C0, cosfreq );      /*Qin+16 */
    3809        5112 :         L_C1 = L_msu( L_C1, S0, sinfreq ); /*Qin+16 */
    3810        5112 :         L_S1 = L_mult( C0, sinfreq );
    3811        5112 :         S1 = mac_r( L_S1, S0, cosfreq );
    3812        5112 :         *ptr = L_add_sat( *ptr, L_C1 );
    3813        5112 :         move32(); /*Qin+16 */
    3814        5112 :         ptr++;
    3815             : 
    3816        5112 :         C1 = extract_h( L_C1 );
    3817        5112 :         L_C0 = L_mult( C1, cosfreq );
    3818        5112 :         L_C0 = L_msu( L_C0, S1, sinfreq );
    3819        5112 :         L_S0 = L_mult( C1, sinfreq );
    3820        5112 :         S0 = mac_r( L_S0, S1, cosfreq );
    3821        5112 :         *ptr = L_add_sat( *ptr, L_C0 );
    3822        5112 :         move32();
    3823        5112 :         ptr++;
    3824             :     }
    3825             : 
    3826           8 :     C0 = extract_h( L_C0 );
    3827           8 :     S0 = extract_h( L_S0 );
    3828           8 :     L_C1 = L_mult( C0, cosfreq );
    3829           8 :     L_C1 = L_msu( L_C1, S0, sinfreq );
    3830           8 :     *ptr = L_add_sat( *ptr, L_C1 );
    3831           8 :     move32();
    3832           8 :     ptr++;
    3833             : 
    3834           8 :     return;
    3835             : }
    3836             : 
    3837           1 : static void sinusoidal_synthesis_fx(
    3838             :     const Word16 *Tfr, /*Qin */
    3839             :     const Word16 *Tfi, /*Qin */
    3840             :     Word16 *Tf_abs,    /*Qin */
    3841             :     const Word16 N,
    3842             :     const Word16 L,
    3843             :     const Word16 decimate_factor,
    3844             :     const Word16 Nfft,
    3845             :     const Word32 sum_Tf_abs, /*Qin */
    3846             :     Word16 *synthesis,       /*Qin */
    3847             :     const Word16 HqVoicing,
    3848             :     Word16 exp )
    3849             : {
    3850           1 :     Word16 i, k, nb_pulses, indmax = 0, nb_pulses_final;
    3851             :     Word16 pulses[FEC_MAX / 2];
    3852             :     Word16 mmax, maxi;
    3853             :     Word32 cumsum, freq, L_tmp;
    3854             :     Word16 freqi[FEC_NB_PULSE_MAX], tmp, q, inv_den, new_s, old, cpt;
    3855             :     Word16 a_re[FEC_NB_PULSE_MAX], a_im[FEC_NB_PULSE_MAX];
    3856           1 :     Word16 Lon20_10 = 80;
    3857             :     Word16 flag, Len;
    3858             :     Word16 cosfreq, sinfreq, sN, PL, glued;
    3859             :     Word32 synthesis_fx[2 * L_FRAME48k];
    3860             :     Word16 *pt1, *pt2, *pt3, *pt4;
    3861             : 
    3862           1 :     move16(); // indmax
    3863           1 :     move16(); // Lon20_10
    3864           1 :     flag = HqVoicing;
    3865           1 :     move16();
    3866           1 :     if ( GT_16( N, Lon20_10 ) )
    3867             :     {
    3868           0 :         flag = 1;
    3869           0 :         move16(); /*flag corresponds to condition sub(N, Lon20_10)>0 || HqVoicing */
    3870             :     }
    3871             : 
    3872             : 
    3873           1 :     pt4 = pulses;
    3874           1 :     nb_pulses = 0;
    3875           1 :     move16();
    3876           1 :     PL = 0;
    3877           1 :     move16();
    3878           1 :     cpt = 0;
    3879           1 :     move16();
    3880           1 :     old = 0;
    3881           1 :     move16();
    3882           1 :     glued = 1;
    3883           1 :     move16();
    3884           1 :     new_s = Tf_abs[1]; // Qin
    3885           1 :     move16();
    3886           1 :     if ( flag )
    3887             :     {
    3888           0 :         PL = 1;
    3889           0 :         move16();
    3890             :     }
    3891           1 :     tmp = sub( shr( N, 1 ), 3 );
    3892          26 :     WHILE( LE_16( cpt, tmp ) )
    3893             :     {
    3894          25 :         test();
    3895          25 :         IF( GT_16( Tf_abs[cpt], old ) && GT_16( Tf_abs[cpt], new_s ) )
    3896          11 :         {
    3897             :             Word16 tmp2;
    3898             : 
    3899          11 :             glued = cpt;
    3900          11 :             move16();
    3901             : 
    3902          11 :             tmp2 = add( add( cpt, PL ), 1 );
    3903          22 :             FOR( i = glued; i < tmp2; i++ )
    3904             :             {
    3905          11 :                 *pt4++ = i;
    3906          11 :                 move16();
    3907          11 :                 nb_pulses++;
    3908          11 :                 move16();
    3909             :             }
    3910          11 :             old = Tf_abs[cpt + PL];
    3911          11 :             move16();
    3912          11 :             new_s = Tf_abs[cpt + 2 + PL];
    3913          11 :             move16();
    3914          11 :             cpt = add( add( cpt, PL ), 1 );
    3915          11 :             move16();
    3916          11 :             glued = 1;
    3917          11 :             move16();
    3918             :         }
    3919             :         ELSE
    3920             :         {
    3921          14 :             old = Tf_abs[cpt];
    3922          14 :             move16();
    3923          14 :             new_s = Tf_abs[cpt + 2];
    3924          14 :             move16();
    3925          14 :             cpt++;
    3926          14 :             glued = 0;
    3927          14 :             move16();
    3928             :         }
    3929             :     }
    3930             : 
    3931             : 
    3932           1 :     nb_pulses_final = 0;
    3933           1 :     move16();
    3934             : 
    3935           1 :     sN = sub( 13, norm_s( Nfft ) ); /*for amplitude normalization by 2/nfft */
    3936             : 
    3937           1 :     cumsum = L_deposit_l( 0 );
    3938             : 
    3939             : 
    3940           1 :     L_tmp = Mult_32_16( sum_Tf_abs, 22938 ); // Qin
    3941             : 
    3942           1 :     pt1 = a_re;
    3943           1 :     pt2 = a_im;
    3944           1 :     pt3 = freqi;
    3945             : 
    3946           1 :     maxi = s_min( FEC_NB_PULSE_MAX, nb_pulses );
    3947           1 :     nb_pulses_final = maxi;
    3948           1 :     move16();
    3949             : 
    3950           1 :     Len = shl( L, 1 );
    3951           1 :     IF( HqVoicing )
    3952             :     {
    3953           0 :         FOR( i = 0; i < maxi; i++ )
    3954             :         {
    3955           0 :             mmax = 0;
    3956           0 :             move16();
    3957           0 :             pt4 = pulses;
    3958           0 :             FOR( k = 0; k < nb_pulses; k++ )
    3959             :             {
    3960           0 :                 tmp = *pt4++;
    3961           0 :                 move16();
    3962           0 :                 if ( GT_16( Tf_abs[tmp], mmax ) )
    3963             :                 {
    3964           0 :                     indmax = tmp;
    3965           0 :                     move16();
    3966             :                 }
    3967           0 :                 mmax = s_max( Tf_abs[tmp], mmax );
    3968             :             }
    3969             : 
    3970           0 :             *pt1++ = Tfr[indmax];
    3971           0 :             move16(); /*L_shr(Tfr[indmax], sN); //instead shr -> scaling of a_re is Qin+sN */
    3972           0 :             *pt2++ = Tfi[indmax];
    3973           0 :             move16(); /*L_shr(Tfi[indmax], sN); //instead shr -> scaling of a_im is Qin+sN */
    3974           0 :             *pt3++ = indmax;
    3975           0 :             move16();
    3976           0 :             Tf_abs[indmax] = -1;
    3977           0 :             move16();
    3978             :         }
    3979             :     }
    3980             :     ELSE
    3981             :     {
    3982             :         DO
    3983             :         {
    3984           8 :             mmax = 0;
    3985           8 :             move16();
    3986           8 :             pt4 = pulses;
    3987          96 :             FOR( k = 0; k < nb_pulses; k++ )
    3988             :             {
    3989          88 :                 tmp = *pt4++;
    3990          88 :                 move16();
    3991          88 :                 if ( GT_16( Tf_abs[tmp], mmax ) )
    3992             :                 {
    3993          19 :                     indmax = tmp;
    3994          19 :                     move16();
    3995             :                 }
    3996          88 :                 mmax = s_max( Tf_abs[tmp], mmax );
    3997             :             }
    3998             : 
    3999           8 :             cumsum = L_mac0( cumsum, mmax, 1 ); // Qin
    4000             : 
    4001           8 :             *pt1++ = Tfr[indmax];
    4002           8 :             move16(); /*L_shr(Tfr[indmax], sN); //instead shr -> scaling of a_re is Qin+sN */
    4003           8 :             *pt2++ = Tfi[indmax];
    4004           8 :             move16(); /*L_shr(Tfi[indmax], sN); //instead shr -> scaling of a_im is Qin+sN */
    4005           8 :             *pt3++ = indmax;
    4006           8 :             move16();
    4007           8 :             Tf_abs[indmax] = -1;
    4008           8 :             move16();
    4009             : 
    4010           8 :             maxi = sub( maxi, 1 );
    4011             :         }
    4012           8 :         WHILE( maxi > 0 && LT_32( cumsum, L_tmp ) );
    4013             : 
    4014           1 :         nb_pulses_final = sub( nb_pulses_final, maxi );
    4015           1 :         move16();
    4016             :     }
    4017             : 
    4018             : 
    4019             :     /* sinusoidal synthesis */
    4020             : 
    4021             : 
    4022           1 :     set32_fx( synthesis_fx, 0, Len );
    4023             : 
    4024           1 :     exp = add( exp, sN );
    4025             : 
    4026             : 
    4027           1 :     pt1 = a_re;
    4028           1 :     pt2 = a_im;
    4029           1 :     pt3 = freqi;
    4030           1 :     q = shr_r( N, 2 );
    4031           1 :     if ( GT_16( N, shl( q, 2 ) ) )
    4032             :     {
    4033           0 :         q = add( q, 1 );
    4034             :     }
    4035             : 
    4036           1 :     inv_den = i_mult2( N, decimate_factor ); /*Q0 */
    4037             : 
    4038             :     /*tmp = div_s(12868,inv_den);*/ /*Q15 */
    4039             : 
    4040             : 
    4041           9 :     FOR( i = 0; i < nb_pulses_final; i++ )
    4042             :     {
    4043             : 
    4044           8 :         tmp = div_s( shl( *pt3, 1 ), inv_den ); /*Q15 */                    /* ind*2/(N*decim) */
    4045           8 :         freq = L_shl( L_mult( tmp, 25736 ), 1 ); /*Q30 */                   /* ind*2/(N*decim)*pi/4*4    never greater than PI/2 */
    4046           8 :         sin_cos_est_fx( freq, &cosfreq, &sinfreq );                         /*cosfreq & sinfreq in Q15 */
    4047           8 :         singenerator_fx( Len, cosfreq, sinfreq, *pt1, *pt2, synthesis_fx ); /*Qin      */
    4048             : 
    4049           8 :         pt1++;
    4050           8 :         pt2++;
    4051           8 :         pt3++;
    4052             :     }
    4053           1 :     Copy_Scale_sig_32_16( synthesis_fx, synthesis, Len, negate( add( exp, 16 ) ) ); /*Qin */
    4054             : 
    4055             : 
    4056           1 :     return;
    4057             : }
    4058             : 
    4059           1 : static void ivas_fec_noise_filling_fx(
    4060             :     const Word16 *prevsynth_fx, /*Qsynth   */
    4061             :     Word16 *synthesis_fx,       /*Qsynth */
    4062             :     Word16 *ni_seed_forfec,
    4063             :     const Word16 L,
    4064             :     const Word16 N,
    4065             :     const Word16 HqVoicing,
    4066             :     Word16 *gapsynth_fx,       /*Qsynth */
    4067             :     const Word16 element_mode, /* i  : IVAS element mode                          */
    4068             :     const Word16 *old_out,
    4069             :     const Word16 Q_old_out )
    4070             : {
    4071             : 
    4072             :     Word16 Rnd_N_noise;
    4073             :     Word16 k, kk, i;
    4074             :     Word16 N_noise;
    4075             : 
    4076             :     Word16 tmp_fx, ind, q1, q2, L20, flag;
    4077             :     Word16 noisevect_fx[34 * L_FRAME48k / 20], SS_fx[L_FRAME48k / 2];
    4078             :     Word16 *pt1, *pt2, *pt3, *pt4, *pt5;
    4079             :     const Word16 *pt6;
    4080             :     Word32 L_tmp;
    4081             :     const Word16 *sinq_tab;
    4082             : 
    4083             :     const Word16 *p_mdct_ola;
    4084             :     Word16 alignment_point;
    4085             :     // PMTE()
    4086           1 :     L20 = extract_h( L_mult( 1639, L ) ); /*L/20 */
    4087           1 :     IF( element_mode == EVS_MONO )
    4088             :     {
    4089           0 :         alignment_point = sub( shl( L, 1 ), i_mult2( 3, L20 ) );
    4090             :     }
    4091             :     ELSE
    4092             :     {
    4093           1 :         alignment_point = shl( L, 1 );
    4094             :     }
    4095             : 
    4096           1 :     IF( EQ_16( L, L_FRAME32k ) )
    4097             :     {
    4098           1 :         sinq_tab = sinq_32k;
    4099             :     }
    4100           0 :     ELSE IF( EQ_16( L, L_FRAME48k ) )
    4101             :     {
    4102           0 :         sinq_tab = sinq_48k;
    4103             :     }
    4104             :     ELSE
    4105             :     {
    4106           0 :         sinq_tab = sinq_16k;
    4107             :     }
    4108             : 
    4109           1 :     Copy( prevsynth_fx + sub( alignment_point, N ), noisevect_fx, N );
    4110             : 
    4111             :     /* Noise addition on full band  */
    4112             :     /* residual  */
    4113             : 
    4114           1 :     tmp_fx = s_min( N, L );
    4115           1 :     N_noise = shr( tmp_fx, 1 );
    4116           1 :     ind = sub( N, tmp_fx );
    4117           1 :     pt1 = noisevect_fx;
    4118           1 :     pt2 = pt1 + ind;
    4119           1 :     move16();
    4120           1 :     pt3 = &synthesis_fx[ind];
    4121           1 :     move16();
    4122         221 :     FOR( k = 0; k < tmp_fx; k++ )
    4123             :     {
    4124         220 :         ( *pt1++ ) = sub_sat( ( *pt2++ ), ( *pt3++ ) );
    4125         220 :         move16();
    4126             :     }
    4127             : 
    4128           1 :     IF( HqVoicing )
    4129             :     {
    4130           0 :         Scale_sig( noisevect_fx, N, -2 );
    4131             :     }
    4132             : 
    4133           1 :     kk = 0;
    4134           1 :     move16();
    4135           1 :     k = 0;
    4136           1 :     move16();
    4137           1 :     Rnd_N_noise = N_noise;
    4138           1 :     move16();
    4139             : 
    4140           1 :     ind = shl( L, 1 );
    4141           1 :     flag = ind;
    4142           1 :     move16();
    4143           1 :     pt5 = synthesis_fx;
    4144          21 :     WHILE( flag > 0 )
    4145             :     {
    4146          20 :         tmp_fx = Random( ni_seed_forfec );
    4147             : 
    4148          20 :         L_tmp = L_mac( 1503264768, tmp_fx, 9830 );
    4149          20 :         IF( EQ_16( kk, 0 ) )
    4150             :         {
    4151          10 :             L_tmp = L_mac( 1073741824, tmp_fx, 6554 );
    4152             :         }
    4153             : 
    4154          20 :         kk = sub( 1, kk );
    4155          20 :         tmp_fx = round_fx( L_tmp );
    4156          20 :         Rnd_N_noise = extract_h( L_mult( N_noise, tmp_fx ) ); /*Q0 */
    4157             : 
    4158             : 
    4159          20 :         tmp_fx = div_s( 1, Rnd_N_noise );                         /*Q15 */
    4160          20 :         tmp_fx = round_fx( L_shl( L_mult( tmp_fx, 25736 ), 2 ) ); /*Q15 */
    4161             : 
    4162          20 :         sinq_fx( shr( tmp_fx, 1 ), shr( tmp_fx, 2 ), Rnd_N_noise, SS_fx );
    4163             : 
    4164          20 :         pt2 = &noisevect_fx[N_noise];
    4165          20 :         pt1 = pt2 - Rnd_N_noise;
    4166          20 :         pt3 = SS_fx;
    4167          20 :         pt4 = pt3 + sub( Rnd_N_noise, 1 );
    4168          20 :         tmp_fx = s_min( Rnd_N_noise, flag );
    4169        1300 :         FOR( i = 0; i < tmp_fx; i++ )
    4170             :         {
    4171        1280 :             L_tmp = L_mult( ( *pt1++ ), ( *pt3++ ) );           /*Qsynth+16 */
    4172        1280 :             L_tmp = L_mac_sat( L_tmp, ( *pt2++ ), ( *pt4-- ) ); /*Qsynth+16 */
    4173        1280 :             *pt5 = add_sat( *pt5, round_fx_sat( L_tmp ) );
    4174        1280 :             move16(); /*Qsynth */
    4175        1280 :             pt5++;
    4176             :         }
    4177          20 :         flag = sub( flag, tmp_fx );
    4178             :     }
    4179             : 
    4180           1 :     IF( element_mode == EVS_MONO )
    4181             :     {
    4182           0 :         kk = i_mult2( 7, L20 );
    4183           0 :         tmp_fx = i_mult2( 37, L20 );
    4184           0 :         p_mdct_ola = prevsynth_fx + tmp_fx;
    4185             :     }
    4186             :     ELSE
    4187             :     {
    4188           1 :         kk = NS2SA_FX2( L_mult0( L, FRAMES_PER_SEC ), N_ZERO_MDCT_NS );
    4189           1 :         p_mdct_ola = old_out + kk;
    4190             :     }
    4191             : 
    4192             :     /* overlappadd with the ms of valid mdct of the last frame */
    4193           1 :     tmp_fx = i_mult2( 3, L20 );
    4194           1 :     pt1 = &synthesis_fx[0];
    4195           1 :     pt6 = &p_mdct_ola[0];
    4196          97 :     FOR( k = 0; k < tmp_fx; k++ )
    4197             :     {
    4198          96 :         L_tmp = L_mult( *sinq_tab, *sinq_tab ); /*Q31 */
    4199          96 :         sinq_tab++;
    4200          96 :         q2 = round_fx( L_sub( 2147483647, L_tmp ) );                                                  /*Q15 */
    4201          96 :         q1 = round_fx( L_tmp );                                                                       /*Q15 */
    4202          96 :         L_tmp = L_mult( ( *pt1 ), q1 );                                                               /*Qsynth+16 */
    4203          96 :         L_tmp = L_add_sat( L_tmp, L_shr_sat( Mpy_32_16_1( L_deposit_h( *pt6++ ), q2 ), Q_old_out ) ); /*Qsynth+16 */
    4204          96 :         ( *pt1++ ) = round_fx_sat( L_tmp );                                                           /*Qsynth */
    4205          96 :         move16();
    4206             :     }
    4207             : 
    4208           1 :     Copy( synthesis_fx, synthesis_fx + kk, sub( 2 * L, kk ) );
    4209           1 :     Copy( synthesis_fx + L, gapsynth_fx, L );
    4210           1 :     Copy( prevsynth_fx + sub( alignment_point, kk ), synthesis_fx, kk );
    4211           1 : }
    4212             : 
    4213           0 : static void fec_noise_filling_fx(
    4214             :     const Word16 *prevsynth_fx, /*Qsynth   */
    4215             :     Word16 *synthesis_fx,       /*Qsynth */
    4216             :     Word16 *ni_seed_forfec,
    4217             :     const Word16 L,
    4218             :     const Word16 N,
    4219             :     const Word16 HqVoicing,
    4220             :     Word16 *gapsynth_fx /*Qsynth */
    4221             : )
    4222             : {
    4223             : 
    4224             :     Word16 Rnd_N_noise;
    4225             :     Word16 k, kk, i;
    4226             :     Word16 N_noise;
    4227             : 
    4228             :     Word16 tmp_fx, ind, q1, q2, L20, flag;
    4229             :     Word16 noisevect_fx[34 * L_FRAME48k / 20], SS_fx[L_FRAME48k / 2];
    4230             :     Word16 *pt1, *pt2, *pt3, *pt4, *pt5;
    4231             :     const Word16 *pt6;
    4232             :     Word32 L_tmp;
    4233             :     const Word16 *sinq_tab;
    4234             : 
    4235           0 :     IF( EQ_16( L, L_FRAME32k ) )
    4236             :     {
    4237           0 :         sinq_tab = sinq_32k;
    4238             :     }
    4239           0 :     ELSE IF( EQ_16( L, L_FRAME48k ) )
    4240             :     {
    4241           0 :         sinq_tab = sinq_48k;
    4242             :     }
    4243             :     ELSE
    4244             :     {
    4245           0 :         sinq_tab = sinq_16k;
    4246             :     }
    4247             : 
    4248           0 :     L20 = extract_h( L_mult( 1639, L ) ); /*L/20 */
    4249             : 
    4250             :     /*N=47*L/20-delay_ind*decimatefator-6*L/20; */
    4251             : 
    4252           0 :     tmp_fx = sub( sub( shl( L, 1 ), i_mult2( 3, L20 ) ), N );
    4253           0 :     Copy( prevsynth_fx + tmp_fx, noisevect_fx, N );
    4254             : 
    4255             :     /* Noise addition on full band  */
    4256             :     /* residual  */
    4257             : 
    4258           0 :     tmp_fx = s_min( N, L );
    4259           0 :     N_noise = shr( tmp_fx, 1 );
    4260           0 :     ind = sub( N, tmp_fx );
    4261           0 :     pt1 = noisevect_fx;
    4262           0 :     pt2 = pt1 + ind;
    4263           0 :     move16();
    4264           0 :     pt3 = &synthesis_fx[ind];
    4265           0 :     move16();
    4266           0 :     FOR( k = 0; k < tmp_fx; k++ )
    4267             :     {
    4268           0 :         ( *pt1++ ) = sub_sat( ( *pt2++ ), ( *pt3++ ) );
    4269           0 :         move16();
    4270             :     }
    4271             : 
    4272           0 :     IF( HqVoicing )
    4273             :     {
    4274           0 :         Scale_sig( noisevect_fx, N, -2 );
    4275             :     }
    4276             : 
    4277           0 :     kk = 0;
    4278           0 :     move16();
    4279           0 :     k = 0;
    4280           0 :     move16();
    4281           0 :     Rnd_N_noise = N_noise;
    4282           0 :     move16();
    4283             : 
    4284           0 :     ind = shl( L, 1 );
    4285           0 :     flag = ind;
    4286           0 :     move16();
    4287           0 :     pt5 = synthesis_fx;
    4288           0 :     WHILE( flag > 0 )
    4289             :     {
    4290           0 :         tmp_fx = Random( ni_seed_forfec );
    4291             : 
    4292           0 :         L_tmp = L_mac( 1503264768, tmp_fx, 9830 );
    4293           0 :         if ( kk == 0 )
    4294             :         {
    4295           0 :             L_tmp = L_mac( 1073741824, tmp_fx, 6554 );
    4296             :         }
    4297             : 
    4298           0 :         kk = sub( 1, kk );
    4299           0 :         tmp_fx = round_fx( L_tmp );
    4300           0 :         Rnd_N_noise = extract_h( L_mult( N_noise, tmp_fx ) ); /*Q0 */
    4301             : 
    4302             : 
    4303           0 :         tmp_fx = div_s( 1, Rnd_N_noise );                                 /*Q15 */
    4304           0 :         tmp_fx = round_fx_sat( L_shl_sat( L_mult( tmp_fx, 25736 ), 2 ) ); /*Q15 */
    4305             : 
    4306           0 :         sinq_fx( shr( tmp_fx, 1 ), shr( tmp_fx, 2 ), Rnd_N_noise, SS_fx );
    4307             : 
    4308           0 :         pt2 = &noisevect_fx[N_noise];
    4309           0 :         pt1 = pt2 - Rnd_N_noise;
    4310           0 :         pt3 = SS_fx;
    4311           0 :         pt4 = pt3 + sub( Rnd_N_noise, 1 );
    4312           0 :         tmp_fx = s_min( Rnd_N_noise, flag );
    4313           0 :         FOR( i = 0; i < tmp_fx; i++ )
    4314             :         {
    4315           0 :             L_tmp = L_mult( ( *pt1++ ), ( *pt3++ ) );           /*Qsynth+16 */
    4316           0 :             L_tmp = L_mac_sat( L_tmp, ( *pt2++ ), ( *pt4-- ) ); /*Qsynth+16 */
    4317           0 :             *pt5 = add_sat( *pt5, round_fx_sat( L_tmp ) );
    4318           0 :             move16(); /*Qsynth */
    4319           0 :             pt5++;
    4320             :         }
    4321           0 :         flag = sub( flag, tmp_fx );
    4322             :     }
    4323             : 
    4324           0 :     q1 = i_mult2( 7, L20 );
    4325           0 :     q2 = i_mult2( 33, L20 );
    4326             : 
    4327           0 :     Copy( synthesis_fx, synthesis_fx + q1, q2 );
    4328           0 :     Copy( synthesis_fx + L, gapsynth_fx, L );
    4329           0 :     Copy( prevsynth_fx + sub( i_mult2( 37, L20 ), q1 ), synthesis_fx, q1 );
    4330           0 :     pt1 = &synthesis_fx[q1];
    4331           0 :     q2 = i_mult2( 37, L20 );
    4332           0 :     pt6 = &prevsynth_fx[q2];
    4333           0 :     tmp_fx = i_mult2( 3, L20 );
    4334             : 
    4335             :     /* overlappadd with the ms of valid mdct of the last frame */
    4336           0 :     FOR( k = 0; k < tmp_fx; k++ )
    4337             :     {
    4338           0 :         L_tmp = L_mult( *sinq_tab, *sinq_tab ); /*Q30 */
    4339           0 :         sinq_tab++;
    4340           0 :         q2 = round_fx( L_sub( 2147483647, L_tmp ) ); /*Q15 */
    4341           0 :         q1 = round_fx( L_tmp );                      /*Q15 */
    4342           0 :         L_tmp = L_mult( ( *pt1 ), q1 );              /*Qsynth+16 */
    4343           0 :         L_tmp = L_mac( L_tmp, ( *pt6++ ), q2 );      /*Qsynth+16 */
    4344           0 :         ( *pt1++ ) = round_fx( L_tmp );              /*Qsynth */
    4345           0 :         move16();
    4346             :     }
    4347           0 : }
    4348             : 
    4349           1 : static void ivas_fec_alg_fx(
    4350             :     const Word16 *prevsynth,    /*Qin */
    4351             :     const Word16 *prevsynth_LP, /*Qin */
    4352             :     Word16 *ni_seed_forfec,
    4353             :     Word32 *ecu_rec, /*Qin+16 (Qin+15 to be coherent witch other scaling) */
    4354             :     const Word16 output_frame,
    4355             :     const Word16 N,
    4356             :     const Word16 decimatefactor,
    4357             :     const Word16 HqVoicing,
    4358             :     Word16 *gapsynth,          /*Qin */
    4359             :     const Word16 element_mode, /* i  : IVAS element mode                          */
    4360             :     const Word16 *old_out,
    4361             :     const Word16 Q_old_out )
    4362             : {
    4363             :     Word16 Nfft;
    4364             :     Word32 sum_Tf_abs;
    4365             :     Word16 Tfr[FEC_FFT_MAX_SIZE];
    4366             :     Word16 Tfi[FEC_FFT_MAX_SIZE];
    4367             :     Word16 Tf_abs[FEC_FFT_MAX_SIZE / 2];
    4368             :     Word16 synthesis[2 * L_FRAME48k];
    4369             :     Word16 exp;
    4370             :     Word16 n, Q;
    4371             : 
    4372           1 :     ivas_fec_ecu_dft_fx( prevsynth_LP, N, Tfr, Tfi, &sum_Tf_abs, Tf_abs, &Nfft, &exp, element_mode );
    4373             : 
    4374           1 :     sinusoidal_synthesis_fx( Tfr, Tfi, Tf_abs, N, output_frame, decimatefactor, Nfft, sum_Tf_abs, synthesis, HqVoicing, exp );
    4375             : 
    4376           1 :     ivas_fec_noise_filling_fx( prevsynth, synthesis, ni_seed_forfec, output_frame, i_mult2( N, decimatefactor ), HqVoicing, gapsynth, element_mode, old_out, Q_old_out );
    4377             : 
    4378           1 :     n = R1_48 - R2_48;
    4379           1 :     move16();
    4380             : 
    4381           1 :     test();
    4382           1 :     IF( EQ_16( output_frame, L_FRAME32k ) || EQ_16( output_frame, L_FRAME16k ) )
    4383             :     {
    4384           1 :         n = R1_16 - R2_16;
    4385           1 :         move16();
    4386             : 
    4387           1 :         if ( EQ_16( output_frame, L_FRAME32k ) )
    4388             :         {
    4389           1 :             n = 2 * N16_CORE_SW;
    4390           1 :             move16();
    4391             :         }
    4392             :     }
    4393           1 :     Q = 0;
    4394           1 :     move16();
    4395           1 :     wtda_fx( synthesis + sub( output_frame, n ), &Q, ecu_rec,
    4396             :              NULL,
    4397             :              NULL, ALDO_WINDOW, ALDO_WINDOW, output_frame ); /* return Q15 */
    4398             : 
    4399           1 :     return;
    4400             : }
    4401             : 
    4402           0 : static void fec_alg_fx(
    4403             :     const Word16 *prevsynth,    /*Qin */
    4404             :     const Word16 *prevsynth_LP, /*Qin */
    4405             :     Word16 *ni_seed_forfec,
    4406             :     Word32 *ecu_rec, /*Qin+16 (Qin+15 to be coherent witch other scaling) */
    4407             :     const Word16 output_frame,
    4408             :     const Word16 N,
    4409             :     const Word16 decimatefactor,
    4410             :     const Word16 HqVoicing,
    4411             :     Word16 *gapsynth /*Qin */
    4412             : )
    4413             : {
    4414             :     Word16 Nfft;
    4415             :     Word32 sum_Tf_abs;
    4416             :     Word16 Tfr[FEC_FFT_MAX_SIZE];
    4417             :     Word16 Tfi[FEC_FFT_MAX_SIZE];
    4418             :     Word16 Tf_abs[FEC_FFT_MAX_SIZE / 2];
    4419             :     Word16 synthesis[2 * L_FRAME48k];
    4420             :     Word16 exp;
    4421             :     Word16 n, Q;
    4422             : 
    4423           0 :     fec_ecu_dft_fx( prevsynth_LP, N, Tfr, Tfi, &sum_Tf_abs, Tf_abs, &Nfft, &exp );
    4424             : 
    4425           0 :     sinusoidal_synthesis_fx( Tfr, Tfi, Tf_abs, N, output_frame, decimatefactor, Nfft, sum_Tf_abs, synthesis, HqVoicing, exp );
    4426             : 
    4427           0 :     fec_noise_filling_fx( prevsynth, synthesis, ni_seed_forfec, output_frame, i_mult2( N, decimatefactor ), HqVoicing, gapsynth );
    4428             : 
    4429           0 :     n = R1_48 - R2_48;
    4430           0 :     move16();
    4431             : 
    4432           0 :     test();
    4433           0 :     IF( EQ_16( output_frame, L_FRAME32k ) || EQ_16( output_frame, L_FRAME16k ) )
    4434             :     {
    4435           0 :         n = R1_16 - R2_16;
    4436           0 :         move16();
    4437             : 
    4438           0 :         if ( EQ_16( output_frame, L_FRAME32k ) )
    4439             :         {
    4440           0 :             n = 2 * N16_CORE_SW;
    4441           0 :             move16();
    4442             :         }
    4443             :     }
    4444           0 :     Q = 0;
    4445           0 :     move16();
    4446           0 :     wtda_fx( synthesis + sub( output_frame, n ), &Q, ecu_rec,
    4447             :              NULL,
    4448             :              NULL, ALDO_WINDOW, ALDO_WINDOW, output_frame ); /* return Q15 */
    4449             : 
    4450           0 :     return;
    4451             : }
    4452             : 
    4453             : /*--------------------------------------------------------------------------
    4454             :  *  hq_phase_ecu_fx()
    4455             :  *
    4456             :  *  Main routine for HQ phase ECU
    4457             :  *--------------------------------------------------------------------------*/
    4458             : 
    4459         132 : static void ivas_hq_phase_ecu_fx(
    4460             :     const Word16 *prevsynth,          /* i  : buffer of previously synthesized signal Q0   */
    4461             :     Word32 *ecu_rec,                  /* o  : reconstructed frame in tda domain         */
    4462             :     Word16 *time_offs,                /* i/o: Sample offset for consecutive frame losses Q0*/
    4463             :     Word16 *X_sav,                    /* i/o: Stored spectrum of prototype frame        */
    4464             :     Word16 *Q_spec,                   /* i/o: Q value of stored spectrum                */
    4465             :     Word16 *num_p,                    /* i/o: Number of identified peaks Q0                */
    4466             :     Word16 *plocs,                    /* i/o: Peak locations Q0                            */
    4467             :     Word32 *plocsi,                   /* i/o: Interpolated peak locations           Q16 */
    4468             :     const Word16 env_stab,            /* i  : Envelope stability parameter              */
    4469             :     Word16 *last_fec,                 /* i/o: Flag for usage of pitch dependent ECU     */
    4470             :     Word16 *ph_ecu_active,            /* i  : Phase ECU active flag                     */
    4471             :     const Word16 prev_bfi,            /* i   : indicating burst frame error             */
    4472             :     const Word16 old_is_transient[2], /* i   : flags indicating previous transient frames */
    4473             :     Word16 *mag_chg_1st,              /* i/o: per band magnitude modifier for transients*/
    4474             :     Word16 *Xavg,                     /* i/o: Frequency group average gain to fade to Q0  */
    4475             :     Word16 *beta_mute,                /* o   : Factor for long-term mute Q15                */
    4476             :     const Word16 bwidth_fx,           /* i  : Encoded bandwidth                         */
    4477             :     const Word16 output_frame,        /* i   : frame length                             */
    4478             :     const Word16 pcorr,
    4479             :     const Word16 element_mode /* i  : IVAS element mode                          */
    4480             : )
    4481             : {
    4482             :     Word16 lprot, offset;
    4483             :     Word16 mag_chg[LGW_MAX], ph_dith, X[L_PROT48k];
    4484             :     Word16 seed;
    4485             :     Word16 alpha[LGW_MAX], beta[LGW_MAX];
    4486             : 
    4487             :     const Word16 *old_dec;
    4488             :     Word16 noise_fac;
    4489             :     Word16 ph_ecu_lookahead;
    4490             : 
    4491         132 :     noise_fac = 32767; /* 1.0f in Q15 */
    4492         132 :     move16();
    4493             : 
    4494         132 :     IF( element_mode == EVS_MONO )
    4495             :     {
    4496           0 :         ph_ecu_lookahead = NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), PH_ECU_LOOKAHEAD_NS );
    4497           0 :         move16();
    4498             :     }
    4499             :     ELSE
    4500             :     {
    4501         132 :         ph_ecu_lookahead = 0;
    4502         132 :         move16();
    4503             :     }
    4504         132 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    4505             :     {
    4506         103 :         lprot = L_PROT48k; /* 1536 = (2*output_frame)*1024/1280 */
    4507         103 :         move16();
    4508             :     }
    4509          29 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    4510             :     {
    4511          29 :         lprot = L_PROT32k; /* 1024 */
    4512          29 :         move16();
    4513             :     }
    4514           0 :     ELSE IF( EQ_16( output_frame, L_FRAME16k ) )
    4515             :     {
    4516           0 :         lprot = 512;
    4517           0 :         move16();
    4518             :     }
    4519             :     ELSE
    4520             :     {
    4521           0 :         lprot = 256;
    4522           0 :         move16();
    4523             :     }
    4524             : 
    4525         132 :     test();
    4526         132 :     test();
    4527         132 :     test();
    4528         132 :     IF( prev_bfi == 0 || ( prev_bfi != 0 && *last_fec != 0 && ( EQ_16( *time_offs, output_frame ) ) ) )
    4529             :     {
    4530          54 :         test();
    4531          54 :         test();
    4532             : #ifdef FIX_1179_USAN_PHASEECU
    4533          54 :         if ( !( prev_bfi != 0 && *last_fec != 0 && element_mode == EVS_MONO ) )
    4534             :         {
    4535          54 :             *time_offs = 0; /* IVAS reset of offset time counter, timeoffset variable later also used to calculate burst length */
    4536          54 :             move16();
    4537             :         }
    4538             : #else
    4539             :         // PMT("verify condition compared to float")
    4540             :         if ( !( prev_bfi != 0 && *last_fec != 0 && element_mode == EVS_MONO ) )
    4541             :         {
    4542             :             *time_offs = 0;
    4543             :             move16();
    4544             :         }
    4545             : #endif
    4546             : 
    4547          54 :         offset = add( sub( sub( shl( output_frame, 1 ), lprot ), *time_offs ), ph_ecu_lookahead );
    4548             : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
    4549          54 :         trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
    4550          54 :                       *last_fec, element_mode, alpha, beta, beta_mute, Xavg );
    4551             : #else
    4552             :         trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
    4553             :                       *last_fec, alpha, beta, beta_mute, Xavg );
    4554             : #endif
    4555             : 
    4556          54 :         ivas_spec_ana_fx( prevsynth + offset, plocs, plocsi, num_p, X_sav, output_frame, bwidth_fx, Q_spec, element_mode, &noise_fac, pcorr );
    4557             : 
    4558          54 :         test();
    4559          54 :         IF( prev_bfi != 0 && *last_fec != 0 )
    4560             :         {
    4561             : #ifdef FIX_1179_USAN_PHASEECU
    4562           0 :             *time_offs = add_sat( *time_offs, output_frame ); /* when saturation is reached, this keeps the long term muting on */
    4563             : #else
    4564             :             *time_offs = add( *time_offs, output_frame );
    4565             : #endif
    4566           0 :             move16();
    4567             :         }
    4568             :     }
    4569             :     ELSE
    4570             :     {
    4571          78 :         *time_offs = add_sat( *time_offs, output_frame );
    4572          78 :         move16();
    4573          78 :         offset = sub( shl( output_frame, 1 ), lprot );
    4574             : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
    4575          78 :         trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
    4576             :                       0, element_mode, alpha, beta, beta_mute, Xavg );
    4577             : #else
    4578             :         trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
    4579             :                       0, alpha, beta, beta_mute, Xavg );
    4580             : #endif
    4581             :     }
    4582             : 
    4583         132 :     Copy( X_sav, X, lprot );
    4584             : 
    4585             :     /* seed for own_rand2 */
    4586         132 :     seed = *time_offs;
    4587         132 :     move16();
    4588         132 :     IF( *num_p > 0 )
    4589             :     {
    4590         132 :         seed = extract_l( L_add( L_deposit_l( seed ), L_deposit_l( plocs[*num_p - 1] ) ) );
    4591             :     }
    4592             : 
    4593         132 :     ivas_subst_spec_fx( plocs, plocsi, num_p, *time_offs, X, mag_chg, ph_dith, old_is_transient, output_frame, &seed,
    4594         132 :                         alpha, beta, *beta_mute, Xavg, element_mode, ph_ecu_lookahead, noise_fac );
    4595             : 
    4596             :     /* reconstructed frame in tda domain */
    4597         132 :     old_dec = prevsynth + sub( shl( output_frame, 1 ), NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS ) );
    4598         132 :     ivas_rec_frame_fx( X, ecu_rec, output_frame, *Q_spec, old_dec, element_mode, num_p, plocs );
    4599             : 
    4600         132 :     *last_fec = 0;
    4601         132 :     move16();
    4602         132 :     *ph_ecu_active = 1;
    4603         132 :     move16();
    4604         132 : }
    4605             : 
    4606           0 : static void hq_phase_ecu_fx(
    4607             :     const Word16 *prevsynth,          /* i  : buffer of previously synthesized signal Q0   */
    4608             :     Word32 *ecu_rec,                  /* o  : reconstructed frame in tda domain         */
    4609             :     Word16 *time_offs,                /* i/o: Sample offset for consecutive frame losses Q0*/
    4610             :     Word16 *X_sav,                    /* i/o: Stored spectrum of prototype frame        */
    4611             :     Word16 *Q_spec,                   /* i/o: Q value of stored spectrum                */
    4612             :     Word16 *num_p,                    /* i/o: Number of identified peaks Q0                */
    4613             :     Word16 *plocs,                    /* i/o: Peak locations Q0                            */
    4614             :     Word32 *plocsi,                   /* i/o: Interpolated peak locations           Q16 */
    4615             :     const Word16 env_stab,            /* i  : Envelope stability parameter              */
    4616             :     Word16 *last_fec,                 /* i/o: Flag for usage of pitch dependent ECU     */
    4617             :     Word16 *ph_ecu_active,            /* i  : Phase ECU active flag                     */
    4618             :     const Word16 prev_bfi,            /* i   : indicating burst frame error             */
    4619             :     const Word16 old_is_transient[2], /* i   : flags indicating previous transient frames */
    4620             :     Word16 *mag_chg_1st,              /* i/o: per band magnitude modifier for transients*/
    4621             :     Word16 *Xavg,                     /* i/o: Frequency group average gain to fade to Q0   */
    4622             :     Word16 *beta_mute,                /* o   : Factor for long-term mute Q15                */
    4623             :     const Word16 bwidth_fx,           /* i  : Encoded bandwidth                         */
    4624             :     const Word16 output_frame         /* i   : frame length                             */
    4625             : )
    4626             : {
    4627             :     Word16 lprot, offset;
    4628             :     Word16 mag_chg[LGW_MAX], ph_dith, X[L_PROT48k];
    4629             :     Word16 seed;
    4630             :     Word16 alpha[LGW_MAX], beta[LGW_MAX];
    4631             : 
    4632           0 :     IF( EQ_16( output_frame, L_FRAME48k ) )
    4633             :     {
    4634           0 :         lprot = L_PROT48k; /* 1536 = (2*output_frame)*1024/1280 */
    4635           0 :         move16();
    4636             :     }
    4637           0 :     ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
    4638             :     {
    4639           0 :         lprot = L_PROT32k; /* 1024 */
    4640           0 :         move16();
    4641             :     }
    4642           0 :     ELSE IF( output_frame == L_FRAME16k )
    4643             :     {
    4644           0 :         lprot = 512;
    4645           0 :         move16();
    4646             :     }
    4647             :     ELSE
    4648             :     {
    4649           0 :         lprot = 256;
    4650           0 :         move16();
    4651             :     }
    4652             : 
    4653           0 :     test();
    4654           0 :     test();
    4655           0 :     test();
    4656           0 :     IF( prev_bfi == 0 || ( prev_bfi != 0 && *last_fec != 0 && ( EQ_16( *time_offs, output_frame ) ) ) )
    4657             :     {
    4658           0 :         test();
    4659             : #ifndef FIX_1179_USAN_PHASEECU
    4660             :         // PMT("verify condition compared to float")
    4661             : #endif
    4662           0 :         if ( !( prev_bfi != 0 && *last_fec != 0 ) )
    4663             :         {
    4664           0 :             *time_offs = 0;
    4665           0 :             move16();
    4666             :         }
    4667             : 
    4668           0 :         offset = sub( sub( shl( output_frame, 1 ), lprot ), *time_offs );
    4669             : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
    4670           0 :         trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
    4671           0 :                       *last_fec, EVS_MONO, alpha, beta, beta_mute, Xavg );
    4672             : #else
    4673             :         trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
    4674             :                       *last_fec, alpha, beta, beta_mute, Xavg );
    4675             : #endif
    4676             : 
    4677           0 :         spec_ana_fx( prevsynth + offset, plocs, plocsi, num_p, X_sav, output_frame, bwidth_fx, Q_spec );
    4678             : 
    4679           0 :         test();
    4680           0 :         IF( prev_bfi != 0 && *last_fec != 0 )
    4681             :         {
    4682             : #ifdef FIX_1179_USAN_PHASEECU
    4683           0 :             *time_offs = add_sat( *time_offs, output_frame );
    4684             : #else
    4685             :             *time_offs = add( *time_offs, output_frame );
    4686             : #endif
    4687           0 :             move16();
    4688             :         }
    4689             :     }
    4690             :     ELSE
    4691             :     {
    4692             : #ifdef FIX_1179_USAN_PHASEECU
    4693           0 :         *time_offs = add_sat( *time_offs, output_frame );
    4694             : #else
    4695             :         *time_offs = add( *time_offs, output_frame );
    4696             : #endif
    4697           0 :         move16();
    4698             : 
    4699           0 :         offset = sub( shl( output_frame, 1 ), lprot );
    4700             : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
    4701           0 :         trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
    4702             :                       0, EVS_MONO, alpha, beta, beta_mute, Xavg );
    4703             : #else
    4704             :         trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
    4705             :                       0, alpha, beta, beta_mute, Xavg );
    4706             : #endif
    4707             :     }
    4708             : 
    4709           0 :     Copy( X_sav, X, lprot );
    4710             : 
    4711             :     /* seed for own_rand2 */
    4712           0 :     seed = *time_offs;
    4713           0 :     move16();
    4714           0 :     IF( *num_p > 0 )
    4715             :     {
    4716             : #ifdef FIX_1179_USAN_PHASEECU
    4717           0 :         seed = add_sat( seed, plocs[*num_p - 1] );
    4718             : #else
    4719             :         seed = add( seed, plocs[*num_p - 1] );
    4720             : #endif
    4721             :     }
    4722             : 
    4723           0 :     subst_spec_fx( plocs, plocsi, num_p, *time_offs, X, mag_chg, ph_dith, old_is_transient, output_frame, &seed,
    4724           0 :                    alpha, beta, *beta_mute, Xavg );
    4725             : 
    4726             :     /* reconstructed frame in tda domain */
    4727           0 :     rec_frame_fx( X, ecu_rec, output_frame, *Q_spec );
    4728             : 
    4729           0 :     *last_fec = 0;
    4730           0 :     move16();
    4731           0 :     *ph_ecu_active = 1;
    4732           0 :     move16();
    4733           0 : }
    4734             : 
    4735             : 
    4736             : /*--------------------------------------------------------------------------
    4737             :  *  hq_ecu()
    4738             :  *
    4739             :  *  Main routine for HQ ECU
    4740             :  *--------------------------------------------------------------------------*/
    4741             : 
    4742         133 : void ivas_hq_ecu_fx(
    4743             :     const Word16 *prevsynth,          /* i  : buffer of previously synthesized signal Q0     */
    4744             :     Word32 *ecu_rec,                  /* o  : reconstructed frame in tda domain           */
    4745             :     Word16 *time_offs,                /* i/o: Sample offset for consecutive frame losses Q0  */
    4746             :     Word16 *X_sav,                    /* i/o: Stored spectrum of prototype frame          */
    4747             :     Word16 *Q_spec,                   /* i/o: Q value of stored spectrum                  */
    4748             :     Word16 *num_p,                    /* i/o: Number of identified peaks Q0                  */
    4749             :     Word16 *plocs,                    /* i/o: Peak locations Q0                             */
    4750             :     Word32 *plocsi,                   /* i/o: Interpolated peak locations             Q16 */
    4751             :     const Word16 env_stab,            /* i  : Envelope stability parameter                */
    4752             :     Word16 *last_fec,                 /* i/o: Flag for usage of pitch dependent ECU       */
    4753             :     const Word16 ph_ecu_HqVoicing,    /* i  : HQ Voicing flag                             */
    4754             :     Word16 *ph_ecu_active,            /* i  : Phase ECU active flag                       */
    4755             :     Word16 *gapsynth,                 /* o  : Gap synthesis                               */
    4756             :     const Word16 prev_bfi,            /* i  : indicating burst frame error                */
    4757             :     const Word16 old_is_transient[2], /* i  : flags indicating previous transient frames  */
    4758             :     Word16 *mag_chg_1st,              /* i/o: per band magnitude modifier for transients  */
    4759             :     Word16 *Xavg,                     /* i/o: Frequency group average gain to fade to Q0    */
    4760             :     Word16 *beta_mute,                /* o   : Factor for long-term mute Q15                  */
    4761             :     const Word16 output_frame,        /* i   : frame length                               */
    4762             :     Decoder_State *st_fx              /* i/o: decoder state structure                     */
    4763             : )
    4764             : {
    4765             :     Word16 N;
    4766             :     Word16 decimatefactor;
    4767             :     Word16 corr; /*Q15 */
    4768             :     Word16 prevsynth_LP[2 * L_FRAME8k];
    4769             :     HQ_DEC_HANDLE hHQ_core;
    4770             :     const Word16 *fec_alg_input;
    4771             :     Word16 evs_mode_selection;
    4772             :     Word16 ivas_mode_selection;
    4773             : 
    4774         133 :     hHQ_core = st_fx->hHQ_core;
    4775         133 :     corr = 0;
    4776         133 :     move16();
    4777         133 :     IF( EQ_16( st_fx->element_mode, EVS_MONO ) )
    4778             :     {
    4779           0 :         fec_alg_input = prevsynth + NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), ACELP_LOOK_NS / 2 - PH_ECU_LOOKAHEAD_NS );
    4780             :     }
    4781             :     ELSE
    4782             :     {
    4783         133 :         fec_alg_input = prevsynth - NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), PH_ECU_LOOKAHEAD_NS );
    4784             :     }
    4785             :     /* init (values ar changed after) */
    4786             : 
    4787             : 
    4788             :     /* find pitch and R value */
    4789             : 
    4790         133 :     IF( !( LT_16( output_frame, L_FRAME16k ) ) )
    4791             :     {
    4792         133 :         fec_ecu_pitch_ivas_fx( fec_alg_input, prevsynth_LP, output_frame, &N, &corr, &decimatefactor, ph_ecu_HqVoicing );
    4793             :     }
    4794             :     ELSE
    4795             :     {
    4796           0 :         corr = 0;
    4797           0 :         decimatefactor = 4;
    4798           0 :         move16();
    4799           0 :         N = shr( output_frame, 2 );
    4800           0 :         move16(); /* just to avoid using uninitialized value in if statement below */
    4801             :     }
    4802             : 
    4803         133 :     test();
    4804         133 :     test();
    4805         133 :     test();
    4806         133 :     test();
    4807         133 :     test();
    4808         133 :     test();
    4809         133 :     test();
    4810         133 :     test();
    4811         133 :     test();
    4812         133 :     test();
    4813         133 :     test();
    4814         133 :     test();
    4815         133 :     test();
    4816         133 :     test();
    4817         133 :     test();
    4818             : 
    4819         133 :     evs_mode_selection = ( GE_32( st_fx->total_brate, 48000 ) && ( GE_16( output_frame, L_FRAME16k ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) &&
    4820         399 :                                                                    ( ph_ecu_HqVoicing || ( ( ( GT_16( hHQ_core->env_stab_plc_fx, 16384 ) /* 0.5 in Q15 */ ) && ( LT_16( corr, 19661 ) /* 0.6 in Q15 */ ) ) || ( LT_16( hHQ_core->env_stab_plc_fx, 16384 ) /* 0.5 in Q15 */ && ( GT_16( corr, 27853 ) /* 0.85 in Q15 */ ) ) ) ) ) ) ||
    4821         266 :                          ( LT_32( st_fx->total_brate, 48000 ) && ( ( ph_ecu_HqVoicing || GT_16( corr, 27853 ) /* 0.85 in Q15 */ ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) ) );
    4822             : 
    4823         133 :     test();
    4824         133 :     ivas_mode_selection = ( LT_16( N, PH_ECU_N_LIMIT ) ) || ( LT_16( corr, PH_ECU_CORR_LIMIT_Q15 ) );
    4825         133 :     test();
    4826         133 :     test();
    4827         133 :     test();
    4828         133 :     test();
    4829         133 :     IF( ( ( st_fx->element_mode == EVS_MONO ) && evs_mode_selection ) ||
    4830             :         ( ( st_fx->element_mode != EVS_MONO ) && evs_mode_selection && ivas_mode_selection ) )
    4831             :     {
    4832           1 :         ivas_fec_alg_fx( fec_alg_input, prevsynth_LP, &st_fx->hHQ_core->ni_seed_forfec, ecu_rec, output_frame, N, decimatefactor, ph_ecu_HqVoicing, gapsynth, st_fx->element_mode, st_fx->hHQ_core->old_out_fx, st_fx->hHQ_core->Q_old_wtda );
    4833           1 :         *last_fec = 1;
    4834           1 :         move16();
    4835           1 :         *ph_ecu_active = 0;
    4836           1 :         move16();
    4837           1 :         *time_offs = output_frame;
    4838           1 :         move16();
    4839             :     }
    4840             :     ELSE
    4841             :     {
    4842         132 :         ivas_hq_phase_ecu_fx( prevsynth - NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), PH_ECU_LOOKAHEAD_NS ), ecu_rec, time_offs, X_sav, Q_spec, num_p, plocs, plocsi,
    4843             :                               env_stab, last_fec, ph_ecu_active, prev_bfi, old_is_transient,
    4844         132 :                               mag_chg_1st, Xavg, beta_mute, st_fx->bwidth, output_frame, corr, st_fx->element_mode );
    4845             : 
    4846         132 :         *last_fec = 0;
    4847         132 :         move16();
    4848         132 :         *ph_ecu_active = 1;
    4849         132 :         move16();
    4850             :     }
    4851         133 :     return;
    4852             : }
    4853             : 
    4854           0 : void hq_ecu_fx(
    4855             :     const Word16 *prevsynth,          /* i  : buffer of previously synthesized signal Q0     */
    4856             :     Word32 *ecu_rec,                  /* o  : reconstructed frame in tda domain           */
    4857             :     Word16 *time_offs,                /* i/o: Sample offset for consecutive frame losses Q0  */
    4858             :     Word16 *X_sav,                    /* i/o: Stored spectrum of prototype frame          */
    4859             :     Word16 *Q_spec,                   /* i/o: Q value of stored spectrum                  */
    4860             :     Word16 *num_p,                    /* i/o: Number of identified peaks Q0                 */
    4861             :     Word16 *plocs,                    /* i/o: Peak locations Q0                             */
    4862             :     Word32 *plocsi,                   /* i/o: Interpolated peak locations             Q16 */
    4863             :     const Word16 env_stab,            /* i  : Envelope stability parameter                */
    4864             :     Word16 *last_fec,                 /* i/o: Flag for usage of pitch dependent ECU       */
    4865             :     const Word16 ph_ecu_HqVoicing,    /* i  : HQ Voicing flag                             */
    4866             :     Word16 *ph_ecu_active,            /* i  : Phase ECU active flag                       */
    4867             :     Word16 *gapsynth,                 /* o  : Gap synthesis                               */
    4868             :     const Word16 prev_bfi,            /* i  : indicating burst frame error                */
    4869             :     const Word16 old_is_transient[2], /* i  : flags indicating previous transient frames  */
    4870             :     Word16 *mag_chg_1st,              /* i/o: per band magnitude modifier for transients  */
    4871             :     Word16 *Xavg,                     /* i/o: Frequency group average gain to fade to Q0    */
    4872             :     Word16 *beta_mute,                /* o   : Factor for long-term mute Q15                 */
    4873             :     const Word16 output_frame,        /* i   : frame length                               */
    4874             :     Decoder_State *st_fx              /* i/o: decoder state structure                     */
    4875             : )
    4876             : {
    4877             :     Word16 N;
    4878             :     Word16 decimatefactor;
    4879             :     Word16 corr; /*Q15 */
    4880             :     Word16 prevsynth_LP[2 * L_FRAME8k];
    4881             :     /* init (values ar changed after) */
    4882           0 :     decimatefactor = 4;
    4883           0 :     move16();
    4884           0 :     N = shr( output_frame, 2 );
    4885             : 
    4886             : 
    4887             :     /* find pitch and R value */
    4888             : 
    4889           0 :     IF( !( LT_16( output_frame, L_FRAME16k ) ) )
    4890             :     {
    4891           0 :         fec_ecu_pitch_fx( prevsynth + NS2SA_FX2( L_mult0( output_frame, 50 ), ACELP_LOOK_NS / 2 - PH_ECU_LOOKAHEAD_NS ), prevsynth_LP, output_frame, &N, &corr, &decimatefactor, ph_ecu_HqVoicing );
    4892             :     }
    4893             :     ELSE
    4894             :     {
    4895           0 :         corr = 0;
    4896           0 :         move16(); /* just to avoid using uninitialized value in if statement below */
    4897             :     }
    4898             : 
    4899           0 :     test();
    4900           0 :     test();
    4901           0 :     test();
    4902           0 :     test();
    4903           0 :     test();
    4904           0 :     test();
    4905           0 :     test();
    4906           0 :     test();
    4907           0 :     test();
    4908           0 :     test();
    4909           0 :     test();
    4910           0 :     test();
    4911           0 :     test();
    4912           0 :     test();
    4913           0 :     test();
    4914           0 :     IF( ( GE_32( st_fx->total_brate, 48000 ) &&
    4915             :           ( GE_16( output_frame, L_FRAME16k ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) && ( NE_16( ph_ecu_HqVoicing, 0 ) || ( ( ( NE_16( st_fx->hHQ_core->env_stab_plc_fx, 0 ) ) && ( LT_16( corr, 19661 ) ) ) || ( !( NE_16( st_fx->hHQ_core->env_stab_plc_fx, 0 ) ) && ( GT_16( corr, 27853 ) ) ) ) ) ) ) ||
    4916             :         ( LT_32( st_fx->total_brate, 48000 ) && ( ( ph_ecu_HqVoicing || GT_16( corr, 27853 ) ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) ) ) )
    4917             :     {
    4918             : 
    4919           0 :         fec_alg_fx( prevsynth + NS2SA_FX2( L_mult0( output_frame, 50 ), ACELP_LOOK_NS / 2 - PH_ECU_LOOKAHEAD_NS ), prevsynth_LP, &st_fx->hHQ_core->ni_seed_forfec, ecu_rec, output_frame, N, decimatefactor, ph_ecu_HqVoicing, gapsynth );
    4920           0 :         *last_fec = 1;
    4921           0 :         move16();
    4922           0 :         *ph_ecu_active = 0;
    4923           0 :         move16();
    4924           0 :         *time_offs = output_frame;
    4925           0 :         move16();
    4926             :     }
    4927             :     ELSE
    4928             :     {
    4929           0 :         hq_phase_ecu_fx( prevsynth, ecu_rec, time_offs, X_sav, Q_spec, num_p, plocs, plocsi,
    4930             :                          env_stab, last_fec, ph_ecu_active, prev_bfi, old_is_transient,
    4931           0 :                          mag_chg_1st, Xavg, beta_mute, st_fx->bwidth, output_frame );
    4932             :     }
    4933           0 :     return;
    4934             : }
    4935             : 
    4936             : /*******************************************************************************
    4937             :  * The square root of x which MUST be 0.5 <= x < 1, i.e., x must be normalized.
    4938             :  * sqrt(x) is approximated by a polynomial of degree n.
    4939             :  *
    4940             :  * sqrt(x) = a0 x^n + a1 x^(n-1) + a2 x^(n-2) + ... + an
    4941             :  *         = (...((a0 x + a1) x + a2) x + ...) x + an
    4942             :  *
    4943             :  * The coefficients can be readily obtained by the following open source Octave
    4944             :  * (or commercial Matlab) script:
    4945             :  * order = 2;
    4946             :  * N = 400;
    4947             :  * x = linspace(0.5, 1.0, N);
    4948             :  * y = sqrt(x);
    4949             :  * p = polyfit(x, y, order)
    4950             :  * z = polyval(p, x);
    4951             :  * err = y - z;
    4952             :  * plot(err);
    4953             :  ******************************************************************************/
    4954             : 
    4955       28581 : static Word16 sqrt2ndOrder(                /* o: in Q15 (2nd order least square approx.) */
    4956             :                             const Word16 x /* i: x must be in between 0.5 and 1.0 (Q15). */
    4957             : )
    4958             : {
    4959             :     Word32 acc;
    4960             :     Word16 z;
    4961             : 
    4962       28581 :     acc = 1890205600L; /*  0.880195572812922 in Q31 */
    4963       28581 :     move32();
    4964       28581 :     z = mac_r( acc, x, -6506 ); /* -0.198537395405340 in Q15 */
    4965       28581 :     acc = 682030261L;           /*  0.317595089462249 in Q31 */
    4966       28581 :     move32();
    4967       28581 :     z = mac_r( acc, z, x ); /* in Q15 */
    4968       28581 :     return z;
    4969             : }
    4970             : 
    4971             : /*-----------------------------------------------------------------------------
    4972             :  * windowing()
    4973             :  *
    4974             :  * Apply a symmetric Hamming or Hamming-Rectangular window to the signal.
    4975             :  * If the "rectLength" parameter is zero, it is Hamming window; otherwise, the
    4976             :  * rectLength signifies the length of the rectangular part of the Hamming-Rectangular
    4977             :  * window.
    4978             :  *--------------------------------------------------------------------------- */
    4979         108 : static void windowing(
    4980             :     const Word16 *x,         /* i: Input signal Qx*/
    4981             :     Word16 *y,               /* o: Windowed output Qx*/
    4982             :     const Word16 *win,       /* i: Window coefficients Q15*/
    4983             :     const Word16 rectLength, /* i: Offset in between the 1st and 2nd symmetric halves of the Hamming window */
    4984             :     const Word16 halfLength  /* i: Half of the total length of a complete Hamming window. */
    4985             : )
    4986             : {
    4987             :     Word16 i;
    4988             :     Word16 *pY;
    4989             :     const Word16 *pX, *pW;
    4990         108 :     pX = x;
    4991         108 :     pW = win;
    4992         108 :     pY = y;
    4993       17132 :     FOR( i = 0; i < halfLength; i++ ) /* 1st symmetric half of the Hamming window */
    4994             :     {
    4995       17024 :         *pY++ = mult_r( *pX++, *pW++ );
    4996       17024 :         move16();
    4997             :     }
    4998         108 :     FOR( i = 0; i < rectLength; i++ ) /* If rectLength is zero, it's a pure Hamming window; otherwise Hamming-Rectangular. */
    4999             :     {
    5000           0 :         *pY++ = *pX++;
    5001           0 :         move16();
    5002             :     }
    5003       17132 :     FOR( i = 0; i < halfLength; i++ ) /* 2nd symmetric half of the Hamming window. */
    5004             :     {
    5005       17024 :         *pY++ = mult_r( *pX++, *( --pW ) );
    5006       17024 :         move16();
    5007             :     }
    5008         108 : }
    5009             : 
    5010             : /*-----------------------------------------------------------------------------
    5011             :  * windowing_ROM_optimized()
    5012             :  *
    5013             :  * The coefficients of the Hamming window are derived from the sine table
    5014             :  * shared with fft3_fx().
    5015             :  * The entire Hamming-Rectangular window is decomposed into 5 segments:
    5016             :  *   1. 1st half of the left half of the Hamming window
    5017             :  *   2. 2nd half of the left half of the Hamming window
    5018             :  *   3. The flat part of the rectangular region
    5019             :  *   4. 1st half of the right half of the Hamming window
    5020             :  *   5. 2nd half of the right half of the Hamming window
    5021             :  *----------------------------------------------------------------------------*/
    5022           0 : static void windowing_ROM_optimized(
    5023             :     const Word16 *x,          /* i: Input signal Qin*/
    5024             :     Word16 *y,                /* o: Windowed output Qin*/
    5025             :     const Word16 downSamples, /* i: Offset in accessing the sine table. */
    5026             :     const Word16 rectLength,  /* i: Length of the rectangular portion (excluding the Hamming window part) */
    5027             :     const Word16 halfLength   /* i: Half of the total length of the Hamming (excluding rectangular part) window */
    5028             : )
    5029             : {
    5030             :     Word16 i, hamm, quarterLen, initOffset;
    5031             :     Word16 *pY;
    5032             :     const Word16 *pX, *pSine;
    5033             :     Word32 acc;
    5034             : 
    5035           0 :     quarterLen = shr( halfLength, 1 ); /* 1/4 length of the entire Hamming (excluding the rectangular part) window. */
    5036           0 :     initOffset = add( T_SIN_PI_2, shr( downSamples, 1 ) );
    5037           0 :     pSine = sincos_t_rad3_fx + initOffset; // Q15
    5038           0 :     pX = x;
    5039           0 :     pY = y;
    5040             : 
    5041             :     /* 1st half of the left half of the Hamming window. */
    5042           0 :     FOR( i = 0; i < quarterLen; i++ )
    5043             :     {
    5044           0 :         pSine -= downSamples;                       /* Decrement address counter */
    5045           0 :         acc = L_deposit_h( FEC_HQ_WIN_A0 );         /* Derive the Hamming window coefficient from the sine table. Q31*/
    5046           0 :         hamm = msu_r( acc, *pSine, FEC_HQ_WIN_A1 ); // Q15
    5047           0 :         *pY++ = mult_r( hamm, *pX++ );              // Qin
    5048           0 :         move16();
    5049             :     }
    5050             : 
    5051             :     /* 2nd half of the left half of the Hamming window. */
    5052           0 :     FOR( i = 0; i < quarterLen; i++ )
    5053             :     {
    5054           0 :         acc = L_deposit_h( FEC_HQ_WIN_A0 );
    5055           0 :         hamm = mac_r_sat( acc, *pSine, FEC_HQ_WIN_A1 );
    5056           0 :         *pY++ = mult_r( hamm, *pX++ );
    5057           0 :         move16();
    5058           0 :         pSine += downSamples; /* Increment address counter */
    5059             :     }
    5060             : 
    5061             :     /* The rectangular flat region */
    5062           0 :     FOR( i = 0; i < rectLength; i++ )
    5063             :     {
    5064           0 :         *pY++ = *pX++;
    5065           0 :         move16();
    5066             :     }
    5067             : 
    5068             :     /* 1st half of the right half of the Hamming window. */
    5069           0 :     FOR( i = 0; i < quarterLen; i++ )
    5070             :     {
    5071           0 :         pSine -= downSamples;                           /* Decrement address counter */
    5072           0 :         acc = L_deposit_h( FEC_HQ_WIN_A0 );             // Q31
    5073           0 :         hamm = mac_r_sat( acc, *pSine, FEC_HQ_WIN_A1 ); // Q15
    5074           0 :         *pY++ = mult_r( hamm, *pX++ );
    5075           0 :         move16();
    5076             :     }
    5077             : 
    5078             :     /* 2nd half of the right half of the Hamming window. */
    5079           0 :     FOR( i = 0; i < quarterLen; i++ )
    5080             :     {
    5081           0 :         acc = L_deposit_h( FEC_HQ_WIN_A0 );
    5082           0 :         hamm = msu_r( acc, *pSine, FEC_HQ_WIN_A1 );
    5083           0 :         *pY++ = mult_r( hamm, *pX++ );
    5084           0 :         move16();
    5085           0 :         pSine += downSamples; /* Increment address counter */
    5086             :     }
    5087           0 : }

Generated by: LCOV version 1.14