📄 vad.c
字号:
/* ITU-T G.729A Annex B ANSI-C Source Code Version 1.3 Last modified: August 1997 Copyright (c) 1996, France Telecom, Rockwell International, Universite de Sherbrooke. All rights reserved.*/#include <stdio.h>#include "typedef.h"#include "ld8a.h"#include "basic_op.h"#include "oper_32b.h"#include "tab_ld8a.h"#include "vad.h"#include "dtx.h"#include "tab_dtx.h"/* local function */static Word16 MakeDec( Word16 dSLE, /* (i) : differential low band energy */ Word16 dSE, /* (i) : differential full band energy */ Word16 SD, /* (i) : differential spectral distortion */ Word16 dSZC /* (i) : differential zero crossing rate */);/* static variables */static Word16 MeanLSF[M];static Word16 Min_buffer[16];static Word16 Prev_Min, Next_Min, Min;static Word16 MeanE, MeanSE, MeanSLE, MeanSZC;static Word16 prev_energy;static Word16 count_sil, count_update, count_ext;static Word16 flag, v_flag, less_count;/*---------------------------------------------------------------------------* * Function vad_init * * ~~~~~~~~~~~~~~~~~~ * * * * -> Initialization of variables for voice activity detection * * * *---------------------------------------------------------------------------*/void vad_init(void){ /* Static vectors to zero */ Set_zero(MeanLSF, M); /* Initialize VAD parameters */ MeanSE = 0; MeanSLE = 0; MeanE = 0; MeanSZC = 0; count_sil = 0; count_update = 0; count_ext = 0; less_count = 0; flag = 1; Min = MAX_16;}/*-----------------------------------------------------------------* * Functions vad * * ~~~ * * Input: * * rc : reflection coefficient * * lsf[] : unquantized lsf vector * * r_h[] : upper 16-bits of the autocorrelation vector * * r_l[] : lower 16-bits of the autocorrelation vector * * exp_R0 : exponent of the autocorrelation vector * * sigpp[] : preprocessed input signal * * frm_count : frame counter * * prev_marker : VAD decision of the last frame * * pprev_marker : VAD decision of the frame before last frame * * * * Output: * * * * marker : VAD decision of the current frame * * * *-----------------------------------------------------------------*/void vad( Word16 rc, Word16 *lsf, Word16 *r_h, Word16 *r_l, Word16 exp_R0, Word16 *sigpp, Word16 frm_count, Word16 prev_marker, Word16 pprev_marker, Word16 *marker){ /* scalar */ Word32 acc0; Word16 i, j, exp, frac; Word16 ENERGY, ENERGY_low, SD, ZC, dSE, dSLE, dSZC; Word16 COEF, C_COEF, COEFZC, C_COEFZC, COEFSD, C_COEFSD; /* compute the frame energy */ acc0 = L_Comp(r_h[0], r_l[0]); Log2(acc0, &exp, &frac); acc0 = Mpy_32_16(exp, frac, 9864); i = sub(exp_R0, 1); i = sub(i, 1); acc0 = L_mac(acc0, 9864, i); acc0 = L_shl(acc0, 11); ENERGY = extract_h(acc0); ENERGY = sub(ENERGY, 4875); /* compute the low band energy */ acc0 = 0; for (i=1; i<=NP; i++) acc0 = L_mac(acc0, r_h[i], lbf_corr[i]); acc0 = L_shl(acc0, 1); acc0 = L_mac(acc0, r_h[0], lbf_corr[0]); Log2(acc0, &exp, &frac); acc0 = Mpy_32_16(exp, frac, 9864); i = sub(exp_R0, 1); i = sub(i, 1); acc0 = L_mac(acc0, 9864, i); acc0 = L_shl(acc0, 11); ENERGY_low = extract_h(acc0); ENERGY_low = sub(ENERGY_low, 4875); /* compute SD */ acc0 = 0; for (i=0; i<M; i++){ j = sub(lsf[i], MeanLSF[i]); acc0 = L_mac(acc0, j, j); } SD = extract_h(acc0); /* Q15 */ /* compute # zero crossing */ ZC = 0; for (i=ZC_START+1; i<=ZC_END; i++) if (mult(sigpp[i-1], sigpp[i]) < 0) ZC = add(ZC, 410); /* Q15 */ /* Initialize and update Mins */ if(sub(frm_count, 129) < 0){ if (sub(ENERGY, Min) < 0){ Min = ENERGY; Prev_Min = ENERGY; } if((frm_count & 0x0007) == 0){ i = sub(shr(frm_count,3),1); Min_buffer[i] = Min; Min = MAX_16; } } if((frm_count & 0x0007) == 0){ Prev_Min = Min_buffer[0]; for (i=1; i<16; i++){ if (sub(Min_buffer[i], Prev_Min) < 0) Prev_Min = Min_buffer[i]; } } if(sub(frm_count, 129) >= 0){ if(((frm_count & 0x0007) ^ (0x0001)) == 0){ Min = Prev_Min; Next_Min = MAX_16; } if (sub(ENERGY, Min) < 0) Min = ENERGY; if (sub(ENERGY, Next_Min) < 0) Next_Min = ENERGY; if((frm_count & 0x0007) == 0){ for (i=0; i<15; i++) Min_buffer[i] = Min_buffer[i+1]; Min_buffer[15] = Next_Min; Prev_Min = Min_buffer[0]; for (i=1; i<16; i++) if (sub(Min_buffer[i], Prev_Min) < 0) Prev_Min = Min_buffer[i]; } } if (sub(frm_count, INIT_FRAME) <= 0) if(sub(ENERGY, 3072) < 0){ *marker = NOISE; less_count++; } else{ *marker = VOICE; acc0 = L_deposit_h(MeanE); acc0 = L_mac(acc0, ENERGY, 1024); MeanE = extract_h(acc0); acc0 = L_deposit_h(MeanSZC); acc0 = L_mac(acc0, ZC, 1024); MeanSZC = extract_h(acc0); for (i=0; i<M; i++){ acc0 = L_deposit_h(MeanLSF[i]); acc0 = L_mac(acc0, lsf[i], 1024); MeanLSF[i] = extract_h(acc0); } } if (sub(frm_count, INIT_FRAME) >= 0){ if (sub(frm_count, INIT_FRAME) == 0){ acc0 = L_mult(MeanE, factor_fx[less_count]); acc0 = L_shl(acc0, shift_fx[less_count]); MeanE = extract_h(acc0); acc0 = L_mult(MeanSZC, factor_fx[less_count]); acc0 = L_shl(acc0, shift_fx[less_count]); MeanSZC = extract_h(acc0); for (i=0; i<M; i++){ acc0 = L_mult(MeanLSF[i], factor_fx[less_count]); acc0 = L_shl(acc0, shift_fx[less_count]); MeanLSF[i] = extract_h(acc0); } MeanSE = sub(MeanE, 2048); /* Q11 */ MeanSLE = sub(MeanE, 2458); /* Q11 */ } dSE = sub(MeanSE, ENERGY); dSLE = sub(MeanSLE, ENERGY_low); dSZC = sub(MeanSZC, ZC); if(sub(ENERGY, 3072) < 0) *marker = NOISE; else *marker = MakeDec(dSLE, dSE, SD, dSZC); v_flag = 0; if((prev_marker==VOICE) && (*marker==NOISE) && (add(dSE,410) < 0) && (sub(ENERGY, 3072)>0)){ *marker = VOICE; v_flag = 1; } if(flag == 1){ if((pprev_marker == VOICE) && (prev_marker == VOICE) && (*marker == NOISE) && (sub(abs_s(sub(prev_energy,ENERGY)), 614) <= 0)){ count_ext++; *marker = VOICE; v_flag = 1; if(sub(count_ext, 4) <= 0) flag=1; else{ count_ext=0; flag=0; } } } else flag=1; if(*marker == NOISE) count_sil++; if((*marker == VOICE) && (sub(count_sil, 10) > 0) && (sub(sub(ENERGY,prev_energy), 614) <= 0)){ *marker = NOISE; count_sil=0; } if(*marker == VOICE) count_sil=0; if ((sub(sub(ENERGY, 614), MeanSE) < 0) && (sub(frm_count, 128) > 0) && (!v_flag) && (sub(rc, 19661) < 0)) *marker = NOISE; if ((sub(sub(ENERGY,614),MeanSE) < 0) && (sub(rc, 24576) < 0) && (sub(SD, 83) < 0)){ count_update++; if (sub(count_update, INIT_COUNT) < 0){ COEF = 24576; C_COEF = 8192; COEFZC = 26214; C_COEFZC = 6554; COEFSD = 19661; C_COEFSD = 13017; } else if (sub(count_update, INIT_COUNT+10) < 0){ COEF = 31130; C_COEF = 1638; COEFZC = 30147; C_COEFZC = 2621; COEFSD = 21299; C_COEFSD = 11469; } else if (sub(count_update, INIT_COUNT+20) < 0){ COEF = 31785; C_COEF = 983; COEFZC = 30802; C_COEFZC = 1966; COEFSD = 22938; C_COEFSD = 9830; } else if (sub(count_update, INIT_COUNT+30) < 0){ COEF = 32440; C_COEF = 328; COEFZC = 31457; C_COEFZC = 1311; COEFSD = 24576; C_COEFSD = 8192; } else if (sub(count_update, INIT_COUNT+40) < 0){ COEF = 32604; C_COEF = 164; COEFZC = 32440; C_COEFZC = 328; COEFSD = 24576; C_COEFSD = 8192; } else{ COEF = 32604; C_COEF = 164; COEFZC = 32702; C_COEFZC = 66; COEFSD = 24576; C_COEFSD = 8192; } /* compute MeanSE */ acc0 = L_mult(COEF, MeanSE); acc0 = L_mac(acc0, C_COEF, ENERGY); MeanSE = extract_h(acc0); /* compute MeanSLE */ acc0 = L_mult(COEF, MeanSLE); acc0 = L_mac(acc0, C_COEF, ENERGY_low); MeanSLE = extract_h(acc0); /* compute MeanSZC */ acc0 = L_mult(COEFZC, MeanSZC); acc0 = L_mac(acc0, C_COEFZC, ZC); MeanSZC = extract_h(acc0); /* compute MeanLSF */ for (i=0; i<M; i++){ acc0 = L_mult(COEFSD, MeanLSF[i]); acc0 = L_mac(acc0, C_COEFSD, lsf[i]); MeanLSF[i] = extract_h(acc0); } } if((sub(frm_count, 128) > 0) && (((sub(MeanSE,Min) < 0) && (sub(SD, 83) < 0)) || (sub(MeanSE,Min) > 2048))){ MeanSE = Min; count_update = 0; } } prev_energy = ENERGY;}/* local function */ static Word16 MakeDec( Word16 dSLE, /* (i) : differential low band energy */ Word16 dSE, /* (i) : differential full band energy */ Word16 SD, /* (i) : differential spectral distortion */ Word16 dSZC /* (i) : differential zero crossing rate */ ){ Word32 acc0; /* SD vs dSZC */ acc0 = L_mult(dSZC, -14680); /* Q15*Q23*2 = Q39 */ acc0 = L_mac(acc0, 8192, -28521); /* Q15*Q23*2 = Q39 */ acc0 = L_shr(acc0, 8); /* Q39 -> Q31 */ acc0 = L_add(acc0, L_deposit_h(SD)); if (acc0 > 0) return(VOICE); acc0 = L_mult(dSZC, 19065); /* Q15*Q22*2 = Q38 */ acc0 = L_mac(acc0, 8192, -19446); /* Q15*Q22*2 = Q38 */ acc0 = L_shr(acc0, 7); /* Q38 -> Q31 */ acc0 = L_add(acc0, L_deposit_h(SD)); if (acc0 > 0) return(VOICE); /* dSE vs dSZC */ acc0 = L_mult(dSZC, 20480); /* Q15*Q13*2 = Q29 */ acc0 = L_mac(acc0, 8192, 16384); /* Q13*Q15*2 = Q29 */ acc0 = L_shr(acc0, 2); /* Q29 -> Q27 */ acc0 = L_add(acc0, L_deposit_h(dSE)); if (acc0 < 0) return(VOICE); acc0 = L_mult(dSZC, -16384); /* Q15*Q13*2 = Q29 */ acc0 = L_mac(acc0, 8192, 19660); /* Q13*Q15*2 = Q29 */ acc0 = L_shr(acc0, 2); /* Q29 -> Q27 */ acc0 = L_add(acc0, L_deposit_h(dSE)); if (acc0 < 0) return(VOICE); acc0 = L_mult(dSE, 32767); /* Q11*Q15*2 = Q27 */ acc0 = L_mac(acc0, 1024, 30802); /* Q10*Q16*2 = Q27 */ if (acc0 < 0) return(VOICE); /* dSE vs SD */ acc0 = L_mult(SD, -28160); /* Q15*Q5*2 = Q22 */ acc0 = L_mac(acc0, 64, 19988); /* Q6*Q14*2 = Q22 */ acc0 = L_mac(acc0, dSE, 512); /* Q11*Q9*2 = Q22 */ if (acc0 < 0) return(VOICE); acc0 = L_mult(SD, 32767); /* Q15*Q15*2 = Q31 */ acc0 = L_mac(acc0, 32, -30199); /* Q5*Q25*2 = Q31 */ if (acc0 > 0) return(VOICE); /* dSLE vs dSZC */ acc0 = L_mult(dSZC, -20480); /* Q15*Q13*2 = Q29 */ acc0 = L_mac(acc0, 8192, 22938); /* Q13*Q15*2 = Q29 */ acc0 = L_shr(acc0, 2); /* Q29 -> Q27 */ acc0 = L_add(acc0, L_deposit_h(dSE)); if (acc0 < 0) return(VOICE); acc0 = L_mult(dSZC, 23831); /* Q15*Q13*2 = Q29 */ acc0 = L_mac(acc0, 4096, 31576); /* Q12*Q16*2 = Q29 */ acc0 = L_shr(acc0, 2); /* Q29 -> Q27 */ acc0 = L_add(acc0, L_deposit_h(dSE)); if (acc0 < 0) return(VOICE); acc0 = L_mult(dSE, 32767); /* Q11*Q15*2 = Q27 */ acc0 = L_mac(acc0, 2048, 17367); /* Q11*Q15*2 = Q27 */ if (acc0 < 0) return(VOICE); /* dSLE vs SD */ acc0 = L_mult(SD, -22400); /* Q15*Q4*2 = Q20 */ acc0 = L_mac(acc0, 32, 25395); /* Q5*Q14*2 = Q20 */ acc0 = L_mac(acc0, dSLE, 256); /* Q11*Q8*2 = Q20 */ if (acc0 < 0) return(VOICE); /* dSLE vs dSE */ acc0 = L_mult(dSE, -30427); /* Q11*Q15*2 = Q27 */ acc0 = L_mac(acc0, 256, -29959); /* Q8*Q18*2 = Q27 */ acc0 = L_add(acc0, L_deposit_h(dSLE)); if (acc0 > 0) return(VOICE); acc0 = L_mult(dSE, -23406); /* Q11*Q15*2 = Q27 */ acc0 = L_mac(acc0, 512, 28087); /* Q19*Q17*2 = Q27 */ acc0 = L_add(acc0, L_deposit_h(dSLE)); if (acc0 < 0) return(VOICE); acc0 = L_mult(dSE, 24576); /* Q11*Q14*2 = Q26 */ acc0 = L_mac(acc0, 1024, 29491); /* Q10*Q15*2 = Q26 */ acc0 = L_mac(acc0, dSLE, 16384); /* Q11*Q14*2 = Q26 */ if (acc0 < 0) return(VOICE); return (NOISE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -