1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/***********************************************************************
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*      File: wb_vad.c                                                  *
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                                                                      *
20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*      Description: Voice Activity Detection                           *
21e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                                                                      *
22e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard************************************************************************/
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
24e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <stdlib.h>
25e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <stdio.h>
26e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "cnst.h"
27e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "wb_vad.h"
28e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "typedef.h"
29e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h"
30e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "math_op.h"
31e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "wb_vad_c.h"
32e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "mem_align.h"
33e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
34e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
35e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  Calculate Log2 and scale the signal:
36e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
37e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*    ilog2(Word32 in) = -1024*log10(in * 2^-31)/log10(2), where in = [1, 2^31-1]
38e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
39e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  input   output
40e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  32768   16384
41e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  1       31744
42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* When input is in the range of [1,2^16], max error is 0.0380%.
44e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*********************************************************************************/
45e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
46e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 ilog2(                       /* return: output value of the log2 */
475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 mant                        /* i: value to be converted */
485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
49e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 ex, ex2, res;
515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i, l_temp;
525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (mant <= 0)
545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        mant = 1;
565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    ex = norm_s(mant);
585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    mant = mant << ex;
595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 3; i++)
615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        mant = vo_mult(mant, mant);
625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    l_temp = vo_L_mult(mant, mant);
635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    ex2 = norm_l(l_temp);
655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    mant = extract_h(l_temp << ex2);
665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    res = (ex + 16) << 10;
685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    res = add1(res, (ex2 << 6));
695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    res = vo_sub(add1(res, 127), (mant >> 8));
705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return (res);
71e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
72e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
73e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
74e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
75e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function     : filter5
76e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose      : Fifth-order half-band lowpass/highpass filter pair with
77e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                    decimation.
78e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
79e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
80e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
81e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void filter5(
825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * in0,                         /* i/o : input values; output low-pass part  */
835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * in1,                         /* i/o : input values; output high-pass part */
845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 data[]                         /* i/o : filter memory                       */
855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
86e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 temp0, temp1, temp2;
88e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp0 = vo_sub(*in0, vo_mult(COEFF5_1, data[0]));
905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp1 = add1(data[0], vo_mult(COEFF5_1, temp0));
915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    data[0] = temp0;
92e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp0 = vo_sub(*in1, vo_mult(COEFF5_2, data[1]));
945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp2 = add1(data[1], vo_mult(COEFF5_2, temp0));
955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    data[1] = temp0;
96e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *in0 = extract_h((vo_L_add(temp1, temp2) << 15));
985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *in1 = extract_h((vo_L_sub(temp1, temp2) << 15));
99e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
100e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
101e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
102e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
103e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function     : filter3
104e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose      : Third-order half-band lowpass/highpass filter pair with
105e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                    decimation.
106e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
107e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
108e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
109e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void filter3(
1105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * in0,                         /* i/o : input values; output low-pass part  */
1115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * in1,                         /* i/o : input values; output high-pass part */
1125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * data                         /* i/o : filter memory                       */
1135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
114e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 temp1, temp2;
116e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp1 = vo_sub(*in1, vo_mult(COEFF3, *data));
1185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp2 = add1(*data, vo_mult(COEFF3, temp1));
1195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *data = temp1;
120e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *in1 = extract_h((vo_L_sub(*in0, temp2) << 15));
1225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *in0 = extract_h((vo_L_add(*in0, temp2) << 15));
123e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
124e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
125e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
126e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
127e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function   : level_calculation
128e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose    : Calculate signal level in a sub-band. Level is calculated
129e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                  by summing absolute values of the input data.
130e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
131e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                  Signal level calculated from of the end of the frame
132e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                  (data[count1 - count2]) is stored to (*sub_level)
133e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                  and added to the level of the next frame.
134e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard******************************************************************************/
136e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
137e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 level_calculation(                      /* return: signal level */
1385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 data[],                        /* i   : signal buffer                                    */
1395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * sub_level,                   /* i   : level calculated at the end of the previous frame*/
1405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                                              /* o   : level of signal calculated from the last         */
1415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                                              /*       (count2 - count1) samples                        */
1425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 count1,                        /* i   : number of samples to be counted                  */
1435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 count2,                        /* i   : number of samples to be counted                  */
1445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 ind_m,                         /* i   : step size for the index of the data buffer       */
1455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 ind_a,                         /* i   : starting index of the data buffer                */
1465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 scale                          /* i   : scaling for the level calculation                */
1475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
148e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i, l_temp1, l_temp2;
1505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 level;
151e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    l_temp1 = 0L;
1535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = count1; i < count2; i++)
1545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        l_temp1 += (abs_s(data[ind_m * i + ind_a])<<1);
1565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
157e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    l_temp2 = vo_L_add(l_temp1, L_shl(*sub_level, 16 - scale));
1595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *sub_level = extract_h(L_shl(l_temp1, scale));
160e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < count1; i++)
1625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        l_temp2 += (abs_s(data[ind_m * i + ind_a])<<1);
1645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level = extract_h(L_shl2(l_temp2, scale));
166e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return level;
168e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
169e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
170e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
171e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
172e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function     : filter_bank
173e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose      : Divide input signal into bands and calculate level of
174e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                    the signal in each band
175e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
176e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
177e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
178e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void filter_bank(
1795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * st,                         /* i/o : State struct               */
1805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 in[],                          /* i   : input frame                */
1815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 level[]                        /* o   : signal levels at each band */
1825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
183e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i;
1855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 tmp_buf[FRAME_LEN];
1865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* shift input 1 bit down for safe scaling */
1885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < FRAME_LEN; i++)
1895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        tmp_buf[i] = in[i] >> 1;
1915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* run the filter bank */
1945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 128; i++)
1955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter5(&tmp_buf[2 * i], &tmp_buf[2 * i + 1], st->a_data5[0]);
1975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 64; i++)
1995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter5(&tmp_buf[4 * i], &tmp_buf[4 * i + 2], st->a_data5[1]);
2015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter5(&tmp_buf[4 * i + 1], &tmp_buf[4 * i + 3], st->a_data5[2]);
2025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 32; i++)
2045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter5(&tmp_buf[8 * i], &tmp_buf[8 * i + 4], st->a_data5[3]);
2065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter5(&tmp_buf[8 * i + 2], &tmp_buf[8 * i + 6], st->a_data5[4]);
2075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter3(&tmp_buf[8 * i + 3], &tmp_buf[8 * i + 7], &st->a_data3[0]);
2085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 16; i++)
2105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter3(&tmp_buf[16 * i + 0], &tmp_buf[16 * i + 8], &st->a_data3[1]);
2125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter3(&tmp_buf[16 * i + 4], &tmp_buf[16 * i + 12], &st->a_data3[2]);
2135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter3(&tmp_buf[16 * i + 6], &tmp_buf[16 * i + 14], &st->a_data3[3]);
2145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < 8; i++)
2175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter3(&tmp_buf[32 * i + 0], &tmp_buf[32 * i + 16], &st->a_data3[4]);
2195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        filter3(&tmp_buf[32 * i + 8], &tmp_buf[32 * i + 24], &st->a_data3[5]);
2205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
2215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* calculate levels in each frequency band */
2235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 4800 - 6400 Hz */
2255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[11] = level_calculation(tmp_buf, &st->sub_level[11], 16, 64, 4, 1, 14);
2265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 4000 - 4800 Hz */
2275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[10] = level_calculation(tmp_buf, &st->sub_level[10], 8, 32, 8, 7, 15);
2285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 3200 - 4000 Hz */
2295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[9] = level_calculation(tmp_buf, &st->sub_level[9],8, 32, 8, 3, 15);
2305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 2400 - 3200 Hz */
2315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[8] = level_calculation(tmp_buf, &st->sub_level[8],8, 32, 8, 2, 15);
2325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 2000 - 2400 Hz */
2335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[7] = level_calculation(tmp_buf, &st->sub_level[7],4, 16, 16, 14, 16);
2345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 1600 - 2000 Hz */
2355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[6] = level_calculation(tmp_buf, &st->sub_level[6],4, 16, 16, 6, 16);
2365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 1200 - 1600 Hz */
2375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[5] = level_calculation(tmp_buf, &st->sub_level[5],4, 16, 16, 4, 16);
2385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 800 - 1200 Hz */
2395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[4] = level_calculation(tmp_buf, &st->sub_level[4],4, 16, 16, 12, 16);
2405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 600 - 800 Hz */
2415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[3] = level_calculation(tmp_buf, &st->sub_level[3],2, 8, 32, 8, 17);
2425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 400 - 600 Hz */
2435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[2] = level_calculation(tmp_buf, &st->sub_level[2],2, 8, 32, 24, 17);
2445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 200 - 400 Hz */
2455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[1] = level_calculation(tmp_buf, &st->sub_level[1],2, 8, 32, 16, 17);
2465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* 0 - 200 Hz */
2475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    level[0] = level_calculation(tmp_buf, &st->sub_level[0],2, 8, 32, 0, 17);
248e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
249e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
250e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
251e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
252e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function   : update_cntrl
253e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose    : Control update of the background noise estimate.
254e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
255e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
256e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
257e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void update_cntrl(
2585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * st,                         /* i/o : State structure                    */
2595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 level[]                        /* i   : sub-band levels of the input frame */
2605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
261e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
2625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i;
2635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 num, temp, stat_rat, exp, denom;
2645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 alpha;
2655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
2665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* if a tone has been detected for a while, initialize stat_count */
2675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (sub((Word16) (st->tone_flag & 0x7c00), 0x7c00) == 0)
2685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->stat_count = STAT_COUNT;
2705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    } else
2715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
2725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        /* if 8 last vad-decisions have been "0", reinitialize stat_count */
2735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if ((st->vadreg & 0x7f80) == 0)
2745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
2755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->stat_count = STAT_COUNT;
2765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        } else
2775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
2785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            stat_rat = 0;
2795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            for (i = 0; i < COMPLEN; i++)
2805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
2815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                if(level[i] > st->ave_level[i])
2825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                {
2835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    num = level[i];
2845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    denom = st->ave_level[i];
2855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                } else
2865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                {
2875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    num = st->ave_level[i];
2885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    denom = level[i];
2895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                }
2905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                /* Limit nimimum value of num and denom to STAT_THR_LEVEL */
2915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                if(num < STAT_THR_LEVEL)
2925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                {
2935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    num = STAT_THR_LEVEL;
2945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                }
2955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                if(denom < STAT_THR_LEVEL)
2965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                {
2975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    denom = STAT_THR_LEVEL;
2985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                }
2995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                exp = norm_s(denom);
3005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                denom = denom << exp;
3015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                /* stat_rat = num/denom * 64 */
3035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                temp = div_s(num >> 1, denom);
3045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                stat_rat = add1(stat_rat, shr(temp, (8 - exp)));
3055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
3065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            /* compare stat_rat with a threshold and update stat_count */
3085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            if(stat_rat > STAT_THR)
3095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
3105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                st->stat_count = STAT_COUNT;
3115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            } else
3125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
3135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                if ((st->vadreg & 0x4000) != 0)
3145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                {
3155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    if (st->stat_count != 0)
3175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    {
3185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                        st->stat_count = st->stat_count - 1;
3195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                    }
3205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                }
3215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
3225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
3235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
3245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Update average amplitude estimate for stationarity estimation */
3265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    alpha = ALPHA4;
3275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(st->stat_count == STAT_COUNT)
3285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        alpha = 32767;
3305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    } else if ((st->vadreg & 0x4000) == 0)
3315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        alpha = ALPHA5;
3335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
3345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < COMPLEN; i++)
3355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->ave_level[i] = add1(st->ave_level[i], vo_mult_r(alpha, vo_sub(level[i], st->ave_level[i])));
3375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
338e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
339e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
340e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
341e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
342e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function     : hangover_addition
343e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose      : Add hangover after speech bursts
344e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
345e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
346e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
347e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 hangover_addition(                      /* return: VAD_flag indicating final VAD decision */
3485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * st,                         /* i/o : State structure                     */
3495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 low_power,                     /* i   : flag power of the input frame    */
3505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 hang_len,                      /* i   : hangover length */
3515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 burst_len                      /* i   : minimum burst length for hangover addition */
3525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
353e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
3545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* if the input power (pow_sum) is lower than a threshold, clear counters and set VAD_flag to "0"         */
3555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (low_power != 0)
3565d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3575d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->burst_count = 0;
3585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->hang_count = 0;
3595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return 0;
3605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
3615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* update the counters (hang_count, burst_count) */
3625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if ((st->vadreg & 0x4000) != 0)
3635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->burst_count = st->burst_count + 1;
3655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if(st->burst_count >= burst_len)
3665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
3675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->hang_count = hang_len;
3685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
3695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return 1;
3705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    } else
3715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
3725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->burst_count = 0;
3735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (st->hang_count > 0)
3745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
3755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->hang_count = st->hang_count - 1;
3765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            return 1;
3775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
3785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
3795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return 0;
380e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
381e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
382e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
383e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
384e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function   : noise_estimate_update
385e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose    : Update of background noise estimate
386e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
387e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
388e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
389e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void noise_estimate_update(
3905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * st,                         /* i/o : State structure                       */
3915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 level[]                        /* i   : sub-band levels of the input frame */
3925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
393e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
3945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i;
3955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 alpha_up, alpha_down, bckr_add = 2;
3965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
3975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Control update of bckr_est[] */
3985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    update_cntrl(st, level);
3995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Choose update speed */
4015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if ((0x7800 & st->vadreg) == 0)
4025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        alpha_up = ALPHA_UP1;
4045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        alpha_down = ALPHA_DOWN1;
4055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    } else
4065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (st->stat_count == 0)
4085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
4095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            alpha_up = ALPHA_UP2;
4105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            alpha_down = ALPHA_DOWN2;
4115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        } else
4125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
4135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            alpha_up = 0;
4145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            alpha_down = ALPHA3;
4155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            bckr_add = 0;
4165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
4175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Update noise estimate (bckr_est) */
4205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < COMPLEN; i++)
4215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 temp;
4235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        temp = (st->old_level[i] - st->bckr_est[i]);
4245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if (temp < 0)
4265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {                                  /* update downwards */
4275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->bckr_est[i] = add1(-2, add(st->bckr_est[i],vo_mult_r(alpha_down, temp)));
4285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            /* limit minimum value of the noise estimate to NOISE_MIN */
4295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            if(st->bckr_est[i] < NOISE_MIN)
4305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
4315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                st->bckr_est[i] = NOISE_MIN;
4325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
4335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        } else
4345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {                                  /* update upwards */
4355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->bckr_est[i] = add1(bckr_add, add1(st->bckr_est[i],vo_mult_r(alpha_up, temp)));
4365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            /* limit maximum value of the noise estimate to NOISE_MAX */
4385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            if(st->bckr_est[i] > NOISE_MAX)
4395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
4405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                st->bckr_est[i] = NOISE_MAX;
4415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
4425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
4435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Update signal levels of the previous frame (old_level) */
4465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < COMPLEN; i++)
4475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->old_level[i] = level[i];
4495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
450e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
451e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
452e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
453e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
454e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function     : vad_decision
455e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose      : Calculates VAD_flag
456e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
457e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
458e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
459e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 vad_decision(                           /* return value : VAD_flag */
4605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * st,                         /* i/o : State structure                       */
4615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 level[COMPLEN],                /* i   : sub-band levels of the input frame */
4625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word32 pow_sum                        /* i   : power of the input frame           */
4635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
464e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
4655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i;
4665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 L_snr_sum;
4675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 L_temp;
4685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 vad_thr, temp, noise_level;
4695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 low_power_flag;
4705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 hang_len, burst_len;
4715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 ilog2_speech_level, ilog2_noise_level;
4725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 temp2;
4735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Calculate squared sum of the input levels (level) divided by the background noise components
4755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * (bckr_est). */
4765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_snr_sum = 0;
4775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < COMPLEN; i++)
4785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 exp;
4805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        exp = norm_s(st->bckr_est[i]);
4825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        temp = (st->bckr_est[i] << exp);
4835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        temp = div_s((level[i] >> 1), temp);
4845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        temp = shl(temp, (exp - (UNIRSHFT - 1)));
4855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_snr_sum = L_mac(L_snr_sum, temp, temp);
4865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Calculate average level of estimated background noise */
4895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_temp = 0;
4905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 1; i < COMPLEN; i++)          /* ignore lowest band */
4915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
4925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_temp = vo_L_add(L_temp, st->bckr_est[i]);
4935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
4945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    noise_level = extract_h((L_temp << 12));
4965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* if SNR is lower than a threshold (MIN_SPEECH_SNR), and increase speech_level */
4975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp = vo_mult(noise_level, MIN_SPEECH_SNR) << 3;
4985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
4995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(st->speech_level < temp)
5005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->speech_level = temp;
5025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    ilog2_noise_level = ilog2(noise_level);
5045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* If SNR is very poor, speech_level is probably corrupted by noise level. This is correctred by
5065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen     * subtracting MIN_SPEECH_SNR*noise_level from speech level */
5075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    ilog2_speech_level = ilog2(st->speech_level - temp);
5085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp = add1(vo_mult(NO_SLOPE, (ilog2_noise_level - NO_P1)), THR_HIGH);
5105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp2 = add1(SP_CH_MIN, vo_mult(SP_SLOPE, (ilog2_speech_level - SP_P1)));
5125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (temp2 < SP_CH_MIN)
5135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        temp2 = SP_CH_MIN;
5155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (temp2 > SP_CH_MAX)
5175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        temp2 = SP_CH_MAX;
5195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    vad_thr = temp + temp2;
5215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(vad_thr < THR_MIN)
5235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        vad_thr = THR_MIN;
5255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Shift VAD decision register */
5275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->vadreg = (st->vadreg >> 1);
5285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Make intermediate VAD decision */
5305d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(L_snr_sum > vo_L_mult(vad_thr, (512 * COMPLEN)))
5315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->vadreg = (Word16) (st->vadreg | 0x4000);
5335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* check if the input power (pow_sum) is lower than a threshold" */
5355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(pow_sum < VAD_POW_LOW)
5365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        low_power_flag = 1;
5385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    } else
5395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        low_power_flag = 0;
5415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Update background noise estimates */
5435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    noise_estimate_update(st, level);
5445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Calculate values for hang_len and burst_len based on vad_thr */
5465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    hang_len = add1(vo_mult(HANG_SLOPE, (vad_thr - HANG_P1)), HANG_HIGH);
5475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if(hang_len < HANG_LOW)
5485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        hang_len = HANG_LOW;
5505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5515d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    burst_len = add1(vo_mult(BURST_SLOPE, (vad_thr - BURST_P1)), BURST_HIGH);
5525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return (hangover_addition(st, low_power_flag, hang_len, burst_len));
554e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
555e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
556e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
557e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
558e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function : Estimate_Speech()
559e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose  : Estimate speech level
560e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
561e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Maximum signal level is searched and stored to the variable sp_max.
562e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* The speech frames must locate within SP_EST_COUNT number of frames.
563e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* Thus, noisy frames having occasional VAD = "1" decisions will not
564e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard* affect to the estimated speech_level.
565e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
566e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
567e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
568e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic void Estimate_Speech(
5695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * st,                         /* i/o : State structure    */
5705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 in_level                       /* level of the input frame */
5715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
572e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
5735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 alpha;
5745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* if the required activity count cannot be achieved, reset counters */
5765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if((st->sp_est_cnt - st->sp_max_cnt) > (SP_EST_COUNT - SP_ACTIVITY_COUNT))
5775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sp_est_cnt = 0;
5795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sp_max = 0;
5805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sp_max_cnt = 0;
5815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
5825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->sp_est_cnt += 1;
5835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (((st->vadreg & 0x4000)||(in_level > st->speech_level)) && (in_level > MIN_SPEECH_LEVEL1))
5855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
5865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        /* update sp_max */
5875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if(in_level > st->sp_max)
5885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
5895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->sp_max = in_level;
5905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
5915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->sp_max_cnt += 1;
5925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        if(st->sp_max_cnt >= SP_ACTIVITY_COUNT)
5945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
5955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            Word16 tmp;
5965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            /* update speech estimate */
5975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            tmp = (st->sp_max >> 1);      /* scale to get "average" speech level */
5985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
5995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            /* select update speed */
6005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            if(tmp > st->speech_level)
6015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
6025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                alpha = ALPHA_SP_UP;
6035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            } else
6045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
6055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                alpha = ALPHA_SP_DOWN;
6065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
6075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            if(tmp > MIN_SPEECH_LEVEL2)
6085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            {
6095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen                st->speech_level = add1(st->speech_level, vo_mult_r(alpha, vo_sub(tmp, st->speech_level)));
6105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            }
6115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            /* clear all counters used for speech estimation */
6125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->sp_max = 0;
6135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->sp_max_cnt = 0;
6145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            st->sp_est_cnt = 0;
6155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
6165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
617e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
618e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
619e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
620e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
621e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  Function:   wb_vad_init
622e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  Purpose:    Allocates state memory and initializes state memory
623e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
624e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
625e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
626e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord16 wb_vad_init(                        /* return: non-zero with error, zero for ok. */
6275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars ** state,                     /* i/o : State structure    */
6285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VO_MEM_OPERATOR *pMemOP
6295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
630e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
6315d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    VadVars *s;
6325d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
6335d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (state == (VadVars **) NULL)
6345d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
6355d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        fprintf(stderr, "vad_init: invalid parameter\n");
6365d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return -1;
6375d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
6385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *state = NULL;
6395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
6405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* allocate memory */
6415d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if ((s = (VadVars *) mem_malloc(pMemOP, sizeof(VadVars), 32, VO_INDEX_ENC_AMRWB)) == NULL)
6425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
6435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        fprintf(stderr, "vad_init: can not malloc state structure\n");
6445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return -1;
6455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
6465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    wb_vad_reset(s);
6475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
6485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *state = s;
6495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
6505d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return 0;
651e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
652e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
653e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
654e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
655e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  Function:   wb_vad_reset
656e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  Purpose:    Initializes state memory
657e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
658e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
659e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
660e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord16 wb_vad_reset(                       /* return: non-zero with error, zero for ok. */
6615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * state                       /* i/o : State structure    */
6625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
663e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
6645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i, j;
6655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
6665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (state == (VadVars *) NULL)
6675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
6685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        fprintf(stderr, "vad_reset: invalid parameter\n");
6695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return -1;
6705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
6715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->tone_flag = 0;
6725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->vadreg = 0;
6735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->hang_count = 0;
6745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->burst_count = 0;
6755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->hang_count = 0;
6765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
6775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* initialize memory used by the filter bank */
6785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < F_5TH_CNT; i++)
6795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
6805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        for (j = 0; j < 2; j++)
6815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        {
6825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen            state->a_data5[i][j] = 0;
6835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        }
6845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
6855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
6865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < F_3TH_CNT; i++)
6875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
6885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        state->a_data3[i] = 0;
6895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
6905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
6915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* initialize the rest of the memory */
6925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < COMPLEN; i++)
6935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
6945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        state->bckr_est[i] = NOISE_INIT;
6955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        state->old_level[i] = NOISE_INIT;
6965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        state->ave_level[i] = NOISE_INIT;
6975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        state->sub_level[i] = 0;
6985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
6995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
7005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->sp_est_cnt = 0;
7015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->sp_max = 0;
7025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->sp_max_cnt = 0;
7035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->speech_level = SPEECH_LEVEL_INIT;
7045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    state->prev_pow_sum = 0;
7055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return 0;
706e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
707e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
708e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
709e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
710e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  Function:   wb_vad_exit
711e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*  Purpose:    The memory used for state memory is freed
712e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
713e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
714e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
715e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid wb_vad_exit(
7165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars ** state,                      /* i/o : State structure    */
7175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VO_MEM_OPERATOR *pMemOP
7185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
719e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
7205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (state == NULL || *state == NULL)
7215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return;
7225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* deallocate memory */
7235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    mem_free(pMemOP, *state, VO_INDEX_ENC_AMRWB);
7245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *state = NULL;
7255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return;
726e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
727e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
728e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
729e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
730e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function     : wb_vad_tone_detection
731e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose      : Search maximum pitch gain from a frame. Set tone flag if
732e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                    pitch gain is high. This is used to detect
733e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*                    signaling tones and other signals with high pitch gain.
734e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
735e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
736e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
737e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid wb_vad_tone_detection(
7385d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * st,                         /* i/o : State struct            */
7395d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 p_gain                         /* pitch gain      */
7405d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
741e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
7425d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* update tone flag */
7435d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->tone_flag = (st->tone_flag >> 1);
7445d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
7455d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* if (pitch_gain > TONE_THR) set tone flag */
7465d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (p_gain > TONE_THR)
7475d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
7485d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->tone_flag = (Word16) (st->tone_flag | 0x4000);
7495d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
750e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
751e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
752e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/******************************************************************************
753e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
754e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Function     : wb_vad
755e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*     Purpose      : Main program for Voice Activity Detection (VAD) for AMR
756e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*
757e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*******************************************************************************/
758e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
759e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord16 wb_vad(                                /* Return value : VAD Decision, 1 = speech, 0 = noise */
7605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        VadVars * st,                         /* i/o : State structure                 */
7615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 in_buf[]                       /* i   : samples of the input frame   */
7625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen         )
763e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
7645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 level[COMPLEN];
7655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i;
7665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 VAD_flag, temp;
7675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 L_temp, pow_sum;
7685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
7695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Calculate power of the input frame. */
7705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_temp = 0L;
7715d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < FRAME_LEN; i++)
7725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
7735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_temp = L_mac(L_temp, in_buf[i], in_buf[i]);
7745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
7755d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
7765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* pow_sum = power of current frame and previous frame */
7775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    pow_sum = L_add(L_temp, st->prev_pow_sum);
7785d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
7795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* save power of current frame for next call */
7805d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    st->prev_pow_sum = L_temp;
7815d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
7825d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* If input power is very low, clear tone flag */
7835d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (pow_sum < POW_TONE_THR)
7845d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
7855d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        st->tone_flag = (Word16) (st->tone_flag & 0x1fff);
7865d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
7875d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Run the filter bank and calculate signal levels at each band */
7885d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    filter_bank(st, in_buf, level);
7895d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
7905d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* compute VAD decision */
7915d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    VAD_flag = vad_decision(st, level, pow_sum);
7925d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
7935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Calculate input level */
7945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_temp = 0;
7955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 1; i < COMPLEN; i++)          /* ignore lowest band */
7965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
7975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        L_temp = vo_L_add(L_temp, level[i]);
7985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
7995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
8005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    temp = extract_h(L_temp << 12);
8015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
8025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Estimate_Speech(st, temp);             /* Estimate speech level */
8035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return (VAD_flag);
804e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
805e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
806e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
807e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
808e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
809