summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/amrnb/common/src/vad1.cpp
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2009-12-08 15:40:06 -0800
committerAndreas Huber <andih@google.com>2009-12-10 12:23:55 -0800
commit4f1efc098cb5791c3e9f483f2af84aef70d2d0a0 (patch)
treea2873e84aed3eecb1198f85954e24cddb1bdc380 /media/libstagefright/codecs/amrnb/common/src/vad1.cpp
parentc54176addef15699a518b69cd6bbd40ffc95e72e (diff)
downloadframeworks_av-4f1efc098cb5791c3e9f483f2af84aef70d2d0a0.zip
frameworks_av-4f1efc098cb5791c3e9f483f2af84aef70d2d0a0.tar.gz
frameworks_av-4f1efc098cb5791c3e9f483f2af84aef70d2d0a0.tar.bz2
Initial check in of AMR (NB and WB) decoders based on PV source code.
Diffstat (limited to 'media/libstagefright/codecs/amrnb/common/src/vad1.cpp')
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/vad1.cpp2330
1 files changed, 2330 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/amrnb/common/src/vad1.cpp b/media/libstagefright/codecs/amrnb/common/src/vad1.cpp
new file mode 100644
index 0000000..a6e1131
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/vad1.cpp
@@ -0,0 +1,2330 @@
+/* ------------------------------------------------------------------
+ * 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));
+}
+
+