comparison vad.c @ 0:9008dbc8ca74

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