• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
plc_filterma_Fast(int16_t * In,int16_t * Out,int16_t * B,int16_t Blen,int16_t len,int16_t reduceDecay,int16_t decay,int16_t rshift)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 
log2_Q8_T(uint32_t x)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 
exp2_Q10_T(int16_t x)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 */
MemshipValQ15(int16_t in,int16_t * A,int16_t * B)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 
LinearResampler(int16_t * in,int16_t * out,size_t lenIn,size_t lenOut)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 
WebRtcIsacfix_DecodePlcImpl(int16_t * signal_out16,IsacFixDecoderInstance * ISACdec_obj,size_t * current_framesamples)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