📄 vad1.c
字号:
* * Function : complex_estimate_adapt * Purpose : Update/adapt of complex signal estimate * Inputs : low_power: low signal power flag * Outputs : st->corr_hp_fast: long term complex signal estimate * ***************************************************************************/static void complex_estimate_adapt(vadState1 *st, Word16 low_power )
{
Word16 alpha; /* Q15 */ Word32 L_tmp; /* Q31 */ /* adapt speed on own state */
if ( st->best_corr_hp < st->corr_hp_fast ) /* decrease */ { alpha = st->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH ? CVAD_ADAPT_FAST : CVAD_ADAPT_REALLY_FAST; } else /* increase */ { alpha = st->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH ? CVAD_ADAPT_FAST : CVAD_ADAPT_SLOW; } L_tmp = (st->corr_hp_fast <<16 ); L_tmp = L_tmp - (alpha*st->corr_hp_fast<<1 ); L_tmp += alpha*st->best_corr_hp <<1; st->corr_hp_fast = (Word16)(( L_tmp > 0 ) && (L_tmp + 0x00008000L)<0 ? 0x7ffff: (L_tmp + 0x00008000L)>>16); /* Q15 */ st->corr_hp_fast = st->corr_hp_fast <CVAD_MIN_CORR ? CVAD_MIN_CORR : st->corr_hp_fast ; st->corr_hp_fast = low_power != 0 ? CVAD_MIN_CORR :st->corr_hp_fast ;
}
/**************************************************************************** * * Function : vad_decision * Purpose : Calculates VAD_flag * Inputs : bckr_est: background noise estimate * vadreg: intermediate VAD flags
* Outputs : noise_level: average level of the noise estimates * vadreg: intermediate VAD flags
* Return value : VAD_flag * ***************************************************************************/static Word16 vad_decision( vadState1 *st, Word16 level[COMPLEN], Word32 pow_sum )
{
Word16 i; Word16 snr_sum, alpha; Word32 L_temp,L_temp1;
Word16 vad_thr, temp, noise_level; Word16 low_power_flag; Word16 hang_len, burst_len;
vadState1 *pst = st;
Word16*plevel = level;
/*
Calculate squared sum of the input levels (level)
divided by the background noise components (bckr_est).
*/
L_temp = 0;
for (i = 0; i < COMPLEN; i++)
{
Word16 exp;
exp = norm_s(pst->bckr_est[i]);
temp = (pst->bckr_est[i]<<exp);
temp = div_s((plevel[i]>> 1), temp);
temp = exp>5? temp<<(exp-5): temp>> (5-exp);
L_temp += temp*temp <<1;
if(L_temp < 0)
{
L_temp = MAX_32;
break;
}
}
L_temp = L_temp > 0x01ffffff ? MAX_32 : L_temp << 6;
snr_sum = (Word16)(L_temp >> 16);
snr_sum = (snr_sum* INV_COMPLEN)>>15;
L_temp1 = pst->bckr_est[0] + pst->bckr_est[1] + pst->bckr_est[2] + pst->bckr_est[3]+ pst->bckr_est[4];
L_temp = pst->bckr_est[5] + pst->bckr_est[6] + pst->bckr_est[7] + pst->bckr_est[8];
L_temp += L_temp1;
L_temp = L_temp > 0x0003ffff ? MAX_32 : L_temp << 13;
noise_level =(Word16)( L_temp >> 16);
/* Calculate VAD threshold */
vad_thr = (VAD_SLOPE * (noise_level-VAD_P1)>>15) + VAD_THR_HIGH;
vad_thr = (vad_thr < VAD_THR_LOW) ? VAD_THR_LOW : vad_thr;
/* Shift VAD decision register */
pst->vadreg >>= 1;
/* Make intermediate VAD decision */
pst->vadreg = (snr_sum > vad_thr ) ? pst->vadreg | 0x4000: pst->vadreg ;
/* primary vad decsion made */
/* check if the input power (pow_sum) is lower than a threshold" */
low_power_flag = (pow_sum<VAD_POW_LOW ) ? 1 : 0;
/* update complex signal estimate st->corr_hp_fast and hangover reset timer using */ /* low_power_flag and corr_hp_fast and various adaptation speeds */ //complex_estimate_adapt(st, low_power_flag); /* adapt speed on own state */ if ( pst->best_corr_hp < pst->corr_hp_fast ) /* decrease */
{ alpha = pst->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH ? CVAD_ADAPT_FAST : CVAD_ADAPT_REALLY_FAST;
} else /* increase */ { alpha = pst->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH ? CVAD_ADAPT_FAST : CVAD_ADAPT_SLOW;
} L_temp = (pst->corr_hp_fast <<16 );
L_temp = L_temp - (alpha*pst->corr_hp_fast<<1 );
L_temp += alpha*pst->best_corr_hp <<1;
pst->corr_hp_fast = (Word16)(( L_temp > 0 ) && (L_temp + 0x00008000L)<0 ? 0x7ffff: (L_temp + 0x00008000L)>>16); /* Q15 */
pst->corr_hp_fast = pst->corr_hp_fast <CVAD_MIN_CORR ? CVAD_MIN_CORR : pst->corr_hp_fast ;
pst->corr_hp_fast = low_power_flag != 0 ? CVAD_MIN_CORR :st->corr_hp_fast ;
/* check multiple thresholds of the st->corr_hp_fast value */ // st->complex_warning = complex_vad(st, low_power_flag); pst->complex_high >>= 1;
pst->complex_low >>= 1;
pst->complex_high = (low_power_flag == 0)&&(pst->corr_hp_fast > CVAD_THRESH_ADAPT_HIGH) ? pst->complex_high | 0x4000 : pst->complex_high ;
pst->complex_low = (low_power_flag == 0)&&(pst->corr_hp_fast > CVAD_THRESH_ADAPT_LOW) ? pst->complex_low | 0x4000 : pst->complex_low ;
pst->complex_hang_timer = pst->corr_hp_fast > CVAD_THRESH_HANG ? pst->complex_hang_timer + 1 :0;
pst->complex_warning = ( ((pst->complex_high & 0x7f80) ==0x7f80) ||((pst->complex_low & 0x7fff) ==0x7fff) );
/* Update speech subband vad background noise estimates */ noise_estimate_update(pst, plevel);
/* Add speech and complex hangover and return speech VAD_flag */ /* long term complex hangover may be added */ // st->speech_vad_decision = hangover_addition(st, noise_level, low_power_flag);
pst->speech_vad_decision = 0;
burst_len = (noise_level > HANG_NOISE_THR) ? BURST_LEN_HIGH_NOISE :BURST_LEN_LOW_NOISE; hang_len = (noise_level > HANG_NOISE_THR) ? HANG_LEN_HIGH_NOISE :HANG_LEN_LOW_NOISE; /* if the input power (pow_sum) is lower than a threshold, clear counters and set VAD_flag to "0" "fast exit" */ if (low_power_flag != 0) { pst->burst_count = 0;
pst->hang_count = 0;
pst->complex_hang_count = 0;
pst->complex_hang_timer = 0;
pst->speech_vad_decision = 0;
} pst->complex_hang_count = (pst->complex_hang_timer >CVAD_HANG_LIMIT) &&( pst->complex_hang_count < CVAD_HANG_LENGTH) ? CVAD_HANG_LENGTH : st->complex_hang_count ;
/* long time very complex signal override VAD output function */ if (pst->complex_hang_count != 0)
{ pst->burst_count = BURST_LEN_HIGH_NOISE;
pst->complex_hang_count --;
pst->speech_vad_decision = 1;
} else { /* let hp_corr work in from a noise_period indicated by the VAD */ if (((pst->vadreg & 0x3ff0) == 0) && (pst->corr_hp_fast > CVAD_THRESH_IN_NOISE) )
{ pst->speech_vad_decision = 1;
} } /* update the counters (hang_count, burst_count) */ if ((pst->vadreg & 0x4000) != 0)
{ pst->burst_count ++;
pst->hang_count = pst->burst_count >= burst_len? hang_len : pst->hang_count;
pst->speech_vad_decision = 1;
} else { pst->burst_count = 0;
pst->speech_vad_decision = pst->hang_count > 0 ? 1 :st->speech_vad_decision ;
pst->hang_count = pst->hang_count > 0 ? pst->hang_count -1 : pst->hang_count;
} return (pst->speech_vad_decision);
}
int vad1_init (vadState1 **state){
vadState1* pvadState1;
if (state == (vadState1 **) NULL)
{
fprintf(stderr, "vad_init: invalid parameter\n");
return -1;
}
*state = NULL;
/* allocate memory */
if ((pvadState1 = (vadState1 *) malloc(sizeof(vadState1))) == NULL)
{
fprintf(stderr, "vad_init: can not malloc state structure\n");
return -1;
}
//vad1_reset(pvadState1);
/* Initialize pitch detection variables */
pvadState1->oldlag_count = 0;
pvadState1->oldlag = 0;
pvadState1->pitch = 0;
pvadState1->tone = 0;
pvadState1->complex_high = 0;
pvadState1->complex_low = 0;
pvadState1->complex_hang_timer = 0;
pvadState1->vadreg = 0;
pvadState1->stat_count = 0;
pvadState1->burst_count = 0;
pvadState1->hang_count = 0;
pvadState1->complex_hang_count = 0;
/* initialize memory used by the filter bank */ memset(&pvadState1->a_data5[0][0], 0, 6*sizeof(Word16));
memset(&pvadState1->a_data3[0], 0, 5*sizeof(Word16));
memset(&pvadState1->bckr_est[0], NOISE_INIT, COMPLEN*sizeof(Word16));
memset(&pvadState1->old_level[0], NOISE_INIT, COMPLEN*sizeof(Word16));
memset(&pvadState1->old_level[0], NOISE_INIT, COMPLEN*sizeof(Word16));
memset(&pvadState1->sub_level[0], 0, COMPLEN*sizeof(Word16));
pvadState1->best_corr_hp = CVAD_LOWPOW_RESET;
pvadState1->speech_vad_decision = 0;
pvadState1->complex_warning = 0;
pvadState1->sp_burst_count = 0;
pvadState1->corr_hp_fast = CVAD_LOWPOW_RESET;
*state = pvadState1;
return 0;}
void vad1_exit (vadState1 **state){ if (state == NULL || *state == NULL) return; /* deallocate memory */ free(*state); *state = NULL; return;}
/****************************************************************************
Function : vad1
Purpose : Main program for Voice Activity Detection (VAD) for AMR
Return value : VAD Decision, 1 = speech, 0 = noise
Input:
st : State struct
in_buf[] : samples of the input frame
Output :
st : State struct
***************************************************************************/
Word16 vad1(vadState1 *st, Word16 in_buf[] )
{
Word16 level[COMPLEN]; Word32 pow_sum, sum1; Word16 i,temp1, temp2, temp3,temp4; Word16* pInBuf; pInBuf = in_buf; /* Calculate power of the input frame. */ pow_sum = 0L; for (i = 0; i < FRAME_LEN; i+=4 ) { temp1 = pInBuf[i-LOOKAHEAD]; temp2 = pInBuf[i-LOOKAHEAD+1]; temp3 = pInBuf[i-LOOKAHEAD+2]; temp4 = pInBuf[i-LOOKAHEAD+3]; sum1 = temp1*temp1 + temp2*temp2 + temp3*temp3 + temp4*temp4; pow_sum += sum1 <<1 ; if (pow_sum < 0) { pow_sum = MAX_32; break; } } /* If input power is very low, clear pitch flag of the current frame */ st->pitch = pow_sum < POW_PITCH_THR ? st->pitch & 0x3fff : st->pitch ; /* If input power is very low, clear complex flag of the "current" frame */ st->complex_low = pow_sum < POW_COMPLEX_THR ? st->complex_low & 0x3fff : st->complex_low ; /* Run the filter bank which calculates signal levels at each band */ filter_bank(st, in_buf, level); return (vad_decision(st, level, pow_sum));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -