annotate src/opus-1.3/silk/float/noise_shape_analysis_FLP.c @ 79:91c729825bca pa_catalina

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