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 29 /**************************************************************/ 30 /* Compute noise shaping coefficients and initial gain values */ 31 /**************************************************************/ 32 #define OVERRIDE_silk_noise_shape_analysis_FIX 33 34 void silk_noise_shape_analysis_FIX( 35 silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ 36 silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ 37 const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ 38 const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */ 39 int arch /* I Run-time architecture */ 40 ) 41 { 42 silk_shape_state_FIX *psShapeSt = &psEnc->sShape; 43 opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; 44 opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; 45 opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; 46 opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; 47 opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; 48 opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; 49 opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; 50 opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; 51 VARDECL( opus_int16, x_windowed ); 52 const opus_int16 *x_ptr, *pitch_res_ptr; 53 SAVE_STACK; 54 55 /* Point to start of first LPC analysis block */ 56 x_ptr = x - psEnc->sCmn.la_shape; 57 58 /****************/ 59 /* GAIN CONTROL */ 60 /****************/ 61 SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; 62 63 /* Input quality is the average of the quality in the lowest two VAD bands */ 64 psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] 65 + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); 66 67 /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ 68 psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - 69 SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); 70 71 /* Reduce coding SNR during low speech activity */ 72 if( psEnc->sCmn.useCBR == 0 ) { 73 b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; 74 b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 ); 75 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, 76 silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/ 77 silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/ 78 } 79 80 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { 81 /* Reduce gains for periodic signals */ 82 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); 83 } else { 84 /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ 85 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, 86 silk_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ), 87 SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); 88 } 89 90 /*************************/ 91 /* SPARSENESS PROCESSING */ 92 /*************************/ 93 /* Set quantizer offset */ 94 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { 95 /* Initially set to 0; may be overruled in process_gains(..) */ 96 psEnc->sCmn.indices.quantOffsetType = 0; 97 psEncCtrl->sparseness_Q8 = 0; 98 } else { 99 /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ 100 nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); 101 energy_variation_Q7 = 0; 102 log_energy_prev_Q7 = 0; 103 pitch_res_ptr = pitch_res; 104 for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { 105 silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); 106 nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/ 107 108 log_energy_Q7 = silk_lin2log( nrg ); 109 if( k > 0 ) { 110 energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 ); 111 } 112 log_energy_prev_Q7 = log_energy_Q7; 113 pitch_res_ptr += nSamples; 114 } 115 116 psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 - 117 SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 ); 118 119 /* Set quantization offset depending on sparseness measure */ 120 if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { 121 psEnc->sCmn.indices.quantOffsetType = 0; 122 } else { 123 psEnc->sCmn.indices.quantOffsetType = 1; 124 } 125 126 /* Increase coding SNR for sparse signals */ 127 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) ); 128 } 129 130 /*******************************/ 131 /* Control bandwidth expansion */ 132 /*******************************/ 133 /* More BWE for signals with high prediction gain */ 134 strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); 135 BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), 136 silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); 137 delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), 138 SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); 139 BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 ); 140 BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 ); 141 /* BWExp1 will be applied after BWExp2, so make it relative */ 142 BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) ); 143 144 if( psEnc->sCmn.warping_Q16 > 0 ) { 145 /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ 146 warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) ); 147 } else { 148 warping_Q16 = 0; 149 } 150 151 /********************************************/ 152 /* Compute noise shaping AR coefs and gains */ 153 /********************************************/ 154 ALLOC( x_windowed, psEnc->sCmn.shapeWinLength, opus_int16 ); 155 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { 156 /* Apply window: sine slope followed by flat part followed by cosine slope */ 157 opus_int shift, slope_part, flat_part; 158 flat_part = psEnc->sCmn.fs_kHz * 3; 159 slope_part = silk_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); 160 161 silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part ); 162 shift = slope_part; 163 silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) ); 164 shift += flat_part; 165 silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part ); 166 167 /* Update pointer: next LPC analysis block */ 168 x_ptr += psEnc->sCmn.subfr_length; 169 170 if( psEnc->sCmn.warping_Q16 > 0 ) { 171 /* Calculate warped auto correlation */ 172 silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); 173 } else { 174 /* Calculate regular auto correlation */ 175 silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch ); 176 } 177 178 /* Add white noise, as a fraction of energy */ 179 auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ), 180 SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); 181 182 /* Calculate the reflection coefficients using schur */ 183 nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); 184 silk_assert( nrg >= 0 ); 185 186 /* Convert reflection coefficients to prediction coefficients */ 187 silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); 188 189 Qnrg = -scale; /* range: -12...30*/ 190 silk_assert( Qnrg >= -12 ); 191 silk_assert( Qnrg <= 30 ); 192 193 /* Make sure that Qnrg is an even number */ 194 if( Qnrg & 1 ) { 195 Qnrg -= 1; 196 nrg >>= 1; 197 } 198 199 tmp32 = silk_SQRT_APPROX( nrg ); 200 Qnrg >>= 1; /* range: -6...15*/ 201 202 psEncCtrl->Gains_Q16[ k ] = (silk_LSHIFT32( silk_LIMIT( (tmp32), silk_RSHIFT32( silk_int32_MIN, (16 - Qnrg) ), \ 203 silk_RSHIFT32( silk_int32_MAX, (16 - Qnrg) ) ), (16 - Qnrg) )); 204 205 if( psEnc->sCmn.warping_Q16 > 0 ) { 206 /* Adjust gain for warping */ 207 gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); 208 silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); 209 if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) { 210 psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX; 211 } else { 212 psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); 213 } 214 } 215 216 /* Bandwidth expansion for synthesis filter shaping */ 217 silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); 218 219 /* Compute noise shaping filter coefficients */ 220 silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) ); 221 222 /* Bandwidth expansion for analysis filter shaping */ 223 silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) ); 224 silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); 225 226 /* Ratio of prediction gains, in energy domain */ 227 pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder ); 228 nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder ); 229 230 /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/ 231 pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 ); 232 psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); 233 234 /* Convert to monic warped prediction coefficients and limit absolute values */ 235 limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); 236 237 /* Convert from Q24 to Q13 and store in int16 */ 238 for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { 239 psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); 240 psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); 241 } 242 } 243 244 /*****************/ 245 /* Gain tweaking */ 246 /*****************/ 247 /* Increase gains during low speech activity and put lower limit on gains */ 248 gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) ); 249 gain_add_Q16 = silk_log2lin( silk_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) ); 250 silk_assert( gain_mult_Q16 > 0 ); 251 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { 252 psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); 253 silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); 254 psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 ); 255 } 256 257 gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ), 258 psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 ); 259 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { 260 psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] ); 261 } 262 263 /************************************************/ 264 /* Control low-frequency shaping and noise tilt */ 265 /************************************************/ 266 /* Less low frequency shaping for noisy inputs */ 267 strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ), 268 SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) ); 269 strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 ); 270 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { 271 /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ 272 /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ 273 opus_int fs_kHz_inv = silk_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz ); 274 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { 275 b_Q14 = fs_kHz_inv + silk_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] ); 276 /* Pack two coefficients in one int32 */ 277 psEncCtrl->LF_shp_Q14[ k ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - silk_SMULWB( strength_Q16, b_Q14 ), 16 ); 278 psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); 279 } 280 silk_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); /* Guarantees that second argument to SMULWB() is within range of an opus_int16*/ 281 Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) - 282 silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ), 283 silk_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) ); 284 } else { 285 b_Q14 = silk_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); /* 1.3_Q0 = 21299_Q14*/ 286 /* Pack two coefficients in one int32 */ 287 psEncCtrl->LF_shp_Q14[ 0 ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - 288 silk_SMULWB( strength_Q16, silk_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 ); 289 psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); 290 for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { 291 psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ]; 292 } 293 Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 ); 294 } 295 296 /****************************/ 297 /* HARMONIC SHAPING CONTROL */ 298 /****************************/ 299 /* Control boosting of harmonic frequencies */ 300 HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ), 301 psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) ); 302 303 /* More harmonic boost for noisy input signals */ 304 HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16, 305 SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) ); 306 307 if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { 308 /* More harmonic noise shaping for high bitrates or noisy input */ 309 HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ), 310 SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ), 311 psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) ); 312 313 /* Less harmonic noise shaping for less periodic signals */ 314 HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ), 315 silk_SQRT_APPROX( silk_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) ); 316 } else { 317 HarmShapeGain_Q16 = 0; 318 } 319 320 /*************************/ 321 /* Smooth over subframes */ 322 /*************************/ 323 for( k = 0; k < MAX_NB_SUBFR; k++ ) { 324 psShapeSt->HarmBoost_smth_Q16 = 325 silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); 326 psShapeSt->HarmShapeGain_smth_Q16 = 327 silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); 328 psShapeSt->Tilt_smth_Q16 = 329 silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); 330 331 psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 ); 332 psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 ); 333 psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 ); 334 } 335 RESTORE_STACK; 336 } 337