FreeCalypso > hg > gsm-codec-lib
comparison libgsmefr/vad.c @ 110:913fe3c11890
libgsmefr/vad.c: initial import from ETSI code
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 29 Nov 2022 03:01:38 +0000 |
parents | |
children | 756605c4850f |
comparison
equal
deleted
inserted
replaced
109:2361a7d8c1eb | 110:913fe3c11890 |
---|---|
1 /*************************************************************************** | |
2 * | |
3 * File Name: vad.c | |
4 * | |
5 * Purpose: Contains all functions for voice activity detection, as | |
6 * described in the high level specification of VAD. | |
7 * | |
8 * Below is a listing of all the functions appearing in the file. | |
9 * The functions are arranged according to their purpose. Under | |
10 * each heading, the ordering is hierarchical. | |
11 * | |
12 * Resetting of static variables of VAD: | |
13 * reset_vad() | |
14 * | |
15 * Main routine of VAD (called by the speech encoder): | |
16 * vad_computation() | |
17 * Adaptive filtering and energy computation: | |
18 * energy_computation() | |
19 * Averaging of autocorrelation function values: | |
20 * acf_averaging() | |
21 * Computation of predictor values: | |
22 * predictor_values() | |
23 * schur_recursion() | |
24 * step_up() | |
25 * compute_rav1() | |
26 * Spectral comparison: | |
27 * spectral_comparison() | |
28 * Information tone detection: | |
29 * tone_detection() | |
30 * step_up() | |
31 * Threshold adaptation: | |
32 * threshold_adaptation() | |
33 * VAD decision: | |
34 * vad_decision() | |
35 * VAD hangover addition: | |
36 * vad_hangover() | |
37 * | |
38 * Periodicity detection routine (called by the speech encoder): | |
39 * periodicity_detection() | |
40 * | |
41 **************************************************************************/ | |
42 | |
43 #include "typedef.h" | |
44 #include "cnst.h" | |
45 #include "basic_op.h" | |
46 #include "oper_32b.h" | |
47 #include "count.h" | |
48 #include "vad.h" | |
49 | |
50 /* Constants of VAD hangover addition */ | |
51 | |
52 #define HANGCONST 10 | |
53 #define BURSTCONST 3 | |
54 | |
55 /* Constant of spectral comparison */ | |
56 | |
57 #define STAT_THRESH 3670L /* 0.056 */ | |
58 | |
59 /* Constants of periodicity detection */ | |
60 | |
61 #define LTHRESH 2 | |
62 #define NTHRESH 4 | |
63 | |
64 /* Pseudo floating point representations of constants | |
65 for threshold adaptation */ | |
66 | |
67 #define M_PTH 32500 /*** 130000.0 ***/ | |
68 #define E_PTH 17 | |
69 #define M_PLEV 21667 /*** 346666.7 ***/ | |
70 #define E_PLEV 19 | |
71 #define M_MARGIN 16927 /*** 69333340 ***/ | |
72 #define E_MARGIN 27 | |
73 | |
74 #define FAC 17203 /* 2.1 */ | |
75 | |
76 /* Constants of tone detection */ | |
77 | |
78 #define FREQTH 3189 | |
79 #define PREDTH 1464 | |
80 | |
81 /* Static variables of VAD */ | |
82 | |
83 static Word16 rvad[9], scal_rvad; | |
84 static Pfloat thvad; | |
85 static Word32 L_sacf[27]; | |
86 static Word32 L_sav0[36]; | |
87 static Word16 pt_sacf, pt_sav0; | |
88 static Word32 L_lastdm; | |
89 static Word16 adaptcount; | |
90 static Word16 burstcount, hangcount; | |
91 static Word16 oldlagcount, veryoldlagcount, oldlag; | |
92 | |
93 Word16 ptch; | |
94 | |
95 /************************************************************************* | |
96 * | |
97 * FUNCTION NAME: vad_reset | |
98 * | |
99 * PURPOSE: Resets the static variables of the VAD to their | |
100 * initial values | |
101 * | |
102 *************************************************************************/ | |
103 | |
104 void vad_reset () | |
105 { | |
106 Word16 i; | |
107 | |
108 /* Initialize rvad variables */ | |
109 rvad[0] = 0x6000; | |
110 for (i = 1; i < 9; i++) | |
111 { | |
112 rvad[i] = 0; | |
113 } | |
114 scal_rvad = 7; | |
115 | |
116 /* Initialize threshold level */ | |
117 thvad.e = 20; /*** exponent ***/ | |
118 thvad.m = 27083; /*** mantissa ***/ | |
119 | |
120 /* Initialize ACF averaging variables */ | |
121 for (i = 0; i < 27; i++) | |
122 { | |
123 L_sacf[i] = 0L; | |
124 } | |
125 for (i = 0; i < 36; i++) | |
126 { | |
127 L_sav0[i] = 0L; | |
128 } | |
129 pt_sacf = 0; | |
130 pt_sav0 = 0; | |
131 | |
132 /* Initialize spectral comparison variable */ | |
133 L_lastdm = 0L; | |
134 | |
135 /* Initialize threshold adaptation variable */ | |
136 adaptcount = 0; | |
137 | |
138 /* Initialize VAD hangover addition variables */ | |
139 burstcount = 0; | |
140 hangcount = -1; | |
141 | |
142 /* Initialize periodicity detection variables */ | |
143 oldlagcount = 0; | |
144 veryoldlagcount = 0; | |
145 oldlag = 18; | |
146 | |
147 ptch = 1; | |
148 | |
149 return; | |
150 } | |
151 | |
152 /**************************************************************************** | |
153 * | |
154 * FUNCTION: vad_computation | |
155 * | |
156 * PURPOSE: Returns a decision as to whether the current frame being | |
157 * processed by the speech encoder contains speech or not. | |
158 * | |
159 * INPUTS: r_h[0..8] autocorrelation of input signal frame (msb) | |
160 * r_l[0..8] autocorrelation of input signal frame (lsb) | |
161 * scal_acf scaling factor for the autocorrelations | |
162 * rc[0..3] speech encoder reflection coefficients | |
163 * ptch flag to indicate a periodic signal component | |
164 * | |
165 * OUTPUTS: none | |
166 * | |
167 * RETURN VALUE: vad decision | |
168 * | |
169 ***************************************************************************/ | |
170 | |
171 Word16 vad_computation ( | |
172 Word16 r_h[], | |
173 Word16 r_l[], | |
174 Word16 scal_acf, | |
175 Word16 rc[], | |
176 Word16 ptch | |
177 ) | |
178 { | |
179 Word32 L_av0[9], L_av1[9]; | |
180 Word16 vad, vvad, rav1[9], scal_rav1, stat, tone; | |
181 Pfloat acf0, pvad; | |
182 | |
183 energy_computation (r_h, scal_acf, rvad, scal_rvad, &acf0, &pvad); | |
184 acf_averaging (r_h, r_l, scal_acf, L_av0, L_av1); | |
185 predictor_values (L_av1, rav1, &scal_rav1); | |
186 stat = spectral_comparison (rav1, scal_rav1, L_av0); move16 (); | |
187 tone_detection (rc, &tone); | |
188 threshold_adaptation (stat, ptch, tone, rav1, scal_rav1, pvad, acf0, | |
189 rvad, &scal_rvad, &thvad); | |
190 vvad = vad_decision (pvad, thvad); move16 (); | |
191 vad = vad_hangover (vvad); move16 (); | |
192 | |
193 return vad; | |
194 } | |
195 | |
196 /**************************************************************************** | |
197 * | |
198 * FUNCTION: energy_computation | |
199 * | |
200 * PURPOSE: Computes the input and residual energies of the adaptive | |
201 * filter in a floating point representation. | |
202 * | |
203 * INPUTS: r_h[0..8] autocorrelation of input signal frame (msb) | |
204 * scal_acf scaling factor for the autocorrelations | |
205 * rvad[0..8] autocorrelated adaptive filter coefficients | |
206 * scal_rvad scaling factor for rvad[] | |
207 * | |
208 * OUTPUTS: *acf0 signal frame energy (mantissa+exponent) | |
209 * *pvad filtered signal energy (mantissa+exponent) | |
210 * | |
211 * RETURN VALUE: none | |
212 * | |
213 ***************************************************************************/ | |
214 | |
215 void energy_computation ( | |
216 Word16 r_h[], | |
217 Word16 scal_acf, | |
218 Word16 rvad[], | |
219 Word16 scal_rvad, | |
220 Pfloat * acf0, | |
221 Pfloat * pvad | |
222 ) | |
223 { | |
224 Word16 i, temp, norm_prod; | |
225 Word32 L_temp; | |
226 | |
227 /* r[0] is always greater than zero (no need to test for r[0] == 0) */ | |
228 | |
229 /* Computation of acf0 (exponent and mantissa) */ | |
230 | |
231 acf0->e = sub (32, scal_acf); move16 (); | |
232 acf0->m = r_h[0] & 0x7ff8; move16 (); logic16 (); | |
233 | |
234 /* Computation of pvad (exponent and mantissa) */ | |
235 | |
236 pvad->e = add (acf0->e, 14); move16 (); | |
237 pvad->e = sub (pvad->e, scal_rvad); move16 (); | |
238 | |
239 L_temp = 0L; move32 (); | |
240 | |
241 for (i = 1; i <= 8; i++) | |
242 { | |
243 temp = shr (r_h[i], 3); | |
244 L_temp = L_mac (L_temp, temp, rvad[i]); | |
245 } | |
246 | |
247 temp = shr (r_h[0], 3); | |
248 L_temp = L_add (L_temp, L_shr (L_mult (temp, rvad[0]), 1)); | |
249 | |
250 test (); | |
251 if (L_temp <= 0L) | |
252 { | |
253 L_temp = 1L; move32 (); | |
254 } | |
255 norm_prod = norm_l (L_temp); | |
256 pvad->e = sub (pvad->e, norm_prod); move16 (); | |
257 pvad->m = extract_h (L_shl (L_temp, norm_prod)); | |
258 move16 (); | |
259 | |
260 return; | |
261 } | |
262 | |
263 /**************************************************************************** | |
264 * | |
265 * FUNCTION: acf_averaging | |
266 * | |
267 * PURPOSE: Computes the arrays L_av0[0..8] and L_av1[0..8]. | |
268 * | |
269 * INPUTS: r_h[0..8] autocorrelation of input signal frame (msb) | |
270 * r_l[0..8] autocorrelation of input signal frame (lsb) | |
271 * scal_acf scaling factor for the autocorrelations | |
272 * | |
273 * OUTPUTS: L_av0[0..8] ACF averaged over last four frames | |
274 * L_av1[0..8] ACF averaged over previous four frames | |
275 * | |
276 * RETURN VALUE: none | |
277 * | |
278 ***************************************************************************/ | |
279 | |
280 void acf_averaging ( | |
281 Word16 r_h[], | |
282 Word16 r_l[], | |
283 Word16 scal_acf, | |
284 Word32 L_av0[], | |
285 Word32 L_av1[] | |
286 ) | |
287 { | |
288 Word32 L_temp; | |
289 Word16 scale; | |
290 Word16 i; | |
291 | |
292 scale = add (9, scal_acf); | |
293 | |
294 for (i = 0; i <= 8; i++) | |
295 { | |
296 L_temp = L_shr (L_Comp (r_h[i], r_l[i]), scale); | |
297 L_av0[i] = L_add (L_sacf[i], L_temp); move32 (); | |
298 L_av0[i] = L_add (L_sacf[i + 9], L_av0[i]); move32 (); | |
299 L_av0[i] = L_add (L_sacf[i + 18], L_av0[i]); move32 (); | |
300 L_sacf[pt_sacf + i] = L_temp; move32 (); | |
301 L_av1[i] = L_sav0[pt_sav0 + i]; move32 (); | |
302 L_sav0[pt_sav0 + i] = L_av0[i]; move32 (); | |
303 } | |
304 | |
305 /* Update the array pointers */ | |
306 | |
307 test (); | |
308 if (sub (pt_sacf, 18) == 0) | |
309 { | |
310 pt_sacf = 0; move16 (); | |
311 } | |
312 else | |
313 { | |
314 pt_sacf = add (pt_sacf, 9); | |
315 } | |
316 | |
317 test (); | |
318 if (sub (pt_sav0, 27) == 0) | |
319 { | |
320 pt_sav0 = 0; move16 (); | |
321 } | |
322 else | |
323 { | |
324 pt_sav0 = add (pt_sav0, 9); | |
325 } | |
326 | |
327 return; | |
328 } | |
329 | |
330 /**************************************************************************** | |
331 * | |
332 * FUNCTION: predictor_values | |
333 * | |
334 * PURPOSE: Computes the array rav[0..8] needed for the spectral | |
335 * comparison and the threshold adaptation. | |
336 * | |
337 * INPUTS: L_av1[0..8] ACF averaged over previous four frames | |
338 * | |
339 * OUTPUTS: rav1[0..8] ACF obtained from L_av1 | |
340 * *scal_rav1 rav1[] scaling factor | |
341 * | |
342 * RETURN VALUE: none | |
343 * | |
344 ***************************************************************************/ | |
345 | |
346 void predictor_values ( | |
347 Word32 L_av1[], | |
348 Word16 rav1[], | |
349 Word16 *scal_rav1 | |
350 ) | |
351 { | |
352 Word16 vpar[8], aav1[9]; | |
353 | |
354 schur_recursion (L_av1, vpar); | |
355 step_up (8, vpar, aav1); | |
356 compute_rav1 (aav1, rav1, scal_rav1); | |
357 | |
358 return; | |
359 } | |
360 | |
361 /**************************************************************************** | |
362 * | |
363 * FUNCTION: schur_recursion | |
364 * | |
365 * PURPOSE: Uses the Schur recursion to compute adaptive filter | |
366 * reflection coefficients from an autorrelation function. | |
367 * | |
368 * INPUTS: L_av1[0..8] autocorrelation function | |
369 * | |
370 * OUTPUTS: vpar[0..7] reflection coefficients | |
371 * | |
372 * RETURN VALUE: none | |
373 * | |
374 ***************************************************************************/ | |
375 | |
376 void schur_recursion ( | |
377 Word32 L_av1[], | |
378 Word16 vpar[] | |
379 ) | |
380 { | |
381 Word16 acf[9], pp[9], kk[9], temp; | |
382 Word16 i, k, m, n; | |
383 | |
384 /*** Schur recursion with 16-bit arithmetic ***/ | |
385 | |
386 test (); move32 (); | |
387 if (L_av1[0] == 0) | |
388 { | |
389 for (i = 0; i < 8; i++) | |
390 { | |
391 vpar[i] = 0; move16 (); | |
392 } | |
393 return; | |
394 } | |
395 temp = norm_l (L_av1[0]); | |
396 | |
397 for (k = 0; k <= 8; k++) | |
398 { | |
399 acf[k] = extract_h (L_shl (L_av1[k], temp)); move16 (); | |
400 } | |
401 | |
402 /*** Initialize arrays pp[..] and kk[..] for the recursion: ***/ | |
403 | |
404 for (i = 1; i <= 7; i++) | |
405 { | |
406 kk[9 - i] = acf[i]; move16 (); | |
407 } | |
408 | |
409 for (i = 0; i <= 8; i++) | |
410 { | |
411 pp[i] = acf[i]; move16 (); | |
412 } | |
413 | |
414 /*** Compute Parcor coefficients: ***/ | |
415 | |
416 for (n = 0; n < 8; n++) | |
417 { | |
418 test (); | |
419 if ((pp[0] == 0) || | |
420 (sub (pp[0], abs_s (pp[1])) < 0)) | |
421 { | |
422 for (i = n; i < 8; i++) | |
423 { | |
424 vpar[i] = 0; move16 (); | |
425 } | |
426 return; | |
427 } | |
428 vpar[n] = div_s (abs_s (pp[1]), pp[0]); move16 (); | |
429 | |
430 test (); move16 (); | |
431 if (pp[1] > 0) | |
432 { | |
433 vpar[n] = negate (vpar[n]); move16 (); | |
434 } | |
435 test (); | |
436 if (sub (n, 7) == 0) | |
437 { | |
438 return; | |
439 } | |
440 /*** Schur recursion: ***/ | |
441 | |
442 pp[0] = add (pp[0], mult_r (pp[1], vpar[n])); move16 (); | |
443 | |
444 for (m = 1; m <= 7 - n; m++) | |
445 { | |
446 pp[m] = add (pp[1 + m], mult_r (kk[9 - m], vpar[n])); | |
447 move16 (); | |
448 kk[9 - m] = add (kk[9 - m], mult_r (pp[1 + m], vpar[n])); | |
449 move16 (); | |
450 } | |
451 } | |
452 | |
453 return; | |
454 } | |
455 | |
456 /**************************************************************************** | |
457 * | |
458 * FUNCTION: step_up | |
459 * | |
460 * PURPOSE: Computes the transversal filter coefficients from the | |
461 * reflection coefficients. | |
462 * | |
463 * INPUTS: np filter order (2..8) | |
464 * vpar[0..np-1] reflection coefficients | |
465 * | |
466 * OUTPUTS: aav1[0..np] transversal filter coefficients | |
467 * | |
468 * RETURN VALUE: none | |
469 * | |
470 ***************************************************************************/ | |
471 | |
472 void step_up ( | |
473 Word16 np, | |
474 Word16 vpar[], | |
475 Word16 aav1[] | |
476 ) | |
477 { | |
478 Word32 L_coef[9], L_work[9]; | |
479 Word16 temp; | |
480 Word16 i, m; | |
481 | |
482 /*** Initialization of the step-up recursion ***/ | |
483 | |
484 L_coef[0] = 0x20000000L; move32 (); | |
485 L_coef[1] = L_shl (L_deposit_l (vpar[0]), 14); move32 (); | |
486 | |
487 /*** Loop on the LPC analysis order: ***/ | |
488 | |
489 for (m = 2; m <= np; m++) | |
490 { | |
491 for (i = 1; i < m; i++) | |
492 { | |
493 temp = extract_h (L_coef[m - i]); | |
494 L_work[i] = L_mac (L_coef[i], vpar[m - 1], temp); move32 (); | |
495 } | |
496 | |
497 for (i = 1; i < m; i++) | |
498 { | |
499 L_coef[i] = L_work[i]; move32 (); | |
500 } | |
501 | |
502 L_coef[m] = L_shl (L_deposit_l (vpar[m - 1]), 14); move32 (); | |
503 } | |
504 | |
505 /*** Keep the aav1[0..np] in 15 bits ***/ | |
506 | |
507 for (i = 0; i <= np; i++) | |
508 { | |
509 aav1[i] = extract_h (L_shr (L_coef[i], 3)); move32 (); | |
510 } | |
511 | |
512 return; | |
513 } | |
514 | |
515 /**************************************************************************** | |
516 * | |
517 * FUNCTION: compute_rav1 | |
518 * | |
519 * PURPOSE: Computes the autocorrelation function of the adaptive | |
520 * filter coefficients. | |
521 * | |
522 * INPUTS: aav1[0..8] adaptive filter coefficients | |
523 * | |
524 * OUTPUTS: rav1[0..8] ACF of aav1 | |
525 * *scal_rav1 rav1[] scaling factor | |
526 * | |
527 * RETURN VALUE: none | |
528 * | |
529 ***************************************************************************/ | |
530 | |
531 void compute_rav1 ( | |
532 Word16 aav1[], | |
533 Word16 rav1[], | |
534 Word16 *scal_rav1 | |
535 ) | |
536 { | |
537 Word32 L_work[9]; | |
538 Word16 i, k; | |
539 | |
540 /*** Computation of the rav1[0..8] ***/ | |
541 | |
542 for (i = 0; i <= 8; i++) | |
543 { | |
544 L_work[i] = 0L; move32 (); | |
545 | |
546 for (k = 0; k <= 8 - i; k++) | |
547 { | |
548 L_work[i] = L_mac (L_work[i], aav1[k], aav1[k + i]); move32 (); | |
549 } | |
550 } | |
551 | |
552 test (); move32 (); | |
553 if (L_work[0] == 0L) | |
554 { | |
555 *scal_rav1 = 0; move16 (); | |
556 } | |
557 else | |
558 { | |
559 *scal_rav1 = norm_l (L_work[0]); | |
560 } | |
561 | |
562 for (i = 0; i <= 8; i++) | |
563 { | |
564 rav1[i] = extract_h (L_shl (L_work[i], *scal_rav1)); move16 (); | |
565 } | |
566 | |
567 return; | |
568 } | |
569 | |
570 /**************************************************************************** | |
571 * | |
572 * FUNCTION: spectral_comparison | |
573 * | |
574 * PURPOSE: Computes the stat flag needed for the threshold | |
575 * adaptation decision. | |
576 * | |
577 * INPUTS: rav1[0..8] ACF obtained from L_av1 | |
578 * *scal_rav1 rav1[] scaling factor | |
579 * L_av0[0..8] ACF averaged over last four frames | |
580 * | |
581 * OUTPUTS: none | |
582 * | |
583 * RETURN VALUE: flag to indicate spectral stationarity | |
584 * | |
585 ***************************************************************************/ | |
586 | |
587 Word16 spectral_comparison ( | |
588 Word16 rav1[], | |
589 Word16 scal_rav1, | |
590 Word32 L_av0[] | |
591 ) | |
592 { | |
593 Word32 L_dm, L_sump, L_temp; | |
594 Word16 stat, sav0[9], shift, divshift, temp; | |
595 Word16 i; | |
596 | |
597 /*** Re-normalize L_av0[0..8] ***/ | |
598 | |
599 test (); move32 (); | |
600 if (L_av0[0] == 0L) | |
601 { | |
602 for (i = 0; i <= 8; i++) | |
603 { | |
604 sav0[i] = 0x0fff; /* 4095 */ move16 (); | |
605 } | |
606 } | |
607 else | |
608 { | |
609 shift = sub (norm_l (L_av0[0]), 3); | |
610 for (i = 0; i <= 8; i++) | |
611 { | |
612 sav0[i] = extract_h (L_shl (L_av0[i], shift)); move16 (); | |
613 } | |
614 } | |
615 | |
616 /*** Compute partial sum of dm ***/ | |
617 | |
618 L_sump = 0L; move32 (); | |
619 for (i = 1; i <= 8; i++) | |
620 { | |
621 L_sump = L_mac (L_sump, rav1[i], sav0[i]); | |
622 } | |
623 | |
624 /*** Compute the division of the partial sum by sav0[0] ***/ | |
625 | |
626 test (); | |
627 if (L_sump < 0L) | |
628 { | |
629 L_temp = L_negate (L_sump); | |
630 } | |
631 else | |
632 { | |
633 L_temp = L_sump; move32 (); | |
634 } | |
635 | |
636 test (); | |
637 if (L_temp == 0L) | |
638 { | |
639 L_dm = 0L; move32 (); | |
640 shift = 0; move16 (); | |
641 } | |
642 else | |
643 { | |
644 sav0[0] = shl (sav0[0], 3); move16 (); | |
645 shift = norm_l (L_temp); | |
646 temp = extract_h (L_shl (L_temp, shift)); | |
647 | |
648 test (); | |
649 if (sub (sav0[0], temp) >= 0) | |
650 { | |
651 divshift = 0; move16 (); | |
652 temp = div_s (temp, sav0[0]); | |
653 } | |
654 else | |
655 { | |
656 divshift = 1; move16 (); | |
657 temp = sub (temp, sav0[0]); | |
658 temp = div_s (temp, sav0[0]); | |
659 } | |
660 | |
661 test (); | |
662 if (sub (divshift, 1) == 0) | |
663 { | |
664 L_dm = 0x8000L; move32 (); | |
665 } | |
666 else | |
667 { | |
668 L_dm = 0L; move32 (); | |
669 } | |
670 | |
671 L_dm = L_shl (L_add (L_dm, L_deposit_l (temp)), 1); | |
672 | |
673 test (); | |
674 if (L_sump < 0L) | |
675 { | |
676 L_dm = L_negate (L_dm); | |
677 } | |
678 } | |
679 | |
680 /*** Re-normalization and final computation of L_dm ***/ | |
681 | |
682 L_dm = L_shl (L_dm, 14); | |
683 L_dm = L_shr (L_dm, shift); | |
684 L_dm = L_add (L_dm, L_shl (L_deposit_l (rav1[0]), 11)); | |
685 L_dm = L_shr (L_dm, scal_rav1); | |
686 | |
687 /*** Compute the difference and save L_dm ***/ | |
688 | |
689 L_temp = L_sub (L_dm, L_lastdm); | |
690 L_lastdm = L_dm; move32 (); | |
691 | |
692 test (); | |
693 if (L_temp < 0L) | |
694 { | |
695 L_temp = L_negate (L_temp); | |
696 } | |
697 /*** Evaluation of the stat flag ***/ | |
698 | |
699 L_temp = L_sub (L_temp, STAT_THRESH); | |
700 | |
701 test (); | |
702 if (L_temp < 0L) | |
703 { | |
704 stat = 1; move16 (); | |
705 } | |
706 else | |
707 { | |
708 stat = 0; move16 (); | |
709 } | |
710 | |
711 return stat; | |
712 } | |
713 | |
714 /**************************************************************************** | |
715 * | |
716 * FUNCTION: threshold_adaptation | |
717 * | |
718 * PURPOSE: Evaluates the secondary VAD decision. If speech is not | |
719 * present then the noise model rvad and adaptive threshold | |
720 * thvad are updated. | |
721 * | |
722 * INPUTS: stat flag to indicate spectral stationarity | |
723 * ptch flag to indicate a periodic signal component | |
724 * tone flag to indicate a tone signal component | |
725 * rav1[0..8] ACF obtained from L_av1 | |
726 * scal_rav1 rav1[] scaling factor | |
727 * pvad filtered signal energy (mantissa+exponent) | |
728 * acf0 signal frame energy (mantissa+exponent) | |
729 * | |
730 * OUTPUTS: rvad[0..8] autocorrelated adaptive filter coefficients | |
731 * *scal_rvad rvad[] scaling factor | |
732 * *thvad decision threshold (mantissa+exponent) | |
733 * | |
734 * RETURN VALUE: none | |
735 * | |
736 ***************************************************************************/ | |
737 | |
738 void threshold_adaptation ( | |
739 Word16 stat, | |
740 Word16 ptch, | |
741 Word16 tone, | |
742 Word16 rav1[], | |
743 Word16 scal_rav1, | |
744 Pfloat pvad, | |
745 Pfloat acf0, | |
746 Word16 rvad[], | |
747 Word16 *scal_rvad, | |
748 Pfloat * thvad | |
749 ) | |
750 { | |
751 Word16 comp, comp2; | |
752 Word32 L_temp; | |
753 Word16 temp; | |
754 Pfloat p_temp; | |
755 Word16 i; | |
756 | |
757 comp = 0; move16 (); | |
758 | |
759 /*** Test if acf0 < pth; if yes set thvad to plev ***/ | |
760 | |
761 test (); | |
762 if (sub (acf0.e, E_PTH) < 0) | |
763 { | |
764 comp = 1; move16 (); | |
765 } | |
766 test (); test (); | |
767 if ((sub (acf0.e, E_PTH) == 0) && (sub (acf0.m, M_PTH) < 0)) | |
768 { | |
769 comp = 1; move16 (); | |
770 } | |
771 test (); | |
772 if (sub (comp, 1) == 0) | |
773 { | |
774 thvad->e = E_PLEV; move16 (); | |
775 thvad->m = M_PLEV; move16 (); | |
776 | |
777 return; | |
778 } | |
779 /*** Test if an adaption is required ***/ | |
780 | |
781 test (); | |
782 if (sub (ptch, 1) == 0) | |
783 { | |
784 comp = 1; move16 (); | |
785 } | |
786 test (); | |
787 if (stat == 0) | |
788 { | |
789 comp = 1; move16 (); | |
790 } | |
791 test (); | |
792 if (sub (tone, 1) == 0) | |
793 { | |
794 comp = 1; move16 (); | |
795 } | |
796 test (); | |
797 if (sub (comp, 1) == 0) | |
798 { | |
799 adaptcount = 0; move16 (); | |
800 return; | |
801 } | |
802 /*** Increment adaptcount ***/ | |
803 | |
804 adaptcount = add (adaptcount, 1); | |
805 test (); | |
806 if (sub (adaptcount, 8) <= 0) | |
807 { | |
808 return; | |
809 } | |
810 /*** computation of thvad-(thvad/dec) ***/ | |
811 | |
812 thvad->m = sub (thvad->m, shr (thvad->m, 5)); move16 (); | |
813 | |
814 test (); | |
815 if (sub (thvad->m, 0x4000) < 0) | |
816 { | |
817 thvad->m = shl (thvad->m, 1); move16 (); | |
818 thvad->e = sub (thvad->e, 1); move16 (); | |
819 } | |
820 /*** computation of pvad*fac ***/ | |
821 | |
822 L_temp = L_mult (pvad.m, FAC); | |
823 L_temp = L_shr (L_temp, 15); | |
824 p_temp.e = add (pvad.e, 1); move16 (); | |
825 | |
826 test (); | |
827 if (L_temp > 0x7fffL) | |
828 { | |
829 L_temp = L_shr (L_temp, 1); | |
830 p_temp.e = add (p_temp.e, 1); move16 (); | |
831 } | |
832 p_temp.m = extract_l (L_temp); move16 (); | |
833 | |
834 /*** test if thvad < pvad*fac ***/ | |
835 | |
836 test (); | |
837 if (sub (thvad->e, p_temp.e) < 0) | |
838 { | |
839 comp = 1; move16 (); | |
840 } | |
841 test (); test (); | |
842 if ((sub (thvad->e, p_temp.e) == 0) && | |
843 (sub (thvad->m, p_temp.m) < 0)) | |
844 { | |
845 comp = 1; move16 (); | |
846 } | |
847 /*** compute minimum(thvad+(thvad/inc), pvad*fac) when comp = 1 ***/ | |
848 | |
849 test (); | |
850 if (sub (comp, 1) == 0) | |
851 { | |
852 /*** compute thvad + (thvad/inc) ***/ | |
853 | |
854 L_temp = L_add (L_deposit_l (thvad->m), | |
855 L_deposit_l (shr (thvad->m, 4))); | |
856 | |
857 test (); | |
858 if (L_sub (L_temp, 0x7fffL) > 0) | |
859 { | |
860 thvad->m = extract_l (L_shr (L_temp, 1)); move16 (); | |
861 thvad->e = add (thvad->e, 1); move16 (); | |
862 } | |
863 else | |
864 { | |
865 thvad->m = extract_l (L_temp); move16 (); | |
866 } | |
867 | |
868 comp2 = 0; move16 (); | |
869 | |
870 test (); | |
871 if (sub (p_temp.e, thvad->e) < 0) | |
872 { | |
873 comp2 = 1; move16 (); | |
874 } | |
875 test (); test (); | |
876 if ((sub (p_temp.e, thvad->e) == 0) && | |
877 (sub (p_temp.m, thvad->m) < 0)) | |
878 { | |
879 comp2 = 1; move16 (); | |
880 } | |
881 test (); | |
882 if (sub (comp2, 1) == 0) | |
883 { | |
884 thvad->e = p_temp.e;move16 (); | |
885 thvad->m = p_temp.m;move16 (); | |
886 } | |
887 } | |
888 /*** compute pvad + margin ***/ | |
889 | |
890 test (); | |
891 if (sub (pvad.e, E_MARGIN) == 0) | |
892 { | |
893 L_temp = L_add (L_deposit_l (pvad.m), L_deposit_l (M_MARGIN)); | |
894 p_temp.m = extract_l (L_shr (L_temp, 1)); move16 (); | |
895 p_temp.e = add (pvad.e, 1); move16 (); | |
896 } | |
897 else | |
898 { | |
899 test (); | |
900 if (sub (pvad.e, E_MARGIN) > 0) | |
901 { | |
902 temp = sub (pvad.e, E_MARGIN); | |
903 temp = shr (M_MARGIN, temp); | |
904 L_temp = L_add (L_deposit_l (pvad.m), L_deposit_l (temp)); | |
905 | |
906 test (); | |
907 if (L_sub (L_temp, 0x7fffL) > 0) | |
908 { | |
909 p_temp.e = add (pvad.e, 1); move16 (); | |
910 p_temp.m = extract_l (L_shr (L_temp, 1)); | |
911 move16 (); | |
912 } | |
913 else | |
914 { | |
915 p_temp.e = pvad.e; move16 (); | |
916 p_temp.m = extract_l (L_temp); move16 (); | |
917 } | |
918 } | |
919 else | |
920 { | |
921 temp = sub (E_MARGIN, pvad.e); | |
922 temp = shr (pvad.m, temp); | |
923 L_temp = L_add (L_deposit_l (M_MARGIN), L_deposit_l (temp)); | |
924 | |
925 test (); | |
926 if (L_sub (L_temp, 0x7fffL) > 0) | |
927 { | |
928 p_temp.e = add (E_MARGIN, 1); move16 (); | |
929 p_temp.m = extract_l (L_shr (L_temp, 1)); | |
930 move16 (); | |
931 } | |
932 else | |
933 { | |
934 p_temp.e = E_MARGIN; move16 (); | |
935 p_temp.m = extract_l (L_temp); move16 (); | |
936 } | |
937 } | |
938 } | |
939 | |
940 /*** Test if thvad > pvad + margin ***/ | |
941 | |
942 comp = 0; move16 (); | |
943 | |
944 test (); | |
945 if (sub (thvad->e, p_temp.e) > 0) | |
946 { | |
947 comp = 1; move16 (); | |
948 } | |
949 test (); test (); | |
950 if ((sub (thvad->e, p_temp.e) == 0) && | |
951 (sub (thvad->m, p_temp.m) > 0)) | |
952 { | |
953 comp = 1; move16 (); | |
954 } | |
955 test (); | |
956 if (sub (comp, 1) == 0) | |
957 { | |
958 thvad->e = p_temp.e; move16 (); | |
959 thvad->m = p_temp.m; move16 (); | |
960 } | |
961 /*** Normalise and retain rvad[0..8] in memory ***/ | |
962 | |
963 *scal_rvad = scal_rav1; move16 (); | |
964 | |
965 for (i = 0; i <= 8; i++) | |
966 { | |
967 rvad[i] = rav1[i]; move16 (); | |
968 } | |
969 | |
970 /*** Set adaptcount to adp + 1 ***/ | |
971 | |
972 adaptcount = 9; move16 (); | |
973 | |
974 return; | |
975 } | |
976 | |
977 /**************************************************************************** | |
978 * | |
979 * FUNCTION: tone_detection | |
980 * | |
981 * PURPOSE: Computes the tone flag needed for the threshold | |
982 * adaptation decision. | |
983 * | |
984 * INPUTS: rc[0..3] reflection coefficients calculated in the | |
985 * speech encoder short term predictor | |
986 * | |
987 * OUTPUTS: *tone flag to indicate a periodic signal component | |
988 * | |
989 * RETURN VALUE: none | |
990 * | |
991 ***************************************************************************/ | |
992 | |
993 void tone_detection ( | |
994 Word16 rc[], | |
995 Word16 *tone | |
996 ) | |
997 { | |
998 Word32 L_num, L_den, L_temp; | |
999 Word16 temp, prederr, a[3]; | |
1000 Word16 i; | |
1001 | |
1002 *tone = 0; move16 (); | |
1003 | |
1004 /*** Calculate filter coefficients ***/ | |
1005 | |
1006 step_up (2, rc, a); | |
1007 | |
1008 /*** Calculate ( a[1] * a[1] ) ***/ | |
1009 | |
1010 temp = shl (a[1], 3); | |
1011 L_den = L_mult (temp, temp); | |
1012 | |
1013 /*** Calculate ( 4*a[2] - a[1]*a[1] ) ***/ | |
1014 | |
1015 L_temp = L_shl (L_deposit_h (a[2]), 3); | |
1016 L_num = L_sub (L_temp, L_den); | |
1017 | |
1018 /*** Check if pole frequency is less than 385 Hz ***/ | |
1019 | |
1020 test (); | |
1021 if (L_num <= 0) | |
1022 { | |
1023 return; | |
1024 } | |
1025 test (); move16 (); | |
1026 if (a[1] < 0) | |
1027 { | |
1028 temp = extract_h (L_den); | |
1029 L_den = L_mult (temp, FREQTH); | |
1030 | |
1031 L_temp = L_sub (L_num, L_den); | |
1032 | |
1033 test (); | |
1034 if (L_temp < 0) | |
1035 { | |
1036 return; | |
1037 } | |
1038 } | |
1039 /*** Calculate normalised prediction error ***/ | |
1040 | |
1041 prederr = 0x7fff; move16 (); | |
1042 | |
1043 for (i = 0; i < 4; i++) | |
1044 { | |
1045 temp = mult (rc[i], rc[i]); | |
1046 temp = sub (0x7fff, temp); | |
1047 prederr = mult (prederr, temp); | |
1048 } | |
1049 | |
1050 /*** Test if prediction error is smaller than threshold ***/ | |
1051 | |
1052 temp = sub (prederr, PREDTH); | |
1053 | |
1054 test (); | |
1055 if (temp < 0) | |
1056 { | |
1057 *tone = 1; move16 (); | |
1058 } | |
1059 return; | |
1060 } | |
1061 | |
1062 /**************************************************************************** | |
1063 * | |
1064 * FUNCTION: vad_decision | |
1065 * | |
1066 * PURPOSE: Computes the VAD decision based on the comparison of the | |
1067 * floating point representations of pvad and thvad. | |
1068 * | |
1069 * INPUTS: pvad filtered signal energy (mantissa+exponent) | |
1070 * thvad decision threshold (mantissa+exponent) | |
1071 * | |
1072 * OUTPUTS: none | |
1073 * | |
1074 * RETURN VALUE: vad decision before hangover is added | |
1075 * | |
1076 ***************************************************************************/ | |
1077 | |
1078 Word16 vad_decision ( | |
1079 Pfloat pvad, | |
1080 Pfloat thvad | |
1081 ) | |
1082 { | |
1083 Word16 vvad; | |
1084 | |
1085 test (); test (); test (); | |
1086 if (sub (pvad.e, thvad.e) > 0) | |
1087 { | |
1088 vvad = 1; move16 (); | |
1089 } | |
1090 else if ((sub (pvad.e, thvad.e) == 0) && | |
1091 (sub (pvad.m, thvad.m) > 0)) | |
1092 { | |
1093 vvad = 1; move16 (); | |
1094 } | |
1095 else | |
1096 { | |
1097 vvad = 0; move16 (); | |
1098 } | |
1099 | |
1100 return vvad; | |
1101 } | |
1102 | |
1103 /**************************************************************************** | |
1104 * | |
1105 * FUNCTION: vad_hangover | |
1106 * | |
1107 * PURPOSE: Computes the final VAD decision for the current frame | |
1108 * being processed. | |
1109 * | |
1110 * INPUTS: vvad vad decision before hangover is added | |
1111 * | |
1112 * OUTPUTS: none | |
1113 * | |
1114 * RETURN VALUE: vad decision after hangover is added | |
1115 * | |
1116 ***************************************************************************/ | |
1117 | |
1118 Word16 vad_hangover ( | |
1119 Word16 vvad | |
1120 ) | |
1121 { | |
1122 test (); | |
1123 if (sub (vvad, 1) == 0) | |
1124 { | |
1125 burstcount = add (burstcount, 1); | |
1126 } | |
1127 else | |
1128 { | |
1129 burstcount = 0; move16 (); | |
1130 } | |
1131 | |
1132 test (); | |
1133 if (sub (burstcount, BURSTCONST) >= 0) | |
1134 { | |
1135 hangcount = HANGCONST; move16 (); | |
1136 burstcount = BURSTCONST;move16 (); | |
1137 } | |
1138 test (); | |
1139 if (hangcount >= 0) | |
1140 { | |
1141 hangcount = sub (hangcount, 1); | |
1142 return 1; /* vad = 1 */ | |
1143 } | |
1144 return vvad; /* vad = vvad */ | |
1145 } | |
1146 | |
1147 /**************************************************************************** | |
1148 * | |
1149 * FUNCTION: periodicity_update | |
1150 * | |
1151 * PURPOSE: Computes the ptch flag needed for the threshold | |
1152 * adaptation decision for the next frame. | |
1153 * | |
1154 * INPUTS: lags[0..1] speech encoder long term predictor lags | |
1155 * | |
1156 * OUTPUTS: *ptch Boolean voiced / unvoiced decision | |
1157 * | |
1158 * RETURN VALUE: none | |
1159 * | |
1160 ***************************************************************************/ | |
1161 | |
1162 void periodicity_update ( | |
1163 Word16 lags[], | |
1164 Word16 *ptch | |
1165 ) | |
1166 { | |
1167 Word16 minlag, maxlag, lagcount, temp; | |
1168 Word16 i; | |
1169 | |
1170 /*** Run loop for the two halves in the frame ***/ | |
1171 | |
1172 lagcount = 0; move16 (); | |
1173 | |
1174 for (i = 0; i <= 1; i++) | |
1175 { | |
1176 /*** Search the maximum and minimum of consecutive lags ***/ | |
1177 | |
1178 test (); | |
1179 if (sub (oldlag, lags[i]) > 0) | |
1180 { | |
1181 minlag = lags[i]; move16 (); | |
1182 maxlag = oldlag; move16 (); | |
1183 } | |
1184 else | |
1185 { | |
1186 minlag = oldlag; move16 (); | |
1187 maxlag = lags[i]; move16 (); | |
1188 } | |
1189 | |
1190 temp = sub (maxlag, minlag); | |
1191 | |
1192 test (); | |
1193 if (sub (temp, LTHRESH) < 0) | |
1194 { | |
1195 lagcount = add (lagcount, 1); | |
1196 } | |
1197 /*** Save the current LTP lag ***/ | |
1198 | |
1199 oldlag = lags[i]; move16 (); | |
1200 } | |
1201 | |
1202 /*** Update the veryoldlagcount and oldlagcount ***/ | |
1203 | |
1204 veryoldlagcount = oldlagcount; | |
1205 move16 (); | |
1206 oldlagcount = lagcount; move16 (); | |
1207 | |
1208 /*** Make ptch decision ready for next frame ***/ | |
1209 | |
1210 temp = add (oldlagcount, veryoldlagcount); | |
1211 | |
1212 test (); | |
1213 if (sub (temp, NTHRESH) >= 0) | |
1214 { | |
1215 *ptch = 1; move16 (); | |
1216 } | |
1217 else | |
1218 { | |
1219 *ptch = 0; move16 (); | |
1220 } | |
1221 | |
1222 return; | |
1223 } |