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