1*a58d3d2aSXin Li /***********************************************************************
2*a58d3d2aSXin Li Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3*a58d3d2aSXin Li Redistribution and use in source and binary forms, with or without
4*a58d3d2aSXin Li modification, are permitted provided that the following conditions
5*a58d3d2aSXin Li are met:
6*a58d3d2aSXin Li - Redistributions of source code must retain the above copyright notice,
7*a58d3d2aSXin Li this list of conditions and the following disclaimer.
8*a58d3d2aSXin Li - Redistributions in binary form must reproduce the above copyright
9*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer in the
10*a58d3d2aSXin Li documentation and/or other materials provided with the distribution.
11*a58d3d2aSXin Li - Neither the name of Internet Society, IETF or IETF Trust, nor the
12*a58d3d2aSXin Li names of specific contributors, may be used to endorse or promote
13*a58d3d2aSXin Li products derived from this software without specific prior written
14*a58d3d2aSXin Li permission.
15*a58d3d2aSXin Li THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*a58d3d2aSXin Li AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*a58d3d2aSXin Li IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*a58d3d2aSXin Li ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19*a58d3d2aSXin Li LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*a58d3d2aSXin Li CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*a58d3d2aSXin Li SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*a58d3d2aSXin Li INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*a58d3d2aSXin Li CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*a58d3d2aSXin Li ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*a58d3d2aSXin Li POSSIBILITY OF SUCH DAMAGE.
26*a58d3d2aSXin Li ***********************************************************************/
27*a58d3d2aSXin Li
28*a58d3d2aSXin Li #ifdef HAVE_CONFIG_H
29*a58d3d2aSXin Li #include "config.h"
30*a58d3d2aSXin Li #endif
31*a58d3d2aSXin Li
32*a58d3d2aSXin Li #include "main.h"
33*a58d3d2aSXin Li #include "stack_alloc.h"
34*a58d3d2aSXin Li
35*a58d3d2aSXin Li /* Silk VAD noise level estimation */
36*a58d3d2aSXin Li # if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
37*a58d3d2aSXin Li static OPUS_INLINE void silk_VAD_GetNoiseLevels(
38*a58d3d2aSXin Li const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
39*a58d3d2aSXin Li silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
40*a58d3d2aSXin Li );
41*a58d3d2aSXin Li #endif
42*a58d3d2aSXin Li
43*a58d3d2aSXin Li /**********************************/
44*a58d3d2aSXin Li /* Initialization of the Silk VAD */
45*a58d3d2aSXin Li /**********************************/
silk_VAD_Init(silk_VAD_state * psSilk_VAD)46*a58d3d2aSXin Li opus_int silk_VAD_Init( /* O Return value, 0 if success */
47*a58d3d2aSXin Li silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
48*a58d3d2aSXin Li )
49*a58d3d2aSXin Li {
50*a58d3d2aSXin Li opus_int b, ret = 0;
51*a58d3d2aSXin Li
52*a58d3d2aSXin Li /* reset state memory */
53*a58d3d2aSXin Li silk_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) );
54*a58d3d2aSXin Li
55*a58d3d2aSXin Li /* init noise levels */
56*a58d3d2aSXin Li /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */
57*a58d3d2aSXin Li for( b = 0; b < VAD_N_BANDS; b++ ) {
58*a58d3d2aSXin Li psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 );
59*a58d3d2aSXin Li }
60*a58d3d2aSXin Li
61*a58d3d2aSXin Li /* Initialize state */
62*a58d3d2aSXin Li for( b = 0; b < VAD_N_BANDS; b++ ) {
63*a58d3d2aSXin Li psSilk_VAD->NL[ b ] = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] );
64*a58d3d2aSXin Li psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] );
65*a58d3d2aSXin Li }
66*a58d3d2aSXin Li psSilk_VAD->counter = 15;
67*a58d3d2aSXin Li
68*a58d3d2aSXin Li /* init smoothed energy-to-noise ratio*/
69*a58d3d2aSXin Li for( b = 0; b < VAD_N_BANDS; b++ ) {
70*a58d3d2aSXin Li psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */
71*a58d3d2aSXin Li }
72*a58d3d2aSXin Li
73*a58d3d2aSXin Li return( ret );
74*a58d3d2aSXin Li }
75*a58d3d2aSXin Li
76*a58d3d2aSXin Li /* Weighting factors for tilt measure */
77*a58d3d2aSXin Li static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 };
78*a58d3d2aSXin Li
79*a58d3d2aSXin Li /***************************************/
80*a58d3d2aSXin Li /* Get the speech activity level in Q8 */
81*a58d3d2aSXin Li /***************************************/
silk_VAD_GetSA_Q8_c(silk_encoder_state * psEncC,const opus_int16 pIn[])82*a58d3d2aSXin Li opus_int silk_VAD_GetSA_Q8_c( /* O Return value, 0 if success */
83*a58d3d2aSXin Li silk_encoder_state *psEncC, /* I/O Encoder state */
84*a58d3d2aSXin Li const opus_int16 pIn[] /* I PCM input */
85*a58d3d2aSXin Li )
86*a58d3d2aSXin Li {
87*a58d3d2aSXin Li opus_int SA_Q15, pSNR_dB_Q7, input_tilt;
88*a58d3d2aSXin Li opus_int decimated_framelength1, decimated_framelength2;
89*a58d3d2aSXin Li opus_int decimated_framelength;
90*a58d3d2aSXin Li opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
91*a58d3d2aSXin Li opus_int32 sumSquared, smooth_coef_Q16;
92*a58d3d2aSXin Li opus_int16 HPstateTmp;
93*a58d3d2aSXin Li VARDECL( opus_int16, X );
94*a58d3d2aSXin Li opus_int32 Xnrg[ VAD_N_BANDS ];
95*a58d3d2aSXin Li opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
96*a58d3d2aSXin Li opus_int32 speech_nrg, x_tmp;
97*a58d3d2aSXin Li opus_int X_offset[ VAD_N_BANDS ];
98*a58d3d2aSXin Li opus_int ret = 0;
99*a58d3d2aSXin Li silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
100*a58d3d2aSXin Li SAVE_STACK;
101*a58d3d2aSXin Li
102*a58d3d2aSXin Li /* Safety checks */
103*a58d3d2aSXin Li silk_assert( VAD_N_BANDS == 4 );
104*a58d3d2aSXin Li celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
105*a58d3d2aSXin Li celt_assert( psEncC->frame_length <= 512 );
106*a58d3d2aSXin Li celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
107*a58d3d2aSXin Li
108*a58d3d2aSXin Li /***********************/
109*a58d3d2aSXin Li /* Filter and Decimate */
110*a58d3d2aSXin Li /***********************/
111*a58d3d2aSXin Li decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 );
112*a58d3d2aSXin Li decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 );
113*a58d3d2aSXin Li decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
114*a58d3d2aSXin Li /* Decimate into 4 bands:
115*a58d3d2aSXin Li 0 L 3L L 3L 5L
116*a58d3d2aSXin Li - -- - -- --
117*a58d3d2aSXin Li 8 8 2 4 4
118*a58d3d2aSXin Li
119*a58d3d2aSXin Li [0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz |
120*a58d3d2aSXin Li
121*a58d3d2aSXin Li They're arranged to allow the minimal ( frame_length / 4 ) extra
122*a58d3d2aSXin Li scratch space during the downsampling process */
123*a58d3d2aSXin Li X_offset[ 0 ] = 0;
124*a58d3d2aSXin Li X_offset[ 1 ] = decimated_framelength + decimated_framelength2;
125*a58d3d2aSXin Li X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength;
126*a58d3d2aSXin Li X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2;
127*a58d3d2aSXin Li ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 );
128*a58d3d2aSXin Li
129*a58d3d2aSXin Li /* 0-8 kHz to 0-4 kHz and 4-8 kHz */
130*a58d3d2aSXin Li silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ],
131*a58d3d2aSXin Li X, &X[ X_offset[ 3 ] ], psEncC->frame_length );
132*a58d3d2aSXin Li
133*a58d3d2aSXin Li /* 0-4 kHz to 0-2 kHz and 2-4 kHz */
134*a58d3d2aSXin Li silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ],
135*a58d3d2aSXin Li X, &X[ X_offset[ 2 ] ], decimated_framelength1 );
136*a58d3d2aSXin Li
137*a58d3d2aSXin Li /* 0-2 kHz to 0-1 kHz and 1-2 kHz */
138*a58d3d2aSXin Li silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ],
139*a58d3d2aSXin Li X, &X[ X_offset[ 1 ] ], decimated_framelength2 );
140*a58d3d2aSXin Li
141*a58d3d2aSXin Li /*********************************************/
142*a58d3d2aSXin Li /* HP filter on lowest band (differentiator) */
143*a58d3d2aSXin Li /*********************************************/
144*a58d3d2aSXin Li X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 );
145*a58d3d2aSXin Li HPstateTmp = X[ decimated_framelength - 1 ];
146*a58d3d2aSXin Li for( i = decimated_framelength - 1; i > 0; i-- ) {
147*a58d3d2aSXin Li X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 );
148*a58d3d2aSXin Li X[ i ] -= X[ i - 1 ];
149*a58d3d2aSXin Li }
150*a58d3d2aSXin Li X[ 0 ] -= psSilk_VAD->HPstate;
151*a58d3d2aSXin Li psSilk_VAD->HPstate = HPstateTmp;
152*a58d3d2aSXin Li
153*a58d3d2aSXin Li /*************************************/
154*a58d3d2aSXin Li /* Calculate the energy in each band */
155*a58d3d2aSXin Li /*************************************/
156*a58d3d2aSXin Li for( b = 0; b < VAD_N_BANDS; b++ ) {
157*a58d3d2aSXin Li /* Find the decimated framelength in the non-uniformly divided bands */
158*a58d3d2aSXin Li decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) );
159*a58d3d2aSXin Li
160*a58d3d2aSXin Li /* Split length into subframe lengths */
161*a58d3d2aSXin Li dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
162*a58d3d2aSXin Li dec_subframe_offset = 0;
163*a58d3d2aSXin Li
164*a58d3d2aSXin Li /* Compute energy per sub-frame */
165*a58d3d2aSXin Li /* initialize with summed energy of last subframe */
166*a58d3d2aSXin Li Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
167*a58d3d2aSXin Li for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
168*a58d3d2aSXin Li sumSquared = 0;
169*a58d3d2aSXin Li for( i = 0; i < dec_subframe_length; i++ ) {
170*a58d3d2aSXin Li /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */
171*a58d3d2aSXin Li /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */
172*a58d3d2aSXin Li x_tmp = silk_RSHIFT(
173*a58d3d2aSXin Li X[ X_offset[ b ] + i + dec_subframe_offset ], 3 );
174*a58d3d2aSXin Li sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp );
175*a58d3d2aSXin Li
176*a58d3d2aSXin Li /* Safety check */
177*a58d3d2aSXin Li silk_assert( sumSquared >= 0 );
178*a58d3d2aSXin Li }
179*a58d3d2aSXin Li
180*a58d3d2aSXin Li /* Add/saturate summed energy of current subframe */
181*a58d3d2aSXin Li if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
182*a58d3d2aSXin Li Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
183*a58d3d2aSXin Li } else {
184*a58d3d2aSXin Li /* Look-ahead subframe */
185*a58d3d2aSXin Li Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) );
186*a58d3d2aSXin Li }
187*a58d3d2aSXin Li
188*a58d3d2aSXin Li dec_subframe_offset += dec_subframe_length;
189*a58d3d2aSXin Li }
190*a58d3d2aSXin Li psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
191*a58d3d2aSXin Li }
192*a58d3d2aSXin Li
193*a58d3d2aSXin Li /********************/
194*a58d3d2aSXin Li /* Noise estimation */
195*a58d3d2aSXin Li /********************/
196*a58d3d2aSXin Li silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );
197*a58d3d2aSXin Li
198*a58d3d2aSXin Li /***********************************************/
199*a58d3d2aSXin Li /* Signal-plus-noise to noise ratio estimation */
200*a58d3d2aSXin Li /***********************************************/
201*a58d3d2aSXin Li sumSquared = 0;
202*a58d3d2aSXin Li input_tilt = 0;
203*a58d3d2aSXin Li for( b = 0; b < VAD_N_BANDS; b++ ) {
204*a58d3d2aSXin Li speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
205*a58d3d2aSXin Li if( speech_nrg > 0 ) {
206*a58d3d2aSXin Li /* Divide, with sufficient resolution */
207*a58d3d2aSXin Li if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
208*a58d3d2aSXin Li NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
209*a58d3d2aSXin Li } else {
210*a58d3d2aSXin Li NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
211*a58d3d2aSXin Li }
212*a58d3d2aSXin Li
213*a58d3d2aSXin Li /* Convert to log domain */
214*a58d3d2aSXin Li SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;
215*a58d3d2aSXin Li
216*a58d3d2aSXin Li /* Sum-of-squares */
217*a58d3d2aSXin Li sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */
218*a58d3d2aSXin Li
219*a58d3d2aSXin Li /* Tilt measure */
220*a58d3d2aSXin Li if( speech_nrg < ( (opus_int32)1 << 20 ) ) {
221*a58d3d2aSXin Li /* Scale down SNR value for small subband speech energies */
222*a58d3d2aSXin Li SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
223*a58d3d2aSXin Li }
224*a58d3d2aSXin Li input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
225*a58d3d2aSXin Li } else {
226*a58d3d2aSXin Li NrgToNoiseRatio_Q8[ b ] = 256;
227*a58d3d2aSXin Li }
228*a58d3d2aSXin Li }
229*a58d3d2aSXin Li
230*a58d3d2aSXin Li /* Mean-of-squares */
231*a58d3d2aSXin Li sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
232*a58d3d2aSXin Li
233*a58d3d2aSXin Li /* Root-mean-square approximation, scale to dBs, and write to output pointer */
234*a58d3d2aSXin Li pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
235*a58d3d2aSXin Li
236*a58d3d2aSXin Li /*********************************/
237*a58d3d2aSXin Li /* Speech Probability Estimation */
238*a58d3d2aSXin Li /*********************************/
239*a58d3d2aSXin Li SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 );
240*a58d3d2aSXin Li
241*a58d3d2aSXin Li /**************************/
242*a58d3d2aSXin Li /* Frequency Tilt Measure */
243*a58d3d2aSXin Li /**************************/
244*a58d3d2aSXin Li psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 );
245*a58d3d2aSXin Li
246*a58d3d2aSXin Li /**************************************************/
247*a58d3d2aSXin Li /* Scale the sigmoid output based on power levels */
248*a58d3d2aSXin Li /**************************************************/
249*a58d3d2aSXin Li speech_nrg = 0;
250*a58d3d2aSXin Li for( b = 0; b < VAD_N_BANDS; b++ ) {
251*a58d3d2aSXin Li /* Accumulate signal-without-noise energies, higher frequency bands have more weight */
252*a58d3d2aSXin Li speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
253*a58d3d2aSXin Li }
254*a58d3d2aSXin Li
255*a58d3d2aSXin Li if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
256*a58d3d2aSXin Li speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
257*a58d3d2aSXin Li }
258*a58d3d2aSXin Li /* Power scaling */
259*a58d3d2aSXin Li if( speech_nrg <= 0 ) {
260*a58d3d2aSXin Li SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
261*a58d3d2aSXin Li } else if( speech_nrg < 16384 ) {
262*a58d3d2aSXin Li speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
263*a58d3d2aSXin Li
264*a58d3d2aSXin Li /* square-root */
265*a58d3d2aSXin Li speech_nrg = silk_SQRT_APPROX( speech_nrg );
266*a58d3d2aSXin Li SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 );
267*a58d3d2aSXin Li }
268*a58d3d2aSXin Li
269*a58d3d2aSXin Li /* Copy the resulting speech activity in Q8 */
270*a58d3d2aSXin Li psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX );
271*a58d3d2aSXin Li
272*a58d3d2aSXin Li /***********************************/
273*a58d3d2aSXin Li /* Energy Level and SNR estimation */
274*a58d3d2aSXin Li /***********************************/
275*a58d3d2aSXin Li /* Smoothing coefficient */
276*a58d3d2aSXin Li smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) );
277*a58d3d2aSXin Li
278*a58d3d2aSXin Li if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
279*a58d3d2aSXin Li smooth_coef_Q16 >>= 1;
280*a58d3d2aSXin Li }
281*a58d3d2aSXin Li
282*a58d3d2aSXin Li for( b = 0; b < VAD_N_BANDS; b++ ) {
283*a58d3d2aSXin Li /* compute smoothed energy-to-noise ratio per band */
284*a58d3d2aSXin Li psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ],
285*a58d3d2aSXin Li NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 );
286*a58d3d2aSXin Li
287*a58d3d2aSXin Li /* signal to noise ratio in dB per band */
288*a58d3d2aSXin Li SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 );
289*a58d3d2aSXin Li /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */
290*a58d3d2aSXin Li psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
291*a58d3d2aSXin Li }
292*a58d3d2aSXin Li
293*a58d3d2aSXin Li RESTORE_STACK;
294*a58d3d2aSXin Li return( ret );
295*a58d3d2aSXin Li }
296*a58d3d2aSXin Li
297*a58d3d2aSXin Li /**************************/
298*a58d3d2aSXin Li /* Noise level estimation */
299*a58d3d2aSXin Li /**************************/
300*a58d3d2aSXin Li # if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
301*a58d3d2aSXin Li static OPUS_INLINE
302*a58d3d2aSXin Li #endif
silk_VAD_GetNoiseLevels(const opus_int32 pX[VAD_N_BANDS],silk_VAD_state * psSilk_VAD)303*a58d3d2aSXin Li void silk_VAD_GetNoiseLevels(
304*a58d3d2aSXin Li const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
305*a58d3d2aSXin Li silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
306*a58d3d2aSXin Li )
307*a58d3d2aSXin Li {
308*a58d3d2aSXin Li opus_int k;
309*a58d3d2aSXin Li opus_int32 nl, nrg, inv_nrg;
310*a58d3d2aSXin Li opus_int coef, min_coef;
311*a58d3d2aSXin Li
312*a58d3d2aSXin Li /* Initially faster smoothing */
313*a58d3d2aSXin Li if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
314*a58d3d2aSXin Li min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
315*a58d3d2aSXin Li /* Increment frame counter */
316*a58d3d2aSXin Li psSilk_VAD->counter++;
317*a58d3d2aSXin Li } else {
318*a58d3d2aSXin Li min_coef = 0;
319*a58d3d2aSXin Li }
320*a58d3d2aSXin Li
321*a58d3d2aSXin Li for( k = 0; k < VAD_N_BANDS; k++ ) {
322*a58d3d2aSXin Li /* Get old noise level estimate for current band */
323*a58d3d2aSXin Li nl = psSilk_VAD->NL[ k ];
324*a58d3d2aSXin Li silk_assert( nl >= 0 );
325*a58d3d2aSXin Li
326*a58d3d2aSXin Li /* Add bias */
327*a58d3d2aSXin Li nrg = silk_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] );
328*a58d3d2aSXin Li silk_assert( nrg > 0 );
329*a58d3d2aSXin Li
330*a58d3d2aSXin Li /* Invert energies */
331*a58d3d2aSXin Li inv_nrg = silk_DIV32( silk_int32_MAX, nrg );
332*a58d3d2aSXin Li silk_assert( inv_nrg >= 0 );
333*a58d3d2aSXin Li
334*a58d3d2aSXin Li /* Less update when subband energy is high */
335*a58d3d2aSXin Li if( nrg > silk_LSHIFT( nl, 3 ) ) {
336*a58d3d2aSXin Li coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3;
337*a58d3d2aSXin Li } else if( nrg < nl ) {
338*a58d3d2aSXin Li coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16;
339*a58d3d2aSXin Li } else {
340*a58d3d2aSXin Li coef = silk_SMULWB( silk_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 );
341*a58d3d2aSXin Li }
342*a58d3d2aSXin Li
343*a58d3d2aSXin Li /* Initially faster smoothing */
344*a58d3d2aSXin Li coef = silk_max_int( coef, min_coef );
345*a58d3d2aSXin Li
346*a58d3d2aSXin Li /* Smooth inverse energies */
347*a58d3d2aSXin Li psSilk_VAD->inv_NL[ k ] = silk_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef );
348*a58d3d2aSXin Li silk_assert( psSilk_VAD->inv_NL[ k ] >= 0 );
349*a58d3d2aSXin Li
350*a58d3d2aSXin Li /* Compute noise level by inverting again */
351*a58d3d2aSXin Li nl = silk_DIV32( silk_int32_MAX, psSilk_VAD->inv_NL[ k ] );
352*a58d3d2aSXin Li silk_assert( nl >= 0 );
353*a58d3d2aSXin Li
354*a58d3d2aSXin Li /* Limit noise levels (guarantee 7 bits of head room) */
355*a58d3d2aSXin Li nl = silk_min( nl, 0x00FFFFFF );
356*a58d3d2aSXin Li
357*a58d3d2aSXin Li /* Store as part of state */
358*a58d3d2aSXin Li psSilk_VAD->NL[ k ] = nl;
359*a58d3d2aSXin Li }
360*a58d3d2aSXin Li }
361