media/libopus/silk/fixed/noise_shape_analysis_FIX.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /***********************************************************************
michael@0 2 Copyright (c) 2006-2011, Skype Limited. All rights reserved.
michael@0 3 Redistribution and use in source and binary forms, with or without
michael@0 4 modification, are permitted provided that the following conditions
michael@0 5 are met:
michael@0 6 - Redistributions of source code must retain the above copyright notice,
michael@0 7 this list of conditions and the following disclaimer.
michael@0 8 - Redistributions in binary form must reproduce the above copyright
michael@0 9 notice, this list of conditions and the following disclaimer in the
michael@0 10 documentation and/or other materials provided with the distribution.
michael@0 11 - Neither the name of Internet Society, IETF or IETF Trust, nor the
michael@0 12 names of specific contributors, may be used to endorse or promote
michael@0 13 products derived from this software without specific prior written
michael@0 14 permission.
michael@0 15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
michael@0 16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
michael@0 17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
michael@0 18 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
michael@0 19 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
michael@0 20 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
michael@0 21 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
michael@0 22 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
michael@0 23 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
michael@0 24 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
michael@0 25 POSSIBILITY OF SUCH DAMAGE.
michael@0 26 ***********************************************************************/
michael@0 27
michael@0 28 #ifdef HAVE_CONFIG_H
michael@0 29 #include "config.h"
michael@0 30 #endif
michael@0 31
michael@0 32 #include "main_FIX.h"
michael@0 33 #include "stack_alloc.h"
michael@0 34 #include "tuning_parameters.h"
michael@0 35
michael@0 36 /* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */
michael@0 37 /* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */
michael@0 38 /* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */
michael@0 39 /* coefficient in an array of coefficients, for monic filters. */
michael@0 40 static OPUS_INLINE opus_int32 warped_gain( /* gain in Q16*/
michael@0 41 const opus_int32 *coefs_Q24,
michael@0 42 opus_int lambda_Q16,
michael@0 43 opus_int order
michael@0 44 ) {
michael@0 45 opus_int i;
michael@0 46 opus_int32 gain_Q24;
michael@0 47
michael@0 48 lambda_Q16 = -lambda_Q16;
michael@0 49 gain_Q24 = coefs_Q24[ order - 1 ];
michael@0 50 for( i = order - 2; i >= 0; i-- ) {
michael@0 51 gain_Q24 = silk_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 );
michael@0 52 }
michael@0 53 gain_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 );
michael@0 54 return silk_INVERSE32_varQ( gain_Q24, 40 );
michael@0 55 }
michael@0 56
michael@0 57 /* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
michael@0 58 /* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
michael@0 59 static OPUS_INLINE void limit_warped_coefs(
michael@0 60 opus_int32 *coefs_syn_Q24,
michael@0 61 opus_int32 *coefs_ana_Q24,
michael@0 62 opus_int lambda_Q16,
michael@0 63 opus_int32 limit_Q24,
michael@0 64 opus_int order
michael@0 65 ) {
michael@0 66 opus_int i, iter, ind = 0;
michael@0 67 opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16;
michael@0 68 opus_int32 nom_Q16, den_Q24;
michael@0 69
michael@0 70 /* Convert to monic coefficients */
michael@0 71 lambda_Q16 = -lambda_Q16;
michael@0 72 for( i = order - 1; i > 0; i-- ) {
michael@0 73 coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
michael@0 74 coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
michael@0 75 }
michael@0 76 lambda_Q16 = -lambda_Q16;
michael@0 77 nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
michael@0 78 den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
michael@0 79 gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
michael@0 80 den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
michael@0 81 gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
michael@0 82 for( i = 0; i < order; i++ ) {
michael@0 83 coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
michael@0 84 coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
michael@0 85 }
michael@0 86
michael@0 87 for( iter = 0; iter < 10; iter++ ) {
michael@0 88 /* Find maximum absolute value */
michael@0 89 maxabs_Q24 = -1;
michael@0 90 for( i = 0; i < order; i++ ) {
michael@0 91 tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) );
michael@0 92 if( tmp > maxabs_Q24 ) {
michael@0 93 maxabs_Q24 = tmp;
michael@0 94 ind = i;
michael@0 95 }
michael@0 96 }
michael@0 97 if( maxabs_Q24 <= limit_Q24 ) {
michael@0 98 /* Coefficients are within range - done */
michael@0 99 return;
michael@0 100 }
michael@0 101
michael@0 102 /* Convert back to true warped coefficients */
michael@0 103 for( i = 1; i < order; i++ ) {
michael@0 104 coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
michael@0 105 coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
michael@0 106 }
michael@0 107 gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 );
michael@0 108 gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 );
michael@0 109 for( i = 0; i < order; i++ ) {
michael@0 110 coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
michael@0 111 coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
michael@0 112 }
michael@0 113
michael@0 114 /* Apply bandwidth expansion */
michael@0 115 chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ(
michael@0 116 silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
michael@0 117 silk_MUL( maxabs_Q24, ind + 1 ), 22 );
michael@0 118 silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 );
michael@0 119 silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 );
michael@0 120
michael@0 121 /* Convert to monic warped coefficients */
michael@0 122 lambda_Q16 = -lambda_Q16;
michael@0 123 for( i = order - 1; i > 0; i-- ) {
michael@0 124 coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
michael@0 125 coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
michael@0 126 }
michael@0 127 lambda_Q16 = -lambda_Q16;
michael@0 128 nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
michael@0 129 den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
michael@0 130 gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
michael@0 131 den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
michael@0 132 gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
michael@0 133 for( i = 0; i < order; i++ ) {
michael@0 134 coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
michael@0 135 coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
michael@0 136 }
michael@0 137 }
michael@0 138 silk_assert( 0 );
michael@0 139 }
michael@0 140
michael@0 141 /**************************************************************/
michael@0 142 /* Compute noise shaping coefficients and initial gain values */
michael@0 143 /**************************************************************/
michael@0 144 void silk_noise_shape_analysis_FIX(
michael@0 145 silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */
michael@0 146 silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */
michael@0 147 const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */
michael@0 148 const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */
michael@0 149 int arch /* I Run-time architecture */
michael@0 150 )
michael@0 151 {
michael@0 152 silk_shape_state_FIX *psShapeSt = &psEnc->sShape;
michael@0 153 opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0;
michael@0 154 opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32;
michael@0 155 opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
michael@0 156 opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
michael@0 157 opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
michael@0 158 opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ];
michael@0 159 opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ];
michael@0 160 opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ];
michael@0 161 VARDECL( opus_int16, x_windowed );
michael@0 162 const opus_int16 *x_ptr, *pitch_res_ptr;
michael@0 163 SAVE_STACK;
michael@0 164
michael@0 165 /* Point to start of first LPC analysis block */
michael@0 166 x_ptr = x - psEnc->sCmn.la_shape;
michael@0 167
michael@0 168 /****************/
michael@0 169 /* GAIN CONTROL */
michael@0 170 /****************/
michael@0 171 SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7;
michael@0 172
michael@0 173 /* Input quality is the average of the quality in the lowest two VAD bands */
michael@0 174 psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ]
michael@0 175 + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 );
michael@0 176
michael@0 177 /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */
michael@0 178 psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 -
michael@0 179 SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 );
michael@0 180
michael@0 181 /* Reduce coding SNR during low speech activity */
michael@0 182 if( psEnc->sCmn.useCBR == 0 ) {
michael@0 183 b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8;
michael@0 184 b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 );
michael@0 185 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7,
michael@0 186 silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/
michael@0 187 silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/
michael@0 188 }
michael@0 189
michael@0 190 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
michael@0 191 /* Reduce gains for periodic signals */
michael@0 192 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 );
michael@0 193 } else {
michael@0 194 /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */
michael@0 195 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7,
michael@0 196 silk_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ),
michael@0 197 SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 );
michael@0 198 }
michael@0 199
michael@0 200 /*************************/
michael@0 201 /* SPARSENESS PROCESSING */
michael@0 202 /*************************/
michael@0 203 /* Set quantizer offset */
michael@0 204 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
michael@0 205 /* Initially set to 0; may be overruled in process_gains(..) */
michael@0 206 psEnc->sCmn.indices.quantOffsetType = 0;
michael@0 207 psEncCtrl->sparseness_Q8 = 0;
michael@0 208 } else {
michael@0 209 /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
michael@0 210 nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 );
michael@0 211 energy_variation_Q7 = 0;
michael@0 212 log_energy_prev_Q7 = 0;
michael@0 213 pitch_res_ptr = pitch_res;
michael@0 214 for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
michael@0 215 silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples );
michael@0 216 nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/
michael@0 217
michael@0 218 log_energy_Q7 = silk_lin2log( nrg );
michael@0 219 if( k > 0 ) {
michael@0 220 energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 );
michael@0 221 }
michael@0 222 log_energy_prev_Q7 = log_energy_Q7;
michael@0 223 pitch_res_ptr += nSamples;
michael@0 224 }
michael@0 225
michael@0 226 psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 -
michael@0 227 SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 );
michael@0 228
michael@0 229 /* Set quantization offset depending on sparseness measure */
michael@0 230 if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) {
michael@0 231 psEnc->sCmn.indices.quantOffsetType = 0;
michael@0 232 } else {
michael@0 233 psEnc->sCmn.indices.quantOffsetType = 1;
michael@0 234 }
michael@0 235
michael@0 236 /* Increase coding SNR for sparse signals */
michael@0 237 SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) );
michael@0 238 }
michael@0 239
michael@0 240 /*******************************/
michael@0 241 /* Control bandwidth expansion */
michael@0 242 /*******************************/
michael@0 243 /* More BWE for signals with high prediction gain */
michael@0 244 strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) );
michael@0 245 BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
michael@0 246 silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 );
michael@0 247 delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ),
michael@0 248 SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) );
michael@0 249 BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 );
michael@0 250 BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 );
michael@0 251 /* BWExp1 will be applied after BWExp2, so make it relative */
michael@0 252 BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) );
michael@0 253
michael@0 254 if( psEnc->sCmn.warping_Q16 > 0 ) {
michael@0 255 /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
michael@0 256 warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) );
michael@0 257 } else {
michael@0 258 warping_Q16 = 0;
michael@0 259 }
michael@0 260
michael@0 261 /********************************************/
michael@0 262 /* Compute noise shaping AR coefs and gains */
michael@0 263 /********************************************/
michael@0 264 ALLOC( x_windowed, psEnc->sCmn.shapeWinLength, opus_int16 );
michael@0 265 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
michael@0 266 /* Apply window: sine slope followed by flat part followed by cosine slope */
michael@0 267 opus_int shift, slope_part, flat_part;
michael@0 268 flat_part = psEnc->sCmn.fs_kHz * 3;
michael@0 269 slope_part = silk_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 );
michael@0 270
michael@0 271 silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part );
michael@0 272 shift = slope_part;
michael@0 273 silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) );
michael@0 274 shift += flat_part;
michael@0 275 silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part );
michael@0 276
michael@0 277 /* Update pointer: next LPC analysis block */
michael@0 278 x_ptr += psEnc->sCmn.subfr_length;
michael@0 279
michael@0 280 if( psEnc->sCmn.warping_Q16 > 0 ) {
michael@0 281 /* Calculate warped auto correlation */
michael@0 282 silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
michael@0 283 } else {
michael@0 284 /* Calculate regular auto correlation */
michael@0 285 silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
michael@0 286 }
michael@0 287
michael@0 288 /* Add white noise, as a fraction of energy */
michael@0 289 auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ),
michael@0 290 SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) );
michael@0 291
michael@0 292 /* Calculate the reflection coefficients using schur */
michael@0 293 nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder );
michael@0 294 silk_assert( nrg >= 0 );
michael@0 295
michael@0 296 /* Convert reflection coefficients to prediction coefficients */
michael@0 297 silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
michael@0 298
michael@0 299 Qnrg = -scale; /* range: -12...30*/
michael@0 300 silk_assert( Qnrg >= -12 );
michael@0 301 silk_assert( Qnrg <= 30 );
michael@0 302
michael@0 303 /* Make sure that Qnrg is an even number */
michael@0 304 if( Qnrg & 1 ) {
michael@0 305 Qnrg -= 1;
michael@0 306 nrg >>= 1;
michael@0 307 }
michael@0 308
michael@0 309 tmp32 = silk_SQRT_APPROX( nrg );
michael@0 310 Qnrg >>= 1; /* range: -6...15*/
michael@0 311
michael@0 312 psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( tmp32, 16 - Qnrg );
michael@0 313
michael@0 314 if( psEnc->sCmn.warping_Q16 > 0 ) {
michael@0 315 /* Adjust gain for warping */
michael@0 316 gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
michael@0 317 silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
michael@0 318 if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) {
michael@0 319 psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
michael@0 320 } else {
michael@0 321 psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
michael@0 322 }
michael@0 323 }
michael@0 324
michael@0 325 /* Bandwidth expansion for synthesis filter shaping */
michael@0 326 silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 );
michael@0 327
michael@0 328 /* Compute noise shaping filter coefficients */
michael@0 329 silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) );
michael@0 330
michael@0 331 /* Bandwidth expansion for analysis filter shaping */
michael@0 332 silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) );
michael@0 333 silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
michael@0 334
michael@0 335 /* Ratio of prediction gains, in energy domain */
michael@0 336 pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
michael@0 337 nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
michael@0 338
michael@0 339 /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
michael@0 340 pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
michael@0 341 psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 );
michael@0 342
michael@0 343 /* Convert to monic warped prediction coefficients and limit absolute values */
michael@0 344 limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
michael@0 345
michael@0 346 /* Convert from Q24 to Q13 and store in int16 */
michael@0 347 for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
michael@0 348 psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) );
michael@0 349 psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) );
michael@0 350 }
michael@0 351 }
michael@0 352
michael@0 353 /*****************/
michael@0 354 /* Gain tweaking */
michael@0 355 /*****************/
michael@0 356 /* Increase gains during low speech activity and put lower limit on gains */
michael@0 357 gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) );
michael@0 358 gain_add_Q16 = silk_log2lin( silk_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) );
michael@0 359 silk_assert( gain_mult_Q16 > 0 );
michael@0 360 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
michael@0 361 psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
michael@0 362 silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
michael@0 363 psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 );
michael@0 364 }
michael@0 365
michael@0 366 gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ),
michael@0 367 psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 );
michael@0 368 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
michael@0 369 psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] );
michael@0 370 }
michael@0 371
michael@0 372 /************************************************/
michael@0 373 /* Control low-frequency shaping and noise tilt */
michael@0 374 /************************************************/
michael@0 375 /* Less low frequency shaping for noisy inputs */
michael@0 376 strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ),
michael@0 377 SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) );
michael@0 378 strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 );
michael@0 379 if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
michael@0 380 /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */
michael@0 381 /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/
michael@0 382 opus_int fs_kHz_inv = silk_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz );
michael@0 383 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
michael@0 384 b_Q14 = fs_kHz_inv + silk_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] );
michael@0 385 /* Pack two coefficients in one int32 */
michael@0 386 psEncCtrl->LF_shp_Q14[ k ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - silk_SMULWB( strength_Q16, b_Q14 ), 16 );
michael@0 387 psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) );
michael@0 388 }
michael@0 389 silk_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); /* Guarantees that second argument to SMULWB() is within range of an opus_int16*/
michael@0 390 Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) -
michael@0 391 silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ),
michael@0 392 silk_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) );
michael@0 393 } else {
michael@0 394 b_Q14 = silk_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); /* 1.3_Q0 = 21299_Q14*/
michael@0 395 /* Pack two coefficients in one int32 */
michael@0 396 psEncCtrl->LF_shp_Q14[ 0 ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 -
michael@0 397 silk_SMULWB( strength_Q16, silk_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 );
michael@0 398 psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) );
michael@0 399 for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {
michael@0 400 psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ];
michael@0 401 }
michael@0 402 Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 );
michael@0 403 }
michael@0 404
michael@0 405 /****************************/
michael@0 406 /* HARMONIC SHAPING CONTROL */
michael@0 407 /****************************/
michael@0 408 /* Control boosting of harmonic frequencies */
michael@0 409 HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ),
michael@0 410 psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) );
michael@0 411
michael@0 412 /* More harmonic boost for noisy input signals */
michael@0 413 HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16,
michael@0 414 SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) );
michael@0 415
michael@0 416 if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
michael@0 417 /* More harmonic noise shaping for high bitrates or noisy input */
michael@0 418 HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ),
michael@0 419 SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ),
michael@0 420 psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) );
michael@0 421
michael@0 422 /* Less harmonic noise shaping for less periodic signals */
michael@0 423 HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ),
michael@0 424 silk_SQRT_APPROX( silk_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) );
michael@0 425 } else {
michael@0 426 HarmShapeGain_Q16 = 0;
michael@0 427 }
michael@0 428
michael@0 429 /*************************/
michael@0 430 /* Smooth over subframes */
michael@0 431 /*************************/
michael@0 432 for( k = 0; k < MAX_NB_SUBFR; k++ ) {
michael@0 433 psShapeSt->HarmBoost_smth_Q16 =
michael@0 434 silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
michael@0 435 psShapeSt->HarmShapeGain_smth_Q16 =
michael@0 436 silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
michael@0 437 psShapeSt->Tilt_smth_Q16 =
michael@0 438 silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
michael@0 439
michael@0 440 psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 );
michael@0 441 psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 );
michael@0 442 psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 );
michael@0 443 }
michael@0 444 RESTORE_STACK;
michael@0 445 }

mercurial