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