LCOV - code coverage report
Current view: top level - lib_lc3plus - plc_tdc_main_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 415 0.0 %
Date: 2025-08-23 01:22:27 Functions: 0 19 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *                        ETSI TS 103 634 V1.5.1                               *
       3             : *              Low Complexity Communication Codec Plus (LC3plus)              *
       4             : *                                                                             *
       5             : * Copyright licence is solely granted through ETSI Intellectual Property      *
       6             : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
       7             : * estoppel or otherwise.                                                      *
       8             : ******************************************************************************/
       9             : 
      10             : #include "defines.h"
      11             : #include "functions.h"
      12             : 
      13             : /*****************************************************************************/
      14             : 
      15             : static Word16 TDC_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg);
      16             : static Word32 TDC_L_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg);
      17             : static void   TDC_highPassFiltering_fx(const Word16 L_buffer, Word16 exc2[], const Word16 l_fir_fer,
      18             :                                        const Word16 *hp_filt);
      19             : static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg);
      20             : static void   TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, Word16 frame_dms, Word16 lp_gainp, Word32 *lp_gainc);
      21             : static void   TDC_random_fx(Word16 *seed, Word16 lg, Word16 *y);
      22             : static Word16 TDC_preemph(Word16 *x, const Word16 fac, const Word16 lg);
      23             : static void   TDC_LPC_residu_fx(const Word16 *a, Word16 *x, Word16 *y, Word16 lg, Word16 m);
      24             : static void   TDC_deemph_fx(const Word16 *x, Word16 *y, const Word16 fac, const Word16 lg, const Word16 mem);
      25             : static void   TDC_LPC_synthesis_fx(const Word16 sh, const Word16 a[], const Word16 x[], Word16 y[], const Word16 lg,
      26             :                                    const Word16 m);
      27             : static void   TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 *x, const Word16 lg);
      28             :  
      29             : const Word16 beforeNextIncArray_fx[4][4] = {{0,0,0,1},
      30             :                                           {0,1,0,1},
      31             :                                           {0,1,1,1},
      32             :                                           {1,1,1,1}};
      33             : const Word16  nextIncArray_fx[4][4] = {{1,0,0,0},
      34             :                                     {1,0,1,0},
      35             :                                     {1,0,1,1},
      36             :                                     {1,1,1,1}};
      37             : static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, Word16 frame_dms);
      38             : static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest);
      39             : 
      40             : /*****************************************************************************/
      41             : 
      42             : 
      43             : /*
      44             :  * processTimeDomainConcealment_Apply_fx
      45             :  *
      46             :  * Parameters:
      47             :  *   pitch_int                i  : integer pitch lag                 Q0
      48             :  *   preemphFac_fx            i  : preemphase factor                 Q15
      49             :  *   A_fx                     i  : lp filter coefficients            Qx
      50             :  *   pcmbufHist_fx            i  : pointer to input signal           Qq_fx_old_exp
      51             :  *   frame_length             i  : frame length                      Q0
      52             :  *   fs_idx                   i  : sample rate index                 Q0
      53             :  *   nbLostFramesInRow        i  : number of consecutive lost frames Q0
      54             :  *   overlap                  i  : overlap length                    Q0
      55             :  *   stabFac_fx               i  : stability factor                  Q15
      56             :  *   fract                    i/o: fraction of lag                   Q0
      57             :  *   seed_fx                  i/o: pointer to seed                   Q0
      58             :  *   gain_p_fx                i/o: pointer to gainp                  Q15
      59             :  *   gain_c_fx                i/o: pointer to gainc                  15Q16
      60             :  *   synth_fx                 o  : pointer to synthesized signal     Q_syn
      61             :  *   Q_syn                    o  : exponent for synthesized signal   Q0
      62             :  *   alpha                    o  : damping factor                    Q15
      63             :  *   scratchBuffer            i  : scratch buffer
      64             :  *
      65             :  * Function:
      66             :  *    Perform the time domain concealment.
      67             :  *
      68             :  * Returns:
      69             :  *    void
      70             :  */
      71           0 : void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 preemphFac_fx, const Word16 *A_fx,
      72             :                                            const Word16 lpc_order, const Word16 *pcmbufHist_fx, const Word16 frame_length,
      73             :                                            const Word16 frame_dms, const Word16 fs_idx, const Word16 nbLostFramesInRow,
      74             :                                            const Word16 overlap, const Word16 stabFac_fx, Word16 *fract,
      75             :                                            Word16 *seed_fx, 
      76             :                                            Word32 *gain_c_fx, Word16 *synth_fx, Word16 *Q_syn, Word16 *alpha, Word16 max_len_pcm_plc,
      77             :                                            Word16 harmonicBuf_fx[MAX_PITCH], Word16 synthHist_fx[M], Word16 *const harmonicBuf_Q,
      78             :                                            Word8 *scratchBuffer
      79             :                                            , UWord8 plc_fadeout_type
      80             :                                            , Word16 * alpha_type_2_table
      81             : )
      82             : {
      83             :     Counter       i;
      84             :     Word16        s, s1, c1, c2, len, cnt, g_fx, ilen, Tc, nextInc, beforeNextInc;
      85             :     Word32        tmp32, tmp32_2, gainc_tmp;
      86             :     Word16        gain_p_fx;
      87             :     Word32        gain_c_32_fx;
      88             :     Word16        gain_c_16_fx, gain_c_16_fx_exp, gain_inov_fx, gain_inov_fx_exp, ilen_exp;
      89             :     Word16        hpBlendFac;
      90             :     Word16        len_pi_lf_2, frame_length_2, step_fx, step_n_fx, gain_h_fx, nbLostCmpt_loc, mem_deemph;
      91             :     Word16 *      synth_mem_fx, *synth_tmp_fx, *exc2_fx, *exc_fx, *pt_exc, *pt1_exc, *x_pre_fx;
      92             :     Word16 *      harmonicBufPtr;
      93           0 :     Word16        Q_exc = 0, exp_scale;
      94             :     const Word16 *hp_filt_fx, *TDC_high_harm;
      95             :     Word16        alphaPrev_fx;
      96             :     Word16        throttle;
      97             :     Word16        frame_dms_idx, nbLostFramesInRow_mod;
      98             : 
      99             : #ifdef DYNMEM_COUNT
     100             :     Dyn_Mem_In("processTimeDomainConcealment_Apply_fx", sizeof(struct {
     101             :                    Counter i;
     102             :                    Word16 s, s1, c1, c2, len, cnt, g_fx, ilen, Tc, nextInc, beforeNextInc;
     103             :                    Word32 tmp32, tmp32_2, gainc_tmp;
     104             :                    Word16  gain_p_fx;
     105             :                    Word32  gain_c_32_fx;
     106             :                    Word16  gain_c_16_fx, gain_c_16_fx_exp, gain_inov_fx, gain_inov_fx_exp, ilen_exp;
     107             :                    Word16  hpBlendFac;
     108             :                    Word16  len_pi_lf_2, frame_length_2, step_fx, step_n_fx, gain_h_fx, nbLostCmpt_loc, mem_deemph;
     109             :                    Word16 *      synth_mem_fx, *synth_tmp_fx, *exc2_fx, *exc_fx, *pt_exc, *pt1_exc, *x_pre_fx;
     110             :                    Word16 *      harmonicBufPtr;
     111             :                    Word16        Q_exc, exp_scale;
     112             :                    const Word16 *hp_filt_fx, *TDC_high_harm;
     113             :                    Word16        alphaPrev_fx;
     114             :                    Word16        throttle;
     115             :                    Word16        frame_dms_idx, nbLostFramesInRow_mod;
     116             :                }));
     117             : #endif
     118             : 
     119           0 :     Word32 plc_fadeout_len = 0;
     120           0 :     if (plc_fadeout_type >= 1){
     121           0 :         plc_fadeout_len = PLC_FADEOUT_TYPE_1_IN_MS;
     122             :     }
     123             :     else{
     124           0 :         plc_fadeout_len = PLC_FADEOUT_IN_MS;
     125             :     }
     126             : 
     127             :     /* len of output signal */
     128           0 :     len = add(frame_length, overlap);
     129             : 
     130           0 :     nbLostFramesInRow_mod = sub(nbLostFramesInRow, 1) & 0x0003;
     131             :     
     132           0 :     frame_dms_idx  = mult(frame_dms, 0x051F);
     133           0 :     nbLostCmpt_loc = add(shr(L_mult0(frame_dms_idx, sub(nbLostFramesInRow, 1)), 2), 1);
     134           0 :     frame_dms_idx  = sub(frame_dms_idx, 1);
     135           0 :     beforeNextInc = beforeNextIncArray_fx[frame_dms_idx][nbLostFramesInRow_mod]; move16();
     136           0 :     nextInc       = nextIncArray_fx      [frame_dms_idx][nbLostFramesInRow_mod]; move16();
     137             : 
     138           0 :     IF (sub(nbLostCmpt_loc, plc_fadeout_len / 10) > 0)
     139             :     {
     140           0 :         gain_p_fx  = 0; move16();
     141           0 :         *gain_c_fx = 0; move32();
     142           0 :         *Q_syn     = 0; move16();
     143           0 :         *alpha     = 0; move16();
     144           0 :         basop_memset(synth_fx, 0, len * sizeof(Word16));
     145             : #ifdef DYNMEM_COUNT
     146             :         Dyn_Mem_Out();
     147             : #endif
     148           0 :         return;
     149             :     }
     150             : 
     151           0 :     frame_length_2 = shr_pos(frame_length, 1);
     152             : 
     153           0 :     Tc = pitch_int; move16();
     154           0 :     if (sub(*fract, 0) > 0)
     155             :     {
     156           0 :         Tc = add(Tc, 1);
     157             :     }
     158             : 
     159           0 :     len_pi_lf_2 = add(Tc, frame_length_2);
     160             : 
     161             :     /*----------------------------------------------------------------
     162             :      * Buffer Initialization
     163             :      *
     164             :      *                exc_fx       synth_mem_fx
     165             :      * |--exc_buf_past--|--exc_buf_curr--|--syn_mem--|--x_pre--|
     166             :      *                                               |--exc2--|
     167             :      *                                               |--syn--|
     168             :      *
     169             :      *---------------------------------------------------------------*/
     170             : 
     171             :     /* pointer inits */
     172           0 :     exc_fx       = (Word16 *)scratchAlign(scratchBuffer,
     173             :                                     sizeof(Word16) * len_pi_lf_2); /* MAX_PITCH+MAX_LEN/2 + MAX_LEN+MDCT_MEM_LEN_MAX */
     174           0 :     synth_mem_fx = (Word16 *)scratchAlign(exc_fx, sizeof(*exc_fx) * len);           /* M */
     175           0 :     x_pre_fx     = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_PITCH+MAX_LEN/2+M+1 */
     176           0 :     exc2_fx      = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_LEN+MDCT_MEM_LEN_MAX+TDC_L_FIR_HP-1 */
     177           0 :     synth_tmp_fx = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_LEN+MDCT_MEM_LEN_MAX */
     178             :     /* Buffers 'overlap' since they are not used at the same time */
     179             : 
     180             :     /*---------------------------------------------------------------*
     181             :      * LPC Residual                                                  *
     182             :      *---------------------------------------------------------------*/
     183           0 :     IF (sub(nbLostFramesInRow, 1) == 0)
     184             :     {
     185             :  
     186             :     /* copy buffer to pre-emphasis buffer */
     187           0 :         cnt = add(len_pi_lf_2, lpc_order + 1);
     188           0 :         basop_memmove(&x_pre_fx[0], &pcmbufHist_fx[max_len_pcm_plc - cnt], cnt * sizeof(Word16));
     189             : 
     190             :         /* apply pre-emphasis to the signal; x_pre = x_pre_flt * 2^(q_fx_old_exp-15-Q_exc+1) */
     191           0 :         Q_exc = TDC_preemph(&(x_pre_fx[1]), preemphFac_fx, sub(cnt, 1));
     192             : 
     193             :         /* copy memory for LPC synth */
     194           0 :         basop_memmove(&synth_mem_fx[0], &x_pre_fx[len_pi_lf_2 + 1], lpc_order * sizeof(Word16));
     195             : 
     196             :         /* LPC Residual; exc = exc_fx * 2^(q_fx_old_exp-15-Q_exc) */
     197           0 :         TDC_LPC_residu_fx(A_fx, &(x_pre_fx[lpc_order + 1]), &(exc_fx[-len_pi_lf_2]), len_pi_lf_2, lpc_order);
     198             :     }
     199             : 
     200             :     /*---------------------------------------------------------------*
     201             :      * Calculate gains                                               *
     202             :      *---------------------------------------------------------------*/
     203             : 
     204           0 :     IF (sub(nbLostFramesInRow, 1) == 0)
     205             :     {
     206           0 :         IF (sub(pitch_int, Tc) == 0)
     207             :         {
     208             :             gain_p_fx =
     209           0 :                 round_fx_sat(L_shl_sat(TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 1]), frame_length_2), 15));
     210             :         }
     211             :         ELSE
     212             :         {
     213           0 :             tmp32   = TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 2]), frame_length_2);
     214           0 :             tmp32_2 = TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 1]), frame_length_2);
     215             : 
     216           0 :             IF (L_sub(tmp32, tmp32_2) > 0)
     217             :             {
     218           0 :                 Tc         = pitch_int; move16();
     219           0 :                 gain_p_fx = round_fx_sat(L_shl_sat(tmp32, 15));
     220           0 :                 *fract     = 0; move16();
     221             :             }
     222             :             ELSE
     223             :             {
     224           0 :                 gain_p_fx = round_fx_sat(L_shl_sat(tmp32_2, 15));
     225             :             }
     226             :         }
     227             : 
     228           0 :         if (gain_p_fx < 0)
     229             :         {
     230           0 :             gain_p_fx = 0; move16();
     231             :         }
     232             : 
     233           0 :         IF (sub(pitch_int, Tc) == 0)
     234             :         {
     235             :             /* gain_c = gain_c_32_fx * 2^(q_fx_old_exp-31) */
     236           0 :             TDC_calcGainc(exc_fx, Q_exc, Tc, frame_length_2, frame_dms, gain_p_fx, &gain_c_32_fx);
     237             :         }
     238             :         ELSE
     239             :         {
     240           0 :             TDC_calcGainc(exc_fx, Q_exc, pitch_int, frame_length_2, frame_dms, gain_p_fx, &tmp32);
     241           0 :             TDC_calcGainc(exc_fx, Q_exc, Tc       , frame_length_2, frame_dms, gain_p_fx, &gain_c_32_fx);
     242             : 
     243           0 :             gain_c_32_fx = L_min(gain_c_32_fx, tmp32); move32();
     244             :         }
     245             :     }
     246             :     ELSE
     247             :     {
     248           0 :         gain_c_32_fx = *gain_c_fx; move32();
     249           0 :         gain_p_fx = *alpha;
     250             :     }
     251             : 
     252             :     /*---------------------------------------------------------------*
     253             :      * Damping factor                                                *
     254             :      *---------------------------------------------------------------*/
     255             : 
     256           0 :     alphaPrev_fx = 0x7FFF; move16();
     257           0 :     IF (sub(nbLostFramesInRow,1) > 0)
     258             :     {
     259           0 :         alphaPrev_fx = *alpha; move16();
     260             :     }
     261           0 :     IF (sub(plc_fadeout_type,2) == 0 ){
     262           0 :         *alpha = alpha_type_2_table[nbLostFramesInRow];
     263             :     }
     264             :     ELSE{
     265           0 :     IF (nextInc != 0)
     266             :     {
     267           0 :         IF (sub(nbLostCmpt_loc, 1) == 0)
     268             :         {
     269             :             /* Threshold 31470 is 0.98^2 in Q15 format */
     270           0 :             IF (sub(gain_p_fx, 31470) > 0)
     271             :             {
     272           0 :                 *alpha = 0x7D71; /*0.98f*/
     273           0 :                 move16();
     274             :             }
     275             :             /* Threshold 28037 is 0.925^2 in Q15 format */
     276           0 :             ELSE IF (sub(gain_p_fx, 28037) < 0)
     277             :             {
     278           0 :                 *alpha = 0x7666; /*0.925f*/
     279           0 :                 move16();
     280             :             }
     281             :             ELSE
     282             :             {
     283           0 :                 exp_scale = 0;
     284           0 :                 *alpha    = Sqrt16_lc3plus(gain_p_fx, &exp_scale); move16();
     285           0 :                 *alpha    = shl(*alpha, exp_scale);
     286             :             }
     287             :         }
     288             :         ELSE
     289             :         {
     290           0 :             SWITCH (nbLostCmpt_loc)
     291             :             {
     292           0 :             case 2:
     293           0 :                 c1 = 0x50A4; /*0.630f*/
     294           0 :                 move16();
     295           0 :                 c2 = 0x2CCD; /*0.350f*/
     296           0 :                 move16();
     297           0 :                 BREAK;
     298           0 :             default:
     299           0 :                 c1 = 0x5375; /*0.652f*/
     300           0 :                 move16();
     301           0 :                 c2 = 0x29FC; /*0.328f*/
     302           0 :                 move16();
     303           0 :                 BREAK;
     304             :             }
     305             : 
     306           0 :             *alpha = mult_r(stabFac_fx, c2);
     307           0 :             *alpha = add(*alpha, c1);
     308             : 
     309           0 :             *alpha = mult(gain_p_fx, *alpha);
     310             : 
     311             : 
     312           0 :             IF (sub(nbLostCmpt_loc, 2) == 0)
     313             :             {
     314           0 :                 if (sub(*alpha, 0x75A2 /*0.919f*/) < 0)
     315             :                 {
     316           0 :                     *alpha = 0x75A2; move16();
     317             :                 }
     318             :             }
     319           0 :             ELSE IF (sub(nbLostCmpt_loc, 5) > 0)
     320             :             {
     321           0 :                 gain_p_fx = *alpha; move16();
     322             :             }
     323             :         }
     324             :     }
     325             : 
     326           0 :     IF (sub(nbLostCmpt_loc,3) > 0)
     327             :     {
     328           0 :       SWITCH (frame_dms)
     329             :       {
     330           0 :       case  25: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK;
     331           0 :       case  50: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK;
     332           0 :       case  75: *alpha = mult(*alpha, PLC34_ATTEN_FAC_075_FX); BREAK;
     333           0 :       case 100: *alpha = mult(*alpha, PLC34_ATTEN_FAC_100_FX); BREAK;
     334             :       }
     335           0 :     }
     336           0 :     if (sub(nbLostCmpt_loc, 5) > 0)
     337             :     {
     338           0 :         gain_p_fx = *alpha; move16();
     339             :     }
     340             :   }
     341             : 
     342             :     /*---------------------------------------------------------------*
     343             :      * Construct the harmonic part                                   *
     344             :      *  Last pitch cycle of the previous frame is repeatedly copied. *
     345             :      *---------------------------------------------------------------*/
     346             : 
     347           0 :     pt_exc  = harmonicBuf_fx; move16();
     348           0 :     pt1_exc = exc_fx - Tc;    move16();
     349           0 :     s       = s_min(len, Tc); move16();
     350           0 :     test();
     351           0 :     IF (sub(nbLostFramesInRow, 1) == 0)
     352             :     {
     353           0 :         *harmonicBuf_Q = Q_exc; move16();
     354           0 :         IF (sub(stabFac_fx, 32767 /*1.f Q15*/) >= 0)
     355             :         {
     356           0 :             basop_memmove(pt_exc, pt1_exc, Tc * sizeof(Word16));
     357             :         }
     358             :         ELSE
     359             :         {
     360             :             /* These values are necessary for the last five filtered samples */
     361           0 :             basop_memmove(exc_fx, &exc_fx[-Tc], (TDC_L_FIR_HP-1)/2 * sizeof(Word16));
     362           0 :             TDC_high_harm = TDC_high_32_harm;
     363           0 :             if (sub(fs_idx, 1) <= 0)
     364             :             {
     365           0 :                 TDC_high_harm = TDC_high_16_harm;
     366             :             }
     367           0 :             FOR (i = 0; i < Tc; i++)
     368             :             {
     369           0 :                 pt_exc[i] = TDC_Dot_product(&pt1_exc[i-(TDC_L_FIR_HP-1)/2], TDC_high_harm, TDC_L_FIR_HP);
     370             :             }
     371             :         }
     372             :     }
     373             :     ELSE
     374             :     {
     375           0 :         Q_exc = *harmonicBuf_Q; move16();
     376             :     }
     377             : 
     378             :     
     379             :     /*---------------------------------------------------------------*
     380             :      * Construct the random part of excitation                       *
     381             :      *---------------------------------------------------------------*/
     382             : 
     383           0 :     TDC_random_fx(seed_fx, add(len, sub(TDC_L_FIR_HP, 1)), exc2_fx);
     384             : 
     385             :     /* high pass noise */
     386           0 :     hp_filt_fx = TDC_high_32;
     387           0 :     if (sub(fs_idx, 1) <= 0)
     388             :     {
     389           0 :         hp_filt_fx = TDC_high_16;
     390             :     }
     391             : 
     392           0 :     IF (sub(nbLostFramesInRow, 1) == 0)
     393             :     {
     394           0 :         TDC_highPassFiltering_fx(len, exc2_fx, TDC_L_FIR_HP, hp_filt_fx);
     395             :     }
     396             :     ELSE
     397             :     {
     398           0 :         throttle = div_s(nbLostCmpt_loc, add(nbLostCmpt_loc, PLC3_HPBLENDTHROTTLE));
     399           0 :         hpBlendFac = mult(sub(0x7FFF, *alpha), throttle);
     400           0 :         c1 = sub(0x7FFF, hpBlendFac);
     401           0 :         FOR (i = 0; i < len; i++)
     402             :         {
     403             :             /* Return value of dot product is Q1 */
     404           0 :             tmp32      = Mpy_32_16_lc3plus(TDC_L_Dot_product(&exc2_fx[i], hp_filt_fx, TDC_L_FIR_HP), c1 /*Q15*/);
     405           0 :             exc2_fx[i] = round_fx(L_mac0(tmp32, hpBlendFac, exc2_fx[i+TDC_L_FIR_HP/2])); move16();
     406             :         }
     407             :     }
     408             : 
     409             :     /* normalize energy */
     410           0 :     TDC_normalize_energy_fx(&gain_inov_fx, &gain_inov_fx_exp, exc2_fx, frame_length);
     411           0 :     tmp32 = Mpy_32_16_lc3plus(
     412             :         L_sub(590558016l /*1.1 Q29*/, Mpy_32_16_lc3plus(L_shr_pos(L_deposit_h(gain_p_fx), 2), 24576 /*0.75*/)) /*Q29*/,
     413             :         gain_inov_fx /*Q15,gain_inov_e*/); /*Q29,gain_inov_e*/
     414           0 :     s                = norm_l(tmp32);
     415           0 :     tmp32            = L_shl_pos(tmp32, s);
     416           0 :     tmp32            = L_min(tmp32, 0x7FFEFFFF);
     417           0 :     gain_inov_fx_exp = add(sub(gain_inov_fx_exp, s), 31 - 29); /*->Q31*/
     418           0 :     gain_inov_fx     = round_fx(tmp32);                        /*Q15,gain_inov_e*/
     419             : 
     420             :     /* gains */
     421           0 :     gain_h_fx = alphaPrev_fx; move16();
     422             : 
     423             :     /* update steps */
     424           0 :     if (frame_length == 720)
     425             :     {
     426           0 :         ilen = BASOP_Util_Divide1616_Scale_lc3plus((Word16)1, 960, &ilen_exp);
     427             :     } else {
     428           0 :         ilen = BASOP_Util_Divide1616_Scale_lc3plus((Word16)1, frame_length, &ilen_exp);
     429             :     }
     430           0 :     step_fx = round_fx(L_shl(L_mult(sub(gain_h_fx, *alpha), ilen), ilen_exp));
     431             : 
     432           0 :     s     = norm_l(gain_c_32_fx);
     433           0 :     tmp32 = L_shl_pos(gain_c_32_fx, s);
     434             : 
     435           0 :     gain_c_16_fx     = extract_h(tmp32);
     436           0 :     gain_c_16_fx_exp = sub(15, s);
     437           0 :     gainc_tmp = L_mult (gain_c_16_fx, div_s(*alpha, s_max(alphaPrev_fx, 1)));
     438           0 :     tmp32     = L_sub (tmp32, gainc_tmp);
     439           0 :     step_n_fx = round_fx(L_shl(Mpy_32_16_lc3plus(tmp32, ilen), ilen_exp));
     440             : 
     441             :     /*---------------------------------------------------------------*
     442             :      * Construct the total excitation                                *
     443             :      *---------------------------------------------------------------*/
     444             : 
     445           0 :     harmonicBufPtr = harmonicBuf_fx + ((nbLostFramesInRow - 1) * frame_length) % Tc;
     446             : 
     447           0 :     s1  = add(Q_exc, add(gain_inov_fx_exp, gain_c_16_fx_exp));
     448           0 :     cnt = add(frame_length, TDC_L_FIR_HP / 2);
     449             : 
     450           0 :     g_fx = mult_r(gain_c_16_fx, gain_inov_fx);
     451             : 
     452           0 :     FOR (i = 0; i < len; i++)
     453             :     {
     454             :         /* harmonic */
     455           0 :         if (harmonicBufPtr - harmonicBuf_fx >= Tc) {
     456           0 :             harmonicBufPtr = harmonicBuf_fx;
     457             :         }
     458           0 :         exc_fx[i] = *harmonicBufPtr++;
     459           0 :         tmp32 = L_mult(exc_fx[i], gain_h_fx);
     460             :         /* random */
     461           0 :         tmp32_2 = L_shl_sat(L_mult(exc2_fx[i], g_fx), s1);
     462             :         /* total */
     463           0 :         exc_fx[i] = round_fx_sat(L_add_sat(tmp32, tmp32_2)); move16();
     464             :         /* update */
     465           0 :         gain_h_fx    = s_max(sub(gain_h_fx, step_fx), 0);
     466           0 :         gain_c_16_fx = s_max(sub(gain_c_16_fx, step_n_fx), 0);
     467           0 :         g_fx = mult_r(gain_c_16_fx, gain_inov_fx);
     468             :     }
     469             : 
     470             :     /* update gain */
     471           0 :     *gain_c_fx = L_shl(gainc_tmp, sub(gain_c_16_fx_exp, 15)); move32();
     472             : 
     473             : 
     474             :     /*----------------------------------------------------------*
     475             :      * Compute the synthesis speech                             *
     476             :      *----------------------------------------------------------*/
     477             : 
     478             :     /* introduce some headroom to avoid Overflows, 2 bit seem to be sufficient */
     479           0 :     *Q_syn = sub(Q_exc, 2);
     480           0 :     *Q_syn = s_max(*Q_syn, -3);
     481             : 
     482           0 :     exp_scale = sub(*Q_syn, Q_exc - 1);
     483             : 
     484           0 :     IF (sub(nbLostFramesInRow, 1) != 0)
     485             :     {
     486           0 :         synth_mem_fx = synthHist_fx;
     487             :     }
     488           0 :     Copy_Scale_sig(synth_mem_fx, &synth_tmp_fx[-lpc_order], lpc_order, exp_scale);
     489           0 :     TDC_LPC_synthesis_fx(sub(Q_exc, *Q_syn), A_fx, exc_fx, synth_tmp_fx, len, lpc_order);
     490             : 
     491           0 :     FOR (i=0; i<lpc_order; i++)
     492             :     {
     493           0 :         synthHist_fx[i] = shr_sat(synth_tmp_fx[frame_length-lpc_order+i], exp_scale);
     494             :     }
     495             :   
     496             :     /*----------------------------------------------------------*
     497             :      * Deemphasis                                               *
     498             :      *----------------------------------------------------------*/
     499             : 
     500           0 :     mem_deemph = shl_sat(pcmbufHist_fx[max_len_pcm_plc - 1], *Q_syn);
     501           0 :     TDC_deemph_fx(synth_tmp_fx, synth_fx, preemphFac_fx, len, mem_deemph);
     502             : 
     503             :     /*----------------------------------------------------------*
     504             :      * Fade to zero                                             *
     505             :      *----------------------------------------------------------*/
     506             : 
     507           0 :     IF (beforeNextInc != 0)
     508             :     {
     509           0 :         IF (sub(nbLostCmpt_loc, plc_fadeout_len / 10) == 0)
     510             :         {
     511           0 :             gain_h_fx = (Word16)0x7FFF; move16();
     512           0 :             step_fx   = round_fx(L_shl(L_mult(gain_h_fx, ilen), ilen_exp));
     513           0 :             FOR (i = 0; i < frame_length; i++)
     514             :             {
     515           0 :                 assert(gain_h_fx >= 0);
     516           0 :                 synth_fx[i] = mult(synth_fx[i], gain_h_fx);
     517           0 :                 gain_h_fx   = sub(gain_h_fx, step_fx);
     518             :             }
     519           0 :             basop_memset(&synth_fx[frame_length], 0, overlap * sizeof(Word16));
     520             :         }
     521             :     }
     522             : 
     523             : #ifdef DYNMEM_COUNT
     524             :     Dyn_Mem_Out();
     525             : #endif
     526             : }
     527             : 
     528             : 
     529             : /*****************************************************************************/
     530             : 
     531           0 : static Word32 syn_kern_2(Word32 L_tmp, const Word16 a[], const Word16 y[])
     532             : {
     533           0 :     L_tmp = L_msu_sat(L_tmp, y[-1], a[1]);
     534           0 :     L_tmp = L_msu_sat(L_tmp, y[-2], a[2]);
     535           0 :     return L_tmp;
     536             : }
     537             : 
     538           0 : static Word32 syn_kern_4(Word32 L_tmp, const Word16 a[], const Word16 y[])
     539             : {
     540           0 :     L_tmp = syn_kern_2(L_tmp, a, y);
     541           0 :     return syn_kern_2(L_tmp, a + 2, y - 2);
     542             : }
     543             : 
     544           0 : static Word32 syn_kern_8(Word32 L_tmp, const Word16 a[], const Word16 y[])
     545             : {
     546           0 :     L_tmp = syn_kern_4(L_tmp, a, y);
     547           0 :     return syn_kern_4(L_tmp, a + 4, y - 4);
     548             : }
     549             : 
     550           0 : static Word32 syn_kern_16(Word32 L_tmp, const Word16 a[], const Word16 y[])
     551             : {
     552           0 :     L_tmp = syn_kern_8(L_tmp, a, y);
     553           0 :     return syn_kern_8(L_tmp, a + 8, y - 8);
     554             : }
     555             : 
     556             : /*
     557             :  * TDC_Dot_product
     558             :  *
     559             :  * Parameters:
     560             :  *   x     i: x vector       Q0
     561             :  *   y     i: y vector       Q0
     562             :  *   lg    i: vector length  Q0
     563             :  *
     564             :  * Function:
     565             :  *   dot product
     566             :  *
     567             :  * Returns:
     568             :  *   dot product             Q0
     569             :  */
     570           0 : static Word16 TDC_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg)
     571             : {
     572             :     Dyn_Mem_Deluxe_In(
     573             :         Counter i;
     574             :         Word32  sum;
     575             :     );
     576             : 
     577           0 :     sum = L_mult(x[0], y[0]);
     578           0 :     FOR (i = 1; i < lg-1; i++)
     579             :     {
     580           0 :         sum = L_mac_sat(sum, x[i], y[i]);
     581             :     }
     582             :     
     583           0 :     sum = mac_r_sat(sum, x[lg-1], y[lg-1]);
     584             : 
     585             :     Dyn_Mem_Deluxe_Out();
     586             : 
     587           0 :     return sum;
     588             : }
     589             : 
     590             : /*
     591             :  * TDC_L_Dot_product
     592             :  *
     593             :  * Parameters:
     594             :  *   x     i: x vector       Q0
     595             :  *   y     i: y vector       Q0
     596             :  *   lg    i: vector length  Q0
     597             :  *
     598             :  * Function:
     599             :  *   dot product
     600             :  *
     601             :  * Returns:
     602             :  *   dot product              Q1
     603             :  */
     604           0 : static Word32 TDC_L_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg)
     605             : {
     606             :     Dyn_Mem_Deluxe_In(
     607             :         Counter i;
     608             :         Word32  sum;
     609             :     );
     610             : 
     611           0 :     sum = L_mac0(1L, x[0], y[0]);
     612           0 :     FOR (i = 1; i < lg; i++)
     613             :     {
     614           0 :         sum = L_mac0(sum, x[i], y[i]);
     615             :     }
     616             : 
     617             :     Dyn_Mem_Deluxe_Out();
     618             : 
     619           0 :     return sum;
     620             : }
     621             : 
     622             : /*
     623             :  * TDC_highPassFiltering_fx
     624             :  *
     625             :  * Parameters:
     626             :  *   L_buffer     i: buffer length
     627             :  *   exc2         i: unvoiced excitation before the high pass filtering  Qx/Qx+1
     628             :  *   l_fir_fer    i: length highpass filter
     629             :  *   hp_filt      i: highpass filter coefficients                        Q15
     630             :  *
     631             :  * Function:
     632             :  *   Highpass filter
     633             :  *
     634             :  * Returns:
     635             :  *   void
     636             :  */
     637           0 : static void TDC_highPassFiltering_fx(const Word16 L_buffer, Word16 exc2[], const Word16 l_fir_fer,
     638             :                                      const Word16 *hp_filt)
     639             : {
     640             :     Dyn_Mem_Deluxe_In(
     641             :         Counter i;
     642             :     );
     643             : 
     644           0 :     FOR (i = 0; i < L_buffer; i++)
     645             :     {
     646           0 :         exc2[i] = round_fx(L_sub(TDC_L_Dot_product(&exc2[i], hp_filt, l_fir_fer), 1)); move16();
     647             :     }
     648             : 
     649             :     Dyn_Mem_Deluxe_Out();
     650           0 : }
     651             : 
     652             : /*
     653             :  * TDC_calcGainc
     654             :  *
     655             :  * Parameters:
     656             :  *   exc        i: pointer to excitation buffer
     657             :  *   Q_exc      i: Q format of excitation buffer
     658             :  *   old_fpitch i: pitch_int
     659             :  *   lg         i: length
     660             :  *   lp_gainp   i: gain p
     661             :  *   lp_gainc   o: pointer to gain (15Q16)
     662             :  *
     663             :  * Function:
     664             :  *   Gain calculation
     665             :  *
     666             :  * Returns:
     667             :  *   void
     668             :  */
     669           0 : static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, Word16 frame_dms, Word16 lp_gainp, Word32 *lp_gainc)
     670             : {
     671             :     Dyn_Mem_Deluxe_In(
     672             :         Word16  tmp16, tmp_e, tmp2_e;
     673             :         Word32  L_tmp, L_tmp_max;
     674             :         Counter i;
     675             :     );
     676             : 
     677           0 :     L_tmp = L_deposit_l(0);
     678             : 
     679           0 :     FOR (i = 0; i < lg; i++)
     680             :     {
     681             :         /* gain_c += ( exc[-i-1] - *gain_p * exc[-i-1-pitch_int] ) * ( exc[-i-1] - *gain_p * exc[-i-1-pitch_int] ); */
     682           0 :         tmp16 = sub_sat(exc[i - lg] /*Q1*/, mult_r(lp_gainp /*Q15*/, exc[i - lg - old_fpitch] /*Q1*/) /*Q1*/);
     683           0 :         L_tmp = L_mac0_sat(L_tmp, tmp16, tmp16); /*Q3*/
     684             :     }
     685             : 
     686           0 :     IF (sub(frame_dms, 100) < 0)
     687             :     {
     688           0 :         L_tmp_max = L_deposit_l(0);
     689           0 :         FOR (i = 0; i < lg; i++)
     690             :         {
     691           0 :             L_tmp_max = L_mac0_sat(L_tmp_max, exc[i - lg], exc[i - lg]); /*Q3*/
     692             :         }
     693           0 :         L_tmp = L_min(L_tmp, L_tmp_max);
     694             :     }
     695             : 
     696           0 :     tmp_e = norm_l(L_tmp);
     697           0 :     L_tmp = L_shl(L_tmp, tmp_e);
     698           0 :     tmp_e = sub(sub(31, shl_pos(Q_exc, 1)), tmp_e); /*L_tmp is Q31, now*/
     699           0 :     tmp16 = BASOP_Util_Divide3216_Scale_lc3plus(L_tmp /*Q31,norm,tmp_e*/, lg /*Q15,15*/, &tmp2_e) /*Q15,tmp2_e+tmp_e-15*/;
     700           0 :     tmp_e = sub(add(tmp2_e, tmp_e), 15);
     701             : 
     702           0 :     IF (tmp16 != 0)
     703             :     {
     704           0 :         tmp16     = Sqrt16_lc3plus(tmp16, &tmp_e); /*Q15,norm,tmp_e*/
     705           0 :         tmp_e     = L_min(tmp_e, 15);
     706           0 :         *lp_gainc = L_shl_pos(L_deposit_l(tmp16), add(tmp_e, 1)); /*15Q16*/
     707           0 :         move32();
     708             :     }
     709             :     ELSE
     710             :     {
     711           0 :         *lp_gainc = 0;
     712             :     }
     713             : 
     714             :     Dyn_Mem_Deluxe_Out();
     715           0 : }
     716             : 
     717             : /*
     718             :  * TDC_calcGainp
     719             :  *
     720             :  * Parameters:
     721             :  *   x      i: input signal
     722             :  *   y      i: shifted input signal
     723             :  *   lg     i: vector length
     724             :  *
     725             :  * Function:
     726             :  *   Gain calculation
     727             :  *
     728             :  * Returns:
     729             :  *   gain (15Q16)
     730             :  */
     731           0 : static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg)
     732             : {
     733             :     Dyn_Mem_Deluxe_In(
     734             :         Word32  tcorr, tener, Lgain, L_tmp1, L_tmp2;
     735             :         Word16  m_corr, m_ener, negative, Q_corr, Q_ener;
     736             :         Counter i;
     737             :     );
     738             : 
     739           0 :     negative = 0; move16();
     740             : 
     741           0 :     L_tmp1 = L_deposit_l(0);
     742           0 :     L_tmp2 = L_deposit_l(0);
     743           0 :     FOR (i = 0; i < lg; i += 2)
     744             :     {
     745           0 :         L_tmp1 = L_mac0_sat(L_tmp1, x[i], y[i]);
     746           0 :         L_tmp2 = L_mac0_sat(L_tmp2, x[i + 1], y[i + 1]);
     747             :     }
     748           0 :     tcorr  = L_add(L_shr_pos(L_tmp1, 1), L_shr_pos(L_tmp2, 1));
     749           0 :     Q_corr = norm_l(tcorr);
     750           0 :     tcorr  = L_shl(tcorr, Q_corr);
     751           0 :     Q_corr = sub(2, Q_corr);
     752             : 
     753           0 :     L_tmp1 = L_deposit_l(0);
     754           0 :     L_tmp2 = L_deposit_l(0);
     755           0 :     FOR (i = 0; i < lg; i += 2)
     756             :     {
     757           0 :         L_tmp1 = L_mac0_sat(L_tmp1, y[i], y[i]);
     758           0 :         L_tmp2 = L_mac0_sat(L_tmp2, y[i + 1], y[i + 1]);
     759             :     }
     760           0 :     tener  = L_add(L_shr_pos(L_tmp1, 1), L_shr_pos(L_tmp2, 1));
     761           0 :     Q_ener = norm_l(tener);
     762           0 :     tener  = L_shl(tener, Q_ener);
     763           0 :     Q_ener = sub(2, Q_ener);
     764             : 
     765           0 :     tener = L_max(tener, 1);
     766             : 
     767           0 :     if (tcorr <= 0)
     768             :     {
     769           0 :         negative = 1; move16();
     770             :     }
     771           0 :     tcorr = L_abs(tcorr);
     772             : 
     773           0 :     m_corr = extract_h(tcorr);
     774             : 
     775           0 :     m_ener = extract_h(tener);
     776             : 
     777           0 :     IF (sub(m_corr, m_ener) > 0)
     778             :     {
     779           0 :         m_corr = shr_pos(m_corr, 1);
     780           0 :         Q_corr = add(Q_corr, 1);
     781             :     }
     782           0 :     if (m_ener == 0)
     783             :     {
     784           0 :         move16();
     785           0 :         m_corr = 0x7FFF;
     786             :     }
     787           0 :     if (m_ener != 0)
     788             :     {
     789           0 :         m_corr = div_s(m_corr, m_ener);
     790             :     }
     791             : 
     792           0 :     Q_corr = sub(Q_corr, Q_ener);
     793             : 
     794           0 :     Lgain = L_shl(L_deposit_l(m_corr), add(Q_corr, 1));
     795             : 
     796           0 :     if (negative != 0)
     797             :     {
     798           0 :         Lgain = L_negate(Lgain);
     799             :     }
     800             : 
     801             :     Dyn_Mem_Deluxe_Out();
     802             : 
     803           0 :     return Lgain;
     804             : }
     805             : 
     806             : /*
     807             :  * TDC_LPC_synthesis_fx
     808             :  *
     809             :  * Parameters:
     810             :  *   sh          i  : scaling to apply for a[0]                 Q0
     811             :  *   a[]         i  : LP filter coefficients                    Qx
     812             :  *   x[]         i  : input signal                              Qx
     813             :  *   y[]         o  : output signal                             Qx-s
     814             :  *   lg          i  : size of filtering                         Q0
     815             :  *   m           i  : order of LP filter                        Q0
     816             :  *
     817             :  * Function:
     818             :  *    Apply LP filtering to obtain synthesis signal.
     819             :  *    Memory size is always m.
     820             :  *
     821             :  * Returns:
     822             :  *    void
     823             :  */
     824           0 : static void TDC_LPC_synthesis_fx(const Word16 sh, const Word16 a[], const Word16 x[], Word16 y[], const Word16 lg,
     825             :                                  const Word16 m)
     826             : {
     827             :     Dyn_Mem_Deluxe_In(
     828             :         Counter i;
     829             :         Word16  a0;
     830             :         Word16  q;
     831             :         Word32(*syn_kern)(Word32 L_tmp, const Word16 a[], const Word16 y[]
     832             :     ););
     833             : 
     834           0 :     ASSERT(m == 16 || m == 8);
     835             : 
     836           0 :     if (sub(m, 16) == 0)
     837             :     {
     838           0 :         syn_kern = syn_kern_16;
     839             :     }
     840           0 :     if (sub(m, 8) == 0)
     841             :     {
     842           0 :         syn_kern = syn_kern_8;
     843             :     }
     844             : 
     845           0 :     q        = add(norm_s(a[0]), 1);
     846           0 :     a0       = shr_sat(a[0], sh);
     847             : 
     848           0 :     FOR (i = 0; i < lg; i++)
     849             :     {
     850           0 :         y[i] = round_fx_sat(L_shl_sat(syn_kern(L_mult(a0, x[i]), a, &y[i]), q)); move16();
     851             :     }
     852             : 
     853             :     Dyn_Mem_Deluxe_Out();
     854           0 : }
     855             : 
     856             : /* TDC_LPC_residu_fx
     857             :  *
     858             :  * Parameters:
     859             :  *    a           I: LP filter coefficients (Qx)
     860             :  *    x           I: input signal
     861             :  *    y           O: output signal
     862             :  *    lg          I: size of filtering
     863             :  *    m           I: lpc order
     864             :  *
     865             :  * Function:
     866             :  *    Apply inverse filtering to obtain LP residual signal.
     867             :  *
     868             :  * Returns:
     869             :  *    void
     870             :  */
     871           0 : static void TDC_LPC_residu_fx(const Word16 *a, Word16 *x, Word16 *y, Word16 lg, Word16 m)
     872             : {
     873             :     Dyn_Mem_Deluxe_In(
     874             :         Word16  a_exp;
     875             :         Word32  s;
     876             :         Counter i;
     877             :     );
     878             : 
     879           0 :     ASSERT(m == 16 || m == 8);
     880             : 
     881           0 :     a_exp = add(norm_s(a[0]), 1);
     882           0 :     a_exp = add(a_exp, 1);
     883             : 
     884           0 :     IF (sub(m, 16) == 0)
     885             :     {
     886           0 :         FOR (i = 0; i < lg; i++)
     887             :         {
     888           0 :             s = L_mult(x[i], a[0]);
     889           0 :             s = L_mac_sat(s, x[i - 1], a[1]);
     890           0 :             s = L_mac_sat(s, x[i - 2], a[2]);
     891           0 :             s = L_mac_sat(s, x[i - 3], a[3]);
     892           0 :             s = L_mac_sat(s, x[i - 4], a[4]);
     893           0 :             s = L_mac_sat(s, x[i - 5], a[5]);
     894           0 :             s = L_mac_sat(s, x[i - 6], a[6]);
     895           0 :             s = L_mac_sat(s, x[i - 7], a[7]);
     896           0 :             s = L_mac_sat(s, x[i - 8], a[8]);
     897           0 :             s = L_mac_sat(s, x[i - 9], a[9]);
     898           0 :             s = L_mac_sat(s, x[i - 10], a[10]);
     899           0 :             s = L_mac_sat(s, x[i - 11], a[11]);
     900           0 :             s = L_mac_sat(s, x[i - 12], a[12]);
     901           0 :             s = L_mac_sat(s, x[i - 13], a[13]);
     902           0 :             s = L_mac_sat(s, x[i - 14], a[14]);
     903           0 :             s = L_mac_sat(s, x[i - 15], a[15]);
     904           0 :             s = L_mac_sat(s, x[i - 16], a[16]);
     905             : 
     906           0 :             s    = L_shl_sat(s, a_exp);
     907           0 :             y[i] = round_fx_sat(s); move16();
     908             :         }
     909             :     }
     910           0 :     IF (sub(m, 8) == 0)
     911             :     {
     912           0 :         FOR (i = 0; i < lg; i++)
     913             :         {
     914           0 :             s = L_mult(x[i], a[0]);
     915           0 :             s = L_mac_sat(s, x[i - 1], a[1]);
     916           0 :             s = L_mac_sat(s, x[i - 2], a[2]);
     917           0 :             s = L_mac_sat(s, x[i - 3], a[3]);
     918           0 :             s = L_mac_sat(s, x[i - 4], a[4]);
     919           0 :             s = L_mac_sat(s, x[i - 5], a[5]);
     920           0 :             s = L_mac_sat(s, x[i - 6], a[6]);
     921           0 :             s = L_mac_sat(s, x[i - 7], a[7]);
     922           0 :             s = L_mac_sat(s, x[i - 8], a[8]);
     923             : 
     924           0 :             s    = L_shl_sat(s, a_exp);
     925           0 :             y[i] = round_fx_sat(s); move16();
     926             :         }
     927             :     }
     928             : 
     929             :     Dyn_Mem_Deluxe_Out();
     930           0 : }
     931             : 
     932             : /* TDC_random_fx
     933             :  *
     934             :  * Parameters:
     935             :  *    seed        i/o: seed for random number
     936             :  *    lg          i  : vector length
     937             :  *    y           o  : output values
     938             :  *
     939             :  * Function:
     940             :  *    Uniform distributed random generator.
     941             :  *
     942             :  * Returns:
     943             :  *    random number
     944             :  */
     945           0 : static void TDC_random_fx(Word16 *seed, Word16 lg, Word16 *y)
     946             : {
     947             :     Dyn_Mem_Deluxe_In(
     948             :         Counter i;
     949             :     );
     950             : 
     951           0 :     FOR (i = 0; i < lg; i++)
     952             :     {
     953           0 :         *seed = extract_l(L_mac0(16831L, *seed, 12821));
     954           0 :         *y++  = *seed; move16();
     955             :     }
     956             : 
     957             :     Dyn_Mem_Deluxe_Out();
     958           0 : }
     959             : 
     960             : /*
     961             :  * TDC_preemph
     962             :  *
     963             :  * Parameters:
     964             :  *    x              i/o: signal             Qx
     965             :  *    fac            i:   preemphasis factor Q15
     966             :  *    lg             i:   vector length
     967             :  *
     968             :  * Function:
     969             :  *    Filtering through 1 - fac z^-1
     970             :  *
     971             :  * Returns:
     972             :  *    Q-factor
     973             :  */
     974           0 : static Word16 TDC_preemph(Word16 *x, const Word16 fac, const Word16 lg)
     975             : {
     976             :     Dyn_Mem_Deluxe_In(
     977             :         Word16  fac_sh, Q_max_value, Q_out;
     978             :         Word32  max_val;
     979             :         Counter i;
     980             :     );
     981             : 
     982           0 :     fac_sh      = shr(fac, 3);
     983           0 :     Q_max_value = 4096; move16();
     984           0 :     Q_out       = 12;   move16();
     985             : 
     986           0 :     max_val = 0; move32();
     987           0 :     FOR (i = sub(lg, 1); i >= 0; i--)
     988             :     {
     989           0 :         max_val = L_max(L_abs(L_msu(L_mult(x[i], Q_max_value), x[i - 1], fac_sh)), max_val);
     990             :     }
     991             : 
     992           0 :     IF (extract_h(max_val) != 0)
     993             :     {
     994           0 :         Q_out = s_min(s_max(sub(norm_s(extract_h(max_val)), 3), 0), 12);
     995             :     }
     996             : 
     997           0 :     FOR (i = sub(lg, 1); i >= 0; i--)
     998             :     {
     999           0 :         x[i] = round_fx(L_shl(L_msu(L_mult(x[i], Q_max_value), x[i - 1], fac_sh), Q_out)); move16();
    1000             :     }
    1001             : 
    1002             :     Dyn_Mem_Deluxe_Out();
    1003             : 
    1004           0 :     return sub(Q_out, 2);
    1005             : }
    1006             : 
    1007             : /*
    1008             :  * TDC_deemph_fx
    1009             :  *
    1010             :  * Parameters:
    1011             :  *    x              i: input signal        Qx
    1012             :  *    y              o: output signal       Qx
    1013             :  *    fac            i: deemphasis factor   Q15
    1014             :  *    lg             i: size of filtering   Q0
    1015             :  *    mem            i: memory (x[-1])
    1016             :  *
    1017             :  * Function:
    1018             :  *    Filtering through 1/(1-fac z^-1)
    1019             :  *
    1020             :  * Returns:
    1021             :  *    void
    1022             :  */
    1023           0 : static void TDC_deemph_fx(const Word16 *x, Word16 *y, const Word16 fac, const Word16 lg, const Word16 mem)
    1024             : {
    1025             :     Dyn_Mem_Deluxe_In(
    1026             :         Counter i;
    1027             :     );
    1028             : 
    1029           0 :     y[0] = round_fx_sat(L_mac_sat(L_deposit_h(x[0]), mem, fac)); move16();
    1030           0 :     FOR (i = 1; i < lg; i++)
    1031             :     {
    1032           0 :         y[i] = round_fx_sat(L_mac_sat(L_deposit_h(x[i]), y[i - 1], fac)); move16();
    1033             :     }
    1034             : 
    1035             :     Dyn_Mem_Deluxe_Out();
    1036           0 : }
    1037             : 
    1038             : /*
    1039             :  * TDC_normalize_energy_fx
    1040             :  *
    1041             :  * Parameters:
    1042             :  *   gain          o: gain
    1043             :  *   gain_exp      o: exponent of gain
    1044             :  *   x             i: input signal
    1045             :  *   lg            i: length of input signal
    1046             :  *
    1047             :  * Function:
    1048             :  *    Normalizes the energy.
    1049             :  *
    1050             :  * Returns:
    1051             :  *    void
    1052             :  */
    1053           0 : static void TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 *x, const Word16 lg)
    1054             : {
    1055             :     Dyn_Mem_Deluxe_In(
    1056             :         Counter i;
    1057             :         Word16  c;
    1058             :         Word16  e;
    1059             :         Word16  e1;
    1060             :         Word16  e2;
    1061             :         Word32  tmp;
    1062             :         Word16  tmp16;
    1063             :     );
    1064             : 
    1065           0 :     tmp = 0; move32();
    1066           0 :     FOR (i = 0; i < lg; i++)
    1067             :     {
    1068           0 :         tmp16 = mult_r(x[i], 2048);
    1069           0 :         tmp   = L_mac(tmp, tmp16, tmp16);
    1070             :     }
    1071             : 
    1072           0 :     e     = norm_l(tmp);
    1073           0 :     tmp   = L_shl_pos(tmp, e);
    1074           0 :     e1    = sub(sub(30, e), -8); move16();
    1075           0 :     tmp16 = BASOP_Util_Divide3216_Scale_lc3plus(tmp, lg, &e2);
    1076             : 
    1077           0 :     e = 0; move16();
    1078           0 :     if (tmp16 != 0)
    1079             :     {
    1080           0 :         e = sub(add(e1, e2), 15);
    1081             :     }
    1082             : 
    1083           0 :     c = 0x0148; /* 0.01 */
    1084           0 :     move16();
    1085           0 :     IF (e > 0)
    1086             :     {
    1087           0 :         c = shr(c, s_min(e, 15));
    1088             :     }
    1089             :     ELSE
    1090             :     {
    1091           0 :         tmp16 = shr(tmp16, s_min(negate(e), 15));
    1092           0 :         e     = 0; move16();
    1093             :     }
    1094             : 
    1095           0 :     e2 = 2; move16();
    1096           0 :     if (s_and(e, 1))
    1097             :     {
    1098           0 :         e2 = 1; move16();
    1099             :     }
    1100             : 
    1101           0 :     tmp16 = add(shr_pos(tmp16, e2), shr_pos(c, e2));
    1102           0 :     e     = add(e, e2);
    1103             : 
    1104           0 :     tmp16 = Sqrt16_lc3plus(tmp16, &e);
    1105             : 
    1106           0 :     *gain     = BASOP_Util_Divide1616_Scale_lc3plus((Word16)0x7FFF, tmp16, &e1); move16();
    1107           0 :     *gain_exp = sub(e1, e);                                              move16();
    1108             : 
    1109             :     Dyn_Mem_Deluxe_Out();
    1110           0 : }
    1111             : 
    1112           0 : static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, Word16 frame_dms)
    1113             : {   
    1114             :     Word16 n_help;
    1115             :     Word32 n_shift;
    1116             : 
    1117           0 :     if (nbLostFramesInRow <= 3*(100.0/frame_dms)){
    1118           0 :         n_help = (nbLostFramesInRow + (100/frame_dms) - 1) * frame_dms;
    1119           0 :         return powWord16rest(31129,n_help/100,n_help%100);
    1120             :     }
    1121             :     else {
    1122           0 :         n_shift = (nbLostFramesInRow - 3*(100/frame_dms)) * 50/frame_dms;
    1123           0 :         n_help = (n_shift + (100/frame_dms) - 1) * frame_dms;
    1124           0 :         return powWord16rest(22937,n_help/100,n_help%100);
    1125             :     }
    1126             : }
    1127             : 
    1128           0 : Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, Word16 frame_dms)
    1129             : {   
    1130             :     Word16 n_help;
    1131           0 :     Word16 selector = PLC_FADEOUT_TYPE_2_SELECTOR * 2 * (100/frame_dms);
    1132             : 
    1133           0 :     if (selector >= nbLostFramesInRow){
    1134           0 :         return type_2_alpha_long(nbLostFramesInRow, frame_dms);
    1135             :     }
    1136             :     else {
    1137           0 :         n_help = (nbLostFramesInRow + (100/frame_dms) - 1) * frame_dms;
    1138           0 :         return powWord16rest(16383,n_help/100, n_help%100);
    1139             :     } 
    1140             : }
    1141             : 
    1142           0 : static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest) {
    1143           0 :     Word32 exp_result = 32767;
    1144             :     Word32 tmp_result;
    1145             :     Word16 root, i, exp2;
    1146             : 
    1147           0 :     FOR (i = 0; i < exp; ++i) {
    1148           0 :         tmp_result = (Word32)exp_result * base;
    1149           0 :         exp_result = (Word16)(tmp_result >> 15);
    1150             :     }
    1151             : 
    1152           0 :     IF (rest != 0) {
    1153           0 :         exp2 = 0;
    1154           0 :         SWITCH (rest)
    1155             :         {
    1156           0 :             case 50:
    1157           0 :                 root = Sqrt16_lc3plus(base, &exp2);
    1158           0 :                 shr(root,exp2);
    1159           0 :                 exp_result = L_shr(exp_result * root,15); /* 0.5^1.5 = 0.5^(3/2) = 0.5^3*sqrt(0.5) */
    1160           0 :                 BREAK;
    1161           0 :             case 25:
    1162           0 :                 root = Sqrt16_lc3plus(base, &exp2);
    1163           0 :                 shr(root,exp2);
    1164           0 :                 exp2 = 0;
    1165           0 :                 root = Sqrt16_lc3plus(root, &exp2);
    1166           0 :                 shr(root,exp2);
    1167           0 :                 exp_result = L_shr(exp_result * root,15); /* 0.5^(1/4) = 0.5^sqrt(sqrt(0.5)) */
    1168           0 :                 BREAK;
    1169           0 :             case 75:
    1170           0 :                 root = Sqrt16_lc3plus(base, &exp2);
    1171           0 :                 shr(root,exp2);
    1172           0 :                 exp2 = 0;
    1173           0 :                 root = Sqrt16_lc3plus(root, &exp2);
    1174           0 :                 shr(root,exp2);
    1175           0 :                 tmp_result = powWord16rest(root, 3, 0);
    1176           0 :                 exp_result = L_shr( exp_result * tmp_result,15);
    1177           0 :                 BREAK;
    1178             :         }
    1179           0 :     }
    1180           0 :     return (Word16) exp_result;
    1181             : }

Generated by: LCOV version 1.14