annotate src/opus-1.3/silk/float/noise_shape_analysis_FLP.c @ 169:223a55898ab9 tip default

Add null config files
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 02 Mar 2020 14:03:47 +0000
parents 4664ac0c1032
children
rev   line source
cannam@154 1 /***********************************************************************
cannam@154 2 Copyright (c) 2006-2011, Skype Limited. All rights reserved.
cannam@154 3 Redistribution and use in source and binary forms, with or without
cannam@154 4 modification, are permitted provided that the following conditions
cannam@154 5 are met:
cannam@154 6 - Redistributions of source code must retain the above copyright notice,
cannam@154 7 this list of conditions and the following disclaimer.
cannam@154 8 - Redistributions in binary form must reproduce the above copyright
cannam@154 9 notice, this list of conditions and the following disclaimer in the
cannam@154 10 documentation and/or other materials provided with the distribution.
cannam@154 11 - Neither the name of Internet Society, IETF or IETF Trust, nor the
cannam@154 12 names of specific contributors, may be used to endorse or promote
cannam@154 13 products derived from this software without specific prior written
cannam@154 14 permission.
cannam@154 15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
cannam@154 16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
cannam@154 17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
cannam@154 18 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
cannam@154 19 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
cannam@154 20 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
cannam@154 21 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
cannam@154 22 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
cannam@154 23 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
cannam@154 24 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
cannam@154 25 POSSIBILITY OF SUCH DAMAGE.
cannam@154 26 ***********************************************************************/
cannam@154 27
cannam@154 28 #ifdef HAVE_CONFIG_H
cannam@154 29 #include "config.h"
cannam@154 30 #endif
cannam@154 31
cannam@154 32 #include "main_FLP.h"
cannam@154 33 #include "tuning_parameters.h"
cannam@154 34
cannam@154 35 /* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */
cannam@154 36 /* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */
cannam@154 37 /* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */
cannam@154 38 /* coefficient in an array of coefficients, for monic filters. */
cannam@154 39 static OPUS_INLINE silk_float warped_gain(
cannam@154 40 const silk_float *coefs,
cannam@154 41 silk_float lambda,
cannam@154 42 opus_int order
cannam@154 43 ) {
cannam@154 44 opus_int i;
cannam@154 45 silk_float gain;
cannam@154 46
cannam@154 47 lambda = -lambda;
cannam@154 48 gain = coefs[ order - 1 ];
cannam@154 49 for( i = order - 2; i >= 0; i-- ) {
cannam@154 50 gain = lambda * gain + coefs[ i ];
cannam@154 51 }
cannam@154 52 return (silk_float)( 1.0f / ( 1.0f - lambda * gain ) );
cannam@154 53 }
cannam@154 54
cannam@154 55 /* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
cannam@154 56 /* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
cannam@154 57 static OPUS_INLINE void warped_true2monic_coefs(
cannam@154 58 silk_float *coefs,
cannam@154 59 silk_float lambda,
cannam@154 60 silk_float limit,
cannam@154 61 opus_int order
cannam@154 62 ) {
cannam@154 63 opus_int i, iter, ind = 0;
cannam@154 64 silk_float tmp, maxabs, chirp, gain;
cannam@154 65
cannam@154 66 /* Convert to monic coefficients */
cannam@154 67 for( i = order - 1; i > 0; i-- ) {
cannam@154 68 coefs[ i - 1 ] -= lambda * coefs[ i ];
cannam@154 69 }
cannam@154 70 gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
cannam@154 71 for( i = 0; i < order; i++ ) {
cannam@154 72 coefs[ i ] *= gain;
cannam@154 73 }
cannam@154 74
cannam@154 75 /* Limit */
cannam@154 76 for( iter = 0; iter < 10; iter++ ) {
cannam@154 77 /* Find maximum absolute value */
cannam@154 78 maxabs = -1.0f;
cannam@154 79 for( i = 0; i < order; i++ ) {
cannam@154 80 tmp = silk_abs_float( coefs[ i ] );
cannam@154 81 if( tmp > maxabs ) {
cannam@154 82 maxabs = tmp;
cannam@154 83 ind = i;
cannam@154 84 }
cannam@154 85 }
cannam@154 86 if( maxabs <= limit ) {
cannam@154 87 /* Coefficients are within range - done */
cannam@154 88 return;
cannam@154 89 }
cannam@154 90
cannam@154 91 /* Convert back to true warped coefficients */
cannam@154 92 for( i = 1; i < order; i++ ) {
cannam@154 93 coefs[ i - 1 ] += lambda * coefs[ i ];
cannam@154 94 }
cannam@154 95 gain = 1.0f / gain;
cannam@154 96 for( i = 0; i < order; i++ ) {
cannam@154 97 coefs[ i ] *= gain;
cannam@154 98 }
cannam@154 99
cannam@154 100 /* Apply bandwidth expansion */
cannam@154 101 chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
cannam@154 102 silk_bwexpander_FLP( coefs, order, chirp );
cannam@154 103
cannam@154 104 /* Convert to monic warped coefficients */
cannam@154 105 for( i = order - 1; i > 0; i-- ) {
cannam@154 106 coefs[ i - 1 ] -= lambda * coefs[ i ];
cannam@154 107 }
cannam@154 108 gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
cannam@154 109 for( i = 0; i < order; i++ ) {
cannam@154 110 coefs[ i ] *= gain;
cannam@154 111 }
cannam@154 112 }
cannam@154 113 silk_assert( 0 );
cannam@154 114 }
cannam@154 115
cannam@154 116 static OPUS_INLINE void limit_coefs(
cannam@154 117 silk_float *coefs,
cannam@154 118 silk_float limit,
cannam@154 119 opus_int order
cannam@154 120 ) {
cannam@154 121 opus_int i, iter, ind = 0;
cannam@154 122 silk_float tmp, maxabs, chirp;
cannam@154 123
cannam@154 124 for( iter = 0; iter < 10; iter++ ) {
cannam@154 125 /* Find maximum absolute value */
cannam@154 126 maxabs = -1.0f;
cannam@154 127 for( i = 0; i < order; i++ ) {
cannam@154 128 tmp = silk_abs_float( coefs[ i ] );
cannam@154 129 if( tmp > maxabs ) {
cannam@154 130 maxabs = tmp;
cannam@154 131 ind = i;
cannam@154 132 }
cannam@154 133 }
cannam@154 134 if( maxabs <= limit ) {
cannam@154 135 /* Coefficients are within range - done */
cannam@154 136 return;
cannam@154 137 }
cannam@154 138
cannam@154 139 /* Apply bandwidth expansion */
cannam@154 140 chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
cannam@154 141 silk_bwexpander_FLP( coefs, order, chirp );
cannam@154 142 }
cannam@154 143 silk_assert( 0 );
cannam@154 144 }
cannam@154 145
cannam@154 146 /* Compute noise shaping coefficients and initial gain values */
cannam@154 147 void silk_noise_shape_analysis_FLP(
cannam@154 148 silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
cannam@154 149 silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
cannam@154 150 const silk_float *pitch_res, /* I LPC residual from pitch analysis */
cannam@154 151 const silk_float *x /* I Input signal [frame_length + la_shape] */
cannam@154 152 )
cannam@154 153 {
cannam@154 154 silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
cannam@154 155 opus_int k, nSamples, nSegs;
cannam@154 156 silk_float SNR_adj_dB, HarmShapeGain, Tilt;
cannam@154 157 silk_float nrg, log_energy, log_energy_prev, energy_variation;
cannam@154 158 silk_float BWExp, gain_mult, gain_add, strength, b, warping;
cannam@154 159 silk_float x_windowed[ SHAPE_LPC_WIN_MAX ];
cannam@154 160 silk_float auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
cannam@154 161 silk_float rc[ MAX_SHAPE_LPC_ORDER + 1 ];
cannam@154 162 const silk_float *x_ptr, *pitch_res_ptr;
cannam@154 163
cannam@154 164 /* Point to start of first LPC analysis block */
cannam@154 165 x_ptr = x - psEnc->sCmn.la_shape;
cannam@154 166
cannam@154 167 /****************/
cannam@154 168 /* GAIN CONTROL */
cannam@154 169 /****************/
cannam@154 170 SNR_adj_dB = psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f );
cannam@154 171
cannam@154 172 /* Input quality is the average of the quality in the lowest two VAD bands */
cannam@154 173 psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f );
cannam@154 174
cannam@154 175 /* Coding quality level, between 0.0 and 1.0 */
cannam@154 176 psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) );
cannam@154 177
cannam@154 178 if( psEnc->sCmn.useCBR == 0 ) {
cannam@154 179 /* Reduce coding SNR during low speech activity */
cannam@154 180 b = 1.0f - psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f );
cannam@154 181 SNR_adj_dB -= BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b;
cannam@154 182 }
cannam@154 183
cannam@154 184 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
cannam@154 185 /* Reduce gains for periodic signals */
cannam@154 186 SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr;
cannam@154 187 } else {
cannam@154 188 /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */
cannam@154 189 SNR_adj_dB += ( -0.4f * psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) + 6.0f ) * ( 1.0f - psEncCtrl->input_quality );
cannam@154 190 }
cannam@154 191
cannam@154 192 /*************************/
cannam@154 193 /* SPARSENESS PROCESSING */
cannam@154 194 /*************************/
cannam@154 195 /* Set quantizer offset */
cannam@154 196 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
cannam@154 197 /* Initially set to 0; may be overruled in process_gains(..) */
cannam@154 198 psEnc->sCmn.indices.quantOffsetType = 0;
cannam@154 199 } else {
cannam@154 200 /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
cannam@154 201 nSamples = 2 * psEnc->sCmn.fs_kHz;
cannam@154 202 energy_variation = 0.0f;
cannam@154 203 log_energy_prev = 0.0f;
cannam@154 204 pitch_res_ptr = pitch_res;
cannam@154 205 nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
cannam@154 206 for( k = 0; k < nSegs; k++ ) {
cannam@154 207 nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
cannam@154 208 log_energy = silk_log2( nrg );
cannam@154 209 if( k > 0 ) {
cannam@154 210 energy_variation += silk_abs_float( log_energy - log_energy_prev );
cannam@154 211 }
cannam@154 212 log_energy_prev = log_energy;
cannam@154 213 pitch_res_ptr += nSamples;
cannam@154 214 }
cannam@154 215
cannam@154 216 /* Set quantization offset depending on sparseness measure */
cannam@154 217 if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) {
cannam@154 218 psEnc->sCmn.indices.quantOffsetType = 0;
cannam@154 219 } else {
cannam@154 220 psEnc->sCmn.indices.quantOffsetType = 1;
cannam@154 221 }
cannam@154 222 }
cannam@154 223
cannam@154 224 /*******************************/
cannam@154 225 /* Control bandwidth expansion */
cannam@154 226 /*******************************/
cannam@154 227 /* More BWE for signals with high prediction gain */
cannam@154 228 strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain; /* between 0.0 and 1.0 */
cannam@154 229 BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
cannam@154 230
cannam@154 231 /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
cannam@154 232 warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
cannam@154 233
cannam@154 234 /********************************************/
cannam@154 235 /* Compute noise shaping AR coefs and gains */
cannam@154 236 /********************************************/
cannam@154 237 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
cannam@154 238 /* Apply window: sine slope followed by flat part followed by cosine slope */
cannam@154 239 opus_int shift, slope_part, flat_part;
cannam@154 240 flat_part = psEnc->sCmn.fs_kHz * 3;
cannam@154 241 slope_part = ( psEnc->sCmn.shapeWinLength - flat_part ) / 2;
cannam@154 242
cannam@154 243 silk_apply_sine_window_FLP( x_windowed, x_ptr, 1, slope_part );
cannam@154 244 shift = slope_part;
cannam@154 245 silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(silk_float) );
cannam@154 246 shift += flat_part;
cannam@154 247 silk_apply_sine_window_FLP( x_windowed + shift, x_ptr + shift, 2, slope_part );
cannam@154 248
cannam@154 249 /* Update pointer: next LPC analysis block */
cannam@154 250 x_ptr += psEnc->sCmn.subfr_length;
cannam@154 251
cannam@154 252 if( psEnc->sCmn.warping_Q16 > 0 ) {
cannam@154 253 /* Calculate warped auto correlation */
cannam@154 254 silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping,
cannam@154 255 psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
cannam@154 256 } else {
cannam@154 257 /* Calculate regular auto correlation */
cannam@154 258 silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 );
cannam@154 259 }
cannam@154 260
cannam@154 261 /* Add white noise, as a fraction of energy */
cannam@154 262 auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f;
cannam@154 263
cannam@154 264 /* Convert correlations to prediction coefficients, and compute residual energy */
cannam@154 265 nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder );
cannam@154 266 silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder );
cannam@154 267 psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
cannam@154 268
cannam@154 269 if( psEnc->sCmn.warping_Q16 > 0 ) {
cannam@154 270 /* Adjust gain for warping */
cannam@154 271 psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
cannam@154 272 }
cannam@154 273
cannam@154 274 /* Bandwidth expansion for synthesis filter shaping */
cannam@154 275 silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp );
cannam@154 276
cannam@154 277 if( psEnc->sCmn.warping_Q16 > 0 ) {
cannam@154 278 /* Convert to monic warped prediction coefficients and limit absolute values */
cannam@154 279 warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
cannam@154 280 } else {
cannam@154 281 /* Limit absolute values */
cannam@154 282 limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder );
cannam@154 283 }
cannam@154 284 }
cannam@154 285
cannam@154 286 /*****************/
cannam@154 287 /* Gain tweaking */
cannam@154 288 /*****************/
cannam@154 289 /* Increase gains during low speech activity */
cannam@154 290 gain_mult = (silk_float)pow( 2.0f, -0.16f * SNR_adj_dB );
cannam@154 291 gain_add = (silk_float)pow( 2.0f, 0.16f * MIN_QGAIN_DB );
cannam@154 292 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
cannam@154 293 psEncCtrl->Gains[ k ] *= gain_mult;
cannam@154 294 psEncCtrl->Gains[ k ] += gain_add;
cannam@154 295 }
cannam@154 296
cannam@154 297 /************************************************/
cannam@154 298 /* Control low-frequency shaping and noise tilt */
cannam@154 299 /************************************************/
cannam@154 300 /* Less low frequency shaping for noisy inputs */
cannam@154 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 ) );
cannam@154 302 strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f );
cannam@154 303 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
cannam@154 304 /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */
cannam@154 305 /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/
cannam@154 306 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
cannam@154 307 b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->pitchL[ k ];
cannam@154 308 psEncCtrl->LF_MA_shp[ k ] = -1.0f + b;
cannam@154 309 psEncCtrl->LF_AR_shp[ k ] = 1.0f - b - b * strength;
cannam@154 310 }
cannam@154 311 Tilt = - HP_NOISE_COEF -
cannam@154 312 (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f );
cannam@154 313 } else {
cannam@154 314 b = 1.3f / psEnc->sCmn.fs_kHz;
cannam@154 315 psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b;
cannam@154 316 psEncCtrl->LF_AR_shp[ 0 ] = 1.0f - b - b * strength * 0.6f;
cannam@154 317 for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {
cannam@154 318 psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ 0 ];
cannam@154 319 psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ];
cannam@154 320 }
cannam@154 321 Tilt = -HP_NOISE_COEF;
cannam@154 322 }
cannam@154 323
cannam@154 324 /****************************/
cannam@154 325 /* HARMONIC SHAPING CONTROL */
cannam@154 326 /****************************/
cannam@154 327 if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
cannam@154 328 /* Harmonic noise shaping */
cannam@154 329 HarmShapeGain = HARMONIC_SHAPING;
cannam@154 330
cannam@154 331 /* More harmonic noise shaping for high bitrates or noisy input */
cannam@154 332 HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING *
cannam@154 333 ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality );
cannam@154 334
cannam@154 335 /* Less harmonic noise shaping for less periodic signals */
cannam@154 336 HarmShapeGain *= ( silk_float )sqrt( psEnc->LTPCorr );
cannam@154 337 } else {
cannam@154 338 HarmShapeGain = 0.0f;
cannam@154 339 }
cannam@154 340
cannam@154 341 /*************************/
cannam@154 342 /* Smooth over subframes */
cannam@154 343 /*************************/
cannam@154 344 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
cannam@154 345 psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
cannam@154 346 psEncCtrl->HarmShapeGain[ k ] = psShapeSt->HarmShapeGain_smth;
cannam@154 347 psShapeSt->Tilt_smth += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
cannam@154 348 psEncCtrl->Tilt[ k ] = psShapeSt->Tilt_smth;
cannam@154 349 }
cannam@154 350 }