a695d1dd2cdda519ebea96dee67f0d3af6bda631
[opus.git] / src_FIX / SKP_Silk_noise_shape_analysis_FIX.c
1 /***********************************************************************\r
2 Copyright (c) 2006-2010, Skype Limited. All rights reserved. \r
3 Redistribution and use in source and binary forms, with or without \r
4 modification, (subject to the limitations in the disclaimer below) \r
5 are permitted provided that the following conditions are met:\r
6 - Redistributions of source code must retain the above copyright notice,\r
7 this list of conditions and the following disclaimer.\r
8 - Redistributions in binary form must reproduce the above copyright \r
9 notice, this list of conditions and the following disclaimer in the \r
10 documentation and/or other materials provided with the distribution.\r
11 - Neither the name of Skype Limited, nor the names of specific \r
12 contributors, may be used to endorse or promote products derived from \r
13 this software without specific prior written permission.\r
14 NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED \r
15 BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \r
16 CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\r
17 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \r
18 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
19 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, \r
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
22 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
23 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
26 ***********************************************************************/\r
27 \r
28 #include "SKP_Silk_main_FIX.h"\r
29 #include "SKP_Silk_perceptual_parameters_FIX.h"\r
30 \r
31 /* Compute gain to make warped filter coefficients have a zero mean log frequency response on a     */\r
32 /* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.)   */\r
33 SKP_INLINE SKP_int32 warped_gain( // gain in Q16\r
34     const SKP_int32     *coefs_Q24, \r
35     SKP_int             lambda_Q16, \r
36     SKP_int             order \r
37 ) {\r
38     SKP_int   i;\r
39     SKP_int32 gain_Q24;\r
40 \r
41     lambda_Q16 = -lambda_Q16;\r
42     gain_Q24 = coefs_Q24[ order - 1 ];\r
43     for( i = order - 2; i >= 0; i-- ) {\r
44         gain_Q24 = SKP_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 );\r
45     }\r
46     gain_Q24  = SKP_SMLAWB( 1 << 24, gain_Q24, -lambda_Q16 );\r
47     return SKP_INVERSE32_varQ( gain_Q24, 40 );\r
48 }\r
49 \r
50 /* Convert warped filter coefficients to monic pseudo-warped coefficients */\r
51 SKP_INLINE void warped_true2monic_coefs( \r
52     SKP_int32           *coefs_Q24,\r
53     SKP_int             lambda_Q16,\r
54     SKP_int             order \r
55 ) {\r
56     SKP_int   i;\r
57     SKP_int32 gain_Q16, nom_Q16, den_Q24;\r
58 \r
59     lambda_Q16 = -lambda_Q16;\r
60     for( i = order - 1; i > 0; i-- ) {\r
61         coefs_Q24[ i - 1 ] = SKP_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );\r
62     }\r
63     nom_Q16  = SKP_SMLAWB( 1 << 16, lambda_Q16,     -lambda_Q16 );\r
64     den_Q24  = SKP_SMLAWB( 1 << 24, coefs_Q24[ 0 ], -lambda_Q16 );\r
65     gain_Q16 = SKP_DIV32_varQ( nom_Q16, den_Q24, 24 );\r
66     for( i = 0; i < order; i++ ) {\r
67         coefs_Q24[ i ] = SKP_SMULWW( gain_Q16, coefs_Q24[ i ] );\r
68     }\r
69 }\r
70 \r
71 /* Limit max amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */\r
72 SKP_INLINE void limit_warped_coefs( \r
73     SKP_int32           *coefs_syn_Q24,\r
74     SKP_int32           *coefs_ana_Q24,\r
75     SKP_int             lambda_Q16,\r
76     SKP_int32           limit_Q24,\r
77     SKP_int             order\r
78 ) {\r
79     SKP_int   i, iter, ind;\r
80     SKP_int32 tmp, maxabs_Q24, chirp_Q16;\r
81 \r
82     for( iter = 0; iter < 10; iter++ ) {\r
83         /* Find maximum absolute value */\r
84         ind = 1;\r
85         maxabs_Q24 = SKP_abs( coefs_syn_Q24[ ind ] );\r
86         for( i = 2; i < order - 1; i++ ) {\r
87             tmp = SKP_abs( coefs_syn_Q24[ i ] );\r
88             if( tmp > maxabs_Q24 ) {\r
89                 maxabs_Q24 = tmp;\r
90                 ind = i;\r
91             }\r
92         }\r
93         if( maxabs_Q24 <= limit_Q24 ) {\r
94             return;\r
95         }\r
96 \r
97         /* Convert to true warped coefficients */\r
98         for( i = 1; i < order; i++ ) {\r
99             coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );\r
100             coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );\r
101         }\r
102 \r
103         /* Apply bandwidth expansion */\r
104         chirp_Q16 = SKP_FIX_CONST( 0.99, 16 ) - SKP_DIV32_varQ(\r
105             SKP_SMULWB( maxabs_Q24 - limit_Q24, SKP_SMLABB( SKP_FIX_CONST( 0.8, 10 ), SKP_FIX_CONST( 0.1, 10 ), iter ) ), \r
106             SKP_MUL( maxabs_Q24, ind + 1 ), 22 );\r
107         SKP_Silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 );\r
108         SKP_Silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 );\r
109 \r
110         /* Convert back to monic warped coefficients */\r
111         lambda_Q16 = -lambda_Q16;\r
112         for( i = order - 1; i > 0; i-- ) {\r
113             coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );\r
114             coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );\r
115         }\r
116         lambda_Q16 = -lambda_Q16;\r
117     }\r
118 }\r
119 \r
120 /**************************************************************/\r
121 /* Compute noise shaping coefficients and initial gain values */\r
122 /**************************************************************/\r
123 void SKP_Silk_noise_shape_analysis_FIX(\r
124     SKP_Silk_encoder_state_FIX      *psEnc,         /* I/O  Encoder state FIX                           */\r
125     SKP_Silk_encoder_control_FIX    *psEncCtrl,     /* I/O  Encoder control FIX                         */\r
126     const SKP_int16                 *pitch_res,     /* I    LPC residual from pitch analysis            */\r
127     const SKP_int16                 *x              /* I    Input signal [ frame_length + la_shape ]    */\r
128 )\r
129 {\r
130     SKP_Silk_shape_state_FIX *psShapeSt = &psEnc->sShape;\r
131     SKP_int     k, i, nSamples, Qnrg, b_Q14, scale = 0, sz;\r
132     SKP_int32   SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32;\r
133     SKP_int32   nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;\r
134     SKP_int32   delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;\r
135     SKP_int32   auto_corr[     MAX_SHAPE_LPC_ORDER + 1 ];\r
136     SKP_int32   refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ];\r
137     SKP_int32   AR1_Q24[       MAX_SHAPE_LPC_ORDER ];\r
138     SKP_int32   AR2_Q24[       MAX_SHAPE_LPC_ORDER ];\r
139     SKP_int16   x_windowed[    SHAPE_LPC_WIN_MAX ];\r
140     const SKP_int16 *x_ptr, *pitch_res_ptr;\r
141 \r
142     SKP_int32   sqrt_nrg[ MAX_NB_SUBFR ], Qnrg_vec[ MAX_NB_SUBFR ];\r
143 \r
144     /* Point to start of first LPC analysis block */\r
145     x_ptr = x + psEnc->sCmn.la_shape - SKP_SMULBB( SHAPE_LPC_WIN_MS, psEnc->sCmn.fs_kHz ) + psEnc->sCmn.subfr_length;\r
146 \r
147     /****************/\r
148     /* CONTROL SNR  */\r
149     /****************/\r
150 #if DEACTIVATE_SNR_FEEDBACK\r
151     psEncCtrl->current_SNR_dB_Q7 = psEnc->SNR_dB_Q7;\r
152 #else\r
153     /* Reduce SNR_dB values if recent bitstream has exceeded TargetRate */\r
154     psEncCtrl->current_SNR_dB_Q7 = psEnc->SNR_dB_Q7 - SKP_SMULWB( SKP_LSHIFT( ( SKP_int32 )psEnc->BufferedInChannel_ms, 7 ), 3277 );\r
155 #endif\r
156 \r
157     /* Reduce SNR_dB if inband FEC used */\r
158     if( psEnc->speech_activity_Q8 > LBRR_SPEECH_ACTIVITY_THRES_Q8 ) {\r
159         psEncCtrl->current_SNR_dB_Q7 -= SKP_RSHIFT( psEnc->inBandFEC_SNR_comp_Q8, 1 );\r
160     }\r
161 \r
162     /****************/\r
163     /* GAIN CONTROL */\r
164     /****************/\r
165     /* Input quality is the average of the quality in the lowest two VAD bands */\r
166     psEncCtrl->input_quality_Q14 = ( SKP_int )SKP_RSHIFT( ( SKP_int32 )psEncCtrl->input_quality_bands_Q15[ 0 ] \r
167         + psEncCtrl->input_quality_bands_Q15[ 1 ], 2 );\r
168 \r
169     /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */\r
170     psEncCtrl->coding_quality_Q14 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->current_SNR_dB_Q7 - ( 17 << 7 ), 4 ) ), 1 );\r
171 \r
172     /* Reduce coding SNR during low speech activity */\r
173     b_Q8 = ( 1 << 8 ) - psEnc->speech_activity_Q8;\r
174     b_Q8 = SKP_SMULWB( SKP_LSHIFT( b_Q8, 8 ), b_Q8 );\r
175     SNR_adj_dB_Q7 = SKP_SMLAWB( psEncCtrl->current_SNR_dB_Q7,\r
176         SKP_SMULBB( -BG_SNR_DECR_dB_Q7 >> ( 4 + 1 ), b_Q8 ),                                            // Q11\r
177         SKP_SMULWB( ( 1 << 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) );      // Q12\r
178 \r
179     if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) {\r
180         /* Reduce gains for periodic signals */\r
181         SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, HARM_SNR_INCR_dB_Q7 << 1, psEnc->LTPCorr_Q15 );\r
182     } else { \r
183         /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */\r
184         SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, \r
185             SKP_SMLAWB( 6 << ( 7 + 2 ), -104856, psEncCtrl->current_SNR_dB_Q7 ),    //-104856_Q18 = -0.4_Q0, Q9\r
186             ( 1 << 14 ) - psEncCtrl->input_quality_Q14 );                           // Q14\r
187     }\r
188 \r
189     /*************************/\r
190     /* SPARSENESS PROCESSING */\r
191     /*************************/\r
192     /* Set quantizer offset */\r
193     if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) {\r
194         /* Initally set to 0; may be overruled in process_gains(..) */\r
195         psEncCtrl->sCmn.QuantOffsetType = 0;\r
196         psEncCtrl->sparseness_Q8 = 0;\r
197     } else {\r
198         /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */\r
199         nSamples = SKP_LSHIFT( psEnc->sCmn.fs_kHz, 1 );\r
200         energy_variation_Q7 = 0;\r
201         log_energy_prev_Q7  = 0;\r
202         pitch_res_ptr = pitch_res;\r
203         for( k = 0; k < SKP_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {\r
204             SKP_Silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples );\r
205             nrg += SKP_RSHIFT( nSamples, scale );           // Q(-scale)\r
206             \r
207             log_energy_Q7 = SKP_Silk_lin2log( nrg );\r
208             if( k > 0 ) {\r
209                 energy_variation_Q7 += SKP_abs( log_energy_Q7 - log_energy_prev_Q7 );\r
210             }\r
211             log_energy_prev_Q7 = log_energy_Q7;\r
212             pitch_res_ptr += nSamples;\r
213         }\r
214 \r
215         psEncCtrl->sparseness_Q8 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_SMULWB( energy_variation_Q7 - ( 5 << 7 ), 6554 ) ), 7 ); // 6554_Q16 = 0.1_Q0\r
216 \r
217         /* Set quantization offset depending on sparseness measure */\r
218         if( psEncCtrl->sparseness_Q8 > SPARSENESS_THRESHOLD_QNT_OFFSET_Q8 ) {\r
219             psEncCtrl->sCmn.QuantOffsetType = 0;\r
220         } else {\r
221             psEncCtrl->sCmn.QuantOffsetType = 1;\r
222         }\r
223         \r
224         /* Increase coding SNR for sparse signals */\r
225         SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SPARSE_SNR_INCR_dB_Q7 << 8, psEncCtrl->sparseness_Q8 - ( 1 << 7 ) );\r
226     }\r
227 \r
228     /*******************************/\r
229     /* Control bandwidth expansion */\r
230     /*******************************/\r
231     delta_Q16  = SKP_SMULWB( ( 1 << 16 ) - SKP_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), LOW_RATE_BANDWIDTH_EXPANSION_DELTA_Q16 );\r
232     BWExp1_Q16 = BANDWIDTH_EXPANSION_Q16 - delta_Q16;\r
233     BWExp2_Q16 = BANDWIDTH_EXPANSION_Q16 + delta_Q16;\r
234     if( psEnc->sCmn.fs_kHz == 24 ) {\r
235         /* Less bandwidth expansion for super wideband */\r
236         BWExp1_Q16 = ( 1 << 16 ) - SKP_SMULWB( SWB_BANDWIDTH_EXPANSION_REDUCTION_Q16, ( 1 << 16 ) - BWExp1_Q16 );\r
237         BWExp2_Q16 = ( 1 << 16 ) - SKP_SMULWB( SWB_BANDWIDTH_EXPANSION_REDUCTION_Q16, ( 1 << 16 ) - BWExp2_Q16 );\r
238     }\r
239     /* BWExp1 will be applied after BWExp2, so make it relative */\r
240     BWExp1_Q16 = SKP_DIV32_16( SKP_LSHIFT( BWExp1_Q16, 14 ), SKP_RSHIFT( BWExp2_Q16, 2 ) );\r
241 \r
242     /* Warping coefficient */\r
243     psEncCtrl->sCmn.warping_Q16 = psEnc->sCmn.fs_kHz * WARPING_MULTIPLIER_Q16;\r
244     psEncCtrl->sCmn.warping_Q16 = SKP_min( psEncCtrl->sCmn.warping_Q16, 32767 );\r
245 \r
246     /********************************************/\r
247     /* Compute noise shaping AR coefs and gains */\r
248     /********************************************/\r
249     sz = ( SKP_int )SKP_SMULBB( SHAPE_LPC_WIN_MS, psEnc->sCmn.fs_kHz );\r
250     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
251         /* Apply window */\r
252         SKP_Silk_apply_sine_window( x_windowed, x_ptr, 0, SHAPE_LPC_WIN_MS * psEnc->sCmn.fs_kHz );\r
253 \r
254         /* Update pointer: next LPC analysis block */\r
255         x_ptr += psEnc->sCmn.subfr_length;\r
256 \r
257         /* Calculate warped auto correlation */\r
258         SKP_Silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, psEncCtrl->sCmn.warping_Q16, sz, psEnc->sCmn.shapingLPCOrder ); \r
259 \r
260         /* Add white noise, as a fraction of energy */\r
261         auto_corr[0] = SKP_ADD32( auto_corr[0], SKP_max_32( SKP_SMULWB( SKP_RSHIFT( auto_corr[ 0 ], 4 ), SHAPE_WHITE_NOISE_FRACTION_Q20 ), 1 ) ); \r
262 \r
263         /* Calculate the reflection coefficients using schur */\r
264         nrg = SKP_Silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder );\r
265         SKP_assert( nrg >= 0 );\r
266 \r
267         /* Convert reflection coefficients to prediction coefficients */\r
268         SKP_Silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );\r
269 \r
270         /* Convert residual energy to non-warped scale */\r
271         gain_mult_Q16 = warped_gain( AR2_Q24, psEncCtrl->sCmn.warping_Q16, psEnc->sCmn.shapingLPCOrder );\r
272         gain_mult_Q16 = SKP_SMULWW( gain_mult_Q16, gain_mult_Q16 );\r
273         SKP_assert( gain_mult_Q16 >= 0 ); // If breaking, add dynamic scaling\r
274         nrg = SKP_SMULWW( nrg, gain_mult_Q16 );\r
275         SKP_assert( nrg >= 0 ); // If breaking, add dynamic scaling\r
276 \r
277         /* Bandwidth expansion for synthesis filter shaping */\r
278         SKP_Silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 );\r
279 \r
280         /* Compute noise shaping filter coefficients */\r
281         SKP_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( SKP_int32 ) );\r
282 \r
283         /* Bandwidth expansion for analysis filter shaping */\r
284         SKP_assert( BWExp1_Q16 <= ( 1 << 16 ) ); // If ever breaking, use LPC_stabilize() in these cases to stay within range\r
285         SKP_Silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );\r
286 \r
287         /* Increase residual energy */\r
288         nrg = SKP_SMLAWB( nrg, SKP_RSHIFT( auto_corr[ 0 ], 8 ), SHAPE_MIN_ENERGY_RATIO_Q24 );\r
289 \r
290         Qnrg = -scale;          // range: -12...30\r
291         SKP_assert( Qnrg >= -12 );\r
292         SKP_assert( Qnrg <=  30 );\r
293 \r
294         /* Make sure that Qnrg is an even number */\r
295         if( Qnrg & 1 ) {\r
296             Qnrg -= 1;\r
297             nrg >>= 1;\r
298         }\r
299 \r
300         tmp32 = SKP_Silk_SQRT_APPROX( nrg );\r
301         Qnrg >>= 1;             // range: -6...15\r
302 \r
303         sqrt_nrg[ k ] = tmp32;\r
304         Qnrg_vec[ k ] = Qnrg;\r
305 \r
306         psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( tmp32, 16 - Qnrg );\r
307 \r
308         /* Ratio of prediction gains, in energy domain */\r
309         SKP_Silk_LPC_inverse_pred_gain_Q24( &pre_nrg_Q30, AR2_Q24, psEnc->sCmn.shapingLPCOrder );\r
310         SKP_Silk_LPC_inverse_pred_gain_Q24( &nrg,         AR1_Q24, psEnc->sCmn.shapingLPCOrder );\r
311 \r
312         //psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;\r
313         pre_nrg_Q30 = SKP_LSHIFT32( SKP_SMULWB( pre_nrg_Q30, SKP_FIX_CONST( 0.7, 15 ) ), 1 );\r
314         psEncCtrl->GainsPre_Q14[ k ] = ( SKP_int ) SKP_FIX_CONST( 0.3, 14 ) + SKP_DIV32_varQ( pre_nrg_Q30, nrg, 14 );\r
315 \r
316         /* Convert to monic warped prediction coefficients */\r
317         warped_true2monic_coefs( AR1_Q24, psEncCtrl->sCmn.warping_Q16, psEnc->sCmn.shapingLPCOrder );\r
318         warped_true2monic_coefs( AR2_Q24, psEncCtrl->sCmn.warping_Q16, psEnc->sCmn.shapingLPCOrder );\r
319 \r
320         /* Limit absolute values */\r
321         limit_warped_coefs( AR2_Q24, AR1_Q24, psEncCtrl->sCmn.warping_Q16, SKP_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );\r
322 \r
323         /* Convert from Q24 to Q13 and store in int16 */\r
324         for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {\r
325             psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) );\r
326             psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) );\r
327         }\r
328     }\r
329 \r
330     /*****************/\r
331     /* Gain tweaking */\r
332     /*****************/\r
333     /* Increase gains during low speech activity and put lower limit on gains */\r
334     gain_mult_Q16 = SKP_Silk_log2lin( -SKP_SMLAWB( -16 << 7, SNR_adj_dB_Q7,           10486 ) ); // 10486_Q16 = 0.16_Q0\r
335     gain_add_Q16  = SKP_Silk_log2lin(  SKP_SMLAWB(  16 << 7, NOISE_FLOOR_dB_Q7,       10486 ) ); // 10486_Q16 = 0.16_Q0\r
336     tmp32         = SKP_Silk_log2lin(  SKP_SMLAWB(  16 << 7, RELATIVE_MIN_GAIN_dB_Q7, 10486 ) ); // 10486_Q16 = 0.16_Q0\r
337     tmp32 = SKP_SMULWW( psEnc->avgGain_Q16, tmp32 );\r
338     gain_add_Q16 = SKP_ADD_SAT32( gain_add_Q16, tmp32 );\r
339     SKP_assert( gain_mult_Q16 >= 0 );\r
340 \r
341     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
342         psEncCtrl->Gains_Q16[ k ] = SKP_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );\r
343         SKP_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );\r
344     }\r
345 \r
346     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
347         psEncCtrl->Gains_Q16[ k ] = SKP_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 );\r
348         psEnc->avgGain_Q16 = SKP_ADD_SAT32( \r
349             psEnc->avgGain_Q16, \r
350             SKP_SMULWB(\r
351                 psEncCtrl->Gains_Q16[ k ] - psEnc->avgGain_Q16, \r
352                 SKP_RSHIFT_ROUND( SKP_SMULBB( psEnc->speech_activity_Q8, GAIN_SMOOTHING_COEF_Q10 ), 2 ) \r
353             ) );\r
354     }\r
355 \r
356     /************************************************/\r
357     /* Decrease level during fricatives (de-essing) */\r
358     /************************************************/\r
359     gain_mult_Q16 = ( 1 << 16 ) + SKP_RSHIFT_ROUND( SKP_MLA( INPUT_TILT_Q26, psEncCtrl->coding_quality_Q14, HIGH_RATE_INPUT_TILT_Q12 ), 10 );\r
360 \r
361     if( psEncCtrl->input_tilt_Q15 <= 0 && psEncCtrl->sCmn.sigtype == SIG_TYPE_UNVOICED ) {\r
362         if( psEnc->sCmn.fs_kHz == 24 ) {\r
363             SKP_int32 essStrength_Q15 = SKP_SMULWW( -psEncCtrl->input_tilt_Q15, \r
364                 SKP_SMULBB( psEnc->speech_activity_Q8, ( 1 << 8 ) - psEncCtrl->sparseness_Q8 ) );\r
365             tmp32 = SKP_Silk_log2lin( ( 16 << 7 ) - SKP_SMULWB( essStrength_Q15, \r
366                 SKP_SMULWB( DE_ESSER_COEF_SWB_dB_Q7, 20972 ) ) ); // 20972_Q17 = 0.16_Q0\r
367             gain_mult_Q16 = SKP_SMULWW( gain_mult_Q16, tmp32 );\r
368         } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
369             SKP_int32 essStrength_Q15 = SKP_SMULWW(-psEncCtrl->input_tilt_Q15, \r
370                 SKP_SMULBB( psEnc->speech_activity_Q8, ( 1 << 8 ) - psEncCtrl->sparseness_Q8 ));\r
371             tmp32 = SKP_Silk_log2lin( ( 16 << 7 ) - SKP_SMULWB( essStrength_Q15, \r
372                 SKP_SMULWB( DE_ESSER_COEF_WB_dB_Q7, 20972 ) ) ); // 20972_Q17 = 0.16_Q0\r
373             gain_mult_Q16 = SKP_SMULWW( gain_mult_Q16, tmp32 );\r
374         } else {\r
375             SKP_assert( psEnc->sCmn.fs_kHz == 12 || psEnc->sCmn.fs_kHz == 8 );\r
376         }\r
377     }\r
378 \r
379     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
380         psEncCtrl->GainsPre_Q14[ k ] = SKP_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] );\r
381     }\r
382 \r
383     /************************************************/\r
384     /* Control low-frequency shaping and noise tilt */\r
385     /************************************************/\r
386     /* Less low frequency shaping for noisy inputs */\r
387     strength_Q16 = SKP_MUL( LOW_FREQ_SHAPING_Q0, ( 1 << 16 ) + SKP_SMULBB( LOW_QUALITY_LOW_FREQ_SHAPING_DECR_Q1, psEncCtrl->input_quality_bands_Q15[ 0 ] - ( 1 << 15 ) ) );\r
388     if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) {\r
389         /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */\r
390         /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/\r
391         SKP_int fs_kHz_inv = SKP_DIV32_16( 3277, psEnc->sCmn.fs_kHz );      // 0.2_Q0 = 3277_Q14\r
392         for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
393             b_Q14 = fs_kHz_inv + SKP_DIV32_16( ( 3 << 14 ), psEncCtrl->sCmn.pitchL[ k ] ); \r
394             /* Pack two coefficients in one int32 */\r
395             psEncCtrl->LF_shp_Q14[ k ]  = SKP_LSHIFT( ( 1 << 14 ) - b_Q14 - SKP_SMULWB( strength_Q16, b_Q14 ), 16 );\r
396             psEncCtrl->LF_shp_Q14[ k ] |= (SKP_uint16)( b_Q14 - ( 1 << 14 ) );\r
397         }\r
398         SKP_assert( HARM_HP_NOISE_COEF_Q24 < ( 1 << 23 ) ); // Guarantees that second argument to SMULWB() is within range of an SKP_int16\r
399         Tilt_Q16 = - HP_NOISE_COEF_Q16 - \r
400             SKP_SMULWB( ( 1 << 16 ) - HP_NOISE_COEF_Q16, SKP_SMULWB( HARM_HP_NOISE_COEF_Q24, psEnc->speech_activity_Q8 ) );\r
401     } else {\r
402         b_Q14 = SKP_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); // 1.3_Q0 = 21299_Q14\r
403         /* Pack two coefficients in one int32 */\r
404         psEncCtrl->LF_shp_Q14[ 0 ]  = SKP_LSHIFT( ( 1 << 14 ) - b_Q14 - SKP_SMULWB( strength_Q16, SKP_SMULWB( 39322, b_Q14 ) ), 16 ); // 0.6_Q0 = 39322_Q16\r
405         psEncCtrl->LF_shp_Q14[ 0 ] |= (SKP_uint16)( b_Q14 - ( 1 << 14 ) );\r
406         for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {\r
407             psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ k - 1 ];\r
408         }\r
409         Tilt_Q16 = -HP_NOISE_COEF_Q16;\r
410     }\r
411 \r
412     /****************************/\r
413     /* HARMONIC SHAPING CONTROL */\r
414     /****************************/\r
415     /* Control boosting of harmonic frequencies */\r
416     HarmBoost_Q16 = SKP_SMULWB( SKP_SMULWB( ( 1 << 17 ) - SKP_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ), \r
417         psEnc->LTPCorr_Q15 ), LOW_RATE_HARMONIC_BOOST_Q16 );\r
418 \r
419     /* More harmonic boost for noisy input signals */\r
420     HarmBoost_Q16 = SKP_SMLAWB( HarmBoost_Q16, \r
421         ( 1 << 16 ) - SKP_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), LOW_INPUT_QUALITY_HARMONIC_BOOST_Q16 );\r
422 \r
423     if( USE_HARM_SHAPING && psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) {\r
424         /* More harmonic noise shaping for high bitrates or noisy input */\r
425         HarmShapeGain_Q16 = SKP_SMLAWB( HARMONIC_SHAPING_Q16, \r
426                 ( 1 << 16 ) - SKP_SMULWB( ( 1 << 18 ) - SKP_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ),\r
427                 psEncCtrl->input_quality_Q14 ), HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING_Q16 );\r
428 \r
429         /* Less harmonic noise shaping for less periodic signals */\r
430         HarmShapeGain_Q16 = SKP_SMULWB( SKP_LSHIFT( HarmShapeGain_Q16, 1 ), \r
431             SKP_Silk_SQRT_APPROX( SKP_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) );\r
432     } else {\r
433         HarmShapeGain_Q16 = 0;\r
434     }\r
435 \r
436     /*************************/\r
437     /* Smooth over subframes */\r
438     /*************************/\r
439     for( k = 0; k < MAX_NB_SUBFR; k++ ) {\r
440         psShapeSt->HarmBoost_smth_Q16 =\r
441             SKP_SMLAWB( psShapeSt->HarmBoost_smth_Q16,     HarmBoost_Q16     - psShapeSt->HarmBoost_smth_Q16,     SUBFR_SMTH_COEF_Q16 );\r
442         psShapeSt->HarmShapeGain_smth_Q16 =\r
443             SKP_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SUBFR_SMTH_COEF_Q16 );\r
444         psShapeSt->Tilt_smth_Q16 =\r
445             SKP_SMLAWB( psShapeSt->Tilt_smth_Q16,          Tilt_Q16          - psShapeSt->Tilt_smth_Q16,          SUBFR_SMTH_COEF_Q16 );\r
446 \r
447         psEncCtrl->HarmBoost_Q14[ k ]     = ( SKP_int )SKP_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16,     2 );\r
448         psEncCtrl->HarmShapeGain_Q14[ k ] = ( SKP_int )SKP_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 );\r
449         psEncCtrl->Tilt_Q14[ k ]          = ( SKP_int )SKP_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16,          2 );\r
450     }\r
451 }\r