FreeCalypso > hg > gsm-codec-lib
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 } |