Coverage Report

Created: 2024-09-06 07:53

/src/opus/silk/x86/VAD_sse4_1.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2014-2020, Cisco Systems, INC
2
   Written by XiangMingZhu WeiZhou MinPeng YanWang FrancisQuiers
3
4
   Redistribution and use in source and binary forms, with or without
5
   modification, are permitted provided that the following conditions
6
   are met:
7
8
   - Redistributions of source code must retain the above copyright
9
   notice, this list of conditions and the following disclaimer.
10
11
   - Redistributions in binary form must reproduce the above copyright
12
   notice, this list of conditions and the following disclaimer in the
13
   documentation and/or other materials provided with the distribution.
14
15
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19
   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
28
#ifdef HAVE_CONFIG_H
29
#include "config.h"
30
#endif
31
32
#include <xmmintrin.h>
33
#include <emmintrin.h>
34
#include <smmintrin.h>
35
36
#include "main.h"
37
#include "stack_alloc.h"
38
39
/* Weighting factors for tilt measure */
40
static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 };
41
42
/***************************************/
43
/* Get the speech activity level in Q8 */
44
/***************************************/
45
opus_int silk_VAD_GetSA_Q8_sse4_1(                  /* O    Return value, 0 if success                  */
46
    silk_encoder_state          *psEncC,            /* I/O  Encoder state                               */
47
    const opus_int16            pIn[]               /* I    PCM input                                   */
48
)
49
0
{
50
0
    opus_int   SA_Q15, pSNR_dB_Q7, input_tilt;
51
0
    opus_int   decimated_framelength1, decimated_framelength2;
52
0
    opus_int   decimated_framelength;
53
0
    opus_int   dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
54
0
    opus_int32 sumSquared, smooth_coef_Q16;
55
0
    opus_int16 HPstateTmp;
56
0
    VARDECL( opus_int16, X );
57
0
    opus_int32 Xnrg[ VAD_N_BANDS ];
58
0
    opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
59
0
    opus_int32 speech_nrg, x_tmp;
60
0
    opus_int   X_offset[ VAD_N_BANDS ];
61
0
    opus_int   ret = 0;
62
0
    silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
63
64
0
    SAVE_STACK;
65
66
#ifdef OPUS_CHECK_ASM
67
    silk_encoder_state psEncC_c;
68
    opus_int ret_c;
69
70
    silk_memcpy( &psEncC_c, psEncC, sizeof( psEncC_c ) );
71
    ret_c = silk_VAD_GetSA_Q8_c( &psEncC_c, pIn );
72
#endif
73
74
    /* Safety checks */
75
0
    silk_assert( VAD_N_BANDS == 4 );
76
0
    celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
77
0
    celt_assert( psEncC->frame_length <= 512 );
78
0
    celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
79
80
    /***********************/
81
    /* Filter and Decimate */
82
    /***********************/
83
0
    decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 );
84
0
    decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 );
85
0
    decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
86
    /* Decimate into 4 bands:
87
       0       L      3L       L              3L                             5L
88
               -      --       -              --                             --
89
               8       8       2               4                              4
90
91
       [0-1 kHz| temp. |1-2 kHz|    2-4 kHz    |            4-8 kHz           |
92
93
       They're arranged to allow the minimal ( frame_length / 4 ) extra
94
       scratch space during the downsampling process */
95
0
    X_offset[ 0 ] = 0;
96
0
    X_offset[ 1 ] = decimated_framelength + decimated_framelength2;
97
0
    X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength;
98
0
    X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2;
99
0
    ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 );
100
101
    /* 0-8 kHz to 0-4 kHz and 4-8 kHz */
102
0
    silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[  0 ],
103
0
        X, &X[ X_offset[ 3 ] ], psEncC->frame_length );
104
105
    /* 0-4 kHz to 0-2 kHz and 2-4 kHz */
106
0
    silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ],
107
0
        X, &X[ X_offset[ 2 ] ], decimated_framelength1 );
108
109
    /* 0-2 kHz to 0-1 kHz and 1-2 kHz */
110
0
    silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ],
111
0
        X, &X[ X_offset[ 1 ] ], decimated_framelength2 );
112
113
    /*********************************************/
114
    /* HP filter on lowest band (differentiator) */
115
    /*********************************************/
116
0
    X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 );
117
0
    HPstateTmp = X[ decimated_framelength - 1 ];
118
0
    for( i = decimated_framelength - 1; i > 0; i-- ) {
119
0
        X[ i - 1 ]  = silk_RSHIFT( X[ i - 1 ], 1 );
120
0
        X[ i ]     -= X[ i - 1 ];
121
0
    }
122
0
    X[ 0 ] -= psSilk_VAD->HPstate;
123
0
    psSilk_VAD->HPstate = HPstateTmp;
124
125
    /*************************************/
126
    /* Calculate the energy in each band */
127
    /*************************************/
128
0
    for( b = 0; b < VAD_N_BANDS; b++ ) {
129
        /* Find the decimated framelength in the non-uniformly divided bands */
130
0
        decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) );
131
132
        /* Split length into subframe lengths */
133
0
        dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
134
0
        dec_subframe_offset = 0;
135
136
        /* Compute energy per sub-frame */
137
        /* initialize with summed energy of last subframe */
138
0
        Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
139
0
        for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
140
0
            __m128i xmm_X, xmm_acc;
141
0
            sumSquared = 0;
142
143
0
            xmm_acc = _mm_setzero_si128();
144
145
0
            for( i = 0; i < dec_subframe_length - 7; i += 8 )
146
0
            {
147
0
                xmm_X   = _mm_loadu_si128( (__m128i *)(void*)&(X[ X_offset[ b ] + i + dec_subframe_offset ] ) );
148
0
                xmm_X   = _mm_srai_epi16( xmm_X, 3 );
149
0
                xmm_X   = _mm_madd_epi16( xmm_X, xmm_X );
150
0
                xmm_acc = _mm_add_epi32( xmm_acc, xmm_X );
151
0
            }
152
153
0
            xmm_acc = _mm_add_epi32( xmm_acc, _mm_unpackhi_epi64( xmm_acc, xmm_acc ) );
154
0
            xmm_acc = _mm_add_epi32( xmm_acc, _mm_shufflelo_epi16( xmm_acc, 0x0E ) );
155
156
0
            sumSquared += _mm_cvtsi128_si32( xmm_acc );
157
158
0
            for( ; i < dec_subframe_length; i++ ) {
159
                /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2.            */
160
                /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128)  */
161
0
                x_tmp = silk_RSHIFT(
162
0
                    X[ X_offset[ b ] + i + dec_subframe_offset ], 3 );
163
0
                sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp );
164
165
                /* Safety check */
166
0
                silk_assert( sumSquared >= 0 );
167
0
            }
168
169
            /* Add/saturate summed energy of current subframe */
170
0
            if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
171
0
                Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
172
0
            } else {
173
                /* Look-ahead subframe */
174
0
                Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) );
175
0
            }
176
177
0
            dec_subframe_offset += dec_subframe_length;
178
0
        }
179
0
        psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
180
0
    }
181
182
    /********************/
183
    /* Noise estimation */
184
    /********************/
185
0
    silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );
186
187
    /***********************************************/
188
    /* Signal-plus-noise to noise ratio estimation */
189
    /***********************************************/
190
0
    sumSquared = 0;
191
0
    input_tilt = 0;
192
0
    for( b = 0; b < VAD_N_BANDS; b++ ) {
193
0
        speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
194
0
        if( speech_nrg > 0 ) {
195
            /* Divide, with sufficient resolution */
196
0
            if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
197
0
                NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
198
0
            } else {
199
0
                NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
200
0
            }
201
202
            /* Convert to log domain */
203
0
            SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;
204
205
            /* Sum-of-squares */
206
0
            sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 );          /* Q14 */
207
208
            /* Tilt measure */
209
0
            if( speech_nrg < ( (opus_int32)1 << 20 ) ) {
210
                /* Scale down SNR value for small subband speech energies */
211
0
                SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
212
0
            }
213
0
            input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
214
0
        } else {
215
0
            NrgToNoiseRatio_Q8[ b ] = 256;
216
0
        }
217
0
    }
218
219
    /* Mean-of-squares */
220
0
    sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
221
222
    /* Root-mean-square approximation, scale to dBs, and write to output pointer */
223
0
    pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
224
225
    /*********************************/
226
    /* Speech Probability Estimation */
227
    /*********************************/
228
0
    SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 );
229
230
    /**************************/
231
    /* Frequency Tilt Measure */
232
    /**************************/
233
0
    psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 );
234
235
    /**************************************************/
236
    /* Scale the sigmoid output based on power levels */
237
    /**************************************************/
238
0
    speech_nrg = 0;
239
0
    for( b = 0; b < VAD_N_BANDS; b++ ) {
240
        /* Accumulate signal-without-noise energies, higher frequency bands have more weight */
241
0
        speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
242
0
    }
243
244
0
    if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
245
0
        speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
246
0
    }
247
    /* Power scaling */
248
0
    if( speech_nrg <= 0 ) {
249
0
        SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
250
0
    } else if( speech_nrg < 16384 ) {
251
0
        speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
252
253
        /* square-root */
254
0
        speech_nrg = silk_SQRT_APPROX( speech_nrg );
255
0
        SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 );
256
0
    }
257
258
    /* Copy the resulting speech activity in Q8 */
259
0
    psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX );
260
261
    /***********************************/
262
    /* Energy Level and SNR estimation */
263
    /***********************************/
264
    /* Smoothing coefficient */
265
0
    smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) );
266
267
0
    if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
268
0
        smooth_coef_Q16 >>= 1;
269
0
    }
270
271
0
    for( b = 0; b < VAD_N_BANDS; b++ ) {
272
        /* compute smoothed energy-to-noise ratio per band */
273
0
        psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ],
274
0
            NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 );
275
276
        /* signal to noise ratio in dB per band */
277
0
        SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 );
278
        /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */
279
0
        psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
280
0
    }
281
282
#ifdef OPUS_CHECK_ASM
283
    silk_assert( ret == ret_c );
284
    silk_assert( !memcmp( &psEncC_c, psEncC, sizeof( psEncC_c ) ) );
285
#endif
286
287
0
    RESTORE_STACK;
288
0
    return( ret );
289
0
}