123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071 |
- /*
- *****************************************************************************
- **-------------------------------------------------------------------------**
- ** **
- ** 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_ex(shr_ex(in[4*i+0], 2), mult_ex(COEFF5_1, data0));
- temp1 = add_ex(data0, mult_ex(COEFF5_1, temp0));
-
- temp3 = sub_ex(shr_ex(in[4*i+1], 2), mult_ex(COEFF5_2, data1));
- temp2 = add_ex(data1, mult_ex(COEFF5_2, temp3));
-
- out[4*i+0] = add_ex(temp1, temp2); move16 ();
- out[4*i+1] = sub_ex(temp1, temp2); move16 ();
-
- data0 = sub_ex(shr_ex(in[4*i+2], 2), mult_ex(COEFF5_1, temp0));
- temp1 = add_ex(temp0, mult_ex(COEFF5_1, data0));
-
- data1 = sub_ex(shr_ex(in[4*i+3], 2), mult_ex(COEFF5_2, temp3));
- temp2 = add_ex(temp3, mult_ex(COEFF5_2, data1));
-
- out[4*i+2] = add_ex(temp1, temp2); move16 ();
- out[4*i+3] = sub_ex(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_ex(*in0, mult_ex(COEFF5_1, data[0]));
- temp1 = add_ex(data[0], mult_ex(COEFF5_1, temp0));
- data[0] = temp0; move16 ();
- temp0 = sub_ex(*in1, mult_ex(COEFF5_2, data[1]));
- temp2 = add_ex(data[1], mult_ex(COEFF5_2, temp0));
- data[1] = temp0; move16 ();
- *in0 = shr_ex(add_ex(temp1, temp2), 1); move16 ();
- *in1 = shr_ex(sub_ex(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_ex(*in1, mult_ex(COEFF3, *data));
- temp2 = add_ex(*data, mult_ex(COEFF3, temp1));
- *data = temp1; move16 ();
- *in1 = shr_ex(sub_ex(*in0, temp2), 1); move16 ();
- *in0 = shr_ex(add_ex(*in0, temp2), 1); move16 ();
- }
- /****************************************************************************
- *
- * Function : level_calculation
- * Purpose : Calculate signal level in a sub_ex-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_ex(l_temp1, 1, abs_s_ex(data[ind_m*i+ind_a]));
- }
-
- l_temp2 = L_add_ex(l_temp1, L_shl_ex(*sub_level, sub_ex(16, scale)));
- *sub_level = extract_h_ex(L_shl_ex(l_temp1, scale));
-
- for (i = 0; i < count1; i++)
- {
- l_temp2 = L_mac_ex(l_temp2, 1, abs_s_ex(data[ind_m*i+ind_a]));
- }
- level = extract_h_ex(L_shl_ex(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_ex-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_ex(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_ex((st->pitch & 0x6000), 0x6000) == 0) ||
- (sub_ex((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_ex(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_ex(num, STAT_THR_LEVEL) < 0)
- {
- num = STAT_THR_LEVEL; move16 ();
- }
- test ();
- if (sub_ex(denom, STAT_THR_LEVEL) < 0)
- {
- denom = STAT_THR_LEVEL; move16 ();
- }
-
- exp = norm_s_ex(denom);
- denom = shl_ex(denom, exp);
-
- /* stat_rat = num/denom * 64 */
- temp = div_s(shr_ex(num, 1), denom);
- stat_rat = add_ex(stat_rat, shr_ex(temp, sub_ex(8, exp)));
- }
-
- /* compare stat_rat with a threshold and update stat_count */
- test ();
- if (sub_ex(stat_rat, STAT_THR) > 0)
- {
- st->stat_count = STAT_COUNT; move16 ();
- }
- else
- {
- logic16 ();test ();
- if ((st->vadreg & 0x4000) != 0)
- {
- test ();
- if (st->stat_count != 0)
- {
- st->stat_count = sub_ex(st->stat_count, 1); move16 ();
- }
- }
- }
- }
- }
-
- /* Update average amplitude estimate for stationarity estimation */
- alpha = ALPHA4; move16 ();
- test ();
- if (sub_ex(st->stat_count, STAT_COUNT) == 0)
- {
- alpha = 32767; move16 ();
- }
- else if ((st->vadreg & 0x4000) == 0)
- {
- logic16 (); test ();
- alpha = ALPHA5; move16 ();
- }
-
- for (i = 0; i < COMPLEN; i++)
- {
- st->ave_level[i] = add_ex(st->ave_level[i],
- mult_r_ex(alpha, sub_ex(level[i], st->ave_level[i])));
- move16 ();
- }
- }
- /****************************************************************************
- *
- * Function : hangover_addition
- * Purpose : Add hangover for complex signal or after speech bursts
- * Inputs : burst_count: counter for the length of speech bursts
- * hang_count: hangover counter
- * vadreg: intermediate VAD decision
- * Outputs : burst_count: counter for the length of speech bursts
- * hang_count: hangover counter
- * Return value : VAD_flag indicating final VAD decision
- *
- ***************************************************************************/
- static Word16 hangover_addition(
- vadState1 *st, /* i/o : State struct */
- Word16 noise_level, /* i : average level of the noise */
- /* estimates */
- Word16 low_power /* i : flag power of the input frame */
- )
- {
- Word16 hang_len, burst_len;
-
- /*
- Calculate burst_len and hang_len
- burst_len: number of consecutive intermediate vad flags with "1"-decision
- required for hangover addition
- hang_len: length of the hangover
- */
- test ();
- if (sub_ex(noise_level, HANG_NOISE_THR) > 0)
- {
- burst_len = BURST_LEN_HIGH_NOISE; move16 ();
- hang_len = HANG_LEN_HIGH_NOISE; move16 ();
- }
- else
- {
- burst_len = BURST_LEN_LOW_NOISE; move16 ();
- hang_len = HANG_LEN_LOW_NOISE; move16 ();
- }
-
- /* if the input power (pow_sum) is lower than a threshold, clear
- counters and set VAD_flag to "0" "fast exit" */
- test ();
- if (low_power != 0)
- {
- st->burst_count = 0; move16 ();
- st->hang_count = 0; move16 ();
- st->complex_hang_count = 0; move16 ();
- st->complex_hang_timer = 0; move16 ();
- return 0;
- }
-
- test ();
- if (sub_ex(st->complex_hang_timer, CVAD_HANG_LIMIT) > 0)
- {
- test ();
- if (sub_ex(st->complex_hang_count, CVAD_HANG_LENGTH) < 0)
- {
- st->complex_hang_count = CVAD_HANG_LENGTH; move16 ();
- }
- }
-
- /* long time very complex signal override VAD output function */
- test ();
- if (st->complex_hang_count != 0)
- {
- st->burst_count = BURST_LEN_HIGH_NOISE; move16 ();
- st->complex_hang_count = sub_ex(st->complex_hang_count, 1); move16 ();
- return 1;
- }
- else
- {
- /* let hp_corr work in from a noise_period indicated by the VAD */
- test (); test (); logic16 ();
- if (((st->vadreg & 0x3ff0) == 0) &&
- (sub_ex(st->corr_hp_fast, CVAD_THRESH_IN_NOISE) > 0))
- {
- return 1;
- }
- }
- /* update the counters (hang_count, burst_count) */
- logic16 (); test ();
- if ((st->vadreg & 0x4000) != 0)
- {
- st->burst_count = add_ex(st->burst_count, 1); move16 ();
- test ();
- if (sub_ex(st->burst_count, burst_len) >= 0)
- {
- st->hang_count = hang_len; move16 ();
- }
- return 1;
- }
- else
- {
- st->burst_count = 0; move16 ();
- test ();
- if (st->hang_count > 0)
- {
- st->hang_count = sub_ex(st->hang_count, 1); move16 ();
- return 1;
- }
- }
- return 0;
- }
- /****************************************************************************
- *
- * Function : noise_estimate_update
- * Purpose : Update of background noise estimate
- * Inputs : bckr_est: background noise estimate
- * pitch: flags for pitch detection
- * stat_count: stationary counter
- * Outputs : bckr_est: background noise estimate
- *
- ***************************************************************************/
- static void noise_estimate_update(
- vadState1 *st, /* i/o : State struct */
- Word16 level[] /* i : sub_ex-band levels of the input frame */
- )
- {
- Word16 i, alpha_up, alpha_down, bckr_add;
-
- /* Control update of bckr_est[] */
- update_cntrl(st, level);
-
- /* Choose update speed */
- bckr_add = 2; move16 ();
-
- logic16 (); test (); logic16 (); test (); test ();
- if (((0x7800 & st->vadreg) == 0) &&
- ((st->pitch & 0x7800) == 0)
- && (st->complex_hang_count == 0))
- {
- alpha_up = ALPHA_UP1; move16 ();
- alpha_down = ALPHA_DOWN1; move16 ();
- }
- else
- {
- test (); test ();
- if ((st->stat_count == 0)
- && (st->complex_hang_count == 0))
- {
- alpha_up = ALPHA_UP2; move16 ();
- alpha_down = ALPHA_DOWN2; move16 ();
- }
- else
- {
- alpha_up = 0; move16 ();
- alpha_down = ALPHA3; move16 ();
- bckr_add = 0; move16 ();
- }
- }
-
- /* Update noise estimate (bckr_est) */
- for (i = 0; i < COMPLEN; i++)
- {
- Word16 temp;
- temp = sub_ex(st->old_level[i], st->bckr_est[i]);
-
- test ();
- if (temp < 0)
- { /* update downwards*/
- st->bckr_est[i] = add_ex(-2, add_ex(st->bckr_est[i], mult_r_ex(alpha_down, temp)));
- move16 ();
-
- /* limit minimum value of the noise estimate to NOISE_MIN */
- test ();
- if (sub_ex(st->bckr_est[i], NOISE_MIN) < 0)
- {
- st->bckr_est[i] = NOISE_MIN; move16 ();
- }
- }
- else
- { /* update upwards */
- st->bckr_est[i] = add_ex(bckr_add, add_ex(st->bckr_est[i], mult_r_ex(alpha_up, temp)));
- move16 ();
-
- /* limit maximum value of the noise estimate to NOISE_MAX */
- test ();
- if (sub_ex(st->bckr_est[i], NOISE_MAX) > 0)
- {
- st->bckr_est[i] = NOISE_MAX; move16 ();
- }
- }
- }
-
- /* Update signal levels of the previous frame (old_level) */
- for(i = 0; i < COMPLEN; i++)
- {
- st->old_level[i] = level[i]; move16 ();
- }
- }
- /****************************************************************************
- *
- * 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, /* i/o : VAD state struct */
- Word16 low_power /* i : very low level flag of the input frame */
- )
- {
- Word16 alpha; /* Q15 */
- Word32 L_tmp; /* Q31 */
- /* adapt speed on own state */
- test ();
- if (sub_ex(st->best_corr_hp, st->corr_hp_fast) < 0) /* decrease */
- {
- test ();
- if (sub_ex(st->corr_hp_fast, CVAD_THRESH_ADAPT_HIGH) < 0)
- { /* low state */
- alpha = CVAD_ADAPT_FAST; move16();
- }
- else
- { /* high state */
- alpha = CVAD_ADAPT_REALLY_FAST; move16();
- }
- }
- else /* increase */
- {
- test ();
- if (sub_ex(st->corr_hp_fast, CVAD_THRESH_ADAPT_HIGH) < 0)
- {
- alpha = CVAD_ADAPT_FAST; move16();
- }
- else
- {
- alpha = CVAD_ADAPT_SLOW; move16();
- }
- }
- L_tmp = L_deposit_h_ex(st->corr_hp_fast);
- L_tmp = L_msu_ex(L_tmp, alpha, st->corr_hp_fast);
- L_tmp = L_mac_ex(L_tmp, alpha, st->best_corr_hp);
- st->corr_hp_fast = round_ex(L_tmp); /* Q15 */ move16();
- test ();
- if (sub_ex(st->corr_hp_fast, CVAD_MIN_CORR) < 0)
- {
- st->corr_hp_fast = CVAD_MIN_CORR; move16();
- }
- test ();
- if (low_power != 0)
- {
- st->corr_hp_fast = CVAD_MIN_CORR; move16();
- }
- }
- /****************************************************************************
- *
- * Function : complex_vad
- * Purpose : complex background decision
- * Return value : the complex background decision
- *
- ***************************************************************************/
- static Word16 complex_vad(vadState1 *st, /* i/o : VAD state struct */
- Word16 low_power /* i : flag power of the input frame */
- )
- {
- st->complex_high = shr_ex(st->complex_high, 1); move16 ();
- st->complex_low = shr_ex(st->complex_low, 1); move16 ();
- test ();
- if (low_power == 0)
- {
- test ();
- if (sub_ex(st->corr_hp_fast, CVAD_THRESH_ADAPT_HIGH) > 0)
- {
- st->complex_high = st->complex_high | 0x4000; logic16 (); move16 ();
- }
-
- test ();
- if (sub_ex(st->corr_hp_fast, CVAD_THRESH_ADAPT_LOW) > 0 )
- {
- st->complex_low = st->complex_low | 0x4000; logic16 (); move16 ();
- }
- }
- test ();
- if (sub_ex(st->corr_hp_fast, CVAD_THRESH_HANG) > 0)
- {
- st->complex_hang_timer = add_ex(st->complex_hang_timer, 1); move16 ();
- }
- else
- {
- st->complex_hang_timer = 0; move16 ();
- }
-
- test (); logic16 (); test (); logic16 ();
- return ((sub_ex((st->complex_high & 0x7f80), 0x7f80) == 0) ||
- (sub_ex((st->complex_low & 0x7fff), 0x7fff) == 0));
- }
- /****************************************************************************
- *
- * 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, /* i/o : State struct */
- Word16 level[COMPLEN], /* i : sub_ex-band levels of the input frame */
- Word32 pow_sum /* i : power of the input frame */
- )
- {
- Word16 i;
- Word16 snr_sum;
- Word32 L_temp;
- Word16 vad_thr, temp, noise_level;
- Word16 low_power_flag;
-
- /*
- Calculate squared sum of the input levels (level)
- divided by the background noise components (bckr_est).
- */
- L_temp = 0; move32();
- for (i = 0; i < COMPLEN; i++)
- {
- Word16 exp;
-
- exp = norm_s_ex(st->bckr_est[i]);
- temp = shl_ex(st->bckr_est[i], exp);
- temp = div_s(shr_ex(level[i], 1), temp);
- temp = shl_ex(temp, sub_ex(exp, UNIRSHFT-1));
- L_temp = L_mac_ex(L_temp, temp, temp);
- }
- snr_sum = extract_h_ex(L_shl_ex(L_temp, 6));
- snr_sum = mult_ex(snr_sum, INV_COMPLEN);
- /* Calculate average level of estimated background noise */
- L_temp = 0; move32();
- for (i = 0; i < COMPLEN; i++)
- {
- L_temp = L_add_ex(L_temp, st->bckr_est[i]);
- }
-
- noise_level = extract_h_ex(L_shl_ex(L_temp, 13));
-
- /* Calculate VAD threshold */
- vad_thr = add_ex(mult_ex(VAD_SLOPE, sub_ex(noise_level, VAD_P1)), VAD_THR_HIGH);
-
- test ();
- if (sub_ex(vad_thr, VAD_THR_LOW) < 0)
- {
- vad_thr = VAD_THR_LOW; move16 ();
- }
-
- /* Shift VAD decision register */
- st->vadreg = shr_ex(st->vadreg, 1); move16 ();
-
- /* Make intermediate VAD decision */
- test ();
- if (sub_ex(snr_sum, vad_thr) > 0)
- {
- st->vadreg = st->vadreg | 0x4000; logic16 (); move16 ();
- }
- /* primary vad decsion made */
-
- /* check if the input power (pow_sum) is lower than a threshold" */
- test ();
- if (L_sub_ex(pow_sum, VAD_POW_LOW) < 0)
- {
- low_power_flag = 1; move16 ();
- }
- else
- {
- low_power_flag = 0; move16 ();
- }
-
- /* 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);
- /* check multiple thresholds of the st->corr_hp_fast value */
- st->complex_warning = complex_vad(st, low_power_flag); move16();
- /* Update speech subband vad background noise estimates */
- noise_estimate_update(st, level);
-
- /* 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);
- move16 ();
-
- return (st->speech_vad_decision);
- }
- /*
- *****************************************************************************
- * PUBLIC PROGRAM CODE
- *****************************************************************************
- */
- /*************************************************************************
- *
- * Function: vad1_init
- * Purpose: Allocates state memory and initializes state memory
- *
- **************************************************************************
- */
- int vad1_init (vadState1 **state)
- {
- vadState1* s;
-
- if (state == (vadState1 **) NULL){
- wfprintf(stderr, "vad_init: invalid parameter\n");
- return -1;
- }
- *state = NULL;
-
- /* allocate memory */
- if ((s = (vadState1 *) wmalloc(sizeof(vadState1))) == NULL){
- wfprintf(stderr, "vad_init: can not malloc state structure\n");
- return -1;
- }
-
- vad1_reset(s);
-
- *state = s;
-
- return 0;
- }
-
- /*************************************************************************
- *
- * Function: vad1_reset
- * Purpose: Initializes state memory to zero
- *
- **************************************************************************
- */
- int vad1_reset (vadState1 *state)
- {
- Word16 i, j;
-
- if (state == (vadState1 *) NULL){
- wfprintf(stderr, "vad_reset: invalid parameter\n");
- return -1;
- }
-
- /* Initialize pitch detection variables */
- state->oldlag_count = 0;
- state->oldlag = 0;
- state->pitch = 0;
- state->tone = 0;
- state->complex_high = 0;
- state->complex_low = 0;
- state->complex_hang_timer = 0;
- state->vadreg = 0;
- state->stat_count = 0;
- state->burst_count = 0;
- state->hang_count = 0;
- state->complex_hang_count = 0;
-
- /* initialize memory used by the filter bank */
- for (i = 0; i < 3; i++)
- {
- for (j = 0; j < 2; j++)
- {
- state->a_data5[i][j] = 0;
- }
- }
-
- for (i = 0; i < 5; i++)
- {
- state->a_data3[i] = 0;
- }
-
- /* initialize the rest of the memory */
- for (i = 0; i < COMPLEN; i++)
- {
- state->bckr_est[i] = NOISE_INIT;
- state->old_level[i] = NOISE_INIT;
- state->ave_level[i] = NOISE_INIT;
- state->sub_level[i] = 0;
- }
-
- state->best_corr_hp = CVAD_LOWPOW_RESET;
- state->speech_vad_decision = 0;
- state->complex_warning = 0;
- state->sp_burst_count = 0;
- state->corr_hp_fast = CVAD_LOWPOW_RESET;
-
- return 0;
- }
- /*************************************************************************
- *
- * Function: vad1_exit
- * Purpose: The memory used for state memory is freed
- *
- **************************************************************************
- */
- void vad1_exit (vadState1 **state)
- {
- if (state == NULL || *state == NULL)
- return;
-
- /* deallocate memory */
- wfree(*state);
- *state = NULL;
-
- return;
- }
- /****************************************************************************
- *
- * Function : vad_complex_detection_update
- * Purpose : update vad->bestCorr_hp complex signal feature state
- *
- ***************************************************************************/
- void vad_complex_detection_update (vadState1 *st, /* i/o : State struct */
- Word16 best_corr_hp /* i : best Corr */
- )
- {
- st->best_corr_hp = best_corr_hp; move16();
- }
- /****************************************************************************
- *
- * Function : vad_tone_detection
- * Purpose : Set tone flag if pitch gain is high. This is used to detect
- * signaling tones and other signals with high pitch gain.
- * Inputs : tone: flags indicating presence of a tone
- * Outputs : tone: flags indicating presence of a tone
- *
- ***************************************************************************/
- void vad_tone_detection (vadState1 *st, /* i/o : State struct */
- Word32 t0, /* i : autocorrelation maxima */
- Word32 t1 /* i : energy */
- )
- {
- Word16 temp;
- /*
- if (t0 > TONE_THR * t1)
- set tone flag
- */
- temp = round_ex(t1);
-
- test (); test ();
- if ((temp > 0) && (L_msu_ex(t0, temp, TONE_THR) > 0))
- {
- st->tone = st->tone | 0x4000; logic16 (); move16 ();
- }
- }
- /****************************************************************************
- *
- * Function : vad_tone_detection_update
- * Purpose : Update the tone flag register. Tone flags are shifted right
- * by one bit. This function should be called from the speech
- * encoder before call to Vad_tone_detection() function.
- *
- ***************************************************************************/
- void vad_tone_detection_update (
- vadState1 *st, /* i/o : State struct */
- Word16 one_lag_per_frame /* i : 1 if one open-loop lag is
- calculated per each frame,
- otherwise 0 */
- )
- {
- /* Shift tone flags right by one bit */
- st->tone = shr_ex(st->tone, 1); move16 ();
-
- /* If open-loop lag is calculated only once in each frame, do extra update
- and assume that the other tone flag of the frame is one. */
- if (one_lag_per_frame != 0)
- {
- st->tone = shr_ex(st->tone, 1);
- st->tone = st->tone | 0x2000; logic16 (); move16 ();
- }
- }
- /****************************************************************************
- *
- * Function : vad_pitch_detection
- * Purpose : Test whether signal contains pitch or other periodic
- * component.
- * Return value : Boolean voiced / unvoiced decision in state variable
- *
- ***************************************************************************/
- void vad_pitch_detection (vadState1 *st, /* i/o : State struct */
- Word16 T_op[] /* i : speech encoder open loop lags */
- )
- {
- Word16 lagcount, i;
-
- lagcount = 0; move16 ();
-
- for (i = 0; i < 2; i++)
- {
- test ();
- if (sub_ex (abs_s_ex (sub_ex (st->oldlag, T_op[i])), LTHRESH) < 0)
- {
- lagcount = add_ex (lagcount, 1);
- }
-
- /* Save the current LTP lag */
- st->oldlag = T_op[i]; move16 ();
- }
-
- /* Make pitch decision.
- Save flag of the pitch detection to the variable pitch.
- */
- st->pitch = shr_ex(st->pitch, 1); move16();
-
- test ();
- if (sub_ex ( add_ex (st->oldlag_count, lagcount), NTHRESH) >= 0)
- {
- st->pitch = st->pitch | 0x4000; logic16(); move16();
- }
-
- /* Update oldlagcount */
- st->oldlag_count = lagcount; move16 ();
- }
- /****************************************************************************
- *
- * Function : vad
- * Purpose : Main program for Voice Activity Detection (VAD) for AMR
- * Return value : VAD Decision, 1 = speech, 0 = noise
- *
- ***************************************************************************/
- Word16 vad1(vadState1 *st, /* i/o : State struct */
- Word16 in_buf[] /* i : samples of the input frame */
- )
- {
- Word16 level[COMPLEN];
- Word32 pow_sum;
- Word16 i;
-
- /* Calculate power of the input frame. */
- pow_sum = 0L; move32 ();
- for (i = 0; i < FRAME_LEN; i++)
- {
- pow_sum = L_mac_ex(pow_sum, in_buf[i-LOOKAHEAD], in_buf[i-LOOKAHEAD]);
- }
- /*
- If input power is very low, clear pitch flag of the current frame
- */
- test ();
- if (L_sub_ex(pow_sum, POW_PITCH_THR) < 0)
- {
- st->pitch = st->pitch & 0x3fff; logic16 (); move16 ();
- }
- /*
- If input power is very low, clear complex flag of the "current" frame
- */
- test ();
- if (L_sub_ex(pow_sum, POW_COMPLEX_THR) < 0)
- {
- st->complex_low = st->complex_low & 0x3fff; logic16 (); move16 ();
- }
-
- /*
- Run the filter bank which calculates signal levels at each band
- */
- filter_bank(st, in_buf, level);
-
- return (vad_decision(st, level, pow_sum));
- }
|