Coverage Report

Created: 2026-02-14 07:28

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