MIPS optimizations
[opus.git] / silk / fixed / mips / noise_shape_analysis_FIX_mipsr1.h
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