FreeCalypso > hg > gsmhr-codec-ref
comparison vad.c @ 0:9008dbc8ca74
import original C code from GSM 06.06
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 14 Jun 2024 23:27:16 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:9008dbc8ca74 |
---|---|
1 /**************************************************************************** | |
2 * | |
3 * TITLE: Half-Rate GSM Voice Activity Detector (VAD) Modules | |
4 * | |
5 * VERSION: 1.2 | |
6 * | |
7 * REFERENCE: Recommendation GSM 06.42 | |
8 * | |
9 ***************************************************************************/ | |
10 | |
11 /*_________________________________________________________________________ | |
12 | | | |
13 | Include Files | | |
14 |_________________________________________________________________________| | |
15 */ | |
16 | |
17 #include "typedefs.h" | |
18 #include "mathhalf.h" | |
19 #include "mathdp31.h" | |
20 #include "vad.h" | |
21 | |
22 | |
23 /*_________________________________________________________________________ | |
24 | | | |
25 | Local Defines | | |
26 |_________________________________________________________________________| | |
27 */ | |
28 | |
29 /*** Floating point representations of constants pth, plev and margin ***/ | |
30 | |
31 #define M_PTH 26250 | |
32 #define E_PTH 18 | |
33 #define M_PLEV 17500 | |
34 #define E_PLEV 20 | |
35 #define M_MARGIN 27343 | |
36 #define E_MARGIN 27 | |
37 | |
38 /*_________________________________________________________________________ | |
39 | | | |
40 | Static Variables | | |
41 |_________________________________________________________________________| | |
42 */ | |
43 | |
44 static Shortword | |
45 pswRvad[9], | |
46 swNormRvad, | |
47 swPt_sacf, | |
48 swPt_sav0, | |
49 swE_thvad, | |
50 swM_thvad, | |
51 swAdaptCount, | |
52 swBurstCount, | |
53 swHangCount, | |
54 swOldLagCount, | |
55 swVeryOldLagCount, | |
56 swOldLag; | |
57 | |
58 static Longword | |
59 pL_sacf[27], | |
60 pL_sav0[36], | |
61 L_lastdm; | |
62 | |
63 /**************************************************************************** | |
64 * | |
65 * FUNCTION: vad_reset | |
66 * | |
67 * VERSION: 1.2 | |
68 * | |
69 * PURPOSE: Resets VAD static variables to their initial value. | |
70 * | |
71 ***************************************************************************/ | |
72 | |
73 void vad_reset(void) | |
74 | |
75 { | |
76 | |
77 /*_________________________________________________________________________ | |
78 | | | |
79 | Automatic Variables | | |
80 |_________________________________________________________________________| | |
81 */ | |
82 | |
83 int i; | |
84 | |
85 /*_________________________________________________________________________ | |
86 | | | |
87 | Executable Code | | |
88 |_________________________________________________________________________| | |
89 */ | |
90 | |
91 pswRvad[0] = 24576; | |
92 swNormRvad = 7; | |
93 swPt_sacf = 0; | |
94 swPt_sav0 = 0; | |
95 L_lastdm = 0; | |
96 swE_thvad = 21; | |
97 swM_thvad = 21875; | |
98 swAdaptCount = 0; | |
99 swBurstCount = 0; | |
100 swHangCount = -1; | |
101 swOldLagCount = 0; | |
102 swVeryOldLagCount = 0; | |
103 swOldLag = 21; | |
104 | |
105 for (i = 1; i < 9; i++) | |
106 pswRvad[i] = 0; | |
107 for (i = 0; i < 27; i++) | |
108 pL_sacf[i] = 0; | |
109 for (i = 0; i < 36; i++) | |
110 pL_sav0[i] = 0; | |
111 | |
112 } | |
113 | |
114 /**************************************************************************** | |
115 * | |
116 * FUNCTION: vad_algorithm | |
117 * | |
118 * VERSION: 1.2 | |
119 * | |
120 * PURPOSE: Returns a decision as to whether the current frame being | |
121 * processed by the speech encoder contains speech or not. | |
122 * | |
123 * INPUTS: pL_acf[0..8] autocorrelation of input signal frame | |
124 * swScaleAcf L_acf scaling factor | |
125 * pswRc[0..3] speech encoder reflection coefficients | |
126 * swPtch flag to indicate a periodic signal component | |
127 * | |
128 * OUTPUTS: pswVadFlag vad decision | |
129 * | |
130 ***************************************************************************/ | |
131 | |
132 void vad_algorithm(Longword pL_acf[9], | |
133 Shortword swScaleAcf, | |
134 Shortword pswRc[4], | |
135 Shortword swPtch, | |
136 Shortword *pswVadFlag) | |
137 { | |
138 | |
139 /*_________________________________________________________________________ | |
140 | | | |
141 | Automatic Variables | | |
142 |_________________________________________________________________________| | |
143 */ | |
144 | |
145 Longword | |
146 pL_av0[9], | |
147 pL_av1[9]; | |
148 | |
149 Shortword | |
150 swM_acf0, | |
151 swE_acf0, | |
152 pswRav1[9], | |
153 swNormRav1, | |
154 swM_pvad, | |
155 swE_pvad, | |
156 swStat, | |
157 swTone, | |
158 swVvad; | |
159 | |
160 | |
161 /*_________________________________________________________________________ | |
162 | | | |
163 | Executable Code | | |
164 |_________________________________________________________________________| | |
165 */ | |
166 | |
167 energy_computation | |
168 ( | |
169 pL_acf, swScaleAcf, | |
170 pswRvad, swNormRvad, | |
171 &swM_pvad, &swE_pvad, | |
172 &swM_acf0, &swE_acf0 | |
173 ); | |
174 | |
175 average_acf | |
176 ( | |
177 pL_acf, swScaleAcf, | |
178 pL_av0, pL_av1 | |
179 ); | |
180 | |
181 predictor_values | |
182 ( | |
183 pL_av1, | |
184 pswRav1, | |
185 &swNormRav1 | |
186 ); | |
187 | |
188 spectral_comparison | |
189 ( | |
190 pswRav1, swNormRav1, | |
191 pL_av0, | |
192 &swStat | |
193 ); | |
194 | |
195 tone_detection | |
196 ( | |
197 pswRc, | |
198 &swTone | |
199 ); | |
200 | |
201 threshold_adaptation | |
202 ( | |
203 swStat, swPtch, swTone, | |
204 pswRav1, swNormRav1, | |
205 swM_pvad, swE_pvad, | |
206 swM_acf0, swE_acf0, | |
207 pswRvad, &swNormRvad, | |
208 &swM_thvad, &swE_thvad | |
209 ); | |
210 | |
211 vad_decision | |
212 ( | |
213 swM_pvad, swE_pvad, | |
214 swM_thvad, swE_thvad, | |
215 &swVvad | |
216 ); | |
217 | |
218 vad_hangover | |
219 ( | |
220 swVvad, | |
221 pswVadFlag | |
222 ); | |
223 | |
224 } | |
225 | |
226 /**************************************************************************** | |
227 * | |
228 * FUNCTION: energy_computation | |
229 * | |
230 * VERSION: 1.2 | |
231 * | |
232 * PURPOSE: Computes the input and residual energies of the adaptive | |
233 * filter in a floating point representation. | |
234 * | |
235 * INPUTS: pL_acf[0..8] autocorrelation of input signal frame | |
236 * swScaleAcf L_acf scaling factor | |
237 * pswRvad[0..8] autocorrelated adaptive filter coefficients | |
238 * swNormRvad rvad scaling factor | |
239 * | |
240 * OUTPUTS: pswM_pvad mantissa of filtered signal energy | |
241 * pswE_pvad exponent of filtered signal energy | |
242 * pswM_acf0 mantissa of signal frame energy | |
243 * pswE_acf0 exponent of signal frame energy | |
244 * | |
245 ***************************************************************************/ | |
246 | |
247 void energy_computation(Longword pL_acf[], | |
248 Shortword swScaleAcf, | |
249 Shortword pswRvad[], | |
250 Shortword swNormRvad, | |
251 Shortword *pswM_pvad, | |
252 Shortword *pswE_pvad, | |
253 Shortword *pswM_acf0, | |
254 Shortword *pswE_acf0) | |
255 { | |
256 | |
257 /*_________________________________________________________________________ | |
258 | | | |
259 | Automatic Variables | | |
260 |_________________________________________________________________________| | |
261 */ | |
262 | |
263 Longword | |
264 L_temp; | |
265 | |
266 Shortword | |
267 pswSacf[9], | |
268 swNormAcf, | |
269 swNormProd, | |
270 swShift; | |
271 | |
272 int | |
273 i; | |
274 | |
275 | |
276 /*_________________________________________________________________________ | |
277 | | | |
278 | Executable Code | | |
279 |_________________________________________________________________________| | |
280 */ | |
281 | |
282 /*** Test if acf[0] is zero ***/ | |
283 | |
284 if (pL_acf[0] == 0) | |
285 { | |
286 *pswE_pvad = -0x8000; | |
287 *pswM_pvad = 0; | |
288 *pswE_acf0 = -0x8000; | |
289 *pswM_acf0 = 0; | |
290 return; | |
291 } | |
292 | |
293 | |
294 /*** Re-normalisation of L_acf[0..8] ***/ | |
295 | |
296 swNormAcf = norm_l(pL_acf[0]); | |
297 swShift = sub(swNormAcf, 3); | |
298 | |
299 for (i = 0; i <= 8; i++) | |
300 pswSacf[i] = extract_h(L_shl(pL_acf[i], swShift)); | |
301 | |
302 | |
303 /*** Computation of e_acf0 and m_acf0 ***/ | |
304 | |
305 *pswE_acf0 = add(32, shl(swScaleAcf, 1)); | |
306 *pswE_acf0 = sub(*pswE_acf0, swNormAcf); | |
307 *pswM_acf0 = shl(pswSacf[0], 3); | |
308 | |
309 | |
310 /*** Computation of e_pvad and m_pvad ***/ | |
311 | |
312 *pswE_pvad = add(*pswE_acf0, 14); | |
313 *pswE_pvad = sub(*pswE_pvad, swNormRvad); | |
314 | |
315 L_temp = 0; | |
316 | |
317 for (i = 1; i <= 8; i++) | |
318 L_temp = L_mac(L_temp, pswSacf[i], pswRvad[i]); | |
319 | |
320 L_temp = L_add(L_temp, L_shr(L_mult(pswSacf[0], pswRvad[0]), 1)); | |
321 | |
322 if (L_temp <= 0) | |
323 L_temp = 1; | |
324 | |
325 swNormProd = norm_l(L_temp); | |
326 *pswE_pvad = sub(*pswE_pvad, swNormProd); | |
327 *pswM_pvad = extract_h(L_shl(L_temp, swNormProd)); | |
328 | |
329 } | |
330 | |
331 /**************************************************************************** | |
332 * | |
333 * FUNCTION: average_acf | |
334 * | |
335 * VERSION: 1.2 | |
336 * | |
337 * PURPOSE: Computes the arrays L_av0 [0..8] and L_av1 [0..8]. | |
338 * | |
339 * INPUTS: pL_acf[0..8] autocorrelation of input signal frame | |
340 * swScaleAcf L_acf scaling factor | |
341 * | |
342 * OUTPUTS: pL_av0[0..8] ACF averaged over last four frames | |
343 * pL_av1[0..8] ACF averaged over previous four frames | |
344 * | |
345 ***************************************************************************/ | |
346 | |
347 void average_acf(Longword pL_acf[], | |
348 Shortword swScaleAcf, | |
349 Longword pL_av0[], | |
350 Longword pL_av1[]) | |
351 { | |
352 | |
353 /*_________________________________________________________________________ | |
354 | | | |
355 | Automatic Variables | | |
356 |_________________________________________________________________________| | |
357 */ | |
358 | |
359 Longword L_temp; | |
360 | |
361 Shortword swScale; | |
362 | |
363 int i; | |
364 | |
365 /*_________________________________________________________________________ | |
366 | | | |
367 | Executable Code | | |
368 |_________________________________________________________________________| | |
369 */ | |
370 | |
371 /*** computation of the scaleing factor ***/ | |
372 | |
373 swScale = sub(10, shl(swScaleAcf, 1)); | |
374 | |
375 | |
376 /*** Computation of the arrays L_av0 and L_av1 ***/ | |
377 | |
378 for (i = 0; i <= 8; i++) | |
379 { | |
380 L_temp = L_shr(pL_acf[i], swScale); | |
381 pL_av0[i] = L_add(pL_sacf[i], L_temp); | |
382 pL_av0[i] = L_add(pL_sacf[i + 9], pL_av0[i]); | |
383 pL_av0[i] = L_add(pL_sacf[i + 18], pL_av0[i]); | |
384 pL_sacf[swPt_sacf + i] = L_temp; | |
385 pL_av1[i] = pL_sav0[swPt_sav0 + i]; | |
386 pL_sav0[swPt_sav0 + i] = pL_av0[i]; | |
387 } | |
388 | |
389 | |
390 /*** Update the array pointers ***/ | |
391 | |
392 if (swPt_sacf == 18) | |
393 swPt_sacf = 0; | |
394 else | |
395 swPt_sacf = add(swPt_sacf, 9); | |
396 | |
397 if (swPt_sav0 == 27) | |
398 swPt_sav0 = 0; | |
399 else | |
400 swPt_sav0 = add(swPt_sav0, 9); | |
401 | |
402 } | |
403 | |
404 /**************************************************************************** | |
405 * | |
406 * FUNCTION: predictor_values | |
407 * | |
408 * VERSION: 1.2 | |
409 * | |
410 * PURPOSE: Computes the array rav [0..8] needed for the spectral | |
411 * comparison and the threshold adaptation. | |
412 * | |
413 * INPUTS: pL_av1 [0..8] ACF averaged over previous four frames | |
414 * | |
415 * OUTPUTS: pswRav1 [0..8] ACF obtained from L_av1 | |
416 * pswNormRav1 r_av1 scaling factor | |
417 * | |
418 ***************************************************************************/ | |
419 | |
420 void predictor_values(Longword pL_av1[], | |
421 Shortword pswRav1[], | |
422 Shortword *pswNormRav1) | |
423 { | |
424 | |
425 /*_________________________________________________________________________ | |
426 | | | |
427 | Automatic Variables | | |
428 |_________________________________________________________________________| | |
429 */ | |
430 | |
431 Shortword | |
432 pswVpar[8], | |
433 pswAav1[9]; | |
434 | |
435 /*_________________________________________________________________________ | |
436 | | | |
437 | Executable Code | | |
438 |_________________________________________________________________________| | |
439 */ | |
440 | |
441 schur_recursion(pL_av1, pswVpar); | |
442 step_up(8, pswVpar, pswAav1); | |
443 compute_rav1(pswAav1, pswRav1, pswNormRav1); | |
444 | |
445 } | |
446 | |
447 /**************************************************************************** | |
448 * | |
449 * FUNCTION: schur_recursion | |
450 * | |
451 * VERSION: 1.2 | |
452 * | |
453 * PURPOSE: Uses the Schur recursion to compute adaptive filter | |
454 * reflection coefficients from an autorrelation function. | |
455 * | |
456 * INPUTS: pL_av1[0..8] autocorrelation function | |
457 * | |
458 * OUTPUTS: pswVpar[0..7] reflection coefficients | |
459 * | |
460 ***************************************************************************/ | |
461 | |
462 void schur_recursion(Longword pL_av1[], | |
463 Shortword pswVpar[]) | |
464 { | |
465 | |
466 /*_________________________________________________________________________ | |
467 | | | |
468 | Automatic Variables | | |
469 |_________________________________________________________________________| | |
470 */ | |
471 | |
472 Shortword | |
473 pswAcf[9], | |
474 pswPp[9], | |
475 pswKk[9], | |
476 swTemp; | |
477 | |
478 int i, | |
479 k, | |
480 m, | |
481 n; | |
482 | |
483 | |
484 /*_________________________________________________________________________ | |
485 | | | |
486 | Executable Code | | |
487 |_________________________________________________________________________| | |
488 */ | |
489 | |
490 /*** Schur recursion with 16-bit arithmetic ***/ | |
491 | |
492 if (pL_av1[0] == 0) | |
493 { | |
494 for (i = 0; i < 8; i++) | |
495 pswVpar[i] = 0; | |
496 return; | |
497 } | |
498 | |
499 swTemp = norm_l(pL_av1[0]); | |
500 | |
501 for (k = 0; k <= 8; k++) | |
502 pswAcf[k] = extract_h(L_shl(pL_av1[k], swTemp)); | |
503 | |
504 | |
505 /*** Initialise array pp[..] and kk[..] for the recursion: ***/ | |
506 | |
507 for (i = 1; i <= 7; i++) | |
508 pswKk[9 - i] = pswAcf[i]; | |
509 | |
510 for (i = 0; i <= 8; i++) | |
511 pswPp[i] = pswAcf[i]; | |
512 | |
513 | |
514 /*** Compute Parcor coefficients: ***/ | |
515 | |
516 for (n = 0; n < 8; n++) | |
517 { | |
518 if (pswPp[0] < abs_s(pswPp[1])) | |
519 { | |
520 for (i = n; i < 8; i++) | |
521 pswVpar[i] = 0; | |
522 return; | |
523 } | |
524 pswVpar[n] = divide_s(abs_s(pswPp[1]), pswPp[0]); | |
525 | |
526 if (pswPp[1] > 0) | |
527 pswVpar[n] = negate(pswVpar[n]); | |
528 if (n == 7) | |
529 return; | |
530 | |
531 | |
532 /*** Schur recursion: ***/ | |
533 | |
534 pswPp[0] = add(pswPp[0], mult_r(pswPp[1], pswVpar[n])); | |
535 | |
536 for (m = 1; m <= (7 - n); m++) | |
537 { | |
538 pswPp[m] = add(pswPp[1 + m], mult_r(pswKk[9 - m], pswVpar[n])); | |
539 pswKk[9 - m] = add(pswKk[9 - m], mult_r(pswPp[1 + m], pswVpar[n])); | |
540 } | |
541 } | |
542 | |
543 } | |
544 | |
545 /**************************************************************************** | |
546 * | |
547 * FUNCTION: step_up | |
548 * | |
549 * VERSION: 1.2 | |
550 * | |
551 * PURPOSE: Computes the transversal filter coefficients from the | |
552 * reflection coefficients. | |
553 * | |
554 * INPUTS: swNp filter order (2..8) | |
555 * pswVpar[0..np-1] reflection coefficients | |
556 * | |
557 * OUTPUTS: pswAav1[0..np] transversal filter coefficients | |
558 * | |
559 ***************************************************************************/ | |
560 | |
561 void step_up(Shortword swNp, | |
562 Shortword pswVpar[], | |
563 Shortword pswAav1[]) | |
564 { | |
565 | |
566 /*_________________________________________________________________________ | |
567 | | | |
568 | Automatic Variables | | |
569 |_________________________________________________________________________| | |
570 */ | |
571 | |
572 Longword | |
573 pL_coef[9], | |
574 pL_work[9]; | |
575 | |
576 Shortword | |
577 swTemp; | |
578 | |
579 int | |
580 i, | |
581 m; | |
582 | |
583 | |
584 /*_________________________________________________________________________ | |
585 | | | |
586 | Executable Code | | |
587 |_________________________________________________________________________| | |
588 */ | |
589 | |
590 /*** Initialisation of the step-up recursion ***/ | |
591 | |
592 pL_coef[0] = L_shl(0x4000L, 15); | |
593 pL_coef[1] = L_shl(L_deposit_l(pswVpar[0]), 14); | |
594 | |
595 | |
596 /*** Loop on the LPC analysis order: ***/ | |
597 | |
598 for (m = 2; m <= swNp; m++) | |
599 { | |
600 for (i = 1; i < m; i++) | |
601 { | |
602 swTemp = extract_h(pL_coef[m - i]); | |
603 pL_work[i] = L_mac(pL_coef[i], pswVpar[m - 1], swTemp); | |
604 } | |
605 for (i = 1; i < m; i++) | |
606 pL_coef[i] = pL_work[i]; | |
607 pL_coef[m] = L_shl(L_deposit_l(pswVpar[m - 1]), 14); | |
608 } | |
609 | |
610 | |
611 /*** Keep the aav1[0..swNp] in 15 bits for the following subclause ***/ | |
612 | |
613 for (i = 0; i <= swNp; i++) | |
614 pswAav1[i] = extract_h(L_shr(pL_coef[i], 3)); | |
615 | |
616 } | |
617 | |
618 /**************************************************************************** | |
619 * | |
620 * FUNCTION: compute_rav1 | |
621 * | |
622 * VERSION: 1.2 | |
623 * | |
624 * PURPOSE: Computes the autocorrelation function of the adaptive | |
625 * filter coefficients. | |
626 * | |
627 * INPUTS: pswAav1[0..8] adaptive filter coefficients | |
628 * | |
629 * OUTPUTS: pswRav1[0..8] ACF of aav1 | |
630 * pswNormRav1 r_av1 scaling factor | |
631 * | |
632 ***************************************************************************/ | |
633 | |
634 void compute_rav1(Shortword pswAav1[], | |
635 Shortword pswRav1[], | |
636 Shortword *pswNormRav1) | |
637 { | |
638 | |
639 /*_________________________________________________________________________ | |
640 | | | |
641 | Automatic Variables | | |
642 |_________________________________________________________________________| | |
643 */ | |
644 | |
645 Longword | |
646 pL_work[9]; | |
647 | |
648 int | |
649 i, | |
650 k; | |
651 | |
652 | |
653 /*_________________________________________________________________________ | |
654 | | | |
655 | Executable Code | | |
656 |_________________________________________________________________________| | |
657 */ | |
658 | |
659 /*** Computation of the rav1[0..8] ***/ | |
660 | |
661 for (i = 0; i <= 8; i++) | |
662 { | |
663 pL_work[i] = 0; | |
664 | |
665 for (k = 0; k <= 8 - i; k++) | |
666 pL_work[i] = L_mac(pL_work[i], pswAav1[k], pswAav1[k + i]); | |
667 } | |
668 | |
669 if (pL_work[0] == 0) | |
670 *pswNormRav1 = 0; | |
671 else | |
672 *pswNormRav1 = norm_l(pL_work[0]); | |
673 | |
674 for (i = 0; i <= 8; i++) | |
675 pswRav1[i] = extract_h(L_shl(pL_work[i], *pswNormRav1)); | |
676 | |
677 } | |
678 | |
679 /**************************************************************************** | |
680 * | |
681 * FUNCTION: spectral_comparison | |
682 * | |
683 * VERSION: 1.2 | |
684 * | |
685 * PURPOSE: Computes the stat flag needed for the threshold | |
686 * adaptation decision. | |
687 * | |
688 * INPUTS: pswRav1[0..8] ACF obtained from L_av1 | |
689 * swNormRav1 rav1 scaling factor | |
690 * pL_av0[0..8] ACF averaged over last four frames | |
691 * | |
692 * OUTPUTS: pswStat flag to indicate spectral stationarity | |
693 * | |
694 ***************************************************************************/ | |
695 | |
696 void spectral_comparison(Shortword pswRav1[], | |
697 Shortword swNormRav1, | |
698 Longword pL_av0[], | |
699 Shortword *pswStat) | |
700 { | |
701 | |
702 /*_________________________________________________________________________ | |
703 | | | |
704 | Automatic Variables | | |
705 |_________________________________________________________________________| | |
706 */ | |
707 | |
708 Longword | |
709 L_dm, | |
710 L_sump, | |
711 L_temp; | |
712 | |
713 Shortword | |
714 pswSav0[9], | |
715 swShift, | |
716 swDivShift, | |
717 swTemp; | |
718 | |
719 int | |
720 i; | |
721 | |
722 | |
723 /*_________________________________________________________________________ | |
724 | | | |
725 | Executable Code | | |
726 |_________________________________________________________________________| | |
727 */ | |
728 | |
729 /*** Re-normalise L_av0[0..8] ***/ | |
730 | |
731 if (pL_av0[0] == 0) | |
732 { | |
733 for (i = 0; i <= 8; i++) | |
734 pswSav0[i] = 4095; | |
735 } | |
736 else | |
737 { | |
738 swShift = sub(norm_l(pL_av0[0]), 3); | |
739 for (i = 0; i <= 8; i++) | |
740 pswSav0[i] = extract_h(L_shl(pL_av0[i], swShift)); | |
741 } | |
742 | |
743 /*** compute partial sum of dm ***/ | |
744 | |
745 L_sump = 0; | |
746 | |
747 for (i = 1; i <= 8; i++) | |
748 L_sump = L_mac(L_sump, pswRav1[i], pswSav0[i]); | |
749 | |
750 /*** compute the division of the partial sum by sav0[0] ***/ | |
751 | |
752 if (L_sump < 0) | |
753 L_temp = L_negate(L_sump); | |
754 else | |
755 L_temp = L_sump; | |
756 | |
757 if (L_temp == 0) | |
758 { | |
759 L_dm = 0; | |
760 swShift = 0; | |
761 } | |
762 else | |
763 { | |
764 pswSav0[0] = shl(pswSav0[0], 3); | |
765 swShift = norm_l(L_temp); | |
766 swTemp = extract_h(L_shl(L_temp, swShift)); | |
767 | |
768 if (pswSav0[0] >= swTemp) | |
769 { | |
770 swDivShift = 0; | |
771 swTemp = divide_s(swTemp, pswSav0[0]); | |
772 } | |
773 else | |
774 { | |
775 swDivShift = 1; | |
776 swTemp = sub(swTemp, pswSav0[0]); | |
777 swTemp = divide_s(swTemp, pswSav0[0]); | |
778 } | |
779 | |
780 if (swDivShift == 1) | |
781 L_dm = 0x8000L; | |
782 else | |
783 L_dm = 0; | |
784 | |
785 L_dm = L_shl((L_add(L_dm, L_deposit_l(swTemp))), 1); | |
786 | |
787 if (L_sump < 0) | |
788 L_dm = L_sub(0L, L_dm); | |
789 } | |
790 | |
791 | |
792 /*** Re-normalisation and final computation of L_dm ***/ | |
793 | |
794 L_dm = L_shl(L_dm, 14); | |
795 L_dm = L_shr(L_dm, swShift); | |
796 L_dm = L_add(L_dm, L_shl(L_deposit_l(pswRav1[0]), 11)); | |
797 L_dm = L_shr(L_dm, swNormRav1); | |
798 | |
799 | |
800 /*** Compute the difference and save L_dm ***/ | |
801 | |
802 L_temp = L_sub(L_dm, L_lastdm); | |
803 L_lastdm = L_dm; | |
804 | |
805 if (L_temp < 0L) | |
806 L_temp = L_negate(L_temp); | |
807 | |
808 | |
809 /*** Evaluation of the state flag ***/ | |
810 | |
811 L_temp = L_sub(L_temp, 4456L); | |
812 | |
813 if (L_temp < 0) | |
814 *pswStat = 1; | |
815 else | |
816 *pswStat = 0; | |
817 | |
818 } | |
819 | |
820 /**************************************************************************** | |
821 * | |
822 * FUNCTION: tone_detection | |
823 * | |
824 * VERSION: 1.2 | |
825 * | |
826 * PURPOSE: Computes the tone flag needed for the threshold | |
827 * adaptation decision. | |
828 * | |
829 * INPUTS: pswRc[0..3] reflection coefficients calculated in the | |
830 * speech encoder short term predictor | |
831 * | |
832 * OUTPUTS: pswTone flag to indicate a periodic signal component | |
833 * | |
834 ***************************************************************************/ | |
835 | |
836 void tone_detection(Shortword pswRc[4], | |
837 Shortword *pswTone) | |
838 { | |
839 | |
840 /*_________________________________________________________________________ | |
841 | | | |
842 | Automatic Variables | | |
843 |_________________________________________________________________________| | |
844 */ | |
845 | |
846 Longword | |
847 L_num, | |
848 L_den, | |
849 L_temp; | |
850 | |
851 Shortword | |
852 swTemp, | |
853 swPredErr, | |
854 pswA[3]; | |
855 | |
856 int | |
857 i; | |
858 | |
859 /*_________________________________________________________________________ | |
860 | | | |
861 | Executable Code | | |
862 |_________________________________________________________________________| | |
863 */ | |
864 | |
865 *pswTone = 0; | |
866 | |
867 | |
868 /*** Calculate filter coefficients ***/ | |
869 | |
870 step_up(2, pswRc, pswA); | |
871 | |
872 | |
873 /*** Calculate ( a[1] * a[1] ) ***/ | |
874 | |
875 swTemp = shl(pswA[1], 3); | |
876 L_den = L_mult(swTemp, swTemp); | |
877 | |
878 | |
879 /*** Calculate ( 4*a[2] - a[1]*a[1] ) ***/ | |
880 | |
881 L_temp = L_shl(L_deposit_h(pswA[2]), 3); | |
882 L_num = L_sub(L_temp, L_den); | |
883 | |
884 | |
885 /*** Check if pole frequency is less than 385 Hz ***/ | |
886 | |
887 if (L_num <= 0) | |
888 return; | |
889 | |
890 if (pswA[1] < 0) | |
891 { | |
892 swTemp = extract_h(L_den); | |
893 L_temp = L_msu(L_num, swTemp, 3189); | |
894 | |
895 if (L_temp < 0) | |
896 return; | |
897 } | |
898 | |
899 | |
900 /*** Calculate normalised prediction error ***/ | |
901 | |
902 swPredErr = 0x7fff; | |
903 | |
904 for (i = 0; i < 4; i++) | |
905 { | |
906 swTemp = mult(pswRc[i], pswRc[i]); | |
907 swTemp = sub(32767, swTemp); | |
908 swPredErr = mult(swPredErr, swTemp); | |
909 } | |
910 | |
911 | |
912 /*** Test if prediction error is smaller than threshold ***/ | |
913 | |
914 swTemp = sub(swPredErr, 1464); | |
915 | |
916 if (swTemp < 0) | |
917 *pswTone = 1; | |
918 | |
919 } | |
920 | |
921 /**************************************************************************** | |
922 * | |
923 * FUNCTION: threshold_adaptation | |
924 * | |
925 * VERSION: 1.2 | |
926 * | |
927 * PURPOSE: Evaluates the secondary VAD decision. If speech is not | |
928 * present then the noise model rvad and adaptive threshold | |
929 * thvad are updated. | |
930 * | |
931 * INPUTS: swStat flag to indicate spectral stationarity | |
932 * swPtch flag to indicate a periodic signal component | |
933 * swTone flag to indicate a tone signal component | |
934 * pswRav1[0..8] ACF obtained from l_av1 | |
935 * swNormRav1 r_av1 scaling factor | |
936 * swM_pvad mantissa of filtered signal energy | |
937 * swE_pvad exponent of filtered signal energy | |
938 * swM_acf0 mantissa of signal frame energy | |
939 * swE_acf0 exponent of signal frame energy | |
940 * | |
941 * OUTPUTS: pswRvad[0..8] autocorrelated adaptive filter coefficients | |
942 * pswNormRvad rvad scaling factor | |
943 * pswM_thvad mantissa of decision threshold | |
944 * pswE_thvad exponent of decision threshold | |
945 * | |
946 ***************************************************************************/ | |
947 | |
948 void threshold_adaptation(Shortword swStat, | |
949 Shortword swPtch, | |
950 Shortword swTone, | |
951 Shortword pswRav1[], | |
952 Shortword swNormRav1, | |
953 Shortword swM_pvad, | |
954 Shortword swE_pvad, | |
955 Shortword swM_acf0, | |
956 Shortword swE_acf0, | |
957 Shortword pswRvad[], | |
958 Shortword *pswNormRvad, | |
959 Shortword *pswM_thvad, | |
960 Shortword *pswE_thvad) | |
961 { | |
962 | |
963 /*_________________________________________________________________________ | |
964 | | | |
965 | Automatic Variables | | |
966 |_________________________________________________________________________| | |
967 */ | |
968 | |
969 Longword | |
970 L_temp; | |
971 | |
972 Shortword | |
973 swTemp, | |
974 swComp, | |
975 swComp2, | |
976 swM_temp, | |
977 swE_temp; | |
978 | |
979 int | |
980 i; | |
981 | |
982 | |
983 /*_________________________________________________________________________ | |
984 | | | |
985 | Executable Code | | |
986 |_________________________________________________________________________| | |
987 */ | |
988 | |
989 swComp = 0; | |
990 | |
991 /*** Test if acf0 < pth; if yes set thvad to plev ***/ | |
992 | |
993 if (swE_acf0 < E_PTH) | |
994 swComp = 1; | |
995 if ((swE_acf0 == E_PTH) && (swM_acf0 < M_PTH)) | |
996 swComp = 1; | |
997 | |
998 if (swComp == 1) | |
999 { | |
1000 *pswE_thvad = E_PLEV; | |
1001 *pswM_thvad = M_PLEV; | |
1002 | |
1003 return; | |
1004 } | |
1005 | |
1006 | |
1007 /*** Test if an adaption is required ***/ | |
1008 | |
1009 if (swPtch == 1) | |
1010 swComp = 1; | |
1011 if (swStat == 0) | |
1012 swComp = 1; | |
1013 if (swTone == 1) | |
1014 swComp = 1; | |
1015 | |
1016 if (swComp == 1) | |
1017 { | |
1018 swAdaptCount = 0; | |
1019 return; | |
1020 } | |
1021 | |
1022 | |
1023 /*** Increment adaptcount ***/ | |
1024 | |
1025 swAdaptCount = add(swAdaptCount, 1); | |
1026 if (swAdaptCount <= 8) | |
1027 return; | |
1028 | |
1029 | |
1030 /*** computation of thvad-(thvad/dec) ***/ | |
1031 | |
1032 *pswM_thvad = sub(*pswM_thvad, shr(*pswM_thvad, 5)); | |
1033 | |
1034 if (*pswM_thvad < 0x4000) | |
1035 { | |
1036 *pswM_thvad = shl(*pswM_thvad, 1); | |
1037 *pswE_thvad = sub(*pswE_thvad, 1); | |
1038 } | |
1039 | |
1040 | |
1041 /*** computation of pvad*fac ***/ | |
1042 | |
1043 L_temp = L_mult(swM_pvad, 20889); | |
1044 L_temp = L_shr(L_temp, 15); | |
1045 swE_temp = add(swE_pvad, 1); | |
1046 | |
1047 if (L_temp > 0x7fffL) | |
1048 { | |
1049 L_temp = L_shr(L_temp, 1); | |
1050 swE_temp = add(swE_temp, 1); | |
1051 } | |
1052 swM_temp = extract_l(L_temp); | |
1053 | |
1054 | |
1055 /*** test if thvad < pavd*fac ***/ | |
1056 | |
1057 if (*pswE_thvad < swE_temp) | |
1058 swComp = 1; | |
1059 | |
1060 if ((*pswE_thvad == swE_temp) && (*pswM_thvad < swM_temp)) | |
1061 swComp = 1; | |
1062 | |
1063 | |
1064 /*** compute minimum(thvad+(thvad/inc), pvad*fac) when comp = 1 ***/ | |
1065 | |
1066 if (swComp == 1) | |
1067 { | |
1068 | |
1069 /*** compute thvad + (thvad/inc) ***/ | |
1070 | |
1071 L_temp = L_add(L_deposit_l(*pswM_thvad),L_deposit_l(shr(*pswM_thvad, 4))); | |
1072 | |
1073 if (L_temp > 0x7fffL) | |
1074 { | |
1075 *pswM_thvad = extract_l(L_shr(L_temp, 1)); | |
1076 *pswE_thvad = add(*pswE_thvad, 1); | |
1077 } | |
1078 else | |
1079 *pswM_thvad = extract_l(L_temp); | |
1080 | |
1081 swComp2 = 0; | |
1082 | |
1083 if (swE_temp < *pswE_thvad) | |
1084 swComp2 = 1; | |
1085 | |
1086 if ((swE_temp == *pswE_thvad) && (swM_temp < *pswM_thvad)) | |
1087 swComp2 = 1; | |
1088 | |
1089 if (swComp2 == 1) | |
1090 { | |
1091 *pswE_thvad = swE_temp; | |
1092 *pswM_thvad = swM_temp; | |
1093 } | |
1094 } | |
1095 | |
1096 | |
1097 /*** compute pvad + margin ***/ | |
1098 | |
1099 if (swE_pvad == E_MARGIN) | |
1100 { | |
1101 L_temp = L_add(L_deposit_l(swM_pvad), L_deposit_l(M_MARGIN)); | |
1102 swM_temp = extract_l(L_shr(L_temp, 1)); | |
1103 swE_temp = add(swE_pvad, 1); | |
1104 } | |
1105 else | |
1106 { | |
1107 if (swE_pvad > E_MARGIN) | |
1108 { | |
1109 swTemp = sub(swE_pvad, E_MARGIN); | |
1110 swTemp = shr(M_MARGIN, swTemp); | |
1111 L_temp = L_add(L_deposit_l(swM_pvad), L_deposit_l(swTemp)); | |
1112 | |
1113 if (L_temp > 0x7fffL) | |
1114 { | |
1115 swE_temp = add(swE_pvad, 1); | |
1116 swM_temp = extract_l(L_shr(L_temp, 1)); | |
1117 } | |
1118 else | |
1119 { | |
1120 swE_temp = swE_pvad; | |
1121 swM_temp = extract_l(L_temp); | |
1122 } | |
1123 } | |
1124 else | |
1125 { | |
1126 swTemp = sub(E_MARGIN, swE_pvad); | |
1127 swTemp = shr(swM_pvad, swTemp); | |
1128 L_temp = L_add(L_deposit_l(M_MARGIN), L_deposit_l(swTemp)); | |
1129 | |
1130 if (L_temp > 0x7fffL) | |
1131 { | |
1132 swE_temp = add(E_MARGIN, 1); | |
1133 swM_temp = extract_l(L_shr(L_temp, 1)); | |
1134 } | |
1135 else | |
1136 { | |
1137 swE_temp = E_MARGIN; | |
1138 swM_temp = extract_l(L_temp); | |
1139 } | |
1140 } | |
1141 } | |
1142 | |
1143 /*** Test if thvad > pvad + margin ***/ | |
1144 | |
1145 swComp = 0; | |
1146 | |
1147 if (*pswE_thvad > swE_temp) | |
1148 swComp = 1; | |
1149 | |
1150 if ((*pswE_thvad == swE_temp) && (*pswM_thvad > swM_temp)) | |
1151 swComp = 1; | |
1152 | |
1153 if (swComp == 1) | |
1154 { | |
1155 *pswE_thvad = swE_temp; | |
1156 *pswM_thvad = swM_temp; | |
1157 } | |
1158 | |
1159 /*** Normalise and retain rvad[0..8] in memory ***/ | |
1160 | |
1161 *pswNormRvad = swNormRav1; | |
1162 | |
1163 for (i = 0; i <= 8; i++) | |
1164 pswRvad[i] = pswRav1[i]; | |
1165 | |
1166 /*** Set adaptcount to adp + 1 ***/ | |
1167 | |
1168 swAdaptCount = 9; | |
1169 | |
1170 } | |
1171 | |
1172 /**************************************************************************** | |
1173 * | |
1174 * FUNCTION: vad_decision | |
1175 * | |
1176 * VERSION: 1.2 | |
1177 * | |
1178 * PURPOSE: Computes the VAD decision based on the comparison of the | |
1179 * floating point representations of pvad and thvad. | |
1180 * | |
1181 * INPUTS: swM_pvad mantissa of filtered signal energy | |
1182 * swE_pvad exponent of filtered signal energy | |
1183 * swM_thvad mantissa of decision threshold | |
1184 * swE_thvad exponent of decision threshold | |
1185 * | |
1186 * OUTPUTS: pswVvad vad decision before hangover is added | |
1187 * | |
1188 ***************************************************************************/ | |
1189 | |
1190 void vad_decision(Shortword swM_pvad, | |
1191 Shortword swE_pvad, | |
1192 Shortword swM_thvad, | |
1193 Shortword swE_thvad, | |
1194 Shortword *pswVvad) | |
1195 { | |
1196 | |
1197 /*_________________________________________________________________________ | |
1198 | | | |
1199 | Executable Code | | |
1200 |_________________________________________________________________________| | |
1201 */ | |
1202 | |
1203 *pswVvad = 0; | |
1204 | |
1205 if (swE_pvad > swE_thvad) | |
1206 *pswVvad = 1; | |
1207 if ((swE_pvad == swE_thvad) && (swM_pvad > swM_thvad)) | |
1208 *pswVvad = 1; | |
1209 | |
1210 } | |
1211 | |
1212 /**************************************************************************** | |
1213 * | |
1214 * FUNCTION: vad_hangover | |
1215 * | |
1216 * VERSION: 1.2 | |
1217 * | |
1218 * PURPOSE: Computes the final VAD decision for the current frame | |
1219 * being processed. | |
1220 * | |
1221 * INPUTS: swVvad vad decision before hangover is added | |
1222 * | |
1223 * OUTPUTS: pswVadFlag vad decision after hangover is added | |
1224 * | |
1225 ***************************************************************************/ | |
1226 | |
1227 void vad_hangover(Shortword swVvad, | |
1228 Shortword *pswVadFlag) | |
1229 { | |
1230 | |
1231 /*_________________________________________________________________________ | |
1232 | | | |
1233 | Executable Code | | |
1234 |_________________________________________________________________________| | |
1235 */ | |
1236 | |
1237 if (swVvad == 1) | |
1238 swBurstCount = add(swBurstCount, 1); | |
1239 else | |
1240 swBurstCount = 0; | |
1241 | |
1242 if (swBurstCount >= 3) | |
1243 { | |
1244 swHangCount = 5; | |
1245 swBurstCount = 3; | |
1246 } | |
1247 | |
1248 *pswVadFlag = swVvad; | |
1249 | |
1250 if (swHangCount >= 0) | |
1251 { | |
1252 *pswVadFlag = 1; | |
1253 swHangCount = sub(swHangCount, 1); | |
1254 } | |
1255 | |
1256 } | |
1257 | |
1258 /**************************************************************************** | |
1259 * | |
1260 * FUNCTION: periodicity_update | |
1261 * | |
1262 * VERSION: 1.2 | |
1263 * | |
1264 * PURPOSE: Computes the ptch flag needed for the threshold | |
1265 * adaptation decision for the next frame. | |
1266 * | |
1267 * INPUTS: pswLags[0..3] speech encoder long term predictor lags | |
1268 * | |
1269 * OUTPUTS: pswPtch Boolean voiced / unvoiced decision | |
1270 * | |
1271 ***************************************************************************/ | |
1272 | |
1273 void periodicity_update(Shortword pswLags[4], | |
1274 Shortword *pswPtch) | |
1275 { | |
1276 | |
1277 /*_________________________________________________________________________ | |
1278 | | | |
1279 | Automatic Variables | | |
1280 |_________________________________________________________________________| | |
1281 */ | |
1282 | |
1283 Shortword | |
1284 swMinLag, | |
1285 swMaxLag, | |
1286 swSmallLag, | |
1287 swLagCount, | |
1288 swTemp; | |
1289 | |
1290 int | |
1291 i, | |
1292 j; | |
1293 | |
1294 /*_________________________________________________________________________ | |
1295 | | | |
1296 | Executable Code | | |
1297 |_________________________________________________________________________| | |
1298 */ | |
1299 | |
1300 /*** Run loop for No. of sub-segments in the frame ***/ | |
1301 | |
1302 swLagCount = 0; | |
1303 | |
1304 for (i = 0; i <= 3; i++) | |
1305 { | |
1306 /*** Search the maximum and minimum of consecutive lags ***/ | |
1307 | |
1308 if (swOldLag > pswLags[i]) | |
1309 { | |
1310 swMinLag = pswLags[i]; | |
1311 swMaxLag = swOldLag; | |
1312 } | |
1313 else | |
1314 { | |
1315 swMinLag = swOldLag; | |
1316 swMaxLag = pswLags[i]; | |
1317 } | |
1318 | |
1319 | |
1320 /*** Compute smallag (modulo operation not defined) ***/ | |
1321 | |
1322 swSmallLag = swMaxLag; | |
1323 | |
1324 for (j = 0; j <= 2; j++) | |
1325 { | |
1326 if (swSmallLag >= swMinLag) | |
1327 swSmallLag = sub(swSmallLag, swMinLag); | |
1328 } | |
1329 | |
1330 | |
1331 /*** Minimum of smallag and minlag - smallag ***/ | |
1332 | |
1333 swTemp = sub(swMinLag, swSmallLag); | |
1334 | |
1335 if (swTemp < swSmallLag) | |
1336 swSmallLag = swTemp; | |
1337 | |
1338 if (swSmallLag < 2) | |
1339 swLagCount = add(swLagCount, 1); | |
1340 | |
1341 | |
1342 /*** Save the current LTP lag ***/ | |
1343 | |
1344 swOldLag = pswLags[i]; | |
1345 } | |
1346 | |
1347 | |
1348 /*** Update the veryoldlagcount and oldlagcount ***/ | |
1349 | |
1350 swVeryOldLagCount = swOldLagCount; | |
1351 swOldLagCount = swLagCount; | |
1352 | |
1353 | |
1354 /*** Make ptch decision ready for next frame ***/ | |
1355 | |
1356 swTemp = add(swOldLagCount, swVeryOldLagCount); | |
1357 | |
1358 if (swTemp >= 7) | |
1359 *pswPtch = 1; | |
1360 else | |
1361 *pswPtch = 0; | |
1362 | |
1363 } |