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