summaryrefslogtreecommitdiff
path: root/audio_codec/libamr/dec_gain.c (plain)
blob: aa69cf20bf3bbbc1c9998f33a9b71a522a3b3742
1/*
2 *===================================================================
3 * 3GPP AMR Wideband Floating-point Speech Codec
4 *===================================================================
5 */
6#include <memory.h>
7#include "typedef.h"
8#include "dec_util.h"
9
10#define L_SUBFR 64 /* Subframe size */
11#define L_LTPHIST 5
12#define ONE_PER_3 10923
13#define ONE_PER_LTPHIST 6554
14#define UP_SAMP 4
15#define L_INTERPOL2 16
16
17extern const Word16 D_ROM_inter4_2[];
18extern const Word16 D_ROM_pdown_unusable[];
19extern const Word16 D_ROM_pdown_usable[];
20extern const Word16 D_ROM_cdown_unusable[];
21extern const Word16 D_ROM_cdown_usable[];
22extern const Word16 D_ROM_qua_gain6b[];
23extern const Word16 D_ROM_qua_gain7b[];
24
25/*
26 * D_GAIN_init
27 *
28 * Parameters:
29 * mem O: static memory
30 *
31 * Function:
32 * Initialisation of 2nd order quantiser energy predictor.
33 *
34 * Returns:
35 * void
36 */
37void D_GAIN_init(Word16 *mem)
38{
39
40 /* 4nd order quantizer energy predictor (init to -14.0 in Q10) */
41 mem[0] = -14336; /* past_qua_en[0] */
42 mem[1] = -14336; /* past_qua_en[1] */
43 mem[2] = -14336; /* past_qua_en[2] */
44 mem[3] = -14336; /* past_qua_en[3] */
45 /*
46 * mem[4] = 0; past_gain_pit
47 * mem[5] = 0; past_gain_code
48 * mem[6] = 0; prev_gc
49 * mem[7 - 11] = 0; pbuf[i]
50 * mem[12 - 16] = 0; gbuf[i]
51 * mem[17 - 21] = 0; pbuf2[i]
52 */
53 memset(&mem[4], 0, 18 * sizeof(Word16));
54
55 mem[22] = 21845; /* seed */
56 return;
57}
58
59
60/*
61 * D_GAIN_median
62 *
63 * Parameters:
64 * buf I: previous gains
65 *
66 * Function:
67 * Median of gains
68 *
69 * Returns:
70 * median of 5 previous gains
71 */
72static Word16 D_GAIN_median(Word16 x[])
73{
74 Word16 x1, x2, x3, x4, x5;
75 Word16 tmp;
76 x1 = x[ - 2];
77 x2 = x[ - 1];
78 x3 = x[0];
79 x4 = x[1];
80 x5 = x[2];
81
82 if (x2 < x1) {
83 tmp = x1;
84 x1 = x2;
85 x2 = tmp;
86 }
87
88 if (x3 < x1) {
89 tmp = x1;
90 x1 = x3;
91 x3 = tmp;
92 }
93
94 if (x4 < x1) {
95 tmp = x1;
96 x1 = x4;
97 x4 = tmp;
98 }
99
100 if (x5 < x1) {
101 x5 = x1;
102 }
103
104 if (x3 < x2) {
105 tmp = x2;
106 x2 = x3;
107 x3 = tmp;
108 }
109
110 if (x4 < x2) {
111 tmp = x2;
112 x2 = x4;
113 x4 = tmp;
114 }
115
116 if (x5 < x2) {
117 x5 = x2;
118 }
119
120 if (x4 < x3) {
121 x3 = x4;
122 }
123
124 if (x5 < x3) {
125 x3 = x5;
126 }
127
128 return(x3);
129}
130
131
132/*
133 * D_GAIN_decode
134 *
135 * Parameters:
136 * index I: Quantization index
137 * nbits I: number of bits (6 or 7)
138 * code I: Innovative code vector
139 * L_subfr I: Subframe size
140 * gain_pit O: (Q14) Quantized pitch gain
141 * gain_code O: (Q16) Quantized codebook gain
142 * bfi I: Bad frame indicator
143 * prev_bfi I: Previous BF indicator
144 * state I: State of BFH
145 * unusable_frame I: UF indicator
146 * vad_hist I: number of non-speech frames
147 * mem I/O: static memory (4 words)
148 *
149 *
150 * Function:
151 * Decoding of pitch and codebook gains
152 *
153 * Returns:
154 * void
155 */
156void D_GAIN_decode(Word16 index, Word16 nbits, Word16 code[], Word16 *gain_pit,
157 Word32 *gain_cod, Word16 bfi, Word16 prev_bfi,
158 Word16 state, Word16 unusable_frame, Word16 vad_hist,
159 Word16 *mem)
160{
161
162 Word32 gcode0, qua_ener, L_tmp;
163 const Word16 * p;
164 Word16 *past_gain_pit, *past_gain_code, *past_qua_en, *prev_gc;
165 Word16 *gbuf, *pbuf, *pbuf2;
166 Word16 i, tmp, exp, frac, exp_gcode0, gcode_inov;
167 Word16 g_code;
168
169 past_qua_en = mem;
170 past_gain_pit = mem + 4;
171 past_gain_code = mem + 5;
172 prev_gc = mem + 6;
173 pbuf = mem + 7;
174 gbuf = mem + 12;
175 pbuf2 = mem + 17;
176
177 /*
178 * Find energy of code and compute:
179 *
180 * L_tmp = 1.0 / sqrt(energy of code/ L_subfr)
181 */
182 L_tmp = D_UTIL_dot_product12(code, code, L_SUBFR, &exp);
183 exp = (Word16)(exp - (18 + 6)); /* exp: -18 (code in Q9), -6 (/L_subfr) */
184 D_UTIL_normalised_inverse_sqrt(&L_tmp, &exp);
185
186 if (exp > 3) {
187 L_tmp <<= (exp - 3);
188 } else {
189 L_tmp >>= (3 - exp);
190 }
191
192 gcode_inov = (Word16)(L_tmp >> 16); /* g_code_inov in Q12 */
193
194 /*
195 * Case of erasure.
196 */
197 if (bfi != 0) {
198 tmp = D_GAIN_median(&pbuf[2]);
199 *past_gain_pit = tmp;
200
201 if (*past_gain_pit > 15565) {
202 *past_gain_pit = 15565; /* 0.95 in Q14 */
203 }
204
205 if (unusable_frame != 0) {
206 *gain_pit =
207 (Word16)((D_ROM_pdown_unusable[state] * *past_gain_pit) >> 15);
208 } else {
209 *gain_pit =
210 (Word16)((D_ROM_pdown_usable[state] * *past_gain_pit) >> 15);
211 }
212
213 tmp = D_GAIN_median(&gbuf[2]);
214
215 if (vad_hist > 2) {
216 *past_gain_code = tmp;
217 } else {
218 if (unusable_frame != 0) {
219 *past_gain_code =
220 (Word16)((D_ROM_cdown_unusable[state] * tmp) >> 15);
221 } else {
222 *past_gain_code =
223 (Word16)((D_ROM_cdown_usable[state] * tmp) >> 15);
224 }
225 }
226
227 /* update table of past quantized energies */
228 L_tmp = past_qua_en[0] + past_qua_en[1] + past_qua_en[2] + past_qua_en[3];
229 qua_ener = L_tmp >> 2;
230 qua_ener = qua_ener - 3072; /* -3 in Q10 */
231
232 if (qua_ener < - 14336) {
233 qua_ener = -14336; /* -14 in Q10 */
234 }
235
236 past_qua_en[3] = past_qua_en[2];
237 past_qua_en[2] = past_qua_en[1];
238 past_qua_en[1] = past_qua_en[0];
239 past_qua_en[0] = (Word16)qua_ener;
240
241 for (i = 1; i < 5; i++) {
242 gbuf[i - 1] = gbuf[i];
243 }
244 gbuf[4] = *past_gain_code;
245
246 for (i = 1; i < 5; i++) {
247 pbuf[i - 1] = pbuf[i];
248 }
249 pbuf[4] = *past_gain_pit;
250
251 /* adjust gain according to energy of code */
252 /* past_gain_code(Q3) * gcode_inov(Q12) => Q16 */
253 *gain_cod = (*past_gain_code * gcode_inov) << 1;
254
255 return;
256 }
257
258 /*
259 * Compute gcode0.
260 * = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code
261 */
262
263 /* MEAN_ENER in Q24 = 0x1e000000 */
264 /* MA prediction coeff = {0.5, 0.4, 0.3, 0.2} in Q13 */
265 L_tmp = 0xF000000 + (4096 * past_qua_en[0]); /* Q13*Q10 -> Q24 */
266 L_tmp = L_tmp + (3277 * past_qua_en[1]); /* Q13*Q10 -> Q24 */
267 L_tmp = L_tmp + (2458 * past_qua_en[2]); /* Q13*Q10 -> Q24 */
268 L_tmp = L_tmp + (1638 * past_qua_en[3]); /* Q13*Q10 -> Q24 */
269 gcode0 = L_tmp >> 15; /* From Q24 to Q8 */
270
271 /*
272 * gcode0 = pow(10.0, gcode0/20)
273 * = pow(2, 3.321928*gcode0/20)
274 * = pow(2, 0.166096*gcode0)
275 */
276 L_tmp = (gcode0 * 5443) >> 7;
277 /* *0.166096 in Q15 -> Q24, From Q24 to Q16 */
278 D_UTIL_l_extract(L_tmp, &exp_gcode0, &frac);
279 /* Extract exponant of gcode0 */
280 gcode0 = D_UTIL_pow2(14, frac); /* Put 14 as exponant so that */
281
282 /*
283 * output of Pow2() will be:
284 * 16384 < Pow2() <= 32767
285 */
286 exp_gcode0 = (Word16)(exp_gcode0 - 14);
287
288 /* Read the quantized gains */
289 if (nbits == 6) {
290 p = &D_ROM_qua_gain6b[(index << 1)];
291 } else {
292 p = &D_ROM_qua_gain7b[(index << 1)];
293 }
294
295 *gain_pit = *p++; /* selected pitch gain in Q14 */
296 g_code = *p++; /* selected code gain in Q11 */
297 L_tmp = g_code * gcode0;
298 exp_gcode0 += 5;
299
300 if (exp_gcode0 >= 0) {
301 *gain_cod = L_tmp << exp_gcode0; /* gain of code in Q16 */
302 } else {
303 *gain_cod = L_tmp >> -exp_gcode0; /* gain of code in Q16 */
304 }
305
306 if (prev_bfi == 1) {
307 L_tmp = (*prev_gc * 5120) << 1; /* prev_gc(Q3) * 1.25(Q12) = Q16 */
308
309 /* if((*gain_cod > ((*prev_gc) * 1.25)) && (*gain_cod > 100.0)) */
310 if ((*gain_cod > L_tmp) & (*gain_cod > 6553600)) {
311 *gain_cod = L_tmp;
312 }
313 }
314
315 /* keep past gain code in Q3 for frame erasure (can saturate) */
316 L_tmp = (*gain_cod + 0x1000) >> 13;
317
318 if (L_tmp < 32768) {
319 *past_gain_code = (Word16)L_tmp;
320 } else {
321 *past_gain_code = 32767;
322 }
323
324 *past_gain_pit = *gain_pit;
325 *prev_gc = *past_gain_code;
326
327 for (i = 1; i < 5; i++) {
328 gbuf[i - 1] = gbuf[i];
329 }
330 gbuf[4] = *past_gain_code;
331
332 for (i = 1; i < 5; i++) {
333 pbuf[i - 1] = pbuf[i];
334 }
335 pbuf[4] = *past_gain_pit;
336
337 for (i = 1; i < 5; i++) {
338 pbuf2[i - 1] = pbuf2[i];
339 }
340 pbuf2[4] = *past_gain_pit;
341
342 /* adjust gain according to energy of code */
343 D_UTIL_l_extract(*gain_cod, &exp, &frac);
344 L_tmp = D_UTIL_mpy_32_16(exp, frac, gcode_inov);
345
346 if (L_tmp < 0xFFFFFFF) {
347 *gain_cod = (L_tmp << 3); /* gcode_inov in Q12 */
348 } else {
349 *gain_cod = 0x7FFFFFFF;
350 }
351
352 /*
353 * qua_ener = 20*log10(g_code)
354 * = 6.0206*log2(g_code)
355 * = 6.0206*(log2(g_codeQ11) - 11)
356 */
357 L_tmp = (Word32)(g_code);
358 D_UTIL_log2(L_tmp, &exp, &frac);
359 exp = (Word16)(exp - 11);
360 L_tmp = D_UTIL_mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */
361 qua_ener = L_tmp >> 3; /* result in Q10 */
362
363 /* update table of past quantized energies */
364 past_qua_en[3] = past_qua_en[2];
365 past_qua_en[2] = past_qua_en[1];
366 past_qua_en[1] = past_qua_en[0];
367 past_qua_en[0] = (Word16)qua_ener;
368
369 return;
370}
371
372
373/*
374 * D_GAIN_adaptive_control
375 *
376 * Parameters:
377 * sig_in I: postfilter input signal
378 * sig_out I/O: postfilter output signal
379 * l_trm I: subframe size
380 *
381 * Function:
382 * Adaptive gain control is used to compensate for
383 * the gain difference between the non-emphasized excitation and
384 * emphasized excitation.
385 *
386 * Returns:
387 * void
388 */
389void D_GAIN_adaptive_control(Word16 *sig_in, Word16 *sig_out, Word16 l_trm)
390{
391 Word32 s, temp, i, exp;
392 Word32 gain_in, gain_out, g0;
393
394 /* calculate gain_out with exponent */
395 temp = sig_out[0] >> 2;
396 s = temp * temp;
397
398 for (i = 1; i < l_trm; i++) {
399 temp = sig_out[i] >> 2;
400 s += temp * temp;
401 }
402
403 s <<= 1;
404
405 if (s == 0) {
406 return;
407 }
408 exp = (D_UTIL_norm_l(s) - 1);
409
410 if (exp >= 0) {
411 gain_out = ((s << exp) + 0x8000) >> 16;
412 } else {
413 gain_out = ((s >> -exp) + 0x8000) >> 16;
414 }
415
416 /* calculate gain_in with exponent */
417 temp = sig_in[0] >> 2;
418 s = temp * temp;
419
420 for (i = 1; i < l_trm; i++) {
421 temp = sig_in[i] >> 2;
422 s += temp * temp;
423 }
424
425 s <<= 1;
426
427 if (s == 0) {
428 g0 = 0;
429 } else {
430 i = D_UTIL_norm_l(s);
431 s = ((s << i) + 0x8000) >> 16;
432
433 if ((s < 32768) & (s > 0)) {
434 gain_in = s;
435 } else {
436 gain_in = 32767;
437 }
438 exp = exp - i;
439
440 /*
441 * g0 = sqrt(gain_in/gain_out)
442 */
443 s = (gain_out << 15) / gain_in;
444 s = s << (7 - exp); /* s = gain_out / gain_in */
445 s = D_UTIL_inverse_sqrt(s);
446 g0 = ((s << 9) + 0x8000) >> 16;
447 }
448
449 /* sig_out(n) = gain(n) sig_out(n) */
450 for (i = 0; i < l_trm; i++) {
451 s = (sig_out[i] * g0) >> 13;
452 sig_out[i] = D_UTIL_saturate(s);
453 }
454
455 return;
456}
457
458
459/*
460 * D_GAIN_insert_lag
461 *
462 * Parameters:
463 * array I/O: pitch lag history
464 * n I: history size
465 * x I: lag value
466 *
467 * Function:
468 * Insert lag into correct location
469 *
470 * Returns:
471 * void
472 */
473static void D_GAIN_insert_lag(Word16 array[], Word32 n, Word16 x)
474{
475 Word32 i;
476
477 for (i = n - 1; i >= 0; i--) {
478 if (x < array[i]) {
479 array[i + 1] = array[i];
480 } else {
481 break;
482 }
483 }
484
485 array[i + 1] = x;
486}
487
488
489/*
490 * D_GAIN_sort_lag
491 *
492 * Parameters:
493 * array I/O: pitch lag history
494 * n I: history size
495 *
496 * Function:
497 * Sorting of the lag history
498 *
499 * Returns:
500 * void
501 */
502static void D_GAIN_sort_lag(Word16 array[], Word16 n)
503{
504 Word32 i;
505
506 for (i = 0; i < n; i++) {
507 D_GAIN_insert_lag(array, i, array[i]);
508 }
509}
510
511
512/*
513 * D_GAIN_lag_concealment_init
514 *
515 * Parameters:
516 * lag_hist O: pitch lag history
517 *
518 * Function:
519 * Initialise lag history to 64
520 *
521 * Returns:
522 * void
523 */
524void D_GAIN_lag_concealment_init(Word16 lag_hist[])
525{
526 Word32 i;
527
528 for (i = 0; i < L_LTPHIST; i++) {
529 lag_hist[i] = 64;
530 }
531}
532
533
534/*
535 * D_GAIN_lag_concealment
536 *
537 * Parameters:
538 * gain_hist I: gain history
539 * lag_hist I: pitch lag history
540 * T0 O: current lag
541 * old_T0 I: previous lag
542 * seed I/O: seed for random
543 * unusable_frame I: lost frame
544 *
545 * Function:
546 * Concealment of LTP lags during bad frames
547 *
548 * Returns:
549 * void
550 */
551void D_GAIN_lag_concealment(Word16 gain_hist[], Word16 lag_hist[],
552 Word32 *T0, Word16 *old_T0, Word16 *seed,
553 Word16 unusable_frame)
554{
555 Word32 i, lagDif, tmp, tmp2, D2, meanLag = 0;
556 Word16 lag_hist2[L_LTPHIST] = {0};
557 Word16 maxLag, minLag, lastLag;
558 Word16 minGain, lastGain, secLastGain;
559 Word16 D;
560
561 /*
562 * Is lag index such that it can be aplied directly
563 * or does it has to be subtituted
564 */
565 lastGain = gain_hist[4];
566 secLastGain = gain_hist[3];
567 lastLag = lag_hist[0];
568
569 /* SMALLEST history lag */
570 minLag = lag_hist[0];
571
572 for (i = 1; i < L_LTPHIST; i++) {
573 if (lag_hist[i] < minLag) {
574 minLag = lag_hist[i];
575 }
576 }
577
578 /* BIGGEST history lag */
579 maxLag = lag_hist[0];
580
581 for (i = 1; i < L_LTPHIST; i++) {
582 if (lag_hist[i] > maxLag) {
583 maxLag = lag_hist[i];
584 }
585 }
586
587 /* SMALLEST history gain */
588 minGain = gain_hist[0];
589
590 for (i = 1; i < L_LTPHIST; i++) {
591 if (gain_hist[i] < minGain) {
592 minGain = gain_hist[i];
593 }
594 }
595
596 /* Difference between MAX and MIN lag */
597 lagDif = maxLag - minLag;
598
599 if (unusable_frame != 0) {
600 /*
601 * LTP-lag for RX_SPEECH_LOST
602 * Recognition of the LTP-history
603 */
604 if ((minGain > 8192) & (lagDif < 10)) {
605 *T0 = *old_T0;
606 } else if ((lastGain > 8192) && (secLastGain > 8192)) {
607 *T0 = lag_hist[0];
608 } else {
609 /*
610 * SORT
611 * The sorting of the lag history
612 */
613 for (i = 0; i < L_LTPHIST; i++) {
614 lag_hist2[i] = lag_hist[i];
615 }
616 D_GAIN_sort_lag(lag_hist2, 5);
617
618 /*
619 * Lag is weighted towards bigger lags
620 * and random variation is added
621 */
622 lagDif = (lag_hist2[4] - lag_hist2[2]);
623
624 if (lagDif > 40) {
625 lagDif = 40;
626 }
627
628 D = D_UTIL_random(seed); /* D={-1, ...,1} */
629
630 /* D2={-lagDif/2..lagDif/2} */
631 tmp = lagDif >> 1;
632 D2 = (tmp * D) >> 15;
633 tmp = (lag_hist2[2] + lag_hist2[3]) + lag_hist2[4];
634 *T0 = ((tmp * ONE_PER_3) >> 15) + D2;
635 }
636
637 /* New lag is not allowed to be bigger or smaller than last lag values */
638 if (*T0 > maxLag) {
639 *T0 = maxLag;
640 }
641
642 if (*T0 < minLag) {
643 *T0 = minLag;
644 }
645 } else {
646 /*
647 * LTP-lag for RX_BAD_FRAME
648 * MEAN lag
649 */
650 meanLag = 0;
651
652 for (i = 0; i < L_LTPHIST; i++) {
653 meanLag = meanLag + lag_hist[i];
654 }
655
656 meanLag = (meanLag * ONE_PER_LTPHIST) >> 15;
657 tmp = *T0 - maxLag;
658 tmp2 = *T0 - lastLag;
659
660 if ((lagDif < 10) & (*T0 > (minLag - 5)) & (tmp < 5)) {
661 *T0 = *T0;
662 } else if ((lastGain > 8192) & (secLastGain > 8192) & ((tmp2 > - 10)
663 & (tmp2 < 10))) {
664 *T0 = *T0;
665 } else if ((minGain < 6554) & (lastGain == minGain) & ((*T0 > minLag)
666 & (*T0 < maxLag))) {
667 *T0 = *T0;
668 } else if ((lagDif < 70) & (*T0 > minLag) & (*T0 < maxLag)) {
669 *T0 = *T0;
670 } else if ((*T0 > meanLag) & (*T0 < maxLag)) {
671 *T0 = *T0;
672 } else {
673 if ((minGain > 8192) & (lagDif < 10)) {
674 *T0 = lag_hist[0];
675 } else if ((lastGain > 8192) & (secLastGain > 8192)) {
676 *T0 = lag_hist[0];
677 } else {
678 /*
679 * SORT
680 * The sorting of the lag history
681 */
682 for (i = 0; i < L_LTPHIST; i++) {
683 lag_hist2[i] = lag_hist[i];
684 }
685
686 D_GAIN_sort_lag(lag_hist2, 5);
687
688 /*
689 * Lag is weighted towards bigger lags
690 * and random variation is added
691 */
692 lagDif = lag_hist2[4] - lag_hist2[2];
693
694 if (lagDif > 40) {
695 lagDif = 40;
696 }
697
698 D = D_UTIL_random(seed); /* D={-1,.., 1} */
699
700 /* D2={-lagDif/2..lagDif/2} */
701 tmp = lagDif >> 1;
702 D2 = (tmp * D) >> 15;
703 tmp = (lag_hist2[2] + lag_hist2[3]) + lag_hist2[4];
704 *T0 = ((tmp * ONE_PER_3) >> 15) + D2;
705 }
706
707 /*
708 * New lag is not allowed to be bigger or
709 * smaller than last lag values
710 */
711 if (*T0 > maxLag) {
712 *T0 = maxLag;
713 }
714
715 if (*T0 < minLag) {
716 *T0 = minLag;
717 }
718 }
719 }
720}
721
722
723/*
724 * D_GAIN_adaptive_codebook_excitation
725 *
726 * Parameters:
727 * exc I/O: excitation buffer
728 * T0 I: integer pitch lag
729 * frac I: fraction of lag
730 *
731 * Function:
732 * Compute the result of Word32 term prediction with fractional
733 * interpolation of resolution 1/4.
734 *
735 * Returns:
736 * interpolated signal (adaptive codebook excitation)
737 */
738void D_GAIN_adaptive_codebook_excitation(Word16 exc[], Word32 T0, Word32 frac)
739{
740 Word32 i, j, k, sum;
741 Word16 *x;
742
743 x = &exc[ - T0];
744 frac = -(frac);
745
746 if (frac < 0) {
747 frac = (frac + UP_SAMP);
748 x--;
749 }
750 x = x - L_INTERPOL2 + 1;
751
752 for (j = 0; j < L_SUBFR + 1; j++) {
753 sum = 0L;
754
755 for (i = 0, k = ((UP_SAMP - 1) - frac); i < 2 * L_INTERPOL2; i++,
756 k += UP_SAMP) {
757 sum += x[i] * D_ROM_inter4_2[k];
758 }
759 sum = (sum + 0x2000) >> 14;
760
761 exc[j] = D_UTIL_saturate(sum);
762
763 x++;
764 }
765 return;
766}
767
768
769/*
770 * D_GAIN_pitch_sharpening
771 *
772 * Parameters:
773 * x I/O: impulse response (or algebraic code)
774 * pit_lag I: pitch lag
775 * sharp I: (Q15) pitch sharpening factor
776 *
777 * Function:
778 * Performs Pitch sharpening routine for one subframe.
779 *
780 * Returns:
781 * void
782 */
783void D_GAIN_pitch_sharpening(Word16 *x, Word32 pit_lag, Word16 sharp)
784{
785 Word32 i;
786 Word32 tmp;
787
788 for (i = pit_lag; i < L_SUBFR; i++) {
789 tmp = x[i] << 15;
790 tmp += x[i - pit_lag] * sharp;
791 x[i] = (Word16)((tmp + 0x4000) >> 15);
792 }
793 return;
794}
795
796
797/*
798 * D_GAIN_find_voice_factor
799 *
800 * Parameters:
801 * exc I: pitch excitation
802 * Q_exc I: exc format
803 * gain_pit I: (Q14) gain of pitch
804 * code I: (Q9) fixed codebook excitation
805 * gain_code I: (Q0) gain of code
806 * L_subfr I: subframe length
807 *
808 * Function:
809 * Find the voicing factor.
810 *
811 * Returns:
812 * (Q15) 1=voice to -1=unvoiced
813 */
814Word16 D_GAIN_find_voice_factor(Word16 exc[], Word16 Q_exc,
815 Word16 gain_pit, Word16 code[],
816 Word16 gain_code, Word16 L_subfr)
817{
818
819 Word32 tmp, ener1, ener2, i;
820 Word16 exp, exp1, exp2;
821
822 ener1 = (D_UTIL_dot_product12(exc, exc, L_subfr, &exp1)) >> 16;
823 exp1 = (Word16)(exp1 - (Q_exc + Q_exc));
824 tmp = (gain_pit * gain_pit) << 1;
825 exp = D_UTIL_norm_l(tmp);
826 tmp = (tmp << exp) >> 16;
827 ener1 = (ener1 * tmp) >> 15;
828 exp1 = (Word16)((exp1 - exp) - 10); /* 10 -> gain_pit Q14 to Q9 */
829 ener2 = D_UTIL_dot_product12(code, code, L_subfr, &exp2) >> 16;
830 exp = D_UTIL_norm_s(gain_code);
831 tmp = gain_code << exp;
832 tmp = (tmp * tmp) >> 15;
833 ener2 = (ener2 * tmp) >> 15;
834 exp2 = (Word16)(exp2 - (exp << 1));
835 i = exp1 - exp2;
836
837 if (i >= 0) {
838 ener1 = ener1 >> 1;
839 ener2 = ener2 >> (i + 1);
840 } else if (i > (-16)) {
841 ener1 = ener1 >> (1 - i);
842 ener2 = ener2 >> 1;
843 } else {
844 ener1 = 0;
845 ener2 = ener2 >> 1;
846 }
847
848 tmp = ener1 - ener2;
849 ener1 = (ener1 + ener2) + 1;
850 tmp = (tmp << 15) / ener1;
851
852 return((Word16)tmp);
853}
854