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 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "main_FIX.h"
33 #include "stack_alloc.h"
34 #include "tuning_parameters.h"
35
36 /* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */
37 /* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */
38 /* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */
39 /* coefficient in an array of coefficients, for monic filters. */
warped_gain(const opus_int32 * coefs_Q24,opus_int lambda_Q16,opus_int order)40 static OPUS_INLINE opus_int32 warped_gain( /* gain in Q16*/
41 const opus_int32 *coefs_Q24,
42 opus_int lambda_Q16,
43 opus_int order
44 ) {
45 opus_int i;
46 opus_int32 gain_Q24;
47
48 lambda_Q16 = -lambda_Q16;
49 gain_Q24 = coefs_Q24[ order - 1 ];
50 for( i = order - 2; i >= 0; i-- ) {
51 gain_Q24 = silk_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 );
52 }
53 gain_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 );
54 return silk_INVERSE32_varQ( gain_Q24, 40 );
55 }
56
57 /* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
58 /* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
limit_warped_coefs(opus_int32 * coefs_syn_Q24,opus_int32 * coefs_ana_Q24,opus_int lambda_Q16,opus_int32 limit_Q24,opus_int order)59 static OPUS_INLINE void limit_warped_coefs(
60 opus_int32 *coefs_syn_Q24,
61 opus_int32 *coefs_ana_Q24,
62 opus_int lambda_Q16,
63 opus_int32 limit_Q24,
64 opus_int order
65 ) {
66 opus_int i, iter, ind = 0;
67 opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16;
68 opus_int32 nom_Q16, den_Q24;
69
70 /* Convert to monic coefficients */
71 lambda_Q16 = -lambda_Q16;
72 for( i = order - 1; i > 0; i-- ) {
73 coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
74 coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
75 }
76 lambda_Q16 = -lambda_Q16;
77 nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
78 den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
79 gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
80 den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
81 gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
82 for( i = 0; i < order; i++ ) {
83 coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
84 coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
85 }
86
87 for( iter = 0; iter < 10; iter++ ) {
88 /* Find maximum absolute value */
89 maxabs_Q24 = -1;
90 for( i = 0; i < order; i++ ) {
91 tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) );
92 if( tmp > maxabs_Q24 ) {
93 maxabs_Q24 = tmp;
94 ind = i;
95 }
96 }
97 if( maxabs_Q24 <= limit_Q24 ) {
98 /* Coefficients are within range - done */
99 return;
100 }
101
102 /* Convert back to true warped coefficients */
103 for( i = 1; i < order; i++ ) {
104 coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
105 coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
106 }
107 gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 );
108 gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 );
109 for( i = 0; i < order; i++ ) {
110 coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
111 coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
112 }
113
114 /* Apply bandwidth expansion */
115 chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ(
116 silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
117 silk_MUL( maxabs_Q24, ind + 1 ), 22 );
118 silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 );
119 silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 );
120
121 /* Convert to monic warped coefficients */
122 lambda_Q16 = -lambda_Q16;
123 for( i = order - 1; i > 0; i-- ) {
124 coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
125 coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
126 }
127 lambda_Q16 = -lambda_Q16;
128 nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
129 den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
130 gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
131 den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
132 gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
133 for( i = 0; i < order; i++ ) {
134 coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
135 coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
136 }
137 }
138 silk_assert( 0 );
139 }
140
141 /**************************************************************/
142 /* Compute noise shaping coefficients and initial gain values */
143 /**************************************************************/
silk_noise_shape_analysis_FIX(silk_encoder_state_FIX * psEnc,silk_encoder_control_FIX * psEncCtrl,const opus_int16 * pitch_res,const opus_int16 * x,int arch)144 void silk_noise_shape_analysis_FIX(
145 silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */
146 silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */
147 const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */
148 const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */
149 int arch /* I Run-time architecture */
150 )
151 {
152 silk_shape_state_FIX *psShapeSt = &psEnc->sShape;
153 opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0;
154 opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32;
155 opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
156 opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
157 opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
158 opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ];
159 opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ];
160 opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ];
161 VARDECL( opus_int16, x_windowed );
162 const opus_int16 *x_ptr, *pitch_res_ptr;
163 SAVE_STACK;
164
165 /* Point to start of first LPC analysis block */
166 x_ptr = x - psEnc->sCmn.la_shape;
167
168 /****************/
169 /* GAIN CONTROL */
170 /****************/
171 SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7;
172
173 /* Input quality is the average of the quality in the lowest two VAD bands */
174 psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ]
175 + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 );
176
177 /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */
178 psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 -
179 SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 );
180
181 /* Reduce coding SNR during low speech activity */
182 if( psEnc->sCmn.useCBR == 0 ) {
183 b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8;
184 b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 );
185 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7,
186 silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/
187 silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/
188 }
189
190 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
191 /* Reduce gains for periodic signals */
192 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 );
193 } else {
194 /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */
195 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7,
196 silk_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ),
197 SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 );
198 }
199
200 /*************************/
201 /* SPARSENESS PROCESSING */
202 /*************************/
203 /* Set quantizer offset */
204 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
205 /* Initially set to 0; may be overruled in process_gains(..) */
206 psEnc->sCmn.indices.quantOffsetType = 0;
207 psEncCtrl->sparseness_Q8 = 0;
208 } else {
209 /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
210 nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 );
211 energy_variation_Q7 = 0;
212 log_energy_prev_Q7 = 0;
213 pitch_res_ptr = pitch_res;
214 for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
215 silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples );
216 nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/
217
218 log_energy_Q7 = silk_lin2log( nrg );
219 if( k > 0 ) {
220 energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 );
221 }
222 log_energy_prev_Q7 = log_energy_Q7;
223 pitch_res_ptr += nSamples;
224 }
225
226 psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 -
227 SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 );
228
229 /* Set quantization offset depending on sparseness measure */
230 if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) {
231 psEnc->sCmn.indices.quantOffsetType = 0;
232 } else {
233 psEnc->sCmn.indices.quantOffsetType = 1;
234 }
235
236 /* Increase coding SNR for sparse signals */
237 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 ) );
238 }
239
240 /*******************************/
241 /* Control bandwidth expansion */
242 /*******************************/
243 /* More BWE for signals with high prediction gain */
244 strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) );
245 BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
246 silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 );
247 delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ),
248 SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) );
249 BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 );
250 BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 );
251 /* BWExp1 will be applied after BWExp2, so make it relative */
252 BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) );
253
254 if( psEnc->sCmn.warping_Q16 > 0 ) {
255 /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
256 warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) );
257 } else {
258 warping_Q16 = 0;
259 }
260
261 /********************************************/
262 /* Compute noise shaping AR coefs and gains */
263 /********************************************/
264 ALLOC( x_windowed, psEnc->sCmn.shapeWinLength, opus_int16 );
265 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
266 /* Apply window: sine slope followed by flat part followed by cosine slope */
267 opus_int shift, slope_part, flat_part;
268 flat_part = psEnc->sCmn.fs_kHz * 3;
269 slope_part = silk_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 );
270
271 silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part );
272 shift = slope_part;
273 silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) );
274 shift += flat_part;
275 silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part );
276
277 /* Update pointer: next LPC analysis block */
278 x_ptr += psEnc->sCmn.subfr_length;
279
280 if( psEnc->sCmn.warping_Q16 > 0 ) {
281 /* Calculate warped auto correlation */
282 silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
283 } else {
284 /* Calculate regular auto correlation */
285 silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
286 }
287
288 /* Add white noise, as a fraction of energy */
289 auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ),
290 SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) );
291
292 /* Calculate the reflection coefficients using schur */
293 nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder );
294 silk_assert( nrg >= 0 );
295
296 /* Convert reflection coefficients to prediction coefficients */
297 silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
298
299 Qnrg = -scale; /* range: -12...30*/
300 silk_assert( Qnrg >= -12 );
301 silk_assert( Qnrg <= 30 );
302
303 /* Make sure that Qnrg is an even number */
304 if( Qnrg & 1 ) {
305 Qnrg -= 1;
306 nrg >>= 1;
307 }
308
309 tmp32 = silk_SQRT_APPROX( nrg );
310 Qnrg >>= 1; /* range: -6...15*/
311
312 psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( tmp32, 16 - Qnrg );
313
314 if( psEnc->sCmn.warping_Q16 > 0 ) {
315 /* Adjust gain for warping */
316 gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
317 silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
318 if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) {
319 psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
320 } else {
321 psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
322 }
323 }
324
325 /* Bandwidth expansion for synthesis filter shaping */
326 silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 );
327
328 /* Compute noise shaping filter coefficients */
329 silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) );
330
331 /* Bandwidth expansion for analysis filter shaping */
332 silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) );
333 silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
334
335 /* Ratio of prediction gains, in energy domain */
336 pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
337 nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
338
339 /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
340 pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
341 psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 );
342
343 /* Convert to monic warped prediction coefficients and limit absolute values */
344 limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
345
346 /* Convert from Q24 to Q13 and store in int16 */
347 for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
348 psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) );
349 psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) );
350 }
351 }
352
353 /*****************/
354 /* Gain tweaking */
355 /*****************/
356 /* Increase gains during low speech activity and put lower limit on gains */
357 gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) );
358 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 ) ) );
359 silk_assert( gain_mult_Q16 > 0 );
360 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
361 psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
362 silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
363 psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 );
364 }
365
366 gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ),
367 psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 );
368 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
369 psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] );
370 }
371
372 /************************************************/
373 /* Control low-frequency shaping and noise tilt */
374 /************************************************/
375 /* Less low frequency shaping for noisy inputs */
376 strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ),
377 SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) );
378 strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 );
379 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
380 /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */
381 /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/
382 opus_int fs_kHz_inv = silk_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz );
383 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
384 b_Q14 = fs_kHz_inv + silk_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] );
385 /* Pack two coefficients in one int32 */
386 psEncCtrl->LF_shp_Q14[ k ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - silk_SMULWB( strength_Q16, b_Q14 ), 16 );
387 psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) );
388 }
389 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*/
390 Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) -
391 silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ),
392 silk_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) );
393 } else {
394 b_Q14 = silk_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); /* 1.3_Q0 = 21299_Q14*/
395 /* Pack two coefficients in one int32 */
396 psEncCtrl->LF_shp_Q14[ 0 ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 -
397 silk_SMULWB( strength_Q16, silk_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 );
398 psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) );
399 for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {
400 psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ];
401 }
402 Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 );
403 }
404
405 /****************************/
406 /* HARMONIC SHAPING CONTROL */
407 /****************************/
408 /* Control boosting of harmonic frequencies */
409 HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ),
410 psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) );
411
412 /* More harmonic boost for noisy input signals */
413 HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16,
414 SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) );
415
416 if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
417 /* More harmonic noise shaping for high bitrates or noisy input */
418 HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ),
419 SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ),
420 psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) );
421
422 /* Less harmonic noise shaping for less periodic signals */
423 HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ),
424 silk_SQRT_APPROX( silk_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) );
425 } else {
426 HarmShapeGain_Q16 = 0;
427 }
428
429 /*************************/
430 /* Smooth over subframes */
431 /*************************/
432 for( k = 0; k < MAX_NB_SUBFR; k++ ) {
433 psShapeSt->HarmBoost_smth_Q16 =
434 silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
435 psShapeSt->HarmShapeGain_smth_Q16 =
436 silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
437 psShapeSt->Tilt_smth_Q16 =
438 silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
439
440 psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 );
441 psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 );
442 psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 );
443 }
444 RESTORE_STACK;
445 }
446