comparison libtwamr/vad1.c @ 408:8847c1740e78

libtwamr: integrate VAD1
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 07 May 2024 00:56:10 +0000
parents
children
comparison
equal deleted inserted replaced
407:5a1d18542f8a 408:8847c1740e78
1 /*
2 *****************************************************************************
3 **-------------------------------------------------------------------------**
4 ** **
5 ** GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 **
6 ** R99 Version 3.3.0 **
7 ** REL-4 Version 4.1.0 **
8 ** **
9 **-------------------------------------------------------------------------**
10 *****************************************************************************
11 *
12 * File : vad1.c
13 * Purpose : Voice Activity Detection (VAD) for AMR (option 1)
14 *
15 *****************************************************************************
16 */
17
18 /*
19 *****************************************************************************
20 * MODULE INCLUDE FILE AND VERSION ID
21 *****************************************************************************
22 */
23 #include "namespace.h"
24 #include "vad1.h"
25
26 /*
27 *****************************************************************************
28 * INCLUDE FILES
29 *****************************************************************************
30 */
31 #include "typedef.h"
32 #include "basic_op.h"
33 #include "no_count.h"
34 #include "oper_32b.h"
35 #include "cnst_vad.h"
36
37 /*
38 *****************************************************************************
39 * LOCAL VARIABLES AND TABLES
40 *****************************************************************************
41 */
42
43 /*
44 ********************************************************************************
45 * PRIVATE PROGRAM CODE
46 ********************************************************************************
47 */
48 /****************************************************************************
49 *
50 * Function : first_filter_stage
51 * Purpose : Scale input down by one bit. Calculate 5th order
52 * half-band lowpass/highpass filter pair with
53 * decimation.
54 *
55 ***************************************************************************/
56 static void first_filter_stage(Word16 in[], /* i : input signal */
57 Word16 out[], /* o : output values, every other */
58 /* output is low-pass part and */
59 /* other is high-pass part every */
60 Word16 data[] /* i/o : filter memory */
61 )
62 {
63 Word16 temp0, temp1, temp2, temp3, i;
64 Word16 data0, data1;
65
66 data0 = data[0]; move16 ();
67 data1 = data[1]; move16 ();
68
69 for (i = 0; i < FRAME_LEN/4; i++)
70 {
71 temp0 = sub(shr(in[4*i+0], 2), mult(COEFF5_1, data0));
72 temp1 = add(data0, mult(COEFF5_1, temp0));
73
74 temp3 = sub(shr(in[4*i+1], 2), mult(COEFF5_2, data1));
75 temp2 = add(data1, mult(COEFF5_2, temp3));
76
77 out[4*i+0] = add(temp1, temp2); move16 ();
78 out[4*i+1] = sub(temp1, temp2); move16 ();
79
80 data0 = sub(shr(in[4*i+2], 2), mult(COEFF5_1, temp0));
81 temp1 = add(temp0, mult(COEFF5_1, data0));
82
83 data1 = sub(shr(in[4*i+3], 2), mult(COEFF5_2, temp3));
84 temp2 = add(temp3, mult(COEFF5_2, data1));
85
86 out[4*i+2] = add(temp1, temp2); move16 ();
87 out[4*i+3] = sub(temp1, temp2); move16 ();
88 }
89
90 data[0] = data0; move16 ();
91 data[1] = data1; move16 ();
92 }
93
94 /****************************************************************************
95 *
96 * Function : filter5
97 * Purpose : Fifth-order half-band lowpass/highpass filter pair with
98 * decimation.
99 *
100 ***************************************************************************/
101 static void filter5(Word16 *in0, /* i/o : input values; output low-pass part */
102 Word16 *in1, /* i/o : input values; output high-pass part */
103 Word16 data[] /* i/o : updated filter memory */
104 )
105 {
106 Word16 temp0, temp1, temp2;
107
108 temp0 = sub(*in0, mult(COEFF5_1, data[0]));
109 temp1 = add(data[0], mult(COEFF5_1, temp0));
110 data[0] = temp0; move16 ();
111
112 temp0 = sub(*in1, mult(COEFF5_2, data[1]));
113 temp2 = add(data[1], mult(COEFF5_2, temp0));
114 data[1] = temp0; move16 ();
115
116 *in0 = shr(add(temp1, temp2), 1); move16 ();
117 *in1 = shr(sub(temp1, temp2), 1); move16 ();
118 }
119
120 /****************************************************************************
121 *
122 * Function : filter3
123 * Purpose : Third-order half-band lowpass/highpass filter pair with
124 * decimation.
125 * Return value :
126 *
127 ***************************************************************************/
128 static void filter3(Word16 *in0, /* i/o : input values; output low-pass part */
129 Word16 *in1, /* i/o : input values; output high-pass part */
130 Word16 *data /* i/o : updated filter memory */
131 )
132 {
133 Word16 temp1, temp2;
134
135 temp1 = sub(*in1, mult(COEFF3, *data));
136 temp2 = add(*data, mult(COEFF3, temp1));
137 *data = temp1; move16 ();
138
139 *in1 = shr(sub(*in0, temp2), 1); move16 ();
140 *in0 = shr(add(*in0, temp2), 1); move16 ();
141 }
142
143 /****************************************************************************
144 *
145 * Function : level_calculation
146 * Purpose : Calculate signal level in a sub-band. Level is calculated
147 * by summing absolute values of the input data.
148 * Return value : signal level
149 *
150 ***************************************************************************/
151 static Word16 level_calculation(
152 Word16 data[], /* i : signal buffer */
153 Word16 *sub_level, /* i : level calculate at the end of the previous frame */
154 /* o : level of signal calculated from the last */
155 /* (count2 - count1) samples */
156 Word16 count1, /* i : number of samples to be counted */
157 Word16 count2, /* i : number of samples to be counted */
158 Word16 ind_m, /* i : step size for the index of the data buffer */
159 Word16 ind_a, /* i : starting index of the data buffer */
160 Word16 scale /* i : scaling for the level calculation */
161 )
162 {
163 Word32 l_temp1, l_temp2;
164 Word16 level, i;
165
166 l_temp1 = 0L; move32 ();
167 for (i = count1; i < count2; i++)
168 {
169 l_temp1 = L_mac(l_temp1, 1, abs_s(data[ind_m*i+ind_a]));
170 }
171
172 l_temp2 = L_add(l_temp1, L_shl(*sub_level, sub(16, scale)));
173 *sub_level = extract_h(L_shl(l_temp1, scale));
174
175 for (i = 0; i < count1; i++)
176 {
177 l_temp2 = L_mac(l_temp2, 1, abs_s(data[ind_m*i+ind_a]));
178 }
179 level = extract_h(L_shl(l_temp2, scale));
180
181 return level;
182 }
183
184 /****************************************************************************
185 *
186 * Function : filter_bank
187 * Purpose : Divides input signal into 9-bands and calculas level of
188 * the signal in each band
189 *
190 ***************************************************************************/
191 static void filter_bank(vadState1 *st, /* i/o : State struct */
192 Word16 in[], /* i : input frame */
193 Word16 level[] /* 0 : signal levels at each band */
194 )
195 {
196 Word16 i;
197 Word16 tmp_buf[FRAME_LEN];
198
199 /* calculate the filter bank */
200
201 first_filter_stage(in, tmp_buf, st->a_data5[0]);
202
203 for (i = 0; i < FRAME_LEN/4; i++)
204 {
205 filter5(&tmp_buf[4*i], &tmp_buf[4*i+2], st->a_data5[1]);
206 filter5(&tmp_buf[4*i+1], &tmp_buf[4*i+3], st->a_data5[2]);
207 }
208 for (i = 0; i < FRAME_LEN/8; i++)
209 {
210 filter3(&tmp_buf[8*i+0], &tmp_buf[8*i+4], &st->a_data3[0]);
211 filter3(&tmp_buf[8*i+2], &tmp_buf[8*i+6], &st->a_data3[1]);
212 filter3(&tmp_buf[8*i+3], &tmp_buf[8*i+7], &st->a_data3[4]);
213 }
214
215 for (i = 0; i < FRAME_LEN/16; i++)
216 {
217 filter3(&tmp_buf[16*i+0], &tmp_buf[16*i+8], &st->a_data3[2]);
218 filter3(&tmp_buf[16*i+4], &tmp_buf[16*i+12], &st->a_data3[3]);
219 }
220
221 /* calculate levels in each frequency band */
222
223 /* 3000 - 4000 Hz*/
224 level[8] = level_calculation(tmp_buf, &st->sub_level[8], FRAME_LEN/4-8,
225 FRAME_LEN/4, 4, 1, 15);
226 move16 ();
227 /* 2500 - 3000 Hz*/
228 level[7] = level_calculation(tmp_buf, &st->sub_level[7], FRAME_LEN/8-4,
229 FRAME_LEN/8, 8, 7, 16);
230 move16 ();
231 /* 2000 - 2500 Hz*/
232 level[6] = level_calculation(tmp_buf, &st->sub_level[6], FRAME_LEN/8-4,
233 FRAME_LEN/8, 8, 3, 16);
234 move16 ();
235 /* 1500 - 2000 Hz*/
236 level[5] = level_calculation(tmp_buf, &st->sub_level[5], FRAME_LEN/8-4,
237 FRAME_LEN/8, 8, 2, 16);
238 move16 ();
239 /* 1000 - 1500 Hz*/
240 level[4] = level_calculation(tmp_buf, &st->sub_level[4], FRAME_LEN/8-4,
241 FRAME_LEN/8, 8, 6, 16);
242 move16 ();
243 /* 750 - 1000 Hz*/
244 level[3] = level_calculation(tmp_buf, &st->sub_level[3], FRAME_LEN/16-2,
245 FRAME_LEN/16, 16, 4, 16);
246 move16 ();
247 /* 500 - 750 Hz*/
248 level[2] = level_calculation(tmp_buf, &st->sub_level[2], FRAME_LEN/16-2,
249 FRAME_LEN/16, 16, 12, 16);
250 move16 ();
251 /* 250 - 500 Hz*/
252 level[1] = level_calculation(tmp_buf, &st->sub_level[1], FRAME_LEN/16-2,
253 FRAME_LEN/16, 16, 8, 16);
254 move16 ();
255 /* 0 - 250 Hz*/
256 level[0] = level_calculation(tmp_buf, &st->sub_level[0], FRAME_LEN/16-2,
257 FRAME_LEN/16, 16, 0, 16);
258 move16 ();
259 }
260
261 /****************************************************************************
262 *
263 * Function : update_cntrl
264 * Purpose : Control update of the background noise estimate.
265 * Inputs : pitch: flags for pitch detection
266 * stat_count: stationary counter
267 * tone: flags indicating presence of a tone
268 * complex: flags for complex detection
269 * vadreg: intermediate VAD flags
270 * Output : stat_count: stationary counter
271 *
272 ***************************************************************************/
273 static void update_cntrl(vadState1 *st, /* i/o : State struct */
274 Word16 level[] /* i : sub-band levels of the input frame */
275 )
276 {
277 Word16 i, temp, stat_rat, exp;
278 Word16 num, denom;
279 Word16 alpha;
280
281 /* handle highband complex signal input separately */
282 /* if ther has been highband correlation for some time */
283 /* make sure that the VAD update speed is low for a while */
284 test ();
285 if (st->complex_warning != 0)
286 {
287 test ();
288 if (sub(st->stat_count, CAD_MIN_STAT_COUNT) < 0)
289 {
290 st->stat_count = CAD_MIN_STAT_COUNT; move16 ();
291 }
292 }
293 /* NB stat_count is allowed to be decreased by one below again */
294 /* deadlock in speech is not possible unless the signal is very */
295 /* complex and need a high rate */
296
297 /* if fullband pitch or tone have been detected for a while, initialize stat_count */
298 logic16 (); test (); logic16 (); test ();
299 if ((sub((st->pitch & 0x6000), 0x6000) == 0) ||
300 (sub((st->tone & 0x7c00), 0x7c00) == 0))
301 {
302 st->stat_count = STAT_COUNT; move16 ();
303 }
304 else
305 {
306 /* if 8 last vad-decisions have been "0", reinitialize stat_count */
307 logic16 (); test ();
308 if ((st->vadreg & 0x7f80) == 0)
309 {
310 st->stat_count = STAT_COUNT; move16 ();
311 }
312 else
313 {
314 stat_rat = 0; move16 ();
315 for (i = 0; i < COMPLEN; i++)
316 {
317 test ();
318 if (sub(level[i], st->ave_level[i]) > 0)
319 {
320 num = level[i]; move16 ();
321 denom = st->ave_level[i]; move16 ();
322 }
323 else
324 {
325 num = st->ave_level[i]; move16 ();
326 denom = level[i]; move16 ();
327 }
328 /* Limit nimimum value of num and denom to STAT_THR_LEVEL */
329 test ();
330 if (sub(num, STAT_THR_LEVEL) < 0)
331 {
332 num = STAT_THR_LEVEL; move16 ();
333 }
334 test ();
335 if (sub(denom, STAT_THR_LEVEL) < 0)
336 {
337 denom = STAT_THR_LEVEL; move16 ();
338 }
339
340 exp = norm_s(denom);
341 denom = shl(denom, exp);
342
343 /* stat_rat = num/denom * 64 */
344 temp = div_s(shr(num, 1), denom);
345 stat_rat = add(stat_rat, shr(temp, sub(8, exp)));
346 }
347
348 /* compare stat_rat with a threshold and update stat_count */
349 test ();
350 if (sub(stat_rat, STAT_THR) > 0)
351 {
352 st->stat_count = STAT_COUNT; move16 ();
353 }
354 else
355 {
356 logic16 ();test ();
357 if ((st->vadreg & 0x4000) != 0)
358 {
359 test ();
360 if (st->stat_count != 0)
361 {
362 st->stat_count = sub(st->stat_count, 1); move16 ();
363 }
364 }
365 }
366 }
367 }
368
369 /* Update average amplitude estimate for stationarity estimation */
370 alpha = ALPHA4; move16 ();
371 test ();
372 if (sub(st->stat_count, STAT_COUNT) == 0)
373 {
374 alpha = 32767; move16 ();
375 }
376 else if ((st->vadreg & 0x4000) == 0)
377 {
378 logic16 (); test ();
379 alpha = ALPHA5; move16 ();
380 }
381
382 for (i = 0; i < COMPLEN; i++)
383 {
384 st->ave_level[i] = add(st->ave_level[i],
385 mult_r(alpha, sub(level[i], st->ave_level[i])));
386 move16 ();
387 }
388 }
389
390 /****************************************************************************
391 *
392 * Function : hangover_addition
393 * Purpose : Add hangover for complex signal or after speech bursts
394 * Inputs : burst_count: counter for the length of speech bursts
395 * hang_count: hangover counter
396 * vadreg: intermediate VAD decision
397 * Outputs : burst_count: counter for the length of speech bursts
398 * hang_count: hangover counter
399 * Return value : VAD_flag indicating final VAD decision
400 *
401 ***************************************************************************/
402 static Word16 hangover_addition(
403 vadState1 *st, /* i/o : State struct */
404 Word16 noise_level, /* i : average level of the noise */
405 /* estimates */
406 Word16 low_power /* i : flag power of the input frame */
407 )
408 {
409 Word16 hang_len, burst_len;
410
411 /*
412 Calculate burst_len and hang_len
413 burst_len: number of consecutive intermediate vad flags with "1"-decision
414 required for hangover addition
415 hang_len: length of the hangover
416 */
417
418 test ();
419 if (sub(noise_level, HANG_NOISE_THR) > 0)
420 {
421 burst_len = BURST_LEN_HIGH_NOISE; move16 ();
422 hang_len = HANG_LEN_HIGH_NOISE; move16 ();
423 }
424 else
425 {
426 burst_len = BURST_LEN_LOW_NOISE; move16 ();
427 hang_len = HANG_LEN_LOW_NOISE; move16 ();
428 }
429
430 /* if the input power (pow_sum) is lower than a threshold, clear
431 counters and set VAD_flag to "0" "fast exit" */
432 test ();
433 if (low_power != 0)
434 {
435 st->burst_count = 0; move16 ();
436 st->hang_count = 0; move16 ();
437 st->complex_hang_count = 0; move16 ();
438 st->complex_hang_timer = 0; move16 ();
439 return 0;
440 }
441
442 test ();
443 if (sub(st->complex_hang_timer, CVAD_HANG_LIMIT) > 0)
444 {
445 test ();
446 if (sub(st->complex_hang_count, CVAD_HANG_LENGTH) < 0)
447 {
448 st->complex_hang_count = CVAD_HANG_LENGTH; move16 ();
449 }
450 }
451
452 /* long time very complex signal override VAD output function */
453 test ();
454 if (st->complex_hang_count != 0)
455 {
456 st->burst_count = BURST_LEN_HIGH_NOISE; move16 ();
457 st->complex_hang_count = sub(st->complex_hang_count, 1); move16 ();
458 return 1;
459 }
460 else
461 {
462 /* let hp_corr work in from a noise_period indicated by the VAD */
463 test (); test (); logic16 ();
464 if (((st->vadreg & 0x3ff0) == 0) &&
465 (sub(st->corr_hp_fast, CVAD_THRESH_IN_NOISE) > 0))
466 {
467 return 1;
468 }
469 }
470
471 /* update the counters (hang_count, burst_count) */
472 logic16 (); test ();
473 if ((st->vadreg & 0x4000) != 0)
474 {
475 st->burst_count = add(st->burst_count, 1); move16 ();
476 test ();
477 if (sub(st->burst_count, burst_len) >= 0)
478 {
479 st->hang_count = hang_len; move16 ();
480 }
481 return 1;
482 }
483 else
484 {
485 st->burst_count = 0; move16 ();
486 test ();
487 if (st->hang_count > 0)
488 {
489 st->hang_count = sub(st->hang_count, 1); move16 ();
490 return 1;
491 }
492 }
493 return 0;
494 }
495
496 /****************************************************************************
497 *
498 * Function : noise_estimate_update
499 * Purpose : Update of background noise estimate
500 * Inputs : bckr_est: background noise estimate
501 * pitch: flags for pitch detection
502 * stat_count: stationary counter
503 * Outputs : bckr_est: background noise estimate
504 *
505 ***************************************************************************/
506 static void noise_estimate_update(
507 vadState1 *st, /* i/o : State struct */
508 Word16 level[] /* i : sub-band levels of the input frame */
509 )
510 {
511 Word16 i, alpha_up, alpha_down, bckr_add;
512
513 /* Control update of bckr_est[] */
514 update_cntrl(st, level);
515
516 /* Choose update speed */
517 bckr_add = 2; move16 ();
518
519 logic16 (); test (); logic16 (); test (); test ();
520 if (((0x7800 & st->vadreg) == 0) &&
521 ((st->pitch & 0x7800) == 0)
522 && (st->complex_hang_count == 0))
523 {
524 alpha_up = ALPHA_UP1; move16 ();
525 alpha_down = ALPHA_DOWN1; move16 ();
526 }
527 else
528 {
529 test (); test ();
530 if ((st->stat_count == 0)
531 && (st->complex_hang_count == 0))
532 {
533 alpha_up = ALPHA_UP2; move16 ();
534 alpha_down = ALPHA_DOWN2; move16 ();
535 }
536 else
537 {
538 alpha_up = 0; move16 ();
539 alpha_down = ALPHA3; move16 ();
540 bckr_add = 0; move16 ();
541 }
542 }
543
544 /* Update noise estimate (bckr_est) */
545 for (i = 0; i < COMPLEN; i++)
546 {
547 Word16 temp;
548 temp = sub(st->old_level[i], st->bckr_est[i]);
549
550 test ();
551 if (temp < 0)
552 { /* update downwards*/
553 st->bckr_est[i] = add(-2, add(st->bckr_est[i], mult_r(alpha_down, temp)));
554 move16 ();
555
556 /* limit minimum value of the noise estimate to NOISE_MIN */
557 test ();
558 if (sub(st->bckr_est[i], NOISE_MIN) < 0)
559 {
560 st->bckr_est[i] = NOISE_MIN; move16 ();
561 }
562 }
563 else
564 { /* update upwards */
565 st->bckr_est[i] = add(bckr_add, add(st->bckr_est[i], mult_r(alpha_up, temp)));
566 move16 ();
567
568 /* limit maximum value of the noise estimate to NOISE_MAX */
569 test ();
570 if (sub(st->bckr_est[i], NOISE_MAX) > 0)
571 {
572 st->bckr_est[i] = NOISE_MAX; move16 ();
573 }
574 }
575 }
576
577 /* Update signal levels of the previous frame (old_level) */
578 for(i = 0; i < COMPLEN; i++)
579 {
580 st->old_level[i] = level[i]; move16 ();
581 }
582 }
583
584 /****************************************************************************
585 *
586 * Function : complex_estimate_adapt
587 * Purpose : Update/adapt of complex signal estimate
588 * Inputs : low_power: low signal power flag
589 * Outputs : st->corr_hp_fast: long term complex signal estimate
590 *
591 ***************************************************************************/
592 static void complex_estimate_adapt(
593 vadState1 *st, /* i/o : VAD state struct */
594 Word16 low_power /* i : very low level flag of the input frame */
595 )
596 {
597 Word16 alpha; /* Q15 */
598 Word32 L_tmp; /* Q31 */
599
600
601 /* adapt speed on own state */
602 test ();
603 if (sub(st->best_corr_hp, st->corr_hp_fast) < 0) /* decrease */
604 {
605 test ();
606 if (sub(st->corr_hp_fast, CVAD_THRESH_ADAPT_HIGH) < 0)
607 { /* low state */
608 alpha = CVAD_ADAPT_FAST; move16();
609 }
610 else
611 { /* high state */
612 alpha = CVAD_ADAPT_REALLY_FAST; move16();
613 }
614 }
615 else /* increase */
616 {
617 test ();
618 if (sub(st->corr_hp_fast, CVAD_THRESH_ADAPT_HIGH) < 0)
619 {
620 alpha = CVAD_ADAPT_FAST; move16();
621 }
622 else
623 {
624 alpha = CVAD_ADAPT_SLOW; move16();
625 }
626 }
627
628 L_tmp = L_deposit_h(st->corr_hp_fast);
629 L_tmp = L_msu(L_tmp, alpha, st->corr_hp_fast);
630 L_tmp = L_mac(L_tmp, alpha, st->best_corr_hp);
631 st->corr_hp_fast = round(L_tmp); /* Q15 */ move16();
632
633 test ();
634 if (sub(st->corr_hp_fast, CVAD_MIN_CORR) < 0)
635 {
636 st->corr_hp_fast = CVAD_MIN_CORR; move16();
637 }
638
639 test ();
640 if (low_power != 0)
641 {
642 st->corr_hp_fast = CVAD_MIN_CORR; move16();
643 }
644 }
645
646 /****************************************************************************
647 *
648 * Function : complex_vad
649 * Purpose : complex background decision
650 * Return value : the complex background decision
651 *
652 ***************************************************************************/
653 static Word16 complex_vad(vadState1 *st, /* i/o : VAD state struct */
654 Word16 low_power /* i : flag power of the input frame */
655 )
656 {
657 st->complex_high = shr(st->complex_high, 1); move16 ();
658 st->complex_low = shr(st->complex_low, 1); move16 ();
659
660 test ();
661 if (low_power == 0)
662 {
663 test ();
664 if (sub(st->corr_hp_fast, CVAD_THRESH_ADAPT_HIGH) > 0)
665 {
666 st->complex_high = st->complex_high | 0x4000; logic16 (); move16 ();
667 }
668
669 test ();
670 if (sub(st->corr_hp_fast, CVAD_THRESH_ADAPT_LOW) > 0 )
671 {
672 st->complex_low = st->complex_low | 0x4000; logic16 (); move16 ();
673 }
674 }
675
676 test ();
677 if (sub(st->corr_hp_fast, CVAD_THRESH_HANG) > 0)
678 {
679 st->complex_hang_timer = add(st->complex_hang_timer, 1); move16 ();
680 }
681 else
682 {
683 st->complex_hang_timer = 0; move16 ();
684 }
685
686 test (); logic16 (); test (); logic16 ();
687 return ((sub((st->complex_high & 0x7f80), 0x7f80) == 0) ||
688 (sub((st->complex_low & 0x7fff), 0x7fff) == 0));
689 }
690
691 /****************************************************************************
692 *
693 * Function : vad_decision
694 * Purpose : Calculates VAD_flag
695 * Inputs : bckr_est: background noise estimate
696 * vadreg: intermediate VAD flags
697 * Outputs : noise_level: average level of the noise estimates
698 * vadreg: intermediate VAD flags
699 * Return value : VAD_flag
700 *
701 ***************************************************************************/
702 static Word16 vad_decision(
703 vadState1 *st, /* i/o : State struct */
704 Word16 level[COMPLEN], /* i : sub-band levels of the input frame */
705 Word32 pow_sum /* i : power of the input frame */
706 )
707 {
708 Word16 i;
709 Word16 snr_sum;
710 Word32 L_temp;
711 Word16 vad_thr, temp, noise_level;
712 Word16 low_power_flag;
713
714 /*
715 Calculate squared sum of the input levels (level)
716 divided by the background noise components (bckr_est).
717 */
718 L_temp = 0; move32();
719 for (i = 0; i < COMPLEN; i++)
720 {
721 Word16 exp;
722
723 exp = norm_s(st->bckr_est[i]);
724 temp = shl(st->bckr_est[i], exp);
725 temp = div_s(shr(level[i], 1), temp);
726 temp = shl(temp, sub(exp, UNIRSHFT-1));
727 L_temp = L_mac(L_temp, temp, temp);
728 }
729 snr_sum = extract_h(L_shl(L_temp, 6));
730 snr_sum = mult(snr_sum, INV_COMPLEN);
731
732 /* Calculate average level of estimated background noise */
733 L_temp = 0; move32();
734 for (i = 0; i < COMPLEN; i++)
735 {
736 L_temp = L_add(L_temp, st->bckr_est[i]);
737 }
738
739 noise_level = extract_h(L_shl(L_temp, 13));
740
741 /* Calculate VAD threshold */
742 vad_thr = add(mult(VAD_SLOPE, sub(noise_level, VAD_P1)), VAD_THR_HIGH);
743
744 test ();
745 if (sub(vad_thr, VAD_THR_LOW) < 0)
746 {
747 vad_thr = VAD_THR_LOW; move16 ();
748 }
749
750 /* Shift VAD decision register */
751 st->vadreg = shr(st->vadreg, 1); move16 ();
752
753 /* Make intermediate VAD decision */
754 test ();
755 if (sub(snr_sum, vad_thr) > 0)
756 {
757 st->vadreg = st->vadreg | 0x4000; logic16 (); move16 ();
758 }
759 /* primary vad decsion made */
760
761 /* check if the input power (pow_sum) is lower than a threshold" */
762 test ();
763 if (L_sub(pow_sum, VAD_POW_LOW) < 0)
764 {
765 low_power_flag = 1; move16 ();
766 }
767 else
768 {
769 low_power_flag = 0; move16 ();
770 }
771
772 /* update complex signal estimate st->corr_hp_fast and hangover reset timer using */
773 /* low_power_flag and corr_hp_fast and various adaptation speeds */
774 complex_estimate_adapt(st, low_power_flag);
775
776 /* check multiple thresholds of the st->corr_hp_fast value */
777 st->complex_warning = complex_vad(st, low_power_flag); move16();
778
779 /* Update speech subband vad background noise estimates */
780 noise_estimate_update(st, level);
781
782 /* Add speech and complex hangover and return speech VAD_flag */
783 /* long term complex hangover may be added */
784 st->speech_vad_decision = hangover_addition(st, noise_level, low_power_flag);
785 move16 ();
786
787 return (st->speech_vad_decision);
788 }
789
790 /*
791 *****************************************************************************
792 * PUBLIC PROGRAM CODE
793 *****************************************************************************
794 */
795
796 /*************************************************************************
797 *
798 * Function: vad1_reset
799 * Purpose: Initializes state memory to zero
800 *
801 **************************************************************************
802 */
803 void vad1_reset (vadState1 *state)
804 {
805 Word16 i, j;
806
807 /* Initialize pitch detection variables */
808 state->oldlag_count = 0;
809 state->oldlag = 0;
810 state->pitch = 0;
811 state->tone = 0;
812
813 state->complex_high = 0;
814 state->complex_low = 0;
815 state->complex_hang_timer = 0;
816
817 state->vadreg = 0;
818
819 state->stat_count = 0;
820 state->burst_count = 0;
821 state->hang_count = 0;
822 state->complex_hang_count = 0;
823
824 /* initialize memory used by the filter bank */
825 for (i = 0; i < 3; i++)
826 {
827 for (j = 0; j < 2; j++)
828 {
829 state->a_data5[i][j] = 0;
830 }
831 }
832
833 for (i = 0; i < 5; i++)
834 {
835 state->a_data3[i] = 0;
836 }
837
838 /* initialize the rest of the memory */
839 for (i = 0; i < COMPLEN; i++)
840 {
841 state->bckr_est[i] = NOISE_INIT;
842 state->old_level[i] = NOISE_INIT;
843 state->ave_level[i] = NOISE_INIT;
844 state->sub_level[i] = 0;
845 }
846
847 state->best_corr_hp = CVAD_LOWPOW_RESET;
848
849 state->speech_vad_decision = 0;
850 state->complex_warning = 0;
851 state->sp_burst_count = 0;
852
853 state->corr_hp_fast = CVAD_LOWPOW_RESET;
854 }
855
856 /****************************************************************************
857 *
858 * Function : vad_complex_detection_update
859 * Purpose : update vad->bestCorr_hp complex signal feature state
860 *
861 ***************************************************************************/
862 void vad_complex_detection_update (vadState1 *st, /* i/o : State struct */
863 Word16 best_corr_hp /* i : best Corr */
864 )
865 {
866 st->best_corr_hp = best_corr_hp; move16();
867 }
868
869 /****************************************************************************
870 *
871 * Function : vad_tone_detection
872 * Purpose : Set tone flag if pitch gain is high. This is used to detect
873 * signaling tones and other signals with high pitch gain.
874 * Inputs : tone: flags indicating presence of a tone
875 * Outputs : tone: flags indicating presence of a tone
876 *
877 ***************************************************************************/
878 void vad_tone_detection (vadState1 *st, /* i/o : State struct */
879 Word32 t0, /* i : autocorrelation maxima */
880 Word32 t1 /* i : energy */
881 )
882 {
883 Word16 temp;
884 /*
885 if (t0 > TONE_THR * t1)
886 set tone flag
887 */
888 temp = round(t1);
889
890 test (); test ();
891 if ((temp > 0) && (L_msu(t0, temp, TONE_THR) > 0))
892 {
893 st->tone = st->tone | 0x4000; logic16 (); move16 ();
894 }
895 }
896
897 /****************************************************************************
898 *
899 * Function : vad_tone_detection_update
900 * Purpose : Update the tone flag register. Tone flags are shifted right
901 * by one bit. This function should be called from the speech
902 * encoder before call to Vad_tone_detection() function.
903 *
904 ***************************************************************************/
905 void vad_tone_detection_update (
906 vadState1 *st, /* i/o : State struct */
907 Word16 one_lag_per_frame /* i : 1 if one open-loop lag is
908 calculated per each frame,
909 otherwise 0 */
910 )
911 {
912 /* Shift tone flags right by one bit */
913 st->tone = shr(st->tone, 1); move16 ();
914
915 /* If open-loop lag is calculated only once in each frame, do extra update
916 and assume that the other tone flag of the frame is one. */
917 if (one_lag_per_frame != 0)
918 {
919 st->tone = shr(st->tone, 1);
920 st->tone = st->tone | 0x2000; logic16 (); move16 ();
921 }
922 }
923
924 /****************************************************************************
925 *
926 * Function : vad_pitch_detection
927 * Purpose : Test whether signal contains pitch or other periodic
928 * component.
929 * Return value : Boolean voiced / unvoiced decision in state variable
930 *
931 ***************************************************************************/
932 void vad_pitch_detection (vadState1 *st, /* i/o : State struct */
933 Word16 T_op[] /* i : speech encoder open loop lags */
934 )
935 {
936 Word16 lagcount, i;
937
938 lagcount = 0; move16 ();
939
940 for (i = 0; i < 2; i++)
941 {
942 test ();
943 if (sub (abs_s (sub (st->oldlag, T_op[i])), LTHRESH) < 0)
944 {
945 lagcount = add (lagcount, 1);
946 }
947
948 /* Save the current LTP lag */
949 st->oldlag = T_op[i]; move16 ();
950 }
951
952 /* Make pitch decision.
953 Save flag of the pitch detection to the variable pitch.
954 */
955 st->pitch = shr(st->pitch, 1); move16();
956
957 test ();
958 if (sub ( add (st->oldlag_count, lagcount), NTHRESH) >= 0)
959 {
960 st->pitch = st->pitch | 0x4000; logic16(); move16();
961 }
962
963 /* Update oldlagcount */
964 st->oldlag_count = lagcount; move16 ();
965 }
966
967 /****************************************************************************
968 *
969 * Function : vad
970 * Purpose : Main program for Voice Activity Detection (VAD) for AMR
971 * Return value : VAD Decision, 1 = speech, 0 = noise
972 *
973 ***************************************************************************/
974 Word16 vad1(vadState1 *st, /* i/o : State struct */
975 Word16 in_buf[] /* i : samples of the input frame */
976 )
977 {
978 Word16 level[COMPLEN];
979 Word32 pow_sum;
980 Word16 i;
981
982 /* Calculate power of the input frame. */
983 pow_sum = 0L; move32 ();
984
985 for (i = 0; i < FRAME_LEN; i++)
986 {
987 pow_sum = L_mac(pow_sum, in_buf[i-LOOKAHEAD], in_buf[i-LOOKAHEAD]);
988 }
989
990 /* If input power is very low, clear pitch flag of the current frame */
991 test ();
992 if (L_sub(pow_sum, POW_PITCH_THR) < 0)
993 {
994 st->pitch = st->pitch & 0x3fff; logic16 (); move16 ();
995 }
996
997 /* If input power is very low, clear complex flag of the "current" frame */
998 test ();
999 if (L_sub(pow_sum, POW_COMPLEX_THR) < 0)
1000 {
1001 st->complex_low = st->complex_low & 0x3fff; logic16 (); move16 ();
1002 }
1003
1004 /* Run the filter bank which calculates signal levels at each band */
1005 filter_bank(st, in_buf, level);
1006
1007 return (vad_decision(st, level, pow_sum));
1008 }