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