blob: a6e113146e6e86a12cbc5a67488e0e90e2f9b93a [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/****************************************************************************************
Portions of this file are derived from the following 3GPP standard:
3GPP TS 26.073
ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
Available from http://www.3gpp.org
(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
Permission to distribute, modify and use this file under the standard license
terms listed above has been obtained from the copyright holder.
****************************************************************************************/
/*
Pathname: ./audio/gsm-amr/c/src/vad1.c
Functions:
------------------------------------------------------------------------------
REVISION HISTORY
Description: Updated template used to PV coding template.
Changed to accept the pOverflow flag for EPOC compatibility.
Description: Made changes per review comments
(1) Removed include of "count.h"
(2) Replaced "basic_op.h" with individual include files
(3) Removed some unnecessary instances of sub().
Description: Replaced OSCL mem type functions and eliminated include
files that now are chosen by OSCL definitions
Description: Replaced "int" and/or "char" with OSCL defined types.
Description: Changed round function name to pv_round to avoid conflict with
round function in C standard library.
Who: Date:
Description:
------------------------------------------------------------------------------
MODULE DESCRIPTION
------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#include "vad.h"
#include "typedef.h"
#include "shr.h"
#include "basic_op.h"
#include "cnst_vad.h"
/*----------------------------------------------------------------------------
; MACROS
; Define module specific macros here
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; DEFINES
; Include all pre-processor statements here. Include conditional
; compile variables also.
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; LOCAL FUNCTION DEFINITIONS
; Function Prototype declaration
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; LOCAL VARIABLE DEFINITIONS
; Variable declaration - defined here and used outside this module
----------------------------------------------------------------------------*/
/*
------------------------------------------------------------------------------
FUNCTION NAME: first_filter_stage
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
data -- array of type Word16 -- filter memory
in -- array of type Word16 -- input signal
Outputs:
data -- array of type Word16 -- filter memory
out -- array of type Word16 -- output values, every other
output is low-pass part and
other is high-pass part every
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : Scale input down by one bit. Calculate 5th order
half-band lowpass/highpass filter pair with
decimation.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
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 */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 temp0;
Word16 temp1;
Word16 temp2;
Word16 temp3;
Word16 i;
Word16 data0;
Word16 data1;
data0 = data[0];
data1 = data[1];
for (i = 0; i < FRAME_LEN / 4; i++)
{
temp0 = mult(COEFF5_1, data0, pOverflow);
temp1 = shr(in[4*i+0], 2, pOverflow);
temp0 = sub(temp1, temp0, pOverflow);
temp1 = mult(COEFF5_1, temp0, pOverflow);
temp1 = add(data0, temp1, pOverflow);
temp3 = mult(COEFF5_2, data1, pOverflow);
temp2 = shr(in[4*i+1], 2, pOverflow);
temp3 = sub(temp2, temp3, pOverflow);
temp2 = mult(COEFF5_2, temp3, pOverflow);
temp2 = add(data1, temp2, pOverflow);
out[4*i+0] = add(temp1, temp2, pOverflow);
out[4*i+1] = sub(temp1, temp2, pOverflow);
temp1 = mult(COEFF5_1, temp0, pOverflow);
temp2 = shr(in[4*i+2], 2, pOverflow);
data0 = sub(temp2, temp1, pOverflow);
temp1 = mult(COEFF5_1, data0, pOverflow);
temp1 = add(temp0, temp1, pOverflow);
data1 = mult(COEFF5_2, temp3, pOverflow);
temp2 = shr(in[4*i+3], 2, pOverflow);
data1 = sub(temp2, data1, pOverflow);
temp2 = mult(COEFF5_2, data1, pOverflow);
temp2 = add(temp3, temp2, pOverflow);
out[4*i+2] = add(temp1, temp2, pOverflow);
out[4*i+3] = sub(temp1, temp2, pOverflow);
}
data[0] = data0;
data[1] = data1;
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: filter5
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
in0 -- array of type Word16 -- input values; output low-pass part
in1 -- array of type Word16 -- input values; output high-pass part
data -- array of type Word16 -- updated filter memory
Outputs:
in0 -- array of type Word16 -- input values; output low-pass part
in1 -- array of type Word16 -- input values; output high-pass part
data -- array of type Word16 -- updated filter memory
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : Fifth-order half-band lowpass/highpass filter pair with
decimation.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
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 */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 temp0;
Word16 temp1;
Word16 temp2;
temp0 = mult(COEFF5_1, data[0], pOverflow);
temp0 = sub(*in0, temp0, pOverflow);
temp1 = mult(COEFF5_1, temp0, pOverflow);
temp1 = add(data[0], temp1, pOverflow);
data[0] = temp0;
temp0 = mult(COEFF5_2, data[1], pOverflow);
temp0 = sub(*in1, temp0, pOverflow);
temp2 = mult(COEFF5_2, temp0, pOverflow);
temp2 = add(data[1], temp2, pOverflow);
data[1] = temp0;
temp0 = add(temp1, temp2, pOverflow);
*in0 = shr(temp0, 1, pOverflow);
temp0 = sub(temp1, temp2, pOverflow);
*in1 = shr(temp0, 1, pOverflow);
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: filter3
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
in0 -- array of type Word16 -- input values; output low-pass part
in1 -- array of type Word16 -- input values; output high-pass part
data -- array of type Word16 -- updated filter memory
Outputs:
in0 -- array of type Word16 -- input values; output low-pass part
in1 -- array of type Word16 -- input values; output high-pass part
data -- array of type Word16 -- updated filter memory
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : Third-order half-band lowpass/highpass filter pair with
decimation.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
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 */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 temp1;
Word16 temp2;
temp1 = mult(COEFF3, *data, pOverflow);
temp1 = sub(*in1, temp1, pOverflow);
temp2 = mult(COEFF3, temp1, pOverflow);
temp2 = add(*data, temp2, pOverflow);
*data = temp1;
temp1 = sub(*in0, temp2, pOverflow);
*in1 = shr(temp1, 1, pOverflow);
temp1 = add(*in0, temp2, pOverflow);
*in0 = shr(temp1, 1, pOverflow);
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: level_calculation
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
data -- array of type Word16 -- signal buffer
sub_level -- pointer to type Word16 -- level calculated at the end of
the previous frame
count1 -- Word16 -- number of samples to be counted
count2 -- Word16 -- number of samples to be counted
ind_m -- Word16 -- step size for the index of the data buffer
ind_a -- Word16 -- starting index of the data buffer
scale -- Word16 -- scaling for the level calculation
Outputs:
sub_level -- pointer to tyep Word16 -- level of signal calculated from the
last (count2 - count1) samples.
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
signal level
Global Variables Used:
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : Calculate signal level in a sub-band. Level is calculated
by summing absolute values of the input data.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
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 */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word32 l_temp1;
Word32 l_temp2;
Word16 level;
Word16 i;
l_temp1 = 0L;
for (i = count1; i < count2; i++)
{
l_temp1 = L_mac(l_temp1, 1, abs_s(data[ind_m*i+ind_a]), pOverflow);
}
l_temp2 = L_add(l_temp1, L_shl(*sub_level, sub(16, scale, pOverflow), pOverflow), pOverflow);
*sub_level = extract_h(L_shl(l_temp1, scale, pOverflow));
for (i = 0; i < count1; i++)
{
l_temp2 = L_mac(l_temp2, 1, abs_s(data[ind_m*i+ind_a]), pOverflow);
}
level = extract_h(L_shl(l_temp2, scale, pOverflow));
return level;
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: filter_bank
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st -- pointer to type vadState1 -- State struct
in -- array of type Word16 -- input frame
Outputs:
level -- array of type Word16 -- signal levels at each band
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : Divides input signal into 9-bands and calculas level of
the signal in each band
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
static void filter_bank(
vadState1 *st, /* i/o : State struct */
Word16 in[], /* i : input frame */
Word16 level[], /* 0 : signal levels at each band */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 i;
Word16 tmp_buf[FRAME_LEN];
/* calculate the filter bank */
first_filter_stage(in, tmp_buf, st->a_data5[0], pOverflow);
for (i = 0; i < FRAME_LEN / 4; i++)
{
filter5(&tmp_buf[4*i], &tmp_buf[4*i+2], st->a_data5[1], pOverflow);
filter5(&tmp_buf[4*i+1], &tmp_buf[4*i+3], st->a_data5[2], pOverflow);
}
for (i = 0; i < FRAME_LEN / 8; i++)
{
filter3(&tmp_buf[8*i+0], &tmp_buf[8*i+4], &st->a_data3[0], pOverflow);
filter3(&tmp_buf[8*i+2], &tmp_buf[8*i+6], &st->a_data3[1], pOverflow);
filter3(&tmp_buf[8*i+3], &tmp_buf[8*i+7], &st->a_data3[4], pOverflow);
}
for (i = 0; i < FRAME_LEN / 16; i++)
{
filter3(&tmp_buf[16*i+0], &tmp_buf[16*i+8], &st->a_data3[2], pOverflow);
filter3(&tmp_buf[16*i+4], &tmp_buf[16*i+12], &st->a_data3[3], pOverflow);
}
/* 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, pOverflow);
/* 2500 - 3000 Hz*/
level[7] = level_calculation(tmp_buf, &st->sub_level[7], FRAME_LEN / 8 - 4,
FRAME_LEN / 8, 8, 7, 16, pOverflow);
/* 2000 - 2500 Hz*/
level[6] = level_calculation(tmp_buf, &st->sub_level[6], FRAME_LEN / 8 - 4,
FRAME_LEN / 8, 8, 3, 16, pOverflow);
/* 1500 - 2000 Hz*/
level[5] = level_calculation(tmp_buf, &st->sub_level[5], FRAME_LEN / 8 - 4,
FRAME_LEN / 8, 8, 2, 16, pOverflow);
/* 1000 - 1500 Hz*/
level[4] = level_calculation(tmp_buf, &st->sub_level[4], FRAME_LEN / 8 - 4,
FRAME_LEN / 8, 8, 6, 16, pOverflow);
/* 750 - 1000 Hz*/
level[3] = level_calculation(tmp_buf, &st->sub_level[3], FRAME_LEN / 16 - 2,
FRAME_LEN / 16, 16, 4, 16, pOverflow);
/* 500 - 750 Hz*/
level[2] = level_calculation(tmp_buf, &st->sub_level[2], FRAME_LEN / 16 - 2,
FRAME_LEN / 16, 16, 12, 16, pOverflow);
/* 250 - 500 Hz*/
level[1] = level_calculation(tmp_buf, &st->sub_level[1], FRAME_LEN / 16 - 2,
FRAME_LEN / 16, 16, 8, 16, pOverflow);
/* 0 - 250 Hz*/
level[0] = level_calculation(tmp_buf, &st->sub_level[0], FRAME_LEN / 16 - 2,
FRAME_LEN / 16, 16, 0, 16, pOverflow);
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: update_cntrl
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st -- pointer to type vadState1 -- State struct
level -- array of type Word16 -- sub-band levels of the input frame
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
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
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
static void update_cntrl(
vadState1 *st, /* i/o : State struct */
Word16 level[], /* i : sub-band levels of the input frame */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 i;
Word16 temp;
Word16 stat_rat;
Word16 exp;
Word16 num;
Word16 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 */
if (st->complex_warning != 0)
{
if (st->stat_count < CAD_MIN_STAT_COUNT)
{
st->stat_count = CAD_MIN_STAT_COUNT;
}
}
/* 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 */
if (((Word16)(st->pitch & 0x6000) == 0x6000) ||
((Word16)(st->tone & 0x7c00) == 0x7c00))
{
st->stat_count = STAT_COUNT;
}
else
{
/* if 8 last vad-decisions have been "0", reinitialize stat_count */
if ((st->vadreg & 0x7f80) == 0)
{
st->stat_count = STAT_COUNT;
}
else
{
stat_rat = 0;
for (i = 0; i < COMPLEN; i++)
{
if (level[i] > st->ave_level[i])
{
num = level[i];
denom = st->ave_level[i];
}
else
{
num = st->ave_level[i];
denom = level[i];
}
/* Limit nimimum value of num and denom to STAT_THR_LEVEL */
if (num < STAT_THR_LEVEL)
{
num = STAT_THR_LEVEL;
}
if (denom < STAT_THR_LEVEL)
{
denom = STAT_THR_LEVEL;
}
exp = norm_s(denom);
denom = shl(denom, exp, pOverflow);
/* stat_rat = num/denom * 64 */
temp = shr(num, 1, pOverflow);
temp = div_s(temp, denom);
stat_rat = add(stat_rat, shr(temp, sub(8, exp, pOverflow), pOverflow), pOverflow);
}
/* compare stat_rat with a threshold and update stat_count */
if (stat_rat > STAT_THR)
{
st->stat_count = STAT_COUNT;
}
else
{
if ((st->vadreg & 0x4000) != 0)
{
if (st->stat_count != 0)
{
st->stat_count = sub(st->stat_count, 1, pOverflow);
}
}
}
}
}
/* Update average amplitude estimate for stationarity estimation */
alpha = ALPHA4;
if (st->stat_count == STAT_COUNT)
{
alpha = 32767;
}
else if ((st->vadreg & 0x4000) == 0)
{
alpha = ALPHA5;
}
for (i = 0; i < COMPLEN; i++)
{
temp = sub(level[i], st->ave_level[i], pOverflow);
temp = mult_r(alpha, temp, pOverflow);
st->ave_level[i] =
add(
st->ave_level[i],
temp,
pOverflow);
}
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: hangover_addition
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
noise_level -- Word16 -- average level of the noise estimates
low_power -- Word16 -- flag power of the input frame
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicato
Returns:
VAD_flag indicating final VAD decision (Word16)
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
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
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
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 */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 hang_len;
Word16 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
*/
if (noise_level > HANG_NOISE_THR)
{
burst_len = BURST_LEN_HIGH_NOISE;
hang_len = HANG_LEN_HIGH_NOISE;
}
else
{
burst_len = BURST_LEN_LOW_NOISE;
hang_len = 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 != 0)
{
st->burst_count = 0;
st->hang_count = 0;
st->complex_hang_count = 0;
st->complex_hang_timer = 0;
return 0;
}
if (st->complex_hang_timer > CVAD_HANG_LIMIT)
{
if (st->complex_hang_count < CVAD_HANG_LENGTH)
{
st->complex_hang_count = CVAD_HANG_LENGTH;
}
}
/* long time very complex signal override VAD output function */
if (st->complex_hang_count != 0)
{
st->burst_count = BURST_LEN_HIGH_NOISE;
st->complex_hang_count = sub(st->complex_hang_count, 1, pOverflow);
return 1;
}
else
{
/* let hp_corr work in from a noise_period indicated by the VAD */
if (((st->vadreg & 0x3ff0) == 0) &&
(st->corr_hp_fast > CVAD_THRESH_IN_NOISE))
{
return 1;
}
}
/* update the counters (hang_count, burst_count) */
if ((st->vadreg & 0x4000) != 0)
{
st->burst_count = add(st->burst_count, 1, pOverflow);
if (st->burst_count >= burst_len)
{
st->hang_count = hang_len;
}
return 1;
}
else
{
st->burst_count = 0;
if (st->hang_count > 0)
{
st->hang_count = sub(st->hang_count, 1, pOverflow);
return 1;
}
}
return 0;
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: noise_estimate_update
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st -- pointer to type vadState1 -- State struct
level -- array of type Word16 -- sub-band levels of the input frame
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
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
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
static void noise_estimate_update(
vadState1 *st, /* i/o : State struct */
Word16 level[], /* i : sub-band levels of the input frame */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 i;
Word16 alpha_up;
Word16 alpha_down;
Word16 bckr_add;
/* Control update of bckr_est[] */
update_cntrl(st, level, pOverflow);
/* Choose update speed */
bckr_add = 2;
if (((0x7800 & st->vadreg) == 0) &&
((st->pitch & 0x7800) == 0)
&& (st->complex_hang_count == 0))
{
alpha_up = ALPHA_UP1;
alpha_down = ALPHA_DOWN1;
}
else
{
if ((st->stat_count == 0)
&& (st->complex_hang_count == 0))
{
alpha_up = ALPHA_UP2;
alpha_down = ALPHA_DOWN2;
}
else
{
alpha_up = 0;
alpha_down = ALPHA3;
bckr_add = 0;
}
}
/* Update noise estimate (bckr_est) */
for (i = 0; i < COMPLEN; i++)
{
Word16 temp;
temp = sub(st->old_level[i], st->bckr_est[i], pOverflow);
if (temp < 0)
{ /* update downwards*/
temp = mult_r(alpha_down, temp, pOverflow);
temp = add(st->bckr_est[i], temp, pOverflow);
st->bckr_est[i] = add(-2, temp, pOverflow);
/* limit minimum value of the noise estimate to NOISE_MIN */
if (st->bckr_est[i] < NOISE_MIN)
{
st->bckr_est[i] = NOISE_MIN;
}
}
else
{ /* update upwards */
temp = mult_r(alpha_up, temp, pOverflow);
temp = add(st->bckr_est[i], temp, pOverflow);
st->bckr_est[i] = add(bckr_add, temp, pOverflow);
/* limit maximum value of the noise estimate to NOISE_MAX */
if (st->bckr_est[i] > NOISE_MAX)
{
st->bckr_est[i] = NOISE_MAX;
}
}
}
/* Update signal levels of the previous frame (old_level) */
for (i = 0; i < COMPLEN; i++)
{
st->old_level[i] = level[i];
}
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: complex_estimate_adapt
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st -- pointer to type vadState1 -- State struct
low_power -- Word16 -- very low level flag of the input frame
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
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
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
static void complex_estimate_adapt(
vadState1 *st, /* i/o : VAD state struct */
Word16 low_power, /* i : very low level flag of the input frame */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 alpha; /* Q15 */
Word32 L_tmp; /* Q31 */
/* adapt speed on own state */
if (st->best_corr_hp < st->corr_hp_fast) /* decrease */
{
if (st->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH)
{ /* low state */
alpha = CVAD_ADAPT_FAST;
}
else
{ /* high state */
alpha = CVAD_ADAPT_REALLY_FAST;
}
}
else /* increase */
{
if (st->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH)
{
alpha = CVAD_ADAPT_FAST;
}
else
{
alpha = CVAD_ADAPT_SLOW;
}
}
L_tmp = L_deposit_h(st->corr_hp_fast);
L_tmp = L_msu(L_tmp, alpha, st->corr_hp_fast, pOverflow);
L_tmp = L_mac(L_tmp, alpha, st->best_corr_hp, pOverflow);
st->corr_hp_fast = pv_round(L_tmp, pOverflow); /* Q15 */
if (st->corr_hp_fast < CVAD_MIN_CORR)
{
st->corr_hp_fast = CVAD_MIN_CORR;
}
if (low_power != 0)
{
st->corr_hp_fast = CVAD_MIN_CORR;
}
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: complex_vad
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st -- pointer to type vadState1 -- State struct
low_power -- Word16 -- flag power of the input frame
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
the complex background decision
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : complex background decision
Return value : the complex background decision
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
static Word16 complex_vad(
vadState1 *st, /* i/o : VAD state struct */
Word16 low_power, /* i : flag power of the input frame */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
st->complex_high = shr(st->complex_high, 1, pOverflow);
st->complex_low = shr(st->complex_low, 1, pOverflow);
if (low_power == 0)
{
if (st->corr_hp_fast > CVAD_THRESH_ADAPT_HIGH)
{
st->complex_high |= 0x4000;
}
if (st->corr_hp_fast > CVAD_THRESH_ADAPT_LOW)
{
st->complex_low |= 0x4000;
}
}
if (st->corr_hp_fast > CVAD_THRESH_HANG)
{
st->complex_hang_timer = add(st->complex_hang_timer, 1, pOverflow);
}
else
{
st->complex_hang_timer = 0;
}
return ((Word16)(st->complex_high & 0x7f80) == 0x7f80 ||
(Word16)(st->complex_low & 0x7fff) == 0x7fff);
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: vad_decision
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st -- pointer to type vadState1 -- State struct
level -- array of type Word16 -- sub-band levels of the input frame
pow_sum -- Word32 -- power of the input frame
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
VAD_flag (Word16)
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
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
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
static Word16 vad_decision(
vadState1 *st, /* i/o : State struct */
Word16 level[COMPLEN], /* i : sub-band levels of the input frame */
Word32 pow_sum, /* i : power of the input frame */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 i;
Word16 snr_sum;
Word32 L_temp;
Word16 vad_thr;
Word16 temp;
Word16 noise_level;
Word16 low_power_flag;
Word16 temp1;
/*
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(st->bckr_est[i]);
temp = shl(st->bckr_est[i], exp, pOverflow);
temp = div_s(shr(level[i], 1, pOverflow), temp);
temp = shl(temp, sub(exp, UNIRSHFT - 1, pOverflow), pOverflow);
L_temp = L_mac(L_temp, temp, temp, pOverflow);
}
snr_sum = extract_h(L_shl(L_temp, 6, pOverflow));
snr_sum = mult(snr_sum, INV_COMPLEN, pOverflow);
/* Calculate average level of estimated background noise */
L_temp = 0;
for (i = 0; i < COMPLEN; i++)
{
L_temp = L_add(L_temp, st->bckr_est[i], pOverflow);
}
noise_level = extract_h(L_shl(L_temp, 13, pOverflow));
/* Calculate VAD threshold */
temp1 = sub(noise_level, VAD_P1, pOverflow);
temp1 = mult(VAD_SLOPE, temp1, pOverflow);
vad_thr = add(temp1, VAD_THR_HIGH, pOverflow);
if (vad_thr < VAD_THR_LOW)
{
vad_thr = VAD_THR_LOW;
}
/* Shift VAD decision register */
st->vadreg = shr(st->vadreg, 1, pOverflow);
/* Make intermediate VAD decision */
if (snr_sum > vad_thr)
{
st->vadreg |= 0x4000;
}
/* primary vad decsion made */
/* check if the input power (pow_sum) is lower than a threshold" */
if (L_sub(pow_sum, VAD_POW_LOW, pOverflow) < 0)
{
low_power_flag = 1;
}
else
{
low_power_flag = 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, pOverflow);
/* check multiple thresholds of the st->corr_hp_fast value */
st->complex_warning = complex_vad(st, low_power_flag, pOverflow);
/* Update speech subband vad background noise estimates */
noise_estimate_update(st, level, pOverflow);
/* 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, pOverflow);
return (st->speech_vad_decision);
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: vad1_init
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
state -- double pointer to type vadState1 -- pointer to memory to
be initialized.
Outputs:
state -- points to initalized area in memory.
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Allocates state memory and initializes state memory
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
Word16 vad1_init(vadState1 **state)
{
vadState1* s;
if (state == (vadState1 **) NULL)
{
return -1;
}
*state = NULL;
/* allocate memory */
if ((s = (vadState1 *) malloc(sizeof(vadState1))) == NULL)
{
return -1;
}
vad1_reset(s);
*state = s;
return 0;
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: vad1_reset
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
state -- pointer to type vadState1 -- State struct
Outputs:
state -- pointer to type vadState1 -- State struct
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose: Resets state memory to zero
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
Word16 vad1_reset(vadState1 *state)
{
Word16 i;
Word16 j;
if (state == (vadState1 *) NULL)
{
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 NAME: vad1_exit
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
state -- pointer to type vadState1 -- State struct
Outputs:
None
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
The memory used for state memory is freed
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
void vad1_exit(vadState1 **state)
{
if (state == NULL || *state == NULL)
return;
/* deallocate memory */
free(*state);
*state = NULL;
return;
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: vad_complex_detection_update
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
best_corr_hp -- Word16 -- best Corr
state -- pointer to type vadState1 -- State struct
Outputs:
state -- pointer to type vadState1 -- State struct
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : update vad->bestCorr_hp complex signal feature state
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
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;
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: vad_tone_detection
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st -- pointer to type vadState1 -- State struct
t0 -- Word32 -- autocorrelation maxima
t1 -- Word32 -- energy
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
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
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
void vad_tone_detection(
vadState1 *st, /* i/o : State struct */
Word32 t0, /* i : autocorrelation maxima */
Word32 t1, /* i : energy */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 temp;
/*
if (t0 > TONE_THR * t1)
set tone flag
*/
temp = pv_round(t1, pOverflow);
if ((temp > 0) && (L_msu(t0, temp, TONE_THR, pOverflow) > 0))
{
st->tone |= 0x4000;
}
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: vad_tone_detection_update
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
one_lag_per_frame -- Word16 -- 1 if one open-loop lag is calculated per
each frame, otherwise 0
st -- pointer to type vadState1 -- State struct
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
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.
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this 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 */
Flag *pOverflow /* o : Flags overflow */
)
{
/* Shift tone flags right by one bit */
st->tone = shr(st->tone, 1, pOverflow);
/* 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(st->tone, 1, pOverflow);
st->tone |= 0x2000;
}
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: vad_pitch_detection
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
T_op -- array of type Word16 -- speech encoder open loop lags
st -- pointer to type vadState1 -- State struct
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
None
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : Test whether signal contains pitch or other periodic
component.
Return value : Boolean voiced / unvoiced decision in state variable
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
void vad_pitch_detection(
vadState1 *st, /* i/o : State struct */
Word16 T_op[], /* i : speech encoder open loop lags */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 lagcount;
Word16 i;
Word16 temp;
lagcount = 0;
for (i = 0; i < 2; i++)
{
temp = sub(st->oldlag, T_op[i], pOverflow);
temp = abs_s(temp);
if (temp < LTHRESH)
{
lagcount = add(lagcount, 1, pOverflow);
}
/* Save the current LTP lag */
st->oldlag = T_op[i];
}
/* Make pitch decision.
Save flag of the pitch detection to the variable pitch.
*/
st->pitch = shr(st->pitch, 1, pOverflow);
temp =
add(
st->oldlag_count,
lagcount,
pOverflow);
if (temp >= NTHRESH)
{
st->pitch |= 0x4000;
}
/* Update oldlagcount */
st->oldlag_count = lagcount;
}
/*
------------------------------------------------------------------------------
FUNCTION NAME: vad1
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
st -- pointer to type vadState1 -- State struct
in_buf -- array of type Word16 -- samples of the input frame
Outputs:
st -- pointer to type vadState1 -- State struct
pOverflow -- pointer to type Flag -- overflow indicator
Returns:
VAD Decision, 1 = speech, 0 = noise
Global Variables Used:
None
Local Variables Needed:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
Purpose : Main program for Voice Activity Detection (VAD) for AMR
Return value : VAD Decision, 1 = speech, 0 = noise
------------------------------------------------------------------------------
REQUIREMENTS
None
------------------------------------------------------------------------------
REFERENCES
vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
------------------------------------------------------------------------------
PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED [optional]
When the code is written for a specific target processor the
the resources used should be documented below.
HEAP MEMORY USED: x bytes
STACK MEMORY USED: x bytes
CLOCK CYCLES: (cycle count equation for this function) + (variable
used to represent cycle count for each subroutine
called)
where: (cycle count variable) = cycle count for [subroutine
name]
------------------------------------------------------------------------------
CAUTION [optional]
[State any special notes, constraints or cautions for users of this function]
------------------------------------------------------------------------------
*/
Word16 vad1(
vadState1 *st, /* i/o : State struct */
Word16 in_buf[], /* i : samples of the input frame */
Flag *pOverflow /* o : Flag set when overflow occurs */
)
{
Word16 level[COMPLEN];
Word32 pow_sum;
Word16 i;
/* Calculate power of the input frame. */
pow_sum = 0L;
for (i = 0; i < FRAME_LEN; i++)
{
pow_sum = L_mac(pow_sum, in_buf[i-LOOKAHEAD], in_buf[i-LOOKAHEAD], pOverflow);
}
/*
If input power is very low, clear pitch flag of the current frame
*/
if (L_sub(pow_sum, POW_PITCH_THR, pOverflow) < 0)
{
st->pitch = st->pitch & 0x3fff;
}
/*
If input power is very low, clear complex flag of the "current" frame
*/
if (L_sub(pow_sum, POW_COMPLEX_THR, pOverflow) < 0)
{
st->complex_low = st->complex_low & 0x3fff;
}
/*
Run the filter bank which calculates signal levels at each band
*/
filter_bank(st, in_buf, level, pOverflow);
return (vad_decision(st, level, pow_sum, pOverflow));
}