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
36static 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;
50
51  lim = WEBRTC_SPL_LSHIFT_W32( (int32_t)1, 15 + rshift )-1;
52
53  for (i = 0; i < len; i++)
54  {
55    const int16_t *b_ptr = &B[0];
56    const int16_t *x_ptr = &In[i];
57
58    o = (int32_t)0;
59
60    for (j = 0;j < Blen; j++)
61    {
62      o = WebRtcSpl_AddSatW32(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 = WebRtcSpl_AddSatW32(o, 1 << (rshift - 1));
69
70    /* saturate according to the domain of the filter coefficients */
71    o = WEBRTC_SPL_SAT((int32_t)lim, o, (int32_t)-lim);
72
73    /* o should be in the range of int16_t */
74    o = WEBRTC_SPL_RSHIFT_W32( o, rshift );
75
76    /* decay the output signal; this is specific to plc */
77    *Out++ = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( (int16_t)o, decay, 15); // ((o + (int32_t)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
94static __inline int32_t log2_Q8_T( uint32_t x ) {
95
96  int32_t zeros, lg2;
97  int16_t frac;
98
99  zeros=WebRtcSpl_NormU32(x);
100  frac=(int16_t)WEBRTC_SPL_RSHIFT_W32(((uint32_t)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
108static __inline int16_t  exp2_Q10_T(int16_t x) { // Both in and out in Q10
109
110  int16_t tmp16_1, tmp16_2;
111
112  tmp16_2=(int16_t)(0x0400|(x&0x03FF));
113  tmp16_1=-(int16_t)WEBRTC_SPL_RSHIFT_W16(x,10);
114  if(tmp16_1>0)
115    return (int16_t) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
116  else
117    return (int16_t) 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*/
129static void MemshipValQ15( int16_t in, int16_t *A, int16_t *B )
130{
131  int16_t 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 int16_t            */
146      x = (int16_t)( 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 = (int16_t)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 = (int16_t)( 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 = (int16_t)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
184static void LinearResampler( int16_t *in, int16_t *out, int16_t lenIn, int16_t lenOut )
185{
186  int32_t n;
187  int16_t resOut, i, j, relativePos, diff; /* */
188  uint16_t 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( (int16_t)(lenIn-1), RESAMP_RES );
197  resOut = WebRtcSpl_DivW32W16ResW16( n, (int16_t)(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 = (uint16_t)(in[ j ] - in[j + 1]);
218      out[ i ] = in[ j ] - (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
219    }
220    else
221    {
222      if( (in[j] < 0) && (in[j+1] > 0) )
223      {
224        udiff = (uint16_t)( in[j + 1] - in[ j ] );
225        out[ i ] = in[ j ] + (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
226      }
227      else
228      {
229        diff = in[ j + 1 ] - in[ j ];
230        out[ i ] = in[ j ] + (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( diff, relativePos, RESAMP_RES_BIT );
231      }
232    }
233  }
234}
235
236
237
238
239
240int16_t WebRtcIsacfix_DecodePlcImpl(int16_t *signal_out16,
241                                    ISACFIX_DecInst_t *ISACdec_obj,
242                                    int16_t *current_framesamples )
243{
244  int subframecnt;
245  int16_t len = 0;
246
247  int16_t* Vector_Word16_1;
248  int16_t  Vector_Word16_Extended_1[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
249  int16_t* Vector_Word16_2;
250  int16_t  Vector_Word16_Extended_2[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
251
252  int32_t Vector_Word32_1[FRAMESAMPLES_HALF];
253  int32_t Vector_Word32_2[FRAMESAMPLES_HALF];
254
255  int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
256  int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
257
258  int16_t pitchLags_Q7[PITCH_SUBFRAMES];
259  int16_t pitchGains_Q12[PITCH_SUBFRAMES];
260
261  int16_t tmp_1, tmp_2;
262  int32_t tmp32a, tmp32b;
263  int16_t gainQ13;
264
265  int16_t myDecayRate;
266
267  /* ---------- PLC variables ------------ */
268  int16_t lag0, i, k, noiseIndex;
269  int16_t stretchPitchLP[PITCH_MAX_LAG + 10], stretchPitchLP1[PITCH_MAX_LAG + 10];
270
271  int32_t gain_lo_hiQ17[2*SUBFRAMES];
272
273  int16_t nLP, pLP, wNoisyLP, wPriodicLP, tmp16, minIdx;
274  int32_t nHP, pHP, wNoisyHP, wPriodicHP, corr, minCorr, maxCoeff;
275  int16_t noise1, rshift;
276
277
278  int16_t ltpGain, pitchGain, myVoiceIndicator, myAbs, maxAbs;
279  int32_t 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 = WebRtcSpl_AddSatW32(corr, WEBRTC_SPL_ABS_W32(
329              WebRtcSpl_SubSatW16(
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( (uint32_t)( varIn ) ) +
367        (int32_t)(rightShiftIn << 8);
368    logVarOut = log2_Q8_T( (uint32_t)( varOut ) ) +
369        (int32_t)(rightShiftOut << 8);
370    logMaxAbs = log2_Q8_T( (uint32_t)( maxAbs ) );
371
372    ltpGain = (int16_t)(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( (uint32_t)( lag0 ) );
385    tmp16 = (int16_t)((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] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
461      pitchGains_Q12[3], 1010, 10 );
462  pitchGains_Q12[1] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
463      pitchGains_Q12[2], 1010, 10 );
464  pitchGains_Q12[0] = (int16_t)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], (int16_t) NOISE_FILTER_LEN,
501                      (int16_t) FRAMESAMPLES_HALF, (int16_t)(5),
502                      (ISACdec_obj->plcstr_obj).decayCoeffNoise, (int16_t)(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          (int16_t)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        (int16_t) NOISE_FILTER_LEN,
525        (int16_t) FRAMESAMPLES_HALF,
526        (int16_t) (5),
527        (ISACdec_obj->plcstr_obj).decayCoeffNoise,
528        (int16_t) (7) );
529
530    for( i = 0; i < FRAMESAMPLES_HALF; i++ )
531      Vector_Word32_2[i] = WEBRTC_SPL_LSHIFT_W32(
532          (int32_t)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 = (int16_t)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 = (int32_t)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] = (int16_t)((
594                      (int32_t)stretchPitchLP[k]* 3 +
595                      (int32_t)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] = (int16_t)((
604                      (int32_t)stretchPitchLP[k] +
605                      (int32_t)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] = (int16_t)((stretchPitchLP[k] +
614                                                       (int32_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
645            (int16_t)((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 = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
655            (ISACdec_obj->plcstr_obj).decayCoeffNoise,
656            (int32_t)(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 = (int16_t)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 = (int32_t)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 = (int16_t)(WEBRTC_SPL_MUL_16_16_RSFT(
685            (ISACdec_obj->plcstr_obj).A, nLP, 15 ) );
686        wNoisyHP = (int32_t)(WEBRTC_SPL_MUL_16_32_RSFT15(
687            (ISACdec_obj->plcstr_obj).A, (nHP) ) );
688
689        wPriodicLP = (int16_t)(WEBRTC_SPL_MUL_16_16_RSFT(
690            (ISACdec_obj->plcstr_obj).B, pLP, 15));
691        wPriodicHP = (int32_t)(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] = (int16_t)((
724                      (int32_t)stretchPitchLP[k]* 3 +
725                      (int32_t)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] = (int16_t)((
734                      (int32_t)stretchPitchLP[k] +
735                      (int32_t)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] = (int16_t)(
744                      (stretchPitchLP[k] +
745                       (int32_t)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] = WebRtcSpl_AddSatW16(wNoisyLP, wPriodicLP);
760        Vector_Word32_2[i] = WebRtcSpl_AddSatW32(wNoisyHP, wPriodicHP);
761      }
762    }
763  }
764  /* ----------------- residual signal is reconstructed ------------------ */
765
766  k = (ISACdec_obj->plcstr_obj).pitchIndex;
767  /* --- Write one pitch cycle for recovery block --- */
768
769  for( i = 0; i < RECOVERY_OVERLAP; i++ )
770  {
771    (ISACdec_obj->plcstr_obj).overlapLP[i] = (int16_t)(
772        WEBRTC_SPL_MUL_16_16_RSFT(stretchPitchLP[k],
773                                  (ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15) );
774    k = ( k < ((ISACdec_obj->plcstr_obj).stretchLag - 1) )? (k+1):0;
775  }
776
777  (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = (ISACdec_obj->plcstr_obj).stretchLag << 7;
778
779
780  /* --- Inverse Pitch Filter --- */
781  WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2,
782                            &ISACdec_obj->pitchfiltstr_obj, pitchLags_Q7, pitchGains_Q12, 4);
783
784  /* reduce gain to compensate for pitch enhancer */
785  /* gain = 1.0f - 0.45f * AvgPitchGain; */
786  tmp32a = WEBRTC_SPL_MUL_16_16_RSFT((ISACdec_obj->plcstr_obj).AvgPitchGain_Q12,
787                                     29, 0); // Q18
788  tmp32b = 262144 - tmp32a;  // Q18
789  gainQ13 = (int16_t) (tmp32b >> 5); // Q13
790
791  /* perceptual post-filtering (using normalized lattice filter) */
792  for (k = 0; k < FRAMESAMPLES_HALF; k++)
793    Vector_Word32_1[k] = (int32_t) WEBRTC_SPL_MUL_16_16(
794        Vector_Word16_2[k], gainQ13) << 3; // Q25
795
796
797  WebRtcIsacfix_NormLatticeFilterAr(ORDERLO,
798                                    (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
799                                    Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
800
801  WebRtcIsacfix_NormLatticeFilterAr(ORDERHI,
802                                    (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
803                                    Vector_Word32_2, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
804
805  /* recombine the 2 bands */
806
807  /* Form the polyphase signals, and compensate for DC offset */
808  for (k=0;k<FRAMESAMPLES_HALF;k++)
809  {
810    /* Construct a new upper channel signal*/
811    tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(
812                                           ((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1));
813    /* Construct a new lower channel signal*/
814    tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(
815                                           ((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k]));
816    Vector_Word16_1[k] = tmp_1;
817    Vector_Word16_2[k] = tmp_2;
818  }
819
820
821  WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
822                                  Vector_Word16_2, signal_out16, &ISACdec_obj->postfiltbankstr_obj);
823
824  (ISACdec_obj->plcstr_obj).used = PLC_WAS_USED;
825  *current_framesamples = 480;
826
827  return len;
828}
829