Coverage Report

Created: 2026-06-10 07:10

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
757k
{
50
757k
    opus_int b, ret = 0;
51
52
    /* reset state memory */
53
757k
    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.78M
    for( b = 0; b < VAD_N_BANDS; b++ ) {
58
3.02M
        psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 );
59
3.02M
    }
60
61
    /* Initialize state */
62
3.78M
    for( b = 0; b < VAD_N_BANDS; b++ ) {
63
3.02M
        psSilk_VAD->NL[ b ]     = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] );
64
3.02M
        psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] );
65
3.02M
    }
66
757k
    psSilk_VAD->counter = 15;
67
68
    /* init smoothed energy-to-noise ratio*/
69
3.78M
    for( b = 0; b < VAD_N_BANDS; b++ ) {
70
3.02M
        psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256;       /* 100 * 256 --> 20 dB SNR */
71
3.02M
    }
72
73
757k
    return( ret );
74
757k
}
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
23.8M
{
87
23.8M
    opus_int   SA_Q15, pSNR_dB_Q7, input_tilt;
88
23.8M
    opus_int   decimated_framelength1, decimated_framelength2;
89
23.8M
    opus_int   decimated_framelength;
90
23.8M
    opus_int   dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
91
23.8M
    opus_int32 sumSquared, smooth_coef_Q16;
92
23.8M
    opus_int16 HPstateTmp;
93
23.8M
    VARDECL( opus_int16, X );
94
23.8M
    opus_int32 Xnrg[ VAD_N_BANDS ];
95
23.8M
    opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
96
23.8M
    opus_int32 speech_nrg, x_tmp;
97
23.8M
    opus_int   X_offset[ VAD_N_BANDS ];
98
23.8M
    opus_int   ret = 0;
99
23.8M
    silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
100
23.8M
    SAVE_STACK;
101
102
    /* Safety checks */
103
23.8M
    silk_assert( VAD_N_BANDS == 4 );
104
23.8M
    celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
105
23.8M
    celt_assert( psEncC->frame_length <= 512 );
106
23.8M
    celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
107
108
    /***********************/
109
    /* Filter and Decimate */
110
    /***********************/
111
23.8M
    decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 );
112
23.8M
    decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 );
113
23.8M
    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
23.8M
    X_offset[ 0 ] = 0;
124
23.8M
    X_offset[ 1 ] = decimated_framelength + decimated_framelength2;
125
23.8M
    X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength;
126
23.8M
    X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2;
127
23.8M
    ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 );
128
129
    /* 0-8 kHz to 0-4 kHz and 4-8 kHz */
130
23.8M
    silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[  0 ],
131
23.8M
        X, &X[ X_offset[ 3 ] ], psEncC->frame_length );
132
133
    /* 0-4 kHz to 0-2 kHz and 2-4 kHz */
134
23.8M
    silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ],
135
23.8M
        X, &X[ X_offset[ 2 ] ], decimated_framelength1 );
136
137
    /* 0-2 kHz to 0-1 kHz and 1-2 kHz */
138
23.8M
    silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ],
139
23.8M
        X, &X[ X_offset[ 1 ] ], decimated_framelength2 );
140
141
    /*********************************************/
142
    /* HP filter on lowest band (differentiator) */
143
    /*********************************************/
144
23.8M
    X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 );
145
23.8M
    HPstateTmp = X[ decimated_framelength - 1 ];
146
452M
    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
23.8M
    X[ 0 ] -= psSilk_VAD->HPstate;
151
23.8M
    psSilk_VAD->HPstate = HPstateTmp;
152
153
    /*************************************/
154
    /* Calculate the energy in each band */
155
    /*************************************/
156
119M
    for( b = 0; b < VAD_N_BANDS; b++ ) {
157
        /* Find the decimated framelength in the non-uniformly divided bands */
158
95.2M
        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
95.2M
        dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
162
95.2M
        dec_subframe_offset = 0;
163
164
        /* Compute energy per sub-frame */
165
        /* initialize with summed energy of last subframe */
166
95.2M
        Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
167
476M
        for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
168
381M
            sumSquared = 0;
169
3.97G
            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
381M
            if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
182
285M
                Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
183
285M
            } else {
184
                /* Look-ahead subframe */
185
95.2M
                Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) );
186
95.2M
            }
187
188
381M
            dec_subframe_offset += dec_subframe_length;
189
381M
        }
190
95.2M
        psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
191
95.2M
    }
192
193
    /********************/
194
    /* Noise estimation */
195
    /********************/
196
23.8M
    silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );
197
198
    /***********************************************/
199
    /* Signal-plus-noise to noise ratio estimation */
200
    /***********************************************/
201
23.8M
    sumSquared = 0;
202
23.8M
    input_tilt = 0;
203
119M
    for( b = 0; b < VAD_N_BANDS; b++ ) {
204
95.2M
        speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
205
95.2M
        if( speech_nrg > 0 ) {
206
            /* Divide, with sufficient resolution */
207
1.75M
            if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
208
1.17M
                NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
209
1.17M
            } else {
210
572k
                NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
211
572k
            }
212
213
            /* Convert to log domain */
214
1.75M
            SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;
215
216
            /* Sum-of-squares */
217
1.75M
            sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 );          /* Q14 */
218
219
            /* Tilt measure */
220
1.75M
            if( speech_nrg < ( (opus_int32)1 << 20 ) ) {
221
                /* Scale down SNR value for small subband speech energies */
222
743k
                SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
223
743k
            }
224
1.75M
            input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
225
93.5M
        } else {
226
93.5M
            NrgToNoiseRatio_Q8[ b ] = 256;
227
93.5M
        }
228
95.2M
    }
229
230
    /* Mean-of-squares */
231
23.8M
    sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
232
233
    /* Root-mean-square approximation, scale to dBs, and write to output pointer */
234
23.8M
    pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
235
236
    /*********************************/
237
    /* Speech Probability Estimation */
238
    /*********************************/
239
23.8M
    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
23.8M
    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
23.8M
    speech_nrg = 0;
250
119M
    for( b = 0; b < VAD_N_BANDS; b++ ) {
251
        /* Accumulate signal-without-noise energies, higher frequency bands have more weight */
252
95.2M
        speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
253
95.2M
    }
254
255
23.8M
    if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
256
17.0M
        speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
257
17.0M
    }
258
    /* Power scaling */
259
23.8M
    if( speech_nrg <= 0 ) {
260
23.3M
        SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
261
23.3M
    } else if( speech_nrg < 16384 ) {
262
66.1k
        speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
263
264
        /* square-root */
265
66.1k
        speech_nrg = silk_SQRT_APPROX( speech_nrg );
266
66.1k
        SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 );
267
66.1k
    }
268
269
    /* Copy the resulting speech activity in Q8 */
270
23.8M
    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
23.8M
    smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) );
277
278
23.8M
    if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
279
6.72M
        smooth_coef_Q16 >>= 1;
280
6.72M
    }
281
282
119M
    for( b = 0; b < VAD_N_BANDS; b++ ) {
283
        /* compute smoothed energy-to-noise ratio per band */
284
95.2M
        psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ],
285
95.2M
            NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 );
286
287
        /* signal to noise ratio in dB per band */
288
95.2M
        SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 );
289
        /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */
290
95.2M
        psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
291
95.2M
    }
292
293
23.8M
    RESTORE_STACK;
294
23.8M
    return( ret );
295
23.8M
}
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
47.8M
{
308
47.8M
    opus_int   k;
309
47.8M
    opus_int32 nl, nrg, inv_nrg;
310
47.8M
    opus_int   coef, min_coef;
311
312
    /* Initially faster smoothing */
313
47.8M
    if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
314
4.08M
        min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
315
        /* Increment frame counter */
316
4.08M
        psSilk_VAD->counter++;
317
43.7M
    } else {
318
43.7M
        min_coef = 0;
319
43.7M
    }
320
321
239M
    for( k = 0; k < VAD_N_BANDS; k++ ) {
322
        /* Get old noise level estimate for current band */
323
191M
        nl = psSilk_VAD->NL[ k ];
324
191M
        silk_assert( nl >= 0 );
325
326
        /* Add bias */
327
191M
        nrg = silk_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] );
328
191M
        silk_assert( nrg > 0 );
329
330
        /* Invert energies */
331
191M
        inv_nrg = silk_DIV32( silk_int32_MAX, nrg );
332
191M
        silk_assert( inv_nrg >= 0 );
333
334
        /* Less update when subband energy is high */
335
191M
        if( nrg > silk_LSHIFT( nl, 3 ) ) {
336
3.06M
            coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3;
337
188M
        } else if( nrg < nl ) {
338
2.17M
            coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16;
339
186M
        } else {
340
186M
            coef = silk_SMULWB( silk_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 );
341
186M
        }
342
343
        /* Initially faster smoothing */
344
191M
        coef = silk_max_int( coef, min_coef );
345
346
        /* Smooth inverse energies */
347
191M
        psSilk_VAD->inv_NL[ k ] = silk_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef );
348
191M
        silk_assert( psSilk_VAD->inv_NL[ k ] >= 0 );
349
350
        /* Compute noise level by inverting again */
351
191M
        nl = silk_DIV32( silk_int32_MAX, psSilk_VAD->inv_NL[ k ] );
352
191M
        silk_assert( nl >= 0 );
353
354
        /* Limit noise levels (guarantee 7 bits of head room) */
355
191M
        nl = silk_min( nl, 0x00FFFFFF );
356
357
        /* Store as part of state */
358
191M
        psSilk_VAD->NL[ k ] = nl;
359
191M
    }
360
47.8M
}