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(WebRtc_Word16 * In,WebRtc_Word16 * Out,WebRtc_Word16 * B,WebRtc_Word16 Blen,WebRtc_Word16 len,WebRtc_Word16 reduceDecay,WebRtc_Word16 decay,WebRtc_Word16 rshift)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 
log2_Q8_T(WebRtc_UWord32 x)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 
exp2_Q10_T(WebRtc_Word16 x)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 */
MemshipValQ15(WebRtc_Word16 in,WebRtc_Word16 * A,WebRtc_Word16 * B)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 
LinearResampler(WebRtc_Word16 * in,WebRtc_Word16 * out,WebRtc_Word16 lenIn,WebRtc_Word16 lenOut)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 
WebRtcIsacfix_DecodePlcImpl(WebRtc_Word16 * signal_out16,ISACFIX_DecInst_t * ISACdec_obj,WebRtc_Word16 * current_framesamples)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