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