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