📄 vad1.c
字号:
/********************************************************************************-------------------------------------------------------------------------**** **** GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 **** R99 Version 3.3.0 **** REL-4 Version 4.1.0 **** ****-------------------------------------------------------------------------********************************************************************************* File : vad1.c* Purpose : Voice Activity Detection (VAD) for AMR (option 1)*******************************************************************************//******************************************************************************* MODULE INCLUDE FILE AND VERSION ID******************************************************************************/#include "vad.h"const char vad1_id[] = "@(#)$Id $" vad_h; /******************************************************************************* INCLUDE FILES******************************************************************************/#include <stdlib.h>#include <stdio.h>#include "typedef.h"#include "basic_op.h"#include "count.h"#include "oper_32b.h"#include "cnst_vad.h"/******************************************************************************* LOCAL VARIABLES AND TABLES******************************************************************************//********************************************************************************** PRIVATE PROGRAM CODE*********************************************************************************//**************************************************************************** * * Function : first_filter_stage * Purpose : Scale input down by one bit. Calculate 5th order * half-band lowpass/highpass filter pair with * decimation. * ***************************************************************************/static void first_filter_stage(Word16 in[], /* i : input signal */ Word16 out[], /* o : output values, every other */ /* output is low-pass part and */ /* other is high-pass part every */ Word16 data[] /* i/o : filter memory */ ){ Word16 temp0, temp1, temp2, temp3, i; Word16 data0, data1; data0 = data[0]; move16 (); data1 = data[1]; move16 (); for (i = 0; i < FRAME_LEN/4; i++) { temp0 = sub(shr(in[4*i+0], 2), mult(COEFF5_1, data0)); temp1 = add(data0, mult(COEFF5_1, temp0)); temp3 = sub(shr(in[4*i+1], 2), mult(COEFF5_2, data1)); temp2 = add(data1, mult(COEFF5_2, temp3)); out[4*i+0] = add(temp1, temp2); move16 (); out[4*i+1] = sub(temp1, temp2); move16 (); data0 = sub(shr(in[4*i+2], 2), mult(COEFF5_1, temp0)); temp1 = add(temp0, mult(COEFF5_1, data0)); data1 = sub(shr(in[4*i+3], 2), mult(COEFF5_2, temp3)); temp2 = add(temp3, mult(COEFF5_2, data1)); out[4*i+2] = add(temp1, temp2); move16 (); out[4*i+3] = sub(temp1, temp2); move16 (); } data[0] = data0; move16 (); data[1] = data1; move16 ();}/**************************************************************************** * * Function : filter5 * Purpose : Fifth-order half-band lowpass/highpass filter pair with * decimation. * ***************************************************************************/static void filter5(Word16 *in0, /* i/o : input values; output low-pass part */ Word16 *in1, /* i/o : input values; output high-pass part */ Word16 data[] /* i/o : updated filter memory */ ){ Word16 temp0, temp1, temp2; temp0 = sub(*in0, mult(COEFF5_1, data[0])); temp1 = add(data[0], mult(COEFF5_1, temp0)); data[0] = temp0; move16 (); temp0 = sub(*in1, mult(COEFF5_2, data[1])); temp2 = add(data[1], mult(COEFF5_2, temp0)); data[1] = temp0; move16 (); *in0 = shr(add(temp1, temp2), 1); move16 (); *in1 = shr(sub(temp1, temp2), 1); move16 ();}/**************************************************************************** * * Function : filter3 * Purpose : Third-order half-band lowpass/highpass filter pair with * decimation. * Return value : * ***************************************************************************/static void filter3(Word16 *in0, /* i/o : input values; output low-pass part */ Word16 *in1, /* i/o : input values; output high-pass part */ Word16 *data /* i/o : updated filter memory */ ){ Word16 temp1, temp2; temp1 = sub(*in1, mult(COEFF3, *data)); temp2 = add(*data, mult(COEFF3, temp1)); *data = temp1; move16 (); *in1 = shr(sub(*in0, temp2), 1); move16 (); *in0 = shr(add(*in0, temp2), 1); move16 ();}/**************************************************************************** * * Function : level_calculation * Purpose : Calculate signal level in a sub-band. Level is calculated * by summing absolute values of the input data. * Return value : signal level * ***************************************************************************/static Word16 level_calculation( Word16 data[], /* i : signal buffer */ Word16 *sub_level, /* i : level calculate at the end of the previous frame */ /* o : level of signal calculated from the last */ /* (count2 - count1) samples */ Word16 count1, /* i : number of samples to be counted */ Word16 count2, /* i : number of samples to be counted */ Word16 ind_m, /* i : step size for the index of the data buffer */ Word16 ind_a, /* i : starting index of the data buffer */ Word16 scale /* i : scaling for the level calculation */ ){ Word32 l_temp1, l_temp2; Word16 level, i; l_temp1 = 0L; move32 (); for (i = count1; i < count2; i++) { l_temp1 = L_mac(l_temp1, 1, abs_s(data[ind_m*i+ind_a])); } l_temp2 = L_add(l_temp1, L_shl(*sub_level, sub(16, scale))); *sub_level = extract_h(L_shl(l_temp1, scale)); for (i = 0; i < count1; i++) { l_temp2 = L_mac(l_temp2, 1, abs_s(data[ind_m*i+ind_a])); } level = extract_h(L_shl(l_temp2, scale)); return level;}/**************************************************************************** * * Function : filter_bank * Purpose : Divides input signal into 9-bands and calculas level of * the signal in each band * ***************************************************************************/static void filter_bank(vadState1 *st, /* i/o : State struct */ Word16 in[], /* i : input frame */ Word16 level[] /* 0 : signal levels at each band */ ){ Word16 i; Word16 tmp_buf[FRAME_LEN]; /* calculate the filter bank */ first_filter_stage(in, tmp_buf, st->a_data5[0]); for (i = 0; i < FRAME_LEN/4; i++) { filter5(&tmp_buf[4*i], &tmp_buf[4*i+2], st->a_data5[1]); filter5(&tmp_buf[4*i+1], &tmp_buf[4*i+3], st->a_data5[2]); } for (i = 0; i < FRAME_LEN/8; i++) { filter3(&tmp_buf[8*i+0], &tmp_buf[8*i+4], &st->a_data3[0]); filter3(&tmp_buf[8*i+2], &tmp_buf[8*i+6], &st->a_data3[1]); filter3(&tmp_buf[8*i+3], &tmp_buf[8*i+7], &st->a_data3[4]); } for (i = 0; i < FRAME_LEN/16; i++) { filter3(&tmp_buf[16*i+0], &tmp_buf[16*i+8], &st->a_data3[2]); filter3(&tmp_buf[16*i+4], &tmp_buf[16*i+12], &st->a_data3[3]); } /* calculate levels in each frequency band */ /* 3000 - 4000 Hz*/ level[8] = level_calculation(tmp_buf, &st->sub_level[8], FRAME_LEN/4-8, FRAME_LEN/4, 4, 1, 15); move16 (); /* 2500 - 3000 Hz*/ level[7] = level_calculation(tmp_buf, &st->sub_level[7], FRAME_LEN/8-4, FRAME_LEN/8, 8, 7, 16); move16 (); /* 2000 - 2500 Hz*/ level[6] = level_calculation(tmp_buf, &st->sub_level[6], FRAME_LEN/8-4, FRAME_LEN/8, 8, 3, 16); move16 (); /* 1500 - 2000 Hz*/ level[5] = level_calculation(tmp_buf, &st->sub_level[5], FRAME_LEN/8-4, FRAME_LEN/8, 8, 2, 16); move16 (); /* 1000 - 1500 Hz*/ level[4] = level_calculation(tmp_buf, &st->sub_level[4], FRAME_LEN/8-4, FRAME_LEN/8, 8, 6, 16); move16 (); /* 750 - 1000 Hz*/ level[3] = level_calculation(tmp_buf, &st->sub_level[3], FRAME_LEN/16-2, FRAME_LEN/16, 16, 4, 16); move16 (); /* 500 - 750 Hz*/ level[2] = level_calculation(tmp_buf, &st->sub_level[2], FRAME_LEN/16-2, FRAME_LEN/16, 16, 12, 16); move16 (); /* 250 - 500 Hz*/ level[1] = level_calculation(tmp_buf, &st->sub_level[1], FRAME_LEN/16-2, FRAME_LEN/16, 16, 8, 16); move16 (); /* 0 - 250 Hz*/ level[0] = level_calculation(tmp_buf, &st->sub_level[0], FRAME_LEN/16-2, FRAME_LEN/16, 16, 0, 16); move16 ();}/**************************************************************************** * * Function : update_cntrl * Purpose : Control update of the background noise estimate. * Inputs : pitch: flags for pitch detection * stat_count: stationary counter * tone: flags indicating presence of a tone * complex: flags for complex detection * vadreg: intermediate VAD flags * Output : stat_count: stationary counter * ***************************************************************************/static void update_cntrl(vadState1 *st, /* i/o : State struct */ Word16 level[] /* i : sub-band levels of the input frame */ ){ Word16 i, temp, stat_rat, exp; Word16 num, denom; Word16 alpha; /* handle highband complex signal input separately */ /* if ther has been highband correlation for some time */ /* make sure that the VAD update speed is low for a while */ test (); if (st->complex_warning != 0) { test (); if (sub(st->stat_count, CAD_MIN_STAT_COUNT) < 0) { st->stat_count = CAD_MIN_STAT_COUNT; move16 (); } } /* NB stat_count is allowed to be decreased by one below again */ /* deadlock in speech is not possible unless the signal is very */ /* complex and need a high rate */ /* if fullband pitch or tone have been detected for a while, initialize stat_count */ logic16 (); test (); logic16 (); test (); if ((sub((st->pitch & 0x6000), 0x6000) == 0) || (sub((st->tone & 0x7c00), 0x7c00) == 0)) { st->stat_count = STAT_COUNT; move16 (); } else { /* if 8 last vad-decisions have been "0", reinitialize stat_count */ logic16 (); test (); if ((st->vadreg & 0x7f80) == 0) { st->stat_count = STAT_COUNT; move16 (); } else { stat_rat = 0; move16 (); for (i = 0; i < COMPLEN; i++) { test (); if (sub(level[i], st->ave_level[i]) > 0) { num = level[i]; move16 (); denom = st->ave_level[i]; move16 (); } else { num = st->ave_level[i]; move16 (); denom = level[i]; move16 (); } /* Limit nimimum value of num and denom to STAT_THR_LEVEL */ test (); if (sub(num, STAT_THR_LEVEL) < 0) { num = STAT_THR_LEVEL; move16 (); } test (); if (sub(denom, STAT_THR_LEVEL) < 0) { denom = STAT_THR_LEVEL; move16 (); } exp = norm_s(denom); denom = shl(denom, exp); /* stat_rat = num/denom * 64 */ temp = div_s(shr(num, 1), denom); stat_rat = add(stat_rat, shr(temp, sub(8, exp))); } /* compare stat_rat with a threshold and update stat_count */ test (); if (sub(stat_rat, STAT_THR) > 0) { st->stat_count = STAT_COUNT; move16 (); } else { logic16 ();test ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -