Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 /*
     12  * decode_plc.c
     13  *
     14  * Packet Loss Concealment.
     15  *
     16  */
     17 
     18 #include <string.h>
     19 
     20 #include "settings.h"
     21 #include "entropy_coding.h"
     22 #include "pitch_estimator.h"
     23 #include "bandwidth_estimator.h"
     24 #include "structs.h"
     25 #include "codec.h"
     26 
     27 
     28 #define NO_OF_PRIMES 8
     29 #define NOISE_FILTER_LEN 30
     30 
     31 /*
     32  * function to decode the bitstream
     33  * returns the total number of bytes in the stream
     34  */
     35 
     36 static int16_t plc_filterma_Fast(
     37     int16_t *In,  /* (i)   Vector to be filtered. InOut[-orderCoef+1]
     38                            to InOut[-1] contains state */
     39     int16_t *Out,  /* (o)   Filtered vector */
     40     int16_t *B,   /* (i)   The filter coefficients (in Q0) */
     41     int16_t Blen,  /* (i)   Number of B coefficients */
     42     int16_t len,   /* (i)  Number of samples to be filtered */
     43     int16_t reduceDecay,
     44     int16_t decay,
     45     int16_t rshift )
     46 {
     47   int i, j;
     48   int32_t o;
     49   int32_t lim = (1 << (15 + rshift)) - 1;
     50 
     51   for (i = 0; i < len; i++)
     52   {
     53     const int16_t *b_ptr = &B[0];
     54     const int16_t *x_ptr = &In[i];
     55 
     56     o = (int32_t)0;
     57 
     58     for (j = 0;j < Blen; j++)
     59     {
     60       o = WebRtcSpl_AddSatW32(o, *b_ptr * *x_ptr);
     61       b_ptr++;
     62       x_ptr--;
     63     }
     64 
     65     /* to round off correctly */
     66     o = WebRtcSpl_AddSatW32(o, 1 << (rshift - 1));
     67 
     68     /* saturate according to the domain of the filter coefficients */
     69     o = WEBRTC_SPL_SAT((int32_t)lim, o, (int32_t)-lim);
     70 
     71     /* o should be in the range of int16_t */
     72     o >>= rshift;
     73 
     74     /* decay the output signal; this is specific to plc */
     75     *Out++ = (int16_t)((int16_t)o * decay >> 15);
     76 
     77     /* change the decay */
     78     decay -= reduceDecay;
     79     if( decay < 0 )
     80       decay = 0;
     81   }
     82   return( decay );
     83 }
     84 
     85 
     86 
     87 
     88 
     89 
     90 
     91 
     92 static __inline int32_t log2_Q8_T( uint32_t x ) {
     93 
     94   int32_t zeros;
     95   int16_t frac;
     96 
     97   zeros=WebRtcSpl_NormU32(x);
     98   frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23);
     99 
    100   /* log2(magn(i)) */
    101   return ((31 - zeros) << 8) + frac;
    102 }
    103 
    104 static __inline int16_t  exp2_Q10_T(int16_t x) { // Both in and out in Q10
    105 
    106   int16_t tmp16_1, tmp16_2;
    107 
    108   tmp16_2=(int16_t)(0x0400|(x&0x03FF));
    109   tmp16_1 = -(x >> 10);
    110   if(tmp16_1>0)
    111     return tmp16_2 >> tmp16_1;
    112   else
    113     return tmp16_2 << -tmp16_1;
    114 
    115 }
    116 
    117 
    118 /*
    119   This is a fixed-point version of the above code with limLow = 700 and limHigh = 5000,
    120   hard-coded. The values 700 and 5000 were experimentally obtained.
    121 
    122   The function implements membership values for two sets. The mebership functions are
    123   of second orders corresponding to half-bell-shapped pulses.
    124 */
    125 static void MemshipValQ15( int16_t in, int16_t *A, int16_t *B )
    126 {
    127   int16_t x;
    128 
    129   in -= 700;    /* translate the lowLim to 0, limHigh = 5000 - 700, M = 2150 */
    130 
    131   if( in <= 2150 )
    132   {
    133     if( in > 0 )
    134     {
    135       /* b = in^2 / (2 * M^2), a = 1 - b in Q0.
    136          We have to compute in Q15 */
    137 
    138       /* x = in / 2150 {in Q15} = x * 15.2409 {in Q15} =
    139          x*15 + (x*983)/(2^12); note that 983/2^12 = 0.23999     */
    140 
    141       /* we are sure that x is in the range of int16_t            */
    142       x = (int16_t)(in * 15 + (in * 983 >> 12));
    143       /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
    144          be in correct domain and one more for the division by 2 */
    145       *B = (int16_t)((x * x + 0x00010000) >> 17);
    146       *A = WEBRTC_SPL_WORD16_MAX - *B;
    147     }
    148     else
    149     {
    150       *B = 0;
    151       *A = WEBRTC_SPL_WORD16_MAX;
    152     }
    153   }
    154   else
    155   {
    156     if( in < 4300 )
    157     {
    158       /* This is a mirror case of the above */
    159       in = 4300 - in;
    160       x = (int16_t)(in * 15 + (in * 983 >> 12));
    161       /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
    162          be in correct domain and one more for the division by 2 */
    163       *A = (int16_t)((x * x + 0x00010000) >> 17);
    164       *B = WEBRTC_SPL_WORD16_MAX - *A;
    165 
    166     }
    167     else
    168     {
    169       *A = 0;
    170       *B = WEBRTC_SPL_WORD16_MAX;
    171     }
    172   }
    173 }
    174 
    175 
    176 
    177 
    178 static void LinearResampler(int16_t* in,
    179                             int16_t* out,
    180                             size_t lenIn,
    181                             size_t lenOut)
    182 {
    183   size_t n = (lenIn - 1) * RESAMP_RES;
    184   int16_t resOut, relativePos, diff; /* */
    185   size_t i, j;
    186   uint16_t udiff;
    187 
    188   if( lenIn == lenOut )
    189   {
    190     WEBRTC_SPL_MEMCPY_W16( out, in, lenIn );
    191     return;
    192   }
    193 
    194   resOut = WebRtcSpl_DivW32W16ResW16( (int32_t)n, (int16_t)(lenOut-1) );
    195 
    196   out[0] = in[0];
    197   for( i = 1, j = 0, relativePos = 0; i < lenOut; i++ )
    198   {
    199 
    200     relativePos += resOut;
    201     while( relativePos > RESAMP_RES )
    202     {
    203       j++;
    204       relativePos -= RESAMP_RES;
    205     }
    206 
    207 
    208     /* an overflow may happen and the differce in sample values may
    209      * require more than 16 bits. We like to avoid 32 bit arithmatic
    210      * as much as possible */
    211 
    212     if( (in[ j ] > 0) && (in[j + 1] < 0) )
    213     {
    214       udiff = (uint16_t)(in[ j ] - in[j + 1]);
    215       out[ i ] = in[ j ] - (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
    216     }
    217     else
    218     {
    219       if( (in[j] < 0) && (in[j+1] > 0) )
    220       {
    221         udiff = (uint16_t)( in[j + 1] - in[ j ] );
    222         out[ i ] = in[ j ] + (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
    223       }
    224       else
    225       {
    226         diff = in[ j + 1 ] - in[ j ];
    227         out[i] = in[j] + (int16_t)(diff * relativePos >> RESAMP_RES_BIT);
    228       }
    229     }
    230   }
    231 }
    232 
    233 
    234 
    235 
    236 
    237 void WebRtcIsacfix_DecodePlcImpl(int16_t *signal_out16,
    238                                  IsacFixDecoderInstance *ISACdec_obj,
    239                                  size_t *current_framesamples )
    240 {
    241   int subframecnt;
    242 
    243   int16_t* Vector_Word16_1;
    244   int16_t  Vector_Word16_Extended_1[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
    245   int16_t* Vector_Word16_2;
    246   int16_t  Vector_Word16_Extended_2[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
    247 
    248   int32_t Vector_Word32_1[FRAMESAMPLES_HALF];
    249   int32_t Vector_Word32_2[FRAMESAMPLES_HALF];
    250 
    251   int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
    252   int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
    253 
    254   int16_t pitchLags_Q7[PITCH_SUBFRAMES];
    255   int16_t pitchGains_Q12[PITCH_SUBFRAMES];
    256 
    257   int16_t tmp_1, tmp_2;
    258   int32_t tmp32a, tmp32b;
    259   int16_t gainQ13;
    260 
    261   int16_t myDecayRate;
    262 
    263   /* ---------- PLC variables ------------ */
    264   size_t lag0, i, k;
    265   int16_t noiseIndex;
    266   int16_t stretchPitchLP[PITCH_MAX_LAG + 10], stretchPitchLP1[PITCH_MAX_LAG + 10];
    267 
    268   int32_t gain_lo_hiQ17[2*SUBFRAMES];
    269 
    270   int16_t nLP, pLP, wNoisyLP, wPriodicLP, tmp16;
    271   size_t minIdx;
    272   int32_t nHP, pHP, wNoisyHP, wPriodicHP, corr, minCorr, maxCoeff;
    273   int16_t noise1, rshift;
    274 
    275 
    276   int16_t ltpGain, pitchGain, myVoiceIndicator, myAbs, maxAbs;
    277   int32_t varIn, varOut, logVarIn, logVarOut, Q, logMaxAbs;
    278   int rightShiftIn, rightShiftOut;
    279 
    280 
    281   /* ------------------------------------- */
    282 
    283 
    284   myDecayRate = (DECAY_RATE);
    285   Vector_Word16_1 = &Vector_Word16_Extended_1[NOISE_FILTER_LEN];
    286   Vector_Word16_2 = &Vector_Word16_Extended_2[NOISE_FILTER_LEN];
    287 
    288 
    289   /* ----- Simply Copy Previous LPC parameters ------ */
    290   for( subframecnt = 0; subframecnt < SUBFRAMES; subframecnt++ )
    291   {
    292     /* lower Band */
    293     WEBRTC_SPL_MEMCPY_W16(&lofilt_coefQ15[ subframecnt * ORDERLO ],
    294                           (ISACdec_obj->plcstr_obj).lofilt_coefQ15, ORDERLO);
    295     gain_lo_hiQ17[2*subframecnt] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0];
    296 
    297     /* Upper Band */
    298     WEBRTC_SPL_MEMCPY_W16(&hifilt_coefQ15[ subframecnt * ORDERHI ],
    299                           (ISACdec_obj->plcstr_obj).hifilt_coefQ15, ORDERHI);
    300     gain_lo_hiQ17[2*subframecnt + 1] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1];
    301   }
    302 
    303 
    304 
    305 
    306   lag0 = (size_t)(((ISACdec_obj->plcstr_obj.lastPitchLag_Q7 + 64) >> 7) + 1);
    307 
    308 
    309   if( (ISACdec_obj->plcstr_obj).used != PLC_WAS_USED )
    310   {
    311     (ISACdec_obj->plcstr_obj).pitchCycles = 0;
    312 
    313     (ISACdec_obj->plcstr_obj).lastPitchLP =
    314         &((ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0]);
    315     minCorr = WEBRTC_SPL_WORD32_MAX;
    316 
    317     if ((FRAMESAMPLES_HALF - 10) > 2 * lag0)
    318     {
    319       minIdx = 11;
    320       for( i = 0; i < 21; i++ )
    321       {
    322         corr = 0;
    323         for( k = 0; k < lag0; k++ )
    324         {
    325           corr = WebRtcSpl_AddSatW32(corr, WEBRTC_SPL_ABS_W32(
    326               WebRtcSpl_SubSatW16(
    327                   (ISACdec_obj->plcstr_obj).lastPitchLP[k],
    328                   (ISACdec_obj->plcstr_obj).prevPitchInvIn[
    329                       FRAMESAMPLES_HALF - 2*lag0 - 10 + i + k ] ) ) );
    330         }
    331         if( corr < minCorr )
    332         {
    333           minCorr = corr;
    334           minIdx = i;
    335         }
    336       }
    337       (ISACdec_obj->plcstr_obj).prevPitchLP =
    338           &( (ISACdec_obj->plcstr_obj).prevPitchInvIn[
    339               FRAMESAMPLES_HALF - lag0*2 - 10 + minIdx] );
    340     }
    341     else
    342     {
    343       (ISACdec_obj->plcstr_obj).prevPitchLP =
    344           (ISACdec_obj->plcstr_obj).lastPitchLP;
    345     }
    346     pitchGain = (ISACdec_obj->plcstr_obj).lastPitchGain_Q12;
    347 
    348     WebRtcSpl_AutoCorrelation(
    349         &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0],
    350         lag0, 0, &varIn, &rightShiftIn);
    351     WebRtcSpl_AutoCorrelation(
    352         &(ISACdec_obj->plcstr_obj).prevPitchInvOut[PITCH_MAX_LAG + 10 - lag0],
    353         lag0, 0, &varOut, &rightShiftOut);
    354 
    355     maxAbs = 0;
    356     for( i = 0; i< lag0; i++)
    357     {
    358       myAbs = WEBRTC_SPL_ABS_W16(
    359           (ISACdec_obj->plcstr_obj).prevPitchInvOut[
    360               PITCH_MAX_LAG + 10 - lag0 + i] );
    361       maxAbs = (myAbs > maxAbs)? myAbs:maxAbs;
    362     }
    363     logVarIn = log2_Q8_T( (uint32_t)( varIn ) ) +
    364         (int32_t)(rightShiftIn << 8);
    365     logVarOut = log2_Q8_T( (uint32_t)( varOut ) ) +
    366         (int32_t)(rightShiftOut << 8);
    367     logMaxAbs = log2_Q8_T( (uint32_t)( maxAbs ) );
    368 
    369     ltpGain = (int16_t)(logVarOut - logVarIn);
    370     Q = 2 * logMaxAbs - ( logVarOut - 1512 );
    371 
    372     /*
    373      * ---
    374      * We are computing sqrt( (VarIn/lag0) / var( noise ) )
    375      * var( noise ) is almost 256. we have already computed log2( VarIn ) in Q8
    376      * so we actually compute 2^( 0.5*(log2( VarIn ) - log2( lag0 ) - log2( var(noise ) )  ).
    377      * Note that put log function is in Q8 but the exponential function is in Q10.
    378      * --
    379      */
    380 
    381     logVarIn -= log2_Q8_T( (uint32_t)( lag0 ) );
    382     tmp16 = (int16_t)((logVarIn<<1) - (4<<10) );
    383     rightShiftIn = 0;
    384     if( tmp16 > 4096 )
    385     {
    386       tmp16 -= 4096;
    387       tmp16 = exp2_Q10_T( tmp16 );
    388       tmp16 >>= 6;
    389     }
    390     else
    391       tmp16 = exp2_Q10_T( tmp16 )>>10;
    392 
    393     (ISACdec_obj->plcstr_obj).std = tmp16 - 4;
    394 
    395     if( (ltpGain < 110) || (ltpGain > 230) )
    396     {
    397       if( ltpGain < 100 && (pitchGain < 1800) )
    398       {
    399         (ISACdec_obj->plcstr_obj).A = WEBRTC_SPL_WORD16_MAX;
    400       }
    401       else
    402       {
    403         (ISACdec_obj->plcstr_obj).A = ((ltpGain < 110) && (Q < 800)
    404                                        )? WEBRTC_SPL_WORD16_MAX:0;
    405       }
    406       (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
    407           (ISACdec_obj->plcstr_obj).A;
    408     }
    409     else
    410     {
    411       if( (pitchGain < 450) || (pitchGain > 1600) )
    412       {
    413         (ISACdec_obj->plcstr_obj).A = ((pitchGain < 450)
    414                                        )? WEBRTC_SPL_WORD16_MAX:0;
    415         (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
    416             (ISACdec_obj->plcstr_obj).A;
    417       }
    418       else
    419       {
    420         myVoiceIndicator = ltpGain * 2 + pitchGain;
    421         MemshipValQ15( myVoiceIndicator,
    422                        &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
    423       }
    424     }
    425 
    426 
    427 
    428     myVoiceIndicator = ltpGain * 16 + pitchGain * 2 + (pitchGain >> 8);
    429     MemshipValQ15( myVoiceIndicator,
    430                    &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
    431 
    432 
    433 
    434     (ISACdec_obj->plcstr_obj).stretchLag = lag0;
    435     (ISACdec_obj->plcstr_obj).pitchIndex = 0;
    436 
    437   }
    438   else
    439   {
    440     myDecayRate = (DECAY_RATE<<2);
    441   }
    442 
    443   if( (ISACdec_obj->plcstr_obj).B < 1000 )
    444   {
    445     myDecayRate += (DECAY_RATE<<3);
    446   }
    447 
    448   /* ------------ reconstructing the residual signal ------------------ */
    449 
    450   LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
    451                    stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
    452   /* inverse pitch filter */
    453 
    454   pitchLags_Q7[0] = pitchLags_Q7[1] = pitchLags_Q7[2] = pitchLags_Q7[3] =
    455       (int16_t)((ISACdec_obj->plcstr_obj).stretchLag<<7);
    456   pitchGains_Q12[3] = ( (ISACdec_obj->plcstr_obj).lastPitchGain_Q12);
    457   pitchGains_Q12[2] = (int16_t)(pitchGains_Q12[3] * 1010 >> 10);
    458   pitchGains_Q12[1] = (int16_t)(pitchGains_Q12[2] * 1010 >> 10);
    459   pitchGains_Q12[0] = (int16_t)(pitchGains_Q12[1] * 1010 >> 10);
    460 
    461 
    462   /* most of the time either B or A are zero so seperating */
    463   if( (ISACdec_obj->plcstr_obj).B == 0 )
    464   {
    465     for( i = 0; i < FRAMESAMPLES_HALF; i++ )
    466     {
    467       /* --- Low Pass                                             */
    468       (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
    469           (ISACdec_obj->plcstr_obj).seed );
    470       Vector_Word16_1[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
    471 
    472       /* --- Highpass                                              */
    473       (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
    474           (ISACdec_obj->plcstr_obj).seed );
    475       Vector_Word16_2[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
    476 
    477     }
    478     for( i = 1; i < NOISE_FILTER_LEN; i++ )
    479     {
    480       (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
    481           (ISACdec_obj->plcstr_obj).seed );
    482       Vector_Word16_Extended_1[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
    483 
    484       (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
    485           (ISACdec_obj->plcstr_obj).seed );
    486       Vector_Word16_Extended_2[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
    487     }
    488     plc_filterma_Fast(Vector_Word16_1, Vector_Word16_Extended_1,
    489                       &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF -
    490                                                                 NOISE_FILTER_LEN], (int16_t) NOISE_FILTER_LEN,
    491                       (int16_t) FRAMESAMPLES_HALF, (int16_t)(5),
    492                       (ISACdec_obj->plcstr_obj).decayCoeffNoise, (int16_t)(6));
    493 
    494     maxCoeff = WebRtcSpl_MaxAbsValueW32(
    495         &(ISACdec_obj->plcstr_obj).prevHP[
    496             PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN], NOISE_FILTER_LEN );
    497 
    498     rshift = 0;
    499     while( maxCoeff > WEBRTC_SPL_WORD16_MAX )
    500     {
    501       maxCoeff >>= 1;
    502       rshift++;
    503     }
    504     for( i = 0; i < NOISE_FILTER_LEN; i++ ) {
    505       Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN + i] =(int16_t)(
    506           ISACdec_obj->plcstr_obj.prevHP[PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN +
    507                                          i] >> rshift);
    508     }
    509     (ISACdec_obj->plcstr_obj).decayCoeffNoise = plc_filterma_Fast(
    510         Vector_Word16_2,
    511         Vector_Word16_Extended_2,
    512         &Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN],
    513         (int16_t) NOISE_FILTER_LEN,
    514         (int16_t) FRAMESAMPLES_HALF,
    515         (int16_t) (5),
    516         (ISACdec_obj->plcstr_obj).decayCoeffNoise,
    517         (int16_t) (7) );
    518 
    519     for( i = 0; i < FRAMESAMPLES_HALF; i++ )
    520       Vector_Word32_2[i] = Vector_Word16_Extended_2[i] << rshift;
    521 
    522     Vector_Word16_1 = Vector_Word16_Extended_1;
    523   }
    524   else
    525   {
    526     if( (ISACdec_obj->plcstr_obj).A == 0 )
    527     {
    528       /* ------ Periodic Vector ---                                */
    529       for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
    530       {
    531         /* --- Lowpass                                               */
    532         pLP = (int16_t)(stretchPitchLP[ISACdec_obj->plcstr_obj.pitchIndex] *
    533             ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
    534 
    535         /* --- Highpass                                              */
    536         pHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
    537             (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
    538             (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
    539                                              (ISACdec_obj->plcstr_obj).stretchLag +
    540                                              (ISACdec_obj->plcstr_obj).pitchIndex] );
    541 
    542         /* --- lower the muliplier (more decay at next sample) --- */
    543         (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
    544         if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
    545           (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
    546 
    547         (ISACdec_obj->plcstr_obj).pitchIndex++;
    548 
    549         if( (ISACdec_obj->plcstr_obj).pitchIndex ==
    550             (ISACdec_obj->plcstr_obj).stretchLag )
    551         {
    552           (ISACdec_obj->plcstr_obj).pitchIndex = 0;
    553           (ISACdec_obj->plcstr_obj).pitchCycles++;
    554 
    555           if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
    556           {
    557             (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
    558           }
    559           else
    560           {
    561             (ISACdec_obj->plcstr_obj).stretchLag = lag0;
    562           }
    563 
    564           (ISACdec_obj->plcstr_obj).stretchLag = (
    565               (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
    566                                                   )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
    567 
    568           LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
    569                            stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
    570 
    571           LinearResampler( (ISACdec_obj->plcstr_obj).prevPitchLP,
    572                            stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
    573 
    574           switch( (ISACdec_obj->plcstr_obj).pitchCycles )
    575           {
    576             case 1:
    577               {
    578                 for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
    579                 {
    580                   stretchPitchLP[k] = (int16_t)((
    581                       (int32_t)stretchPitchLP[k]* 3 +
    582                       (int32_t)stretchPitchLP1[k])>>2);
    583                 }
    584                 break;
    585               }
    586             case 2:
    587               {
    588                 for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
    589                 {
    590                   stretchPitchLP[k] = (int16_t)((
    591                       (int32_t)stretchPitchLP[k] +
    592                       (int32_t)stretchPitchLP1[k] )>>1);
    593                 }
    594                 break;
    595               }
    596             case 3:
    597               {
    598                 for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
    599                 {
    600                   stretchPitchLP[k] = (int16_t)((stretchPitchLP[k] +
    601                                                        (int32_t)stretchPitchLP1[k]*3 )>>2);
    602                 }
    603                 break;
    604               }
    605           }
    606 
    607           if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
    608           {
    609             myDecayRate += 35; //(myDecayRate>>1);
    610             (ISACdec_obj->plcstr_obj).pitchCycles = 0;
    611           }
    612 
    613         }
    614 
    615         /* ------ Sum the noisy and periodic signals  ------ */
    616         Vector_Word16_1[i] = pLP;
    617         Vector_Word32_2[i] = pHP;
    618       }
    619     }
    620     else
    621     {
    622       for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
    623       {
    624 
    625         (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
    626             (ISACdec_obj->plcstr_obj).seed );
    627 
    628         noise1 = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
    629 
    630         nLP = (int16_t)((int16_t)(noise1 * ISACdec_obj->plcstr_obj.std) *
    631             ISACdec_obj->plcstr_obj.decayCoeffNoise >> 15);
    632 
    633         /* --- Highpass                                              */
    634         (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
    635             (ISACdec_obj->plcstr_obj).seed );
    636         noise1 = (ISACdec_obj->plcstr_obj.seed >> 11) - 8;
    637 
    638         nHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
    639             (ISACdec_obj->plcstr_obj).decayCoeffNoise,
    640             (int32_t)(noise1*(ISACdec_obj->plcstr_obj).std) );
    641 
    642         /* --- lower the muliplier (more decay at next sample) --- */
    643         (ISACdec_obj->plcstr_obj).decayCoeffNoise -= (myDecayRate);
    644         if( (ISACdec_obj->plcstr_obj).decayCoeffNoise < 0 )
    645           (ISACdec_obj->plcstr_obj).decayCoeffNoise = 0;
    646 
    647         /* ------ Periodic Vector ---                                */
    648         /* --- Lowpass                                               */
    649         pLP = (int16_t)(stretchPitchLP[ISACdec_obj->plcstr_obj.pitchIndex] *
    650             ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
    651 
    652         /* --- Highpass                                              */
    653         pHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
    654             (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
    655             (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
    656                                              (ISACdec_obj->plcstr_obj).stretchLag +
    657                                              (ISACdec_obj->plcstr_obj).pitchIndex] );
    658 
    659         /* --- lower the muliplier (more decay at next sample) --- */
    660         (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
    661         if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
    662         {
    663           (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
    664         }
    665 
    666         /* ------ Weighting the noisy and periodic vectors -------   */
    667         wNoisyLP = (int16_t)(ISACdec_obj->plcstr_obj.A * nLP >> 15);
    668         wNoisyHP = (int32_t)(WEBRTC_SPL_MUL_16_32_RSFT15(
    669             (ISACdec_obj->plcstr_obj).A, (nHP) ) );
    670 
    671         wPriodicLP = (int16_t)(ISACdec_obj->plcstr_obj.B * pLP >> 15);
    672         wPriodicHP = (int32_t)(WEBRTC_SPL_MUL_16_32_RSFT15(
    673             (ISACdec_obj->plcstr_obj).B, pHP));
    674 
    675         (ISACdec_obj->plcstr_obj).pitchIndex++;
    676 
    677         if((ISACdec_obj->plcstr_obj).pitchIndex ==
    678            (ISACdec_obj->plcstr_obj).stretchLag)
    679         {
    680           (ISACdec_obj->plcstr_obj).pitchIndex = 0;
    681           (ISACdec_obj->plcstr_obj).pitchCycles++;
    682 
    683           if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
    684             (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
    685           else
    686             (ISACdec_obj->plcstr_obj).stretchLag = lag0;
    687 
    688           (ISACdec_obj->plcstr_obj).stretchLag = (
    689               (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
    690                                                   )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
    691           LinearResampler(
    692               (ISACdec_obj->plcstr_obj).lastPitchLP,
    693               stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
    694 
    695           LinearResampler((ISACdec_obj->plcstr_obj).prevPitchLP,
    696                           stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
    697 
    698           switch((ISACdec_obj->plcstr_obj).pitchCycles)
    699           {
    700             case 1:
    701               {
    702                 for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
    703                 {
    704                   stretchPitchLP[k] = (int16_t)((
    705                       (int32_t)stretchPitchLP[k]* 3 +
    706                       (int32_t)stretchPitchLP1[k] )>>2);
    707                 }
    708                 break;
    709               }
    710             case 2:
    711               {
    712                 for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
    713                 {
    714                   stretchPitchLP[k] = (int16_t)((
    715                       (int32_t)stretchPitchLP[k] +
    716                       (int32_t)stretchPitchLP1[k])>>1);
    717                 }
    718                 break;
    719               }
    720             case 3:
    721               {
    722                 for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
    723                 {
    724                   stretchPitchLP[k] = (int16_t)(
    725                       (stretchPitchLP[k] +
    726                        (int32_t)stretchPitchLP1[k]*3 )>>2);
    727                 }
    728                 break;
    729               }
    730           }
    731 
    732           if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
    733           {
    734             myDecayRate += 55; //(myDecayRate>>1);
    735             (ISACdec_obj->plcstr_obj).pitchCycles = 0;
    736           }
    737         }
    738 
    739         /* ------ Sum the noisy and periodic signals  ------ */
    740         Vector_Word16_1[i] = WebRtcSpl_AddSatW16(wNoisyLP, wPriodicLP);
    741         Vector_Word32_2[i] = WebRtcSpl_AddSatW32(wNoisyHP, wPriodicHP);
    742       }
    743     }
    744   }
    745   /* ----------------- residual signal is reconstructed ------------------ */
    746 
    747   k = (ISACdec_obj->plcstr_obj).pitchIndex;
    748   /* --- Write one pitch cycle for recovery block --- */
    749 
    750   for( i = 0; i < RECOVERY_OVERLAP; i++ )
    751   {
    752     ISACdec_obj->plcstr_obj.overlapLP[i] = (int16_t)(
    753         stretchPitchLP[k] * ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
    754     k = ( k < ((ISACdec_obj->plcstr_obj).stretchLag - 1) )? (k+1):0;
    755   }
    756 
    757   (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 =
    758       (int16_t)((ISACdec_obj->plcstr_obj).stretchLag << 7);
    759 
    760 
    761   /* --- Inverse Pitch Filter --- */
    762   WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2,
    763                             &ISACdec_obj->pitchfiltstr_obj, pitchLags_Q7, pitchGains_Q12, 4);
    764 
    765   /* reduce gain to compensate for pitch enhancer */
    766   /* gain = 1.0f - 0.45f * AvgPitchGain; */
    767   tmp32a = ISACdec_obj->plcstr_obj.AvgPitchGain_Q12 * 29;  // Q18
    768   tmp32b = 262144 - tmp32a;  // Q18
    769   gainQ13 = (int16_t) (tmp32b >> 5); // Q13
    770 
    771   /* perceptual post-filtering (using normalized lattice filter) */
    772   for (k = 0; k < FRAMESAMPLES_HALF; k++)
    773     Vector_Word32_1[k] = (Vector_Word16_2[k] * gainQ13) << 3;  // Q25
    774 
    775 
    776   WebRtcIsacfix_NormLatticeFilterAr(ORDERLO,
    777                                     (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
    778                                     Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
    779 
    780   WebRtcIsacfix_NormLatticeFilterAr(ORDERHI,
    781                                     (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
    782                                     Vector_Word32_2, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
    783 
    784   /* recombine the 2 bands */
    785 
    786   /* Form the polyphase signals, and compensate for DC offset */
    787   for (k=0;k<FRAMESAMPLES_HALF;k++)
    788   {
    789     /* Construct a new upper channel signal*/
    790     tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(
    791                                            ((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1));
    792     /* Construct a new lower channel signal*/
    793     tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(
    794                                            ((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k]));
    795     Vector_Word16_1[k] = tmp_1;
    796     Vector_Word16_2[k] = tmp_2;
    797   }
    798 
    799 
    800   WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
    801                                   Vector_Word16_2, signal_out16, &ISACdec_obj->postfiltbankstr_obj);
    802 
    803   (ISACdec_obj->plcstr_obj).used = PLC_WAS_USED;
    804   *current_framesamples = 480;
    805 }
    806