1/*********************************************************************** 2Copyright (c) 2006-2011, Skype Limited. All rights reserved. 3Redistribution and use in source and binary forms, with or without 4modification, are permitted provided that the following conditions 5are met: 6- Redistributions of source code must retain the above copyright notice, 7this list of conditions and the following disclaimer. 8- Redistributions in binary form must reproduce the above copyright 9notice, this list of conditions and the following disclaimer in the 10documentation and/or other materials provided with the distribution. 11- Neither the name of Internet Society, IETF or IETF Trust, nor the 12names of specific contributors, may be used to endorse or promote 13products derived from this software without specific prior written 14permission. 15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25POSSIBILITY 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#include "NSQ.h" 35 36 37static OPUS_INLINE void silk_nsq_scale_states( 38 const silk_encoder_state *psEncC, /* I Encoder State */ 39 silk_nsq_state *NSQ, /* I/O NSQ state */ 40 const opus_int32 x_Q3[], /* I input in Q3 */ 41 opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ 42 const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ 43 opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ 44 opus_int subfr, /* I subframe number */ 45 const opus_int LTP_scale_Q14, /* I */ 46 const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ 47 const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ 48 const opus_int signal_type /* I Signal type */ 49); 50 51#if !defined(OPUS_X86_MAY_HAVE_SSE4_1) 52static OPUS_INLINE void silk_noise_shape_quantizer( 53 silk_nsq_state *NSQ, /* I/O NSQ state */ 54 opus_int signalType, /* I Signal type */ 55 const opus_int32 x_sc_Q10[], /* I */ 56 opus_int8 pulses[], /* O */ 57 opus_int16 xq[], /* O */ 58 opus_int32 sLTP_Q15[], /* I/O LTP state */ 59 const opus_int16 a_Q12[], /* I Short term prediction coefs */ 60 const opus_int16 b_Q14[], /* I Long term prediction coefs */ 61 const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ 62 opus_int lag, /* I Pitch lag */ 63 opus_int32 HarmShapeFIRPacked_Q14, /* I */ 64 opus_int Tilt_Q14, /* I Spectral tilt */ 65 opus_int32 LF_shp_Q14, /* I */ 66 opus_int32 Gain_Q16, /* I */ 67 opus_int Lambda_Q10, /* I */ 68 opus_int offset_Q10, /* I */ 69 opus_int length, /* I Input length */ 70 opus_int shapingLPCOrder, /* I Noise shaping AR filter order */ 71 opus_int predictLPCOrder, /* I Prediction filter order */ 72 int arch /* I Architecture */ 73); 74#endif 75 76void silk_NSQ_c 77( 78 const silk_encoder_state *psEncC, /* I/O Encoder State */ 79 silk_nsq_state *NSQ, /* I/O NSQ state */ 80 SideInfoIndices *psIndices, /* I/O Quantization Indices */ 81 const opus_int32 x_Q3[], /* I Prefiltered input signal */ 82 opus_int8 pulses[], /* O Quantized pulse signal */ 83 const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ 84 const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ 85 const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */ 86 const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */ 87 const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ 88 const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */ 89 const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */ 90 const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ 91 const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */ 92 const opus_int LTP_scale_Q14 /* I LTP state scaling */ 93) 94{ 95 opus_int k, lag, start_idx, LSF_interpolation_flag; 96 const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; 97 opus_int16 *pxq; 98 VARDECL( opus_int32, sLTP_Q15 ); 99 VARDECL( opus_int16, sLTP ); 100 opus_int32 HarmShapeFIRPacked_Q14; 101 opus_int offset_Q10; 102 VARDECL( opus_int32, x_sc_Q10 ); 103 SAVE_STACK; 104 105 NSQ->rand_seed = psIndices->Seed; 106 107 /* Set unvoiced lag to the previous one, overwrite later for voiced */ 108 lag = NSQ->lagPrev; 109 110 silk_assert( NSQ->prev_gain_Q16 != 0 ); 111 112 offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; 113 114 if( psIndices->NLSFInterpCoef_Q2 == 4 ) { 115 LSF_interpolation_flag = 0; 116 } else { 117 LSF_interpolation_flag = 1; 118 } 119 120 ALLOC( sLTP_Q15, 121 psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); 122 ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); 123 ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); 124 /* Set up pointers to start of sub frame */ 125 NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; 126 NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; 127 pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; 128 for( k = 0; k < psEncC->nb_subfr; k++ ) { 129 A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ]; 130 B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; 131 AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; 132 133 /* Noise shape parameters */ 134 silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); 135 HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); 136 HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); 137 138 NSQ->rewhite_flag = 0; 139 if( psIndices->signalType == TYPE_VOICED ) { 140 /* Voiced */ 141 lag = pitchL[ k ]; 142 143 /* Re-whitening */ 144 if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { 145 /* Rewhiten with new A coefs */ 146 start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; 147 silk_assert( start_idx > 0 ); 148 149 silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], 150 A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); 151 152 NSQ->rewhite_flag = 1; 153 NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; 154 } 155 } 156 157 silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType ); 158 159 silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14, 160 AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10, 161 offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch ); 162 163 x_Q3 += psEncC->subfr_length; 164 pulses += psEncC->subfr_length; 165 pxq += psEncC->subfr_length; 166 } 167 168 /* Update lagPrev for next frame */ 169 NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; 170 171 /* Save quantized speech and noise shaping signals */ 172 /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */ 173 silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); 174 silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); 175 RESTORE_STACK; 176} 177 178/***********************************/ 179/* silk_noise_shape_quantizer */ 180/***********************************/ 181 182#if !defined(OPUS_X86_MAY_HAVE_SSE4_1) 183static OPUS_INLINE 184#endif 185void silk_noise_shape_quantizer( 186 silk_nsq_state *NSQ, /* I/O NSQ state */ 187 opus_int signalType, /* I Signal type */ 188 const opus_int32 x_sc_Q10[], /* I */ 189 opus_int8 pulses[], /* O */ 190 opus_int16 xq[], /* O */ 191 opus_int32 sLTP_Q15[], /* I/O LTP state */ 192 const opus_int16 a_Q12[], /* I Short term prediction coefs */ 193 const opus_int16 b_Q14[], /* I Long term prediction coefs */ 194 const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ 195 opus_int lag, /* I Pitch lag */ 196 opus_int32 HarmShapeFIRPacked_Q14, /* I */ 197 opus_int Tilt_Q14, /* I Spectral tilt */ 198 opus_int32 LF_shp_Q14, /* I */ 199 opus_int32 Gain_Q16, /* I */ 200 opus_int Lambda_Q10, /* I */ 201 opus_int offset_Q10, /* I */ 202 opus_int length, /* I Input length */ 203 opus_int shapingLPCOrder, /* I Noise shaping AR filter order */ 204 opus_int predictLPCOrder, /* I Prediction filter order */ 205 int arch /* I Architecture */ 206) 207{ 208 opus_int i; 209 opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13; 210 opus_int32 n_LF_Q12, r_Q10, rr_Q10, q1_Q0, q1_Q10, q2_Q10, rd1_Q20, rd2_Q20; 211 opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; 212 opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; 213 opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; 214#ifdef silk_short_prediction_create_arch_coef 215 opus_int32 a_Q12_arch[MAX_LPC_ORDER]; 216#endif 217 218 shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; 219 pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; 220 Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); 221 222 /* Set up short term AR state */ 223 psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; 224 225#ifdef silk_short_prediction_create_arch_coef 226 silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder); 227#endif 228 229 for( i = 0; i < length; i++ ) { 230 /* Generate dither */ 231 NSQ->rand_seed = silk_RAND( NSQ->rand_seed ); 232 233 /* Short-term prediction */ 234 LPC_pred_Q10 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch); 235 236 /* Long-term prediction */ 237 if( signalType == TYPE_VOICED ) { 238 /* Unrolled loop */ 239 /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ 240 LTP_pred_Q13 = 2; 241 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); 242 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); 243 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); 244 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); 245 LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); 246 pred_lag_ptr++; 247 } else { 248 LTP_pred_Q13 = 0; 249 } 250 251 /* Noise shape feedback */ 252 silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ 253 n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(psLPC_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch); 254 255 n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 ); 256 257 n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ); 258 n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 ); 259 260 silk_assert( lag > 0 || signalType != TYPE_VOICED ); 261 262 /* Combine prediction and noise shaping signals */ 263 tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */ 264 tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */ 265 if( lag > 0 ) { 266 /* Symmetric, packed FIR coefficients */ 267 n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); 268 n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); 269 n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 ); 270 shp_lag_ptr++; 271 272 tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */ 273 tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */ 274 tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */ 275 } else { 276 tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */ 277 } 278 279 r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */ 280 281 /* Flip sign depending on dither */ 282 if ( NSQ->rand_seed < 0 ) { 283 r_Q10 = -r_Q10; 284 } 285 r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); 286 287 /* Find two quantization level candidates and measure their rate-distortion */ 288 q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); 289 q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); 290 if( q1_Q0 > 0 ) { 291 q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); 292 q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); 293 q2_Q10 = silk_ADD32( q1_Q10, 1024 ); 294 rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 ); 295 rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); 296 } else if( q1_Q0 == 0 ) { 297 q1_Q10 = offset_Q10; 298 q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); 299 rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 ); 300 rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); 301 } else if( q1_Q0 == -1 ) { 302 q2_Q10 = offset_Q10; 303 q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); 304 rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); 305 rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); 306 } else { /* Q1_Q0 < -1 */ 307 q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); 308 q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); 309 q2_Q10 = silk_ADD32( q1_Q10, 1024 ); 310 rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); 311 rd2_Q20 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); 312 } 313 rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); 314 rd1_Q20 = silk_SMLABB( rd1_Q20, rr_Q10, rr_Q10 ); 315 rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); 316 rd2_Q20 = silk_SMLABB( rd2_Q20, rr_Q10, rr_Q10 ); 317 318 if( rd2_Q20 < rd1_Q20 ) { 319 q1_Q10 = q2_Q10; 320 } 321 322 pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 ); 323 324 /* Excitation */ 325 exc_Q14 = silk_LSHIFT( q1_Q10, 4 ); 326 if ( NSQ->rand_seed < 0 ) { 327 exc_Q14 = -exc_Q14; 328 } 329 330 /* Add predictions */ 331 LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 ); 332 xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 ); 333 334 /* Scale XQ back to normal level before saving */ 335 xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q14, Gain_Q10 ), 8 ) ); 336 337 /* Update states */ 338 psLPC_Q14++; 339 *psLPC_Q14 = xq_Q14; 340 sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 ); 341 NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14; 342 343 NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 ); 344 sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 ); 345 NSQ->sLTP_shp_buf_idx++; 346 NSQ->sLTP_buf_idx++; 347 348 /* Make dither dependent on quantized signal */ 349 NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] ); 350 } 351 352 /* Update LPC synth buffer */ 353 silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); 354} 355 356static OPUS_INLINE void silk_nsq_scale_states( 357 const silk_encoder_state *psEncC, /* I Encoder State */ 358 silk_nsq_state *NSQ, /* I/O NSQ state */ 359 const opus_int32 x_Q3[], /* I input in Q3 */ 360 opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ 361 const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ 362 opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ 363 opus_int subfr, /* I subframe number */ 364 const opus_int LTP_scale_Q14, /* I */ 365 const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ 366 const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ 367 const opus_int signal_type /* I Signal type */ 368) 369{ 370 opus_int i, lag; 371 opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; 372 373 lag = pitchL[ subfr ]; 374 inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); 375 silk_assert( inv_gain_Q31 != 0 ); 376 377 /* Calculate gain adjustment factor */ 378 if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { 379 gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); 380 } else { 381 gain_adj_Q16 = (opus_int32)1 << 16; 382 } 383 384 /* Scale input */ 385 inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); 386 for( i = 0; i < psEncC->subfr_length; i++ ) { 387 x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); 388 } 389 390 /* Save inverse gain */ 391 NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; 392 393 /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ 394 if( NSQ->rewhite_flag ) { 395 if( subfr == 0 ) { 396 /* Do LTP downscaling */ 397 inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); 398 } 399 for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { 400 silk_assert( i < MAX_FRAME_LENGTH ); 401 sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); 402 } 403 } 404 405 /* Adjust for changing gain */ 406 if( gain_adj_Q16 != (opus_int32)1 << 16 ) { 407 /* Scale long-term shaping state */ 408 for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) { 409 NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); 410 } 411 412 /* Scale long-term prediction state */ 413 if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { 414 for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { 415 sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); 416 } 417 } 418 419 NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 ); 420 421 /* Scale short-term prediction and shaping states */ 422 for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { 423 NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] ); 424 } 425 for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { 426 NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] ); 427 } 428 } 429} 430