Mercurial > hg > sv-dependency-builds
comparison src/opus-1.3/silk/float/noise_shape_analysis_FLP.c @ 154:4664ac0c1032
Add Opus sources and macOS builds
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Wed, 23 Jan 2019 13:48:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
153:84bc3a5ec321 | 154:4664ac0c1032 |
---|---|
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_FLP.h" | |
33 #include "tuning_parameters.h" | |
34 | |
35 /* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */ | |
36 /* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */ | |
37 /* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */ | |
38 /* coefficient in an array of coefficients, for monic filters. */ | |
39 static OPUS_INLINE silk_float warped_gain( | |
40 const silk_float *coefs, | |
41 silk_float lambda, | |
42 opus_int order | |
43 ) { | |
44 opus_int i; | |
45 silk_float gain; | |
46 | |
47 lambda = -lambda; | |
48 gain = coefs[ order - 1 ]; | |
49 for( i = order - 2; i >= 0; i-- ) { | |
50 gain = lambda * gain + coefs[ i ]; | |
51 } | |
52 return (silk_float)( 1.0f / ( 1.0f - lambda * gain ) ); | |
53 } | |
54 | |
55 /* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */ | |
56 /* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ | |
57 static OPUS_INLINE void warped_true2monic_coefs( | |
58 silk_float *coefs, | |
59 silk_float lambda, | |
60 silk_float limit, | |
61 opus_int order | |
62 ) { | |
63 opus_int i, iter, ind = 0; | |
64 silk_float tmp, maxabs, chirp, gain; | |
65 | |
66 /* Convert to monic coefficients */ | |
67 for( i = order - 1; i > 0; i-- ) { | |
68 coefs[ i - 1 ] -= lambda * coefs[ i ]; | |
69 } | |
70 gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] ); | |
71 for( i = 0; i < order; i++ ) { | |
72 coefs[ i ] *= gain; | |
73 } | |
74 | |
75 /* Limit */ | |
76 for( iter = 0; iter < 10; iter++ ) { | |
77 /* Find maximum absolute value */ | |
78 maxabs = -1.0f; | |
79 for( i = 0; i < order; i++ ) { | |
80 tmp = silk_abs_float( coefs[ i ] ); | |
81 if( tmp > maxabs ) { | |
82 maxabs = tmp; | |
83 ind = i; | |
84 } | |
85 } | |
86 if( maxabs <= limit ) { | |
87 /* Coefficients are within range - done */ | |
88 return; | |
89 } | |
90 | |
91 /* Convert back to true warped coefficients */ | |
92 for( i = 1; i < order; i++ ) { | |
93 coefs[ i - 1 ] += lambda * coefs[ i ]; | |
94 } | |
95 gain = 1.0f / gain; | |
96 for( i = 0; i < order; i++ ) { | |
97 coefs[ i ] *= gain; | |
98 } | |
99 | |
100 /* Apply bandwidth expansion */ | |
101 chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) ); | |
102 silk_bwexpander_FLP( coefs, order, chirp ); | |
103 | |
104 /* Convert to monic warped coefficients */ | |
105 for( i = order - 1; i > 0; i-- ) { | |
106 coefs[ i - 1 ] -= lambda * coefs[ i ]; | |
107 } | |
108 gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] ); | |
109 for( i = 0; i < order; i++ ) { | |
110 coefs[ i ] *= gain; | |
111 } | |
112 } | |
113 silk_assert( 0 ); | |
114 } | |
115 | |
116 static OPUS_INLINE void limit_coefs( | |
117 silk_float *coefs, | |
118 silk_float limit, | |
119 opus_int order | |
120 ) { | |
121 opus_int i, iter, ind = 0; | |
122 silk_float tmp, maxabs, chirp; | |
123 | |
124 for( iter = 0; iter < 10; iter++ ) { | |
125 /* Find maximum absolute value */ | |
126 maxabs = -1.0f; | |
127 for( i = 0; i < order; i++ ) { | |
128 tmp = silk_abs_float( coefs[ i ] ); | |
129 if( tmp > maxabs ) { | |
130 maxabs = tmp; | |
131 ind = i; | |
132 } | |
133 } | |
134 if( maxabs <= limit ) { | |
135 /* Coefficients are within range - done */ | |
136 return; | |
137 } | |
138 | |
139 /* Apply bandwidth expansion */ | |
140 chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) ); | |
141 silk_bwexpander_FLP( coefs, order, chirp ); | |
142 } | |
143 silk_assert( 0 ); | |
144 } | |
145 | |
146 /* Compute noise shaping coefficients and initial gain values */ | |
147 void silk_noise_shape_analysis_FLP( | |
148 silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ | |
149 silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ | |
150 const silk_float *pitch_res, /* I LPC residual from pitch analysis */ | |
151 const silk_float *x /* I Input signal [frame_length + la_shape] */ | |
152 ) | |
153 { | |
154 silk_shape_state_FLP *psShapeSt = &psEnc->sShape; | |
155 opus_int k, nSamples, nSegs; | |
156 silk_float SNR_adj_dB, HarmShapeGain, Tilt; | |
157 silk_float nrg, log_energy, log_energy_prev, energy_variation; | |
158 silk_float BWExp, gain_mult, gain_add, strength, b, warping; | |
159 silk_float x_windowed[ SHAPE_LPC_WIN_MAX ]; | |
160 silk_float auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; | |
161 silk_float rc[ MAX_SHAPE_LPC_ORDER + 1 ]; | |
162 const silk_float *x_ptr, *pitch_res_ptr; | |
163 | |
164 /* Point to start of first LPC analysis block */ | |
165 x_ptr = x - psEnc->sCmn.la_shape; | |
166 | |
167 /****************/ | |
168 /* GAIN CONTROL */ | |
169 /****************/ | |
170 SNR_adj_dB = psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ); | |
171 | |
172 /* Input quality is the average of the quality in the lowest two VAD bands */ | |
173 psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f ); | |
174 | |
175 /* Coding quality level, between 0.0 and 1.0 */ | |
176 psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) ); | |
177 | |
178 if( psEnc->sCmn.useCBR == 0 ) { | |
179 /* Reduce coding SNR during low speech activity */ | |
180 b = 1.0f - psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); | |
181 SNR_adj_dB -= BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b; | |
182 } | |
183 | |
184 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | |
185 /* Reduce gains for periodic signals */ | |
186 SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr; | |
187 } else { | |
188 /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ | |
189 SNR_adj_dB += ( -0.4f * psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) + 6.0f ) * ( 1.0f - psEncCtrl->input_quality ); | |
190 } | |
191 | |
192 /*************************/ | |
193 /* SPARSENESS PROCESSING */ | |
194 /*************************/ | |
195 /* Set quantizer offset */ | |
196 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | |
197 /* Initially set to 0; may be overruled in process_gains(..) */ | |
198 psEnc->sCmn.indices.quantOffsetType = 0; | |
199 } else { | |
200 /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ | |
201 nSamples = 2 * psEnc->sCmn.fs_kHz; | |
202 energy_variation = 0.0f; | |
203 log_energy_prev = 0.0f; | |
204 pitch_res_ptr = pitch_res; | |
205 nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; | |
206 for( k = 0; k < nSegs; k++ ) { | |
207 nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples ); | |
208 log_energy = silk_log2( nrg ); | |
209 if( k > 0 ) { | |
210 energy_variation += silk_abs_float( log_energy - log_energy_prev ); | |
211 } | |
212 log_energy_prev = log_energy; | |
213 pitch_res_ptr += nSamples; | |
214 } | |
215 | |
216 /* Set quantization offset depending on sparseness measure */ | |
217 if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) { | |
218 psEnc->sCmn.indices.quantOffsetType = 0; | |
219 } else { | |
220 psEnc->sCmn.indices.quantOffsetType = 1; | |
221 } | |
222 } | |
223 | |
224 /*******************************/ | |
225 /* Control bandwidth expansion */ | |
226 /*******************************/ | |
227 /* More BWE for signals with high prediction gain */ | |
228 strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain; /* between 0.0 and 1.0 */ | |
229 BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength ); | |
230 | |
231 /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ | |
232 warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality; | |
233 | |
234 /********************************************/ | |
235 /* Compute noise shaping AR coefs and gains */ | |
236 /********************************************/ | |
237 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | |
238 /* Apply window: sine slope followed by flat part followed by cosine slope */ | |
239 opus_int shift, slope_part, flat_part; | |
240 flat_part = psEnc->sCmn.fs_kHz * 3; | |
241 slope_part = ( psEnc->sCmn.shapeWinLength - flat_part ) / 2; | |
242 | |
243 silk_apply_sine_window_FLP( x_windowed, x_ptr, 1, slope_part ); | |
244 shift = slope_part; | |
245 silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(silk_float) ); | |
246 shift += flat_part; | |
247 silk_apply_sine_window_FLP( x_windowed + shift, x_ptr + shift, 2, slope_part ); | |
248 | |
249 /* Update pointer: next LPC analysis block */ | |
250 x_ptr += psEnc->sCmn.subfr_length; | |
251 | |
252 if( psEnc->sCmn.warping_Q16 > 0 ) { | |
253 /* Calculate warped auto correlation */ | |
254 silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping, | |
255 psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); | |
256 } else { | |
257 /* Calculate regular auto correlation */ | |
258 silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 ); | |
259 } | |
260 | |
261 /* Add white noise, as a fraction of energy */ | |
262 auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f; | |
263 | |
264 /* Convert correlations to prediction coefficients, and compute residual energy */ | |
265 nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder ); | |
266 silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder ); | |
267 psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg ); | |
268 | |
269 if( psEnc->sCmn.warping_Q16 > 0 ) { | |
270 /* Adjust gain for warping */ | |
271 psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder ); | |
272 } | |
273 | |
274 /* Bandwidth expansion for synthesis filter shaping */ | |
275 silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp ); | |
276 | |
277 if( psEnc->sCmn.warping_Q16 > 0 ) { | |
278 /* Convert to monic warped prediction coefficients and limit absolute values */ | |
279 warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder ); | |
280 } else { | |
281 /* Limit absolute values */ | |
282 limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder ); | |
283 } | |
284 } | |
285 | |
286 /*****************/ | |
287 /* Gain tweaking */ | |
288 /*****************/ | |
289 /* Increase gains during low speech activity */ | |
290 gain_mult = (silk_float)pow( 2.0f, -0.16f * SNR_adj_dB ); | |
291 gain_add = (silk_float)pow( 2.0f, 0.16f * MIN_QGAIN_DB ); | |
292 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | |
293 psEncCtrl->Gains[ k ] *= gain_mult; | |
294 psEncCtrl->Gains[ k ] += gain_add; | |
295 } | |
296 | |
297 /************************************************/ | |
298 /* Control low-frequency shaping and noise tilt */ | |
299 /************************************************/ | |
300 /* Less low frequency shaping for noisy inputs */ | |
301 strength = LOW_FREQ_SHAPING * ( 1.0f + LOW_QUALITY_LOW_FREQ_SHAPING_DECR * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] * ( 1.0f / 32768.0f ) - 1.0f ) ); | |
302 strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); | |
303 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | |
304 /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ | |
305 /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ | |
306 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | |
307 b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->pitchL[ k ]; | |
308 psEncCtrl->LF_MA_shp[ k ] = -1.0f + b; | |
309 psEncCtrl->LF_AR_shp[ k ] = 1.0f - b - b * strength; | |
310 } | |
311 Tilt = - HP_NOISE_COEF - | |
312 (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); | |
313 } else { | |
314 b = 1.3f / psEnc->sCmn.fs_kHz; | |
315 psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b; | |
316 psEncCtrl->LF_AR_shp[ 0 ] = 1.0f - b - b * strength * 0.6f; | |
317 for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { | |
318 psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ 0 ]; | |
319 psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ]; | |
320 } | |
321 Tilt = -HP_NOISE_COEF; | |
322 } | |
323 | |
324 /****************************/ | |
325 /* HARMONIC SHAPING CONTROL */ | |
326 /****************************/ | |
327 if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | |
328 /* Harmonic noise shaping */ | |
329 HarmShapeGain = HARMONIC_SHAPING; | |
330 | |
331 /* More harmonic noise shaping for high bitrates or noisy input */ | |
332 HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING * | |
333 ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality ); | |
334 | |
335 /* Less harmonic noise shaping for less periodic signals */ | |
336 HarmShapeGain *= ( silk_float )sqrt( psEnc->LTPCorr ); | |
337 } else { | |
338 HarmShapeGain = 0.0f; | |
339 } | |
340 | |
341 /*************************/ | |
342 /* Smooth over subframes */ | |
343 /*************************/ | |
344 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | |
345 psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth ); | |
346 psEncCtrl->HarmShapeGain[ k ] = psShapeSt->HarmShapeGain_smth; | |
347 psShapeSt->Tilt_smth += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth ); | |
348 psEncCtrl->Tilt[ k ] = psShapeSt->Tilt_smth; | |
349 } | |
350 } |