Update SILK code using the CELT range coder
[opus.git] / src_FLP / SKP_Silk_noise_shape_analysis_FLP.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_FLP.h"\r
29 #include "SKP_Silk_perceptual_parameters.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_float warped_gain( \r
34     const SKP_float     *coefs, \r
35     SKP_float           lambda, \r
36     SKP_int             order \r
37 ) {\r
38     SKP_int   i;\r
39     SKP_float gain;\r
40 \r
41     lambda = -lambda;\r
42     gain = coefs[ order - 1 ];\r
43     for( i = order - 2; i >= 0; i-- ) {\r
44         gain = lambda * gain + coefs[ i ];\r
45     }\r
46     return (SKP_float)( 1.0f / ( 1.0f - lambda * gain ) );\r
47 }\r
48 \r
49 /* Convert warped filter coefficients to monic pseudo-warped coefficients */\r
50 SKP_INLINE void warped_true2monic_coefs( \r
51     SKP_float           *coefs, \r
52     SKP_float           lambda, \r
53     SKP_int             order \r
54 ) {\r
55     SKP_int   i;\r
56     SKP_float gain;\r
57 \r
58     lambda = -lambda;\r
59     for( i = order - 1; i > 0; i-- ) {\r
60         coefs[ i - 1 ] += lambda * coefs[ i ];\r
61     }\r
62     gain = ( 1.0f - lambda * lambda ) / ( 1.0f - lambda * coefs[ 0 ] );\r
63     for( i = 0; i < order; i++ ) {\r
64         coefs[ i ] *= gain;\r
65     }\r
66 }\r
67 \r
68 /* Limit max amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */\r
69 SKP_INLINE void limit_warped_coefs( \r
70     SKP_float           *coefs_syn,\r
71     SKP_float           *coefs_ana,\r
72     SKP_float           lambda,\r
73     SKP_float           limit,\r
74     SKP_int             order\r
75 ) {\r
76     SKP_int   i, iter, ind;\r
77     SKP_float tmp, maxabs, chirp;\r
78 \r
79     for( iter = 0; iter < 10; iter++ ) {\r
80         /* Find maximum absolute value */\r
81         ind = 1;\r
82         maxabs = SKP_abs( coefs_syn[ ind ] );\r
83         for( i = 2; i < order - 1; i++ ) {\r
84             tmp = SKP_abs( coefs_syn[ i ] );\r
85             if( tmp > maxabs ) {\r
86                 maxabs = tmp;\r
87                 ind = i;\r
88             }\r
89         }\r
90         if( maxabs <= limit ) {\r
91             return;\r
92         }\r
93 \r
94         /* Convert to true warped coefficients */\r
95         for( i = 1; i < order; i++ ) {\r
96             coefs_syn[ i - 1 ] += lambda * coefs_syn[ i ];\r
97             coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ];\r
98         }\r
99 \r
100         /* Apply bandwidth expansion */\r
101         chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );\r
102         SKP_Silk_bwexpander_FLP( coefs_syn, order, chirp );\r
103         SKP_Silk_bwexpander_FLP( coefs_ana, order, chirp );\r
104 \r
105         /* Convert back to monic warped coefficients */\r
106         for( i = order - 1; i > 0; i-- ) {\r
107             coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];\r
108             coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];\r
109         }\r
110     }\r
111 }\r
112 \r
113 /* Compute noise shaping coefficients and initial gain values */\r
114 void SKP_Silk_noise_shape_analysis_FLP(\r
115     SKP_Silk_encoder_state_FLP      *psEnc,             /* I/O  Encoder state FLP                       */\r
116     SKP_Silk_encoder_control_FLP    *psEncCtrl,         /* I/O  Encoder control FLP                     */\r
117     const SKP_float                 *pitch_res,         /* I    LPC residual from pitch analysis        */\r
118     const SKP_float                 *x                  /* I    Input signal [frame_length + la_shape]  */\r
119 )\r
120 {\r
121     SKP_Silk_shape_state_FLP *psShapeSt = &psEnc->sShape;\r
122     SKP_int     k, nSamples;\r
123     SKP_float   SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt;\r
124     SKP_float   nrg, pre_nrg, log_energy, log_energy_prev, energy_variation;\r
125     SKP_float   delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping;\r
126     SKP_float   x_windowed[ SHAPE_LPC_WIN_MAX ];\r
127     SKP_float   auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];\r
128     const SKP_float *x_ptr, *pitch_res_ptr;\r
129 \r
130     /* Point to start of first LPC analysis block */\r
131     x_ptr = x + psEnc->sCmn.la_shape - SHAPE_LPC_WIN_MS * psEnc->sCmn.fs_kHz + psEnc->sCmn.subfr_length;\r
132 \r
133     /****************/\r
134     /* CONTROL SNR  */\r
135     /****************/\r
136     /* Reduce SNR_dB values if recent bitstream has exceeded TargetRate */\r
137     psEncCtrl->current_SNR_dB = psEnc->SNR_dB - 0.05f * psEnc->BufferedInChannel_ms;\r
138 \r
139     /* Reduce SNR_dB if inband FEC used */\r
140     if( psEnc->speech_activity > LBRR_SPEECH_ACTIVITY_THRES ) {\r
141         psEncCtrl->current_SNR_dB -= psEnc->inBandFEC_SNR_comp;\r
142     }\r
143 \r
144     /****************/\r
145     /* GAIN CONTROL */\r
146     /****************/\r
147     /* Input quality is the average of the quality in the lowest two VAD bands */\r
148     psEncCtrl->input_quality = 0.5f * ( psEncCtrl->input_quality_bands[ 0 ] + psEncCtrl->input_quality_bands[ 1 ] );\r
149 \r
150     /* Coding quality level, between 0.0 and 1.0 */\r
151     psEncCtrl->coding_quality = SKP_sigmoid( 0.25f * ( psEncCtrl->current_SNR_dB - 17.0f ) );\r
152 \r
153     /* Reduce coding SNR during low speech activity */\r
154     b = 1.0f - psEnc->speech_activity;\r
155     SNR_adj_dB = psEncCtrl->current_SNR_dB - \r
156         BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b;\r
157 \r
158     if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) {\r
159         /* Reduce gains for periodic signals */\r
160         SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr;\r
161     } else { \r
162         /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */\r
163         SNR_adj_dB += ( -0.4f * psEncCtrl->current_SNR_dB + 6.0f ) * ( 1.0f - psEncCtrl->input_quality );\r
164     }\r
165 \r
166     /*************************/\r
167     /* SPARSENESS PROCESSING */\r
168     /*************************/\r
169     /* Set quantizer offset */\r
170     if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) {\r
171         /* Initally set to 0; may be overruled in process_gains(..) */\r
172         psEncCtrl->sCmn.QuantOffsetType = 0;\r
173         psEncCtrl->sparseness = 0.0f;\r
174     } else {\r
175         /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */\r
176         nSamples = 2 * psEnc->sCmn.fs_kHz;\r
177         energy_variation = 0.0f;\r
178         log_energy_prev  = 0.0f;\r
179         pitch_res_ptr = pitch_res;\r
180         for( k = 0; k < SKP_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {\r
181             nrg = ( SKP_float )nSamples + ( SKP_float )SKP_Silk_energy_FLP( pitch_res_ptr, nSamples );\r
182             log_energy = SKP_Silk_log2( nrg );\r
183             if( k > 0 ) {\r
184                 energy_variation += SKP_abs_float( log_energy - log_energy_prev );\r
185             }\r
186             log_energy_prev = log_energy;\r
187             pitch_res_ptr += nSamples;\r
188         }\r
189         psEncCtrl->sparseness = SKP_sigmoid( 0.4f * ( energy_variation - 5.0f ) );\r
190 \r
191         /* Set quantization offset depending on sparseness measure */\r
192         if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) {\r
193             psEncCtrl->sCmn.QuantOffsetType = 0;\r
194         } else {\r
195             psEncCtrl->sCmn.QuantOffsetType = 1;\r
196         }\r
197         \r
198         /* Increase coding SNR for sparse signals */\r
199         SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f );\r
200     }\r
201 \r
202     /*******************************/\r
203     /* Control bandwidth expansion */\r
204     /*******************************/\r
205     delta  = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality );\r
206     BWExp1 = BANDWIDTH_EXPANSION - delta;\r
207     BWExp2 = BANDWIDTH_EXPANSION + delta;\r
208     if( psEnc->sCmn.fs_kHz == 24 ) {\r
209         /* Less bandwidth expansion for super wideband */\r
210         BWExp1 = 1.0f - ( 1.0f - BWExp1 ) * SWB_BANDWIDTH_EXPANSION_REDUCTION;\r
211         BWExp2 = 1.0f - ( 1.0f - BWExp2 ) * SWB_BANDWIDTH_EXPANSION_REDUCTION;\r
212     }\r
213     /* BWExp1 will be applied after BWExp2, so make it relative */\r
214     BWExp1 /= BWExp2;\r
215 \r
216     /* Warping coefficient */\r
217     psEncCtrl->sCmn.warping_Q16 = psEnc->sCmn.fs_kHz * WARPING_MULTIPLIER_Q16;\r
218     psEncCtrl->sCmn.warping_Q16 = SKP_min( psEncCtrl->sCmn.warping_Q16, 32767 );\r
219     warping = (SKP_float)psEncCtrl->sCmn.warping_Q16 / 65536.0f;\r
220 \r
221     /********************************************/\r
222     /* Compute noise shaping AR coefs and gains */\r
223     /********************************************/\r
224     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
225         /* Apply window */\r
226         SKP_Silk_apply_sine_window_FLP( x_windowed, x_ptr, 0, SHAPE_LPC_WIN_MS * psEnc->sCmn.fs_kHz );\r
227 \r
228         /* Update pointer: next LPC analysis block */\r
229         x_ptr += psEnc->sCmn.subfr_length;\r
230 \r
231         /* Calculate warped auto correlation */\r
232         SKP_Silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping, \r
233             SHAPE_LPC_WIN_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.shapingLPCOrder );\r
234 \r
235         /* Add white noise, as a fraction of energy */\r
236         auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION; \r
237 \r
238         /* Convert correlations to prediction coefficients, and compute residual energy */\r
239         nrg = SKP_Silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, psEnc->sCmn.shapingLPCOrder );\r
240 \r
241         /* Convert residual energy to non-warped scale */\r
242         gain_mult = warped_gain( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );\r
243         nrg *= gain_mult * gain_mult; \r
244 \r
245         /* Bandwidth expansion for synthesis filter shaping */\r
246         SKP_Silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 );\r
247 \r
248         /* Compute noise shaping filter coefficients */\r
249         SKP_memcpy(\r
250             &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], \r
251             &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], \r
252             psEnc->sCmn.shapingLPCOrder * sizeof( SKP_float ) );\r
253 \r
254         /* Bandwidth expansion for analysis filter shaping */\r
255         SKP_Silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 );\r
256 \r
257         /* Increase residual energy */\r
258         nrg += SHAPE_MIN_ENERGY_RATIO * auto_corr[ 0 ];\r
259         psEncCtrl->Gains[ k ] = ( SKP_float )sqrt( nrg );\r
260         \r
261         /* Ratio of prediction gains, in energy domain */\r
262         SKP_Silk_LPC_inverse_pred_gain_FLP( &pre_nrg, &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );\r
263         SKP_Silk_LPC_inverse_pred_gain_FLP( &nrg,     &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );\r
264         psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg );\r
265 \r
266         /* Convert to monic warped prediction coefficients */\r
267         warped_true2monic_coefs( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );\r
268         warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );\r
269 \r
270         /* Limit absolute values */\r
271         limit_warped_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], \r
272             warping, 3.999f, psEnc->sCmn.shapingLPCOrder );\r
273     }\r
274 \r
275     /*****************/\r
276     /* Gain tweaking */\r
277     /*****************/\r
278     /* Increase gains during low speech activity and put lower limit on gains */\r
279     gain_mult = ( SKP_float )pow( 2.0f, -0.16f * SNR_adj_dB );\r
280     gain_add  = ( SKP_float )pow( 2.0f,  0.16f * NOISE_FLOOR_dB ) + \r
281                 ( SKP_float )pow( 2.0f,  0.16f * RELATIVE_MIN_GAIN_dB ) * psEnc->avgGain;\r
282     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
283         psEncCtrl->Gains[ k ] *= gain_mult;\r
284         psEncCtrl->Gains[ k ] += gain_add;\r
285         psEnc->avgGain += psEnc->speech_activity * GAIN_SMOOTHING_COEF * ( psEncCtrl->Gains[ k ] - psEnc->avgGain );\r
286     }\r
287 \r
288     /************************************************/\r
289     /* Decrease level during fricatives (de-essing) */\r
290     /************************************************/\r
291     gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT;\r
292     if( psEncCtrl->input_tilt <= 0.0f && psEncCtrl->sCmn.sigtype == SIG_TYPE_UNVOICED ) {\r
293         SKP_float essStrength = -psEncCtrl->input_tilt * psEnc->speech_activity * ( 1.0f - psEncCtrl->sparseness );\r
294         if( psEnc->sCmn.fs_kHz == 24 ) {\r
295             gain_mult *= ( SKP_float )pow( 2.0f, -0.16f * DE_ESSER_COEF_SWB_dB * essStrength );\r
296         } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
297             gain_mult *= (SKP_float)pow( 2.0f, -0.16f * DE_ESSER_COEF_WB_dB * essStrength );\r
298         } else {\r
299             SKP_assert( psEnc->sCmn.fs_kHz == 12 || psEnc->sCmn.fs_kHz == 8 );\r
300         }\r
301     }\r
302 \r
303     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
304         psEncCtrl->GainsPre[ k ] *= gain_mult;\r
305     }\r
306 \r
307     /************************************************/\r
308     /* Control low-frequency shaping and noise tilt */\r
309     /************************************************/\r
310     /* Less low frequency shaping for noisy inputs */\r
311     strength = LOW_FREQ_SHAPING * ( 1.0f + LOW_QUALITY_LOW_FREQ_SHAPING_DECR * ( psEncCtrl->input_quality_bands[ 0 ] - 1.0f ) );\r
312     if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) {\r
313         /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */\r
314         /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/\r
315         for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
316             b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->sCmn.pitchL[ k ];\r
317             psEncCtrl->LF_MA_shp[ k ] = -1.0f + b;\r
318             psEncCtrl->LF_AR_shp[ k ] =  1.0f - b - b * strength;\r
319         }\r
320         Tilt = - HP_NOISE_COEF - \r
321             (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->speech_activity;\r
322     } else {\r
323         b = 1.3f / psEnc->sCmn.fs_kHz;\r
324         psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b;\r
325         psEncCtrl->LF_AR_shp[ 0 ] =  1.0f - b - b * strength * 0.6f;\r
326         for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {\r
327             psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ k - 1 ];\r
328             psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ k - 1 ];\r
329         }\r
330         Tilt = -HP_NOISE_COEF;\r
331     }\r
332 \r
333     /****************************/\r
334     /* HARMONIC SHAPING CONTROL */\r
335     /****************************/\r
336     /* Control boosting of harmonic frequencies */\r
337     HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr;\r
338 \r
339     /* More harmonic boost for noisy input signals */\r
340     HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality );\r
341 \r
342     if( USE_HARM_SHAPING && psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) {\r
343         /* Harmonic noise shaping */\r
344         HarmShapeGain = HARMONIC_SHAPING;\r
345 \r
346         /* More harmonic noise shaping for high bitrates or noisy input */\r
347         HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING * \r
348             ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality );\r
349 \r
350         /* Less harmonic noise shaping for less periodic signals */\r
351         HarmShapeGain *= ( SKP_float )sqrt( psEnc->LTPCorr );\r
352     } else {\r
353         HarmShapeGain = 0.0f;\r
354     }\r
355 \r
356     /*************************/\r
357     /* Smooth over subframes */\r
358     /*************************/\r
359     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {\r
360         psShapeSt->HarmBoost_smth     += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth );\r
361         psEncCtrl->HarmBoost[ k ]      = psShapeSt->HarmBoost_smth;\r
362         psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );\r
363         psEncCtrl->HarmShapeGain[ k ]  = psShapeSt->HarmShapeGain_smth;\r
364         psShapeSt->Tilt_smth          += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );\r
365         psEncCtrl->Tilt[ k ]           = psShapeSt->Tilt_smth;\r
366     }\r
367 }\r