annotate src/opus-1.3/silk/x86/VAD_sse4_1.c @ 83:ae30d91d2ffe

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