decode_plc.c revision 470e71d3649f6cac4688e83819640b012b5d38bb
1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
2470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * decode_plc.c
13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Packet Loss Concealment.
15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
16470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
17470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
18470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <string.h>
19470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "settings.h"
21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "entropy_coding.h"
22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "pitch_estimator.h"
23470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "bandwidth_estimator.h"
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "structs.h"
25470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "codec.h"
26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
27470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
28470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#define NO_OF_PRIMES 8
29470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#define NOISE_FILTER_LEN 30
30470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
31470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
32470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * function to decode the bitstream
33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * returns the total number of bytes in the stream
34470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word16 plc_filterma_Fast(
37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 *In,  /* (i)   Vector to be filtered. InOut[-orderCoef+1]
38470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                           to InOut[-1] contains state */
39470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 *Out,  /* (o)   Filtered vector */
40470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 *B,   /* (i)   The filter coefficients (in Q0) */
41470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 Blen,  /* (i)   Number of B coefficients */
42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 len,   /* (i)  Number of samples to be filtered */
43470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 reduceDecay,
44470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 decay,
45470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 rshift )
46470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int i, j;
48470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 o;
49470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 lim;
50470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  lim = WEBRTC_SPL_LSHIFT_W32( (WebRtc_Word32)1, 15 + rshift )-1;
52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (i = 0; i < len; i++)
54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
55470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    G_CONST WebRtc_Word16 *b_ptr = &B[0];
56470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    G_CONST WebRtc_Word16 *x_ptr = &In[i];
57470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
58470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    o = (WebRtc_Word32)0;
59470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
60470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (j = 0;j < Blen; j++)
61470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      o = WEBRTC_SPL_ADD_SAT_W32( o, WEBRTC_SPL_MUL_16_16( *b_ptr, *x_ptr) );
63470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      b_ptr++;
64470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      x_ptr--;
65470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
66470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
67470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* to round off correctly */
68470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    o = WEBRTC_SPL_ADD_SAT_W32( o, WEBRTC_SPL_LSHIFT_W32( 1, (rshift-1) ) );
69470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
70470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* saturate according to the domain of the filter coefficients */
71470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    o = WEBRTC_SPL_SAT((WebRtc_Word32)lim, o, (WebRtc_Word32)-lim);
72470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
73470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* o should be in the range of WebRtc_Word16 */
74470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    o = WEBRTC_SPL_RSHIFT_W32( o, rshift );
75470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* decay the output signal; this is specific to plc */
77470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    *Out++ = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT( (WebRtc_Word16)o, decay, 15); // ((o + (WebRtc_Word32)2048) >> 12);
78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
79470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* change the decay */
80470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    decay -= reduceDecay;
81470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if( decay < 0 )
82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      decay = 0;
83470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
84470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return( decay );
85470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
86470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
88470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
89470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
94470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comstatic __inline WebRtc_Word32 log2_Q8_T( WebRtc_UWord32 x ) {
95470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
96470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 zeros, lg2;
97470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 frac;
98470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
99470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  zeros=WebRtcSpl_NormU32(x);
100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(((WebRtc_UWord32)WEBRTC_SPL_LSHIFT_W32(x, zeros)&0x7FFFFFFF), 23);
101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* log2(magn(i)) */
102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  lg2= (WEBRTC_SPL_LSHIFT_W16((31-zeros), 8)+frac);
104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return lg2;
105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comstatic __inline WebRtc_Word16  exp2_Q10_T(WebRtc_Word16 x) { // Both in and out in Q10
109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 tmp16_1, tmp16_2;
111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  tmp16_2=(WebRtc_Word16)(0x0400|(x&0x03FF));
113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  tmp16_1=-(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(x,10);
114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if(tmp16_1>0)
115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  This is a fixed-point version of the above code with limLow = 700 and limHigh = 5000,
124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  hard-coded. The values 700 and 5000 were experimentally obtained.
125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  The function implements membership values for two sets. The mebership functions are
127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  of second orders corresponding to half-bell-shapped pulses.
128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/
129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comstatic void MemshipValQ15( WebRtc_Word16 in, WebRtc_Word16 *A, WebRtc_Word16 *B )
130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 x;
132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  in -= 700;    /* translate the lowLim to 0, limHigh = 5000 - 700, M = 2150 */
134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if( in <= 2150 )
136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if( in > 0 )
138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* b = in^2 / (2 * M^2), a = 1 - b in Q0.
140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com         We have to compute in Q15 */
141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* x = in / 2150 {in Q15} = x * 15.2409 {in Q15} =
143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com         x*15 + (x*983)/(2^12); note that 983/2^12 = 0.23999     */
144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* we are sure that x is in the range of WebRtc_Word16            */
146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      x = (WebRtc_Word16)( WEBRTC_SPL_MUL_16_16( in, 15 ) +
147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                           WEBRTC_SPL_MUL_16_16_RSFT( in, 983, 12) );
148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com         be in correct domain and one more for the division by 2 */
150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *B = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( WEBRTC_SPL_MUL_16_16( x, x ) + 0x00010000, 17 );
151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *A = WEBRTC_SPL_WORD16_MAX - *B;
152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *B = 0;
156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *A = WEBRTC_SPL_WORD16_MAX;
157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if( in < 4300 )
162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* This is a mirror case of the above */
164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      in = 4300 - in;
165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      x = (WebRtc_Word16)( WEBRTC_SPL_MUL_16_16( in, 15 ) +
166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                           WEBRTC_SPL_MUL_16_16_RSFT( in, 983, 12) );
167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com         be in correct domain and one more for the division by 2 */
169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *A = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( WEBRTC_SPL_MUL_16_16( x, x ) + 0x00010000, 17 );
170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *B = WEBRTC_SPL_WORD16_MAX - *A;
171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *A = 0;
176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *B = WEBRTC_SPL_WORD16_MAX;
177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comstatic void LinearResampler( WebRtc_Word16 *in, WebRtc_Word16 *out, WebRtc_Word16 lenIn, WebRtc_Word16 lenOut )
185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 n;
187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 resOut, i, j, relativePos, diff; /* */
188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_UWord16 udiff;
189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if( lenIn == lenOut )
191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_SPL_MEMCPY_W16( out, in, lenIn );
193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return;
194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  n = WEBRTC_SPL_MUL_16_16( (WebRtc_Word16)(lenIn-1), RESAMP_RES );
197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  resOut = WebRtcSpl_DivW32W16ResW16( n, (WebRtc_Word16)(lenOut-1) );
198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  out[0] = in[0];
200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for( i = 1, j = 0, relativePos = 0; i < lenOut; i++ )
201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    relativePos += resOut;
204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    while( relativePos > RESAMP_RES )
205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      j++;
207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      relativePos -= RESAMP_RES;
208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* an overflow may happen and the differce in sample values may
212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * require more than 16 bits. We like to avoid 32 bit arithmatic
213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * as much as possible */
214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if( (in[ j ] > 0) && (in[j + 1] < 0) )
216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      udiff = (WebRtc_UWord16)(in[ j ] - in[j + 1]);
218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      out[ i ] = in[ j ] - (WebRtc_UWord16)( ((WebRtc_Word32)( udiff * relativePos )) >> RESAMP_RES_BIT);
219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if( (in[j] < 0) && (in[j+1] > 0) )
223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        udiff = (WebRtc_UWord16)( in[j + 1] - in[ j ] );
225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        out[ i ] = in[ j ] + (WebRtc_UWord16)( ((WebRtc_Word32)( udiff * relativePos )) >> RESAMP_RES_BIT);
226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      else
228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        diff = in[ j + 1 ] - in[ j ];
230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        out[ i ] = in[ j ] + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT( diff, relativePos, RESAMP_RES_BIT );
231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word16 WebRtcIsacfix_DecodePlcImpl(WebRtc_Word16 *signal_out16,
241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          ISACFIX_DecInst_t *ISACdec_obj,
242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          WebRtc_Word16 *current_framesamples )
243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int subframecnt;
245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 len = 0;
246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16* Vector_Word16_1;
248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16  Vector_Word16_Extended_1[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16* Vector_Word16_2;
250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16  Vector_Word16_Extended_2[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 Vector_Word32_1[FRAMESAMPLES_HALF];
253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 Vector_Word32_2[FRAMESAMPLES_HALF];
254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 pitchLags_Q7[PITCH_SUBFRAMES];
259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 pitchGains_Q12[PITCH_SUBFRAMES];
260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 tmp_1, tmp_2;
262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 tmp32a, tmp32b;
263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 gainQ13;
264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 myDecayRate;
266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* ---------- PLC variables ------------ */
268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 lag0, i, k, noiseIndex;
269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 stretchPitchLP[PITCH_MAX_LAG + 10], stretchPitchLP1[PITCH_MAX_LAG + 10];
270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 gain_lo_hiQ17[2*SUBFRAMES];
272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 nLP, pLP, wNoisyLP, wPriodicLP, tmp16, minIdx;
274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 nHP, pHP, wNoisyHP, wPriodicHP, corr, minCorr, maxCoeff;
275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 noise1, rshift;
276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word16 ltpGain, pitchGain, myVoiceIndicator, myAbs, maxAbs;
279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtc_Word32 varIn, varOut, logVarIn, logVarOut, Q, logMaxAbs;
280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int rightShiftIn, rightShiftOut;
281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* ------------------------------------- */
284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  myDecayRate = (DECAY_RATE);
287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  Vector_Word16_1 = &Vector_Word16_Extended_1[NOISE_FILTER_LEN];
288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  Vector_Word16_2 = &Vector_Word16_Extended_2[NOISE_FILTER_LEN];
289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* ----- Simply Copy Previous LPC parameters ------ */
292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for( subframecnt = 0; subframecnt < SUBFRAMES; subframecnt++ )
293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* lower Band */
295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_SPL_MEMCPY_W16(&lofilt_coefQ15[ subframecnt * ORDERLO ],
296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                          (ISACdec_obj->plcstr_obj).lofilt_coefQ15, ORDERLO);
297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gain_lo_hiQ17[2*subframecnt] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0];
298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Upper Band */
300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_SPL_MEMCPY_W16(&hifilt_coefQ15[ subframecnt * ORDERHI ],
301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                          (ISACdec_obj->plcstr_obj).hifilt_coefQ15, ORDERHI);
302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gain_lo_hiQ17[2*subframecnt + 1] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1];
303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  lag0 = WEBRTC_SPL_RSHIFT_W16(
309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 + 64, 7 ) + 1;
310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if( (ISACdec_obj->plcstr_obj).used != PLC_WAS_USED )
313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    (ISACdec_obj->plcstr_obj).pitchCycles = 0;
315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    (ISACdec_obj->plcstr_obj).lastPitchLP =
317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &((ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0]);
318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    minCorr = WEBRTC_SPL_WORD32_MAX;
319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ( (FRAMESAMPLES_HALF - 2*lag0 - 10) > 0 )
321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      minIdx = 11;
323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      for( i = 0; i < 21; i++ )
324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        corr = 0;
326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        for( k = 0; k < lag0; k++ )
327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          corr = WEBRTC_SPL_ADD_SAT_W32( corr, WEBRTC_SPL_ABS_W32(
329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              WEBRTC_SPL_SUB_SAT_W16(
330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  (ISACdec_obj->plcstr_obj).lastPitchLP[k],
331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  (ISACdec_obj->plcstr_obj).prevPitchInvIn[
332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      FRAMESAMPLES_HALF - 2*lag0 - 10 + i + k ] ) ) );
333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if( corr < minCorr )
335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          minCorr = corr;
337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          minIdx = i;
338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      (ISACdec_obj->plcstr_obj).prevPitchLP =
341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          &( (ISACdec_obj->plcstr_obj).prevPitchInvIn[
342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              FRAMESAMPLES_HALF - lag0*2 - 10 + minIdx] );
343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      (ISACdec_obj->plcstr_obj).prevPitchLP =
347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).lastPitchLP;
348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    pitchGain = (ISACdec_obj->plcstr_obj).lastPitchGain_Q12;
350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtcSpl_AutoCorrelation(
352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0],
353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        lag0, 0, &varIn, &rightShiftIn);
354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtcSpl_AutoCorrelation(
355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &(ISACdec_obj->plcstr_obj).prevPitchInvOut[PITCH_MAX_LAG + 10 - lag0],
356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        lag0, 0, &varOut, &rightShiftOut);
357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    maxAbs = 0;
359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for( i = 0; i< lag0; i++)
360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      myAbs = WEBRTC_SPL_ABS_W16(
362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).prevPitchInvOut[
363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              PITCH_MAX_LAG + 10 - lag0 + i] );
364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      maxAbs = (myAbs > maxAbs)? myAbs:maxAbs;
365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    logVarIn = log2_Q8_T( (WebRtc_UWord32)( varIn ) ) +
367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (WebRtc_Word32)(rightShiftIn << 8);
368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    logVarOut = log2_Q8_T( (WebRtc_UWord32)( varOut ) ) +
369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (WebRtc_Word32)(rightShiftOut << 8);
370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    logMaxAbs = log2_Q8_T( (WebRtc_UWord32)( maxAbs ) );
371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    ltpGain = (WebRtc_Word16)(logVarOut - logVarIn);
373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Q = 2 * logMaxAbs - ( logVarOut - 1512 );
374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /*
376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * ---
377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * We are computing sqrt( (VarIn/lag0) / var( noise ) )
378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * var( noise ) is almost 256. we have already computed log2( VarIn ) in Q8
379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * so we actually compute 2^( 0.5*(log2( VarIn ) - log2( lag0 ) - log2( var(noise ) )  ).
380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * Note that put log function is in Q8 but the exponential function is in Q10.
381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     * --
382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     */
383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    logVarIn -= log2_Q8_T( (WebRtc_UWord32)( lag0 ) );
385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmp16 = (WebRtc_Word16)((logVarIn<<1) - (4<<10) );
386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    rightShiftIn = 0;
387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if( tmp16 > 4096 )
388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp16 -= 4096;
390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp16 = exp2_Q10_T( tmp16 );
391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp16 >>= 6;
392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp16 = exp2_Q10_T( tmp16 )>>10;
395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    (ISACdec_obj->plcstr_obj).std = tmp16 - 4;
397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if( (ltpGain < 110) || (ltpGain > 230) )
399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if( ltpGain < 100 && (pitchGain < 1800) )
401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).A = WEBRTC_SPL_WORD16_MAX;
403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      else
405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).A = ((ltpGain < 110) && (Q < 800)
407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                       )? WEBRTC_SPL_WORD16_MAX:0;
408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).A;
411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if( (pitchGain < 450) || (pitchGain > 1600) )
415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).A = ((pitchGain < 450)
417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                       )? WEBRTC_SPL_WORD16_MAX:0;
418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).A;
420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      else
422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        myVoiceIndicator = ltpGain * 2 + pitchGain;
424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        MemshipValQ15( myVoiceIndicator,
425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    myVoiceIndicator = ltpGain * 16 + pitchGain * 2 + (pitchGain >> 8);
432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    MemshipValQ15( myVoiceIndicator,
433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    (ISACdec_obj->plcstr_obj).stretchLag = lag0;
438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    (ISACdec_obj->plcstr_obj).pitchIndex = 0;
439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    myDecayRate = (DECAY_RATE<<2);
444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if( (ISACdec_obj->plcstr_obj).B < 1000 )
447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    myDecayRate += (DECAY_RATE<<3);
449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* ------------ reconstructing the residual signal ------------------ */
452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* inverse pitch filter */
456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  pitchLags_Q7[0] = pitchLags_Q7[1] = pitchLags_Q7[2] = pitchLags_Q7[3] =
458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      ((ISACdec_obj->plcstr_obj).stretchLag<<7);
459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  pitchGains_Q12[3] = ( (ISACdec_obj->plcstr_obj).lastPitchGain_Q12);
460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  pitchGains_Q12[2] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      pitchGains_Q12[3], 1010, 10 );
462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  pitchGains_Q12[1] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      pitchGains_Q12[2], 1010, 10 );
464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  pitchGains_Q12[0] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      pitchGains_Q12[1], 1010, 10 );
466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* most of the time either B or A are zero so seperating */
469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if( (ISACdec_obj->plcstr_obj).B == 0 )
470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for( i = 0; i < FRAMESAMPLES_HALF; i++ )
472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* --- Low Pass                                             */
474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).seed );
476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      Vector_Word16_1[i] = WEBRTC_SPL_RSHIFT_W16(
477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* --- Highpass                                              */
480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).seed );
482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      Vector_Word16_2[i] = WEBRTC_SPL_RSHIFT_W16(
483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for( i = 1; i < NOISE_FILTER_LEN; i++ )
487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).seed );
490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      Vector_Word16_Extended_1[ i ] = WEBRTC_SPL_RSHIFT_W16(
491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).seed );
495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      Vector_Word16_Extended_2[ i ] = WEBRTC_SPL_RSHIFT_W16(
496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    plc_filterma_Fast(Vector_Word16_1, Vector_Word16_Extended_1,
499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF -
500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                                NOISE_FILTER_LEN], (WebRtc_Word16) NOISE_FILTER_LEN,
501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word16) FRAMESAMPLES_HALF, (WebRtc_Word16)(5),
502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (ISACdec_obj->plcstr_obj).decayCoeffNoise, (WebRtc_Word16)(6));
503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    maxCoeff = WebRtcSpl_MaxAbsValueW32(
505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &(ISACdec_obj->plcstr_obj).prevHP[
506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN], NOISE_FILTER_LEN );
507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    rshift = 0;
509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    while( maxCoeff > WEBRTC_SPL_WORD16_MAX )
510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      maxCoeff = WEBRTC_SPL_RSHIFT_W32(maxCoeff, 1);
512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      rshift++;
513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for( i = 0; i < NOISE_FILTER_LEN; i++ ) {
515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      Vector_Word16_1[ FRAMESAMPLES_HALF - NOISE_FILTER_LEN + i] =
516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              (ISACdec_obj->plcstr_obj).prevHP[
518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN + i], rshift);
519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    (ISACdec_obj->plcstr_obj).decayCoeffNoise = plc_filterma_Fast(
521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        Vector_Word16_2,
522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        Vector_Word16_Extended_2,
523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN],
524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (WebRtc_Word16) NOISE_FILTER_LEN,
525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (WebRtc_Word16) FRAMESAMPLES_HALF,
526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (WebRtc_Word16) (5),
527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).decayCoeffNoise,
528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (WebRtc_Word16) (7) );
529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for( i = 0; i < FRAMESAMPLES_HALF; i++ )
531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      Vector_Word32_2[i] = WEBRTC_SPL_LSHIFT_W32(
532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (WebRtc_Word32)Vector_Word16_Extended_2[i], rshift );
533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Vector_Word16_1 = Vector_Word16_Extended_1;
535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if( (ISACdec_obj->plcstr_obj).A == 0 )
539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* ------ Periodic Vector ---                                */
541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* --- Lowpass                                               */
544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        pLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            stretchPitchLP[(ISACdec_obj->plcstr_obj).pitchIndex],
546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15 );
547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* --- Highpass                                              */
549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        pHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             (ISACdec_obj->plcstr_obj).stretchLag +
553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             (ISACdec_obj->plcstr_obj).pitchIndex] );
554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* --- lower the muliplier (more decay at next sample) --- */
556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).pitchIndex++;
561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if( (ISACdec_obj->plcstr_obj).pitchIndex ==
563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).stretchLag )
564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).pitchIndex = 0;
566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).pitchCycles++;
567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          {
570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          }
572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          else
573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          {
574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).stretchLag = lag0;
575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          }
576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).stretchLag = (
578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                  )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                           stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          LinearResampler( (ISACdec_obj->plcstr_obj).prevPitchLP,
585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                           stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          switch( (ISACdec_obj->plcstr_obj).pitchCycles )
588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          {
589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case 1:
590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              {
591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                {
593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  stretchPitchLP[k] = (WebRtc_Word16)((
594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word32)stretchPitchLP[k]* 3 +
595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word32)stretchPitchLP1[k])>>2);
596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                }
597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              }
599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case 2:
600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              {
601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                {
603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  stretchPitchLP[k] = (WebRtc_Word16)((
604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word32)stretchPitchLP[k] +
605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word32)stretchPitchLP1[k] )>>1);
606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                }
607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              }
609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case 3:
610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              {
611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                {
613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  stretchPitchLP[k] = (WebRtc_Word16)((stretchPitchLP[k] +
614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                       (WebRtc_Word32)stretchPitchLP1[k]*3 )>>2);
615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                }
616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              }
618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          }
619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          {
622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            myDecayRate += 35; //(myDecayRate>>1);
623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).pitchCycles = 0;
624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          }
625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* ------ Sum the noisy and periodic signals  ------ */
629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        Vector_Word16_1[i] = pLP;
630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        Vector_Word32_2[i] = pHP;
631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).seed );
640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        noise1 = WEBRTC_SPL_RSHIFT_W16(
642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).seed, 10 ) - 16;
643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        nLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (WebRtc_Word16)((noise1)*(ISACdec_obj->plcstr_obj).std),
646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).decayCoeffNoise, 15 );
647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* --- Highpass                                              */
649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).seed );
651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        noise1 = WEBRTC_SPL_RSHIFT_W16(
652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).seed, 11 ) - 8;
653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        nHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).decayCoeffNoise,
656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (WebRtc_Word32)(noise1*(ISACdec_obj->plcstr_obj).std) );
657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* --- lower the muliplier (more decay at next sample) --- */
659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).decayCoeffNoise -= (myDecayRate);
660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if( (ISACdec_obj->plcstr_obj).decayCoeffNoise < 0 )
661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).decayCoeffNoise = 0;
662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* ------ Periodic Vector ---                                */
664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* --- Lowpass                                               */
665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        pLP = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            stretchPitchLP[(ISACdec_obj->plcstr_obj).pitchIndex],
667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15 );
668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* --- Highpass                                              */
670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        pHP = (WebRtc_Word32)WEBRTC_SPL_MUL_16_32_RSFT15(
671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             (ISACdec_obj->plcstr_obj).stretchLag +
674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             (ISACdec_obj->plcstr_obj).pitchIndex] );
675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* --- lower the muliplier (more decay at next sample) --- */
677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* ------ Weighting the noisy and periodic vectors -------   */
684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        wNoisyLP = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT(
685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).A, nLP, 15 ) );
686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        wNoisyHP = (WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT15(
687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).A, (nHP) ) );
688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        wPriodicLP = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT(
690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).B, pLP, 15));
691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        wPriodicHP = (WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT15(
692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).B, pHP));
693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ISACdec_obj->plcstr_obj).pitchIndex++;
695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if((ISACdec_obj->plcstr_obj).pitchIndex ==
697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com           (ISACdec_obj->plcstr_obj).stretchLag)
698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).pitchIndex = 0;
700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).pitchCycles++;
701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          else
705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).stretchLag = lag0;
706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          (ISACdec_obj->plcstr_obj).stretchLag = (
708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                  )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          LinearResampler(
711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              (ISACdec_obj->plcstr_obj).lastPitchLP,
712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          LinearResampler((ISACdec_obj->plcstr_obj).prevPitchLP,
715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                          stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          switch((ISACdec_obj->plcstr_obj).pitchCycles)
718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          {
719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case 1:
720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              {
721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                {
723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  stretchPitchLP[k] = (WebRtc_Word16)((
724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word32)stretchPitchLP[k]* 3 +
725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word32)stretchPitchLP1[k] )>>2);
726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                }
727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              }
729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case 2:
730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              {
731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                {
733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  stretchPitchLP[k] = (WebRtc_Word16)((
734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word32)stretchPitchLP[k] +
735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (WebRtc_Word32)stretchPitchLP1[k])>>1);
736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                }
737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              }
739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case 3:
740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              {
741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                {
743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  stretchPitchLP[k] = (WebRtc_Word16)(
744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      (stretchPitchLP[k] +
745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       (WebRtc_Word32)stretchPitchLP1[k]*3 )>>2);
746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                }
747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              }
749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          }
750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          {
753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            myDecayRate += 55; //(myDecayRate>>1);
754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (ISACdec_obj->plcstr_obj).pitchCycles = 0;
755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com          }
756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        /* ------ Sum the noisy and periodic signals  ------ */
759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        Vector_Word16_1[i] = (WebRtc_Word16)WEBRTC_SPL_ADD_SAT_W16(
760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            wNoisyLP, wPriodicLP );
761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        Vector_Word32_2[i] = (WebRtc_Word32)WEBRTC_SPL_ADD_SAT_W32(
762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            wNoisyHP, wPriodicHP );
763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* ----------------- residual signal is reconstructed ------------------ */
767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  k = (ISACdec_obj->plcstr_obj).pitchIndex;
769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* --- Write one pitch cycle for recovery block --- */
770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for( i = 0; i < RECOVERY_OVERLAP; i++ )
772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    (ISACdec_obj->plcstr_obj).overlapLP[i] = (WebRtc_Word16)(
774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_SPL_MUL_16_16_RSFT(stretchPitchLP[k],
775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                  (ISACdec_obj->plcstr_obj).decayCoeffPriodic, 15) );
776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    k = ( k < ((ISACdec_obj->plcstr_obj).stretchLag - 1) )? (k+1):0;
777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = (ISACdec_obj->plcstr_obj).stretchLag << 7;
780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* --- Inverse Pitch Filter --- */
783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2,
784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            &ISACdec_obj->pitchfiltstr_obj, pitchLags_Q7, pitchGains_Q12, 4);
785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* reduce gain to compensate for pitch enhancer */
787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* gain = 1.0f - 0.45f * AvgPitchGain; */
788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  tmp32a = WEBRTC_SPL_MUL_16_16_RSFT((ISACdec_obj->plcstr_obj).AvgPitchGain_Q12,
789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     29, 0); // Q18
790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  tmp32b = 262144 - tmp32a;  // Q18
791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  gainQ13 = (WebRtc_Word16) (tmp32b >> 5); // Q13
792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* perceptual post-filtering (using normalized lattice filter) */
794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < FRAMESAMPLES_HALF; k++)
795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Vector_Word32_1[k] = (WebRtc_Word32) WEBRTC_SPL_MUL_16_16(
796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        Vector_Word16_2[k], gainQ13) << 3; // Q25
797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcIsacfix_NormLatticeFilterAr(ORDERLO,
800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcIsacfix_NormLatticeFilterAr(ORDERHI,
804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    Vector_Word32_2, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* recombine the 2 bands */
808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Form the polyphase signals, and compensate for DC offset */
810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0;k<FRAMESAMPLES_HALF;k++)
811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Construct a new upper channel signal*/
813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmp_1 = (WebRtc_Word16) WEBRTC_SPL_SAT(32767,
814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           (((WebRtc_Word32)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)), -32768);
815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Construct a new lower channel signal*/
816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmp_2 = (WebRtc_Word16) WEBRTC_SPL_SAT(32767,
817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           (((WebRtc_Word32)Vector_Word16_1[k]-Vector_Word16_2[k])), -32768);
818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Vector_Word16_1[k] = tmp_1;
819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Vector_Word16_2[k] = tmp_2;
820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                  Vector_Word16_2, signal_out16, &ISACdec_obj->postfiltbankstr_obj);
825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  (ISACdec_obj->plcstr_obj).used = PLC_WAS_USED;
827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  *current_framesamples = 480;
828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return len;
830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
831