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 <stdlib.h>
     33 #include "main_FIX.h"
     34 #include "stack_alloc.h"
     35 #include "tuning_parameters.h"
     36 
     37 /* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate           */
     38 static OPUS_INLINE void silk_LBRR_encode_FIX(
     39     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
     40     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
     41     const opus_int16                x16[],                                  /* I    Input signal                                                                */
     42     opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
     43 );
     44 
     45 void silk_encode_do_VAD_FIX(
     46     silk_encoder_state_FIX          *psEnc                                  /* I/O  Pointer to Silk FIX encoder state                                           */
     47 )
     48 {
     49     /****************************/
     50     /* Voice Activity Detection */
     51     /****************************/
     52     silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
     53 
     54     /**************************************************/
     55     /* Convert speech activity into VAD and DTX flags */
     56     /**************************************************/
     57     if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
     58         psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
     59         psEnc->sCmn.noSpeechCounter++;
     60         if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
     61             psEnc->sCmn.inDTX = 0;
     62         } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
     63             psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
     64             psEnc->sCmn.inDTX           = 0;
     65         }
     66         psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0;
     67     } else {
     68         psEnc->sCmn.noSpeechCounter    = 0;
     69         psEnc->sCmn.inDTX              = 0;
     70         psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
     71         psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
     72     }
     73 }
     74 
     75 /****************/
     76 /* Encode frame */
     77 /****************/
     78 opus_int silk_encode_frame_FIX(
     79     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
     80     opus_int32                      *pnBytesOut,                            /* O    Pointer to number of payload bytes;                                         */
     81     ec_enc                          *psRangeEnc,                            /* I/O  compressor data structure                                                   */
     82     opus_int                        condCoding,                             /* I    The type of conditional coding to use                                       */
     83     opus_int                        maxBits,                                /* I    If > 0: maximum number of output bits                                       */
     84     opus_int                        useCBR                                  /* I    Flag to force constant-bitrate operation                                    */
     85 )
     86 {
     87     silk_encoder_control_FIX sEncCtrl;
     88     opus_int     i, iter, maxIter, found_upper, found_lower, ret = 0;
     89     opus_int16   *x_frame;
     90     ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
     91     silk_nsq_state sNSQ_copy, sNSQ_copy2;
     92     opus_int32   seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
     93     opus_int32   gainsID, gainsID_lower, gainsID_upper;
     94     opus_int16   gainMult_Q8;
     95     opus_int16   ec_prevLagIndex_copy;
     96     opus_int     ec_prevSignalType_copy;
     97     opus_int8    LastGainIndex_copy2;
     98     opus_int     gain_lock[ MAX_NB_SUBFR ] = {0};
     99     opus_int16   best_gain_mult[ MAX_NB_SUBFR ];
    100     opus_int     best_sum[ MAX_NB_SUBFR ];
    101     SAVE_STACK;
    102 
    103     /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
    104     LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
    105 
    106     psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
    107 
    108     /**************************************************************/
    109     /* Set up Input Pointers, and insert frame in input buffer   */
    110     /*************************************************************/
    111     /* start of frame to encode */
    112     x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;
    113 
    114     /***************************************/
    115     /* Ensure smooth bandwidth transitions */
    116     /***************************************/
    117     silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
    118 
    119     /*******************************************/
    120     /* Copy new frame to front of input buffer */
    121     /*******************************************/
    122     silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );
    123 
    124     if( !psEnc->sCmn.prefillFlag ) {
    125         VARDECL( opus_int16, res_pitch );
    126         VARDECL( opus_uint8, ec_buf_copy );
    127         opus_int16 *res_pitch_frame;
    128 
    129         ALLOC( res_pitch,
    130                psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length
    131                    + psEnc->sCmn.ltp_mem_length, opus_int16 );
    132         /* start of pitch LPC residual frame */
    133         res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length;
    134 
    135         /*****************************************/
    136         /* Find pitch lags, initial LPC analysis */
    137         /*****************************************/
    138         silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame - psEnc->sCmn.ltp_mem_length, psEnc->sCmn.arch );
    139 
    140         /************************/
    141         /* Noise shape analysis */
    142         /************************/
    143         silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch );
    144 
    145         /***************************************************/
    146         /* Find linear prediction coefficients (LPC + LTP) */
    147         /***************************************************/
    148         silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
    149 
    150         /****************************************/
    151         /* Process gains                        */
    152         /****************************************/
    153         silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding );
    154 
    155         /****************************************/
    156         /* Low Bitrate Redundant Encoding       */
    157         /****************************************/
    158         silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding );
    159 
    160         /* Loop over quantizer and entropy coding to control bitrate */
    161         maxIter = 6;
    162         gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
    163         found_lower = 0;
    164         found_upper = 0;
    165         gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
    166         gainsID_lower = -1;
    167         gainsID_upper = -1;
    168         /* Copy part of the input state */
    169         silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
    170         silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
    171         seed_copy = psEnc->sCmn.indices.Seed;
    172         ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
    173         ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
    174         ALLOC( ec_buf_copy, 1275, opus_uint8 );
    175         for( iter = 0; ; iter++ ) {
    176             if( gainsID == gainsID_lower ) {
    177                 nBits = nBits_lower;
    178             } else if( gainsID == gainsID_upper ) {
    179                 nBits = nBits_upper;
    180             } else {
    181                 /* Restore part of the input state */
    182                 if( iter > 0 ) {
    183                     silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
    184                     silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) );
    185                     psEnc->sCmn.indices.Seed = seed_copy;
    186                     psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
    187                     psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
    188                 }
    189 
    190                 /*****************************************/
    191                 /* Noise shaping quantization            */
    192                 /*****************************************/
    193                 if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
    194                     silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
    195                            sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
    196                            sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
    197                            psEnc->sCmn.arch );
    198                 } else {
    199                     silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
    200                             sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
    201                             sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
    202                             psEnc->sCmn.arch);
    203                 }
    204 
    205                 if ( iter == maxIter && !found_lower ) {
    206                     silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
    207                 }
    208 
    209                 /****************************************/
    210                 /* Encode Parameters                    */
    211                 /****************************************/
    212                 silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
    213 
    214                 /****************************************/
    215                 /* Encode Excitation Signal             */
    216                 /****************************************/
    217                 silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
    218                     psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
    219 
    220                 nBits = ec_tell( psRangeEnc );
    221 
    222                 /* If we still bust after the last iteration, do some damage control. */
    223                 if ( iter == maxIter && !found_lower && nBits > maxBits ) {
    224                     silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
    225 
    226                     /* Keep gains the same as the last frame. */
    227                     psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
    228                     for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
    229                         psEnc->sCmn.indices.GainsIndices[ i ] = 4;
    230                     }
    231                     if (condCoding != CODE_CONDITIONALLY) {
    232                        psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
    233                     }
    234                     psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
    235                     psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
    236                     /* Clear all pulses. */
    237                     for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
    238                         psEnc->sCmn.pulses[ i ] = 0;
    239                     }
    240 
    241                     silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
    242 
    243                     silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
    244                         psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
    245 
    246                     nBits = ec_tell( psRangeEnc );
    247                 }
    248 
    249                 if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
    250                     break;
    251                 }
    252             }
    253 
    254             if( iter == maxIter ) {
    255                 if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
    256                     /* Restore output state from earlier iteration that did meet the bitrate budget */
    257                     silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
    258                     silk_assert( sRangeEnc_copy2.offs <= 1275 );
    259                     silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
    260                     silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
    261                     psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
    262                 }
    263                 break;
    264             }
    265 
    266             if( nBits > maxBits ) {
    267                 if( found_lower == 0 && iter >= 2 ) {
    268                     /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
    269                     sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 );
    270                     found_upper = 0;
    271                     gainsID_upper = -1;
    272                 } else {
    273                     found_upper = 1;
    274                     nBits_upper = nBits;
    275                     gainMult_upper = gainMult_Q8;
    276                     gainsID_upper = gainsID;
    277                 }
    278             } else if( nBits < maxBits - 5 ) {
    279                 found_lower = 1;
    280                 nBits_lower = nBits;
    281                 gainMult_lower = gainMult_Q8;
    282                 if( gainsID != gainsID_lower ) {
    283                     gainsID_lower = gainsID;
    284                     /* Copy part of the output state */
    285                     silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
    286                     silk_assert( psRangeEnc->offs <= 1275 );
    287                     silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
    288                     silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
    289                     LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
    290                 }
    291             } else {
    292                 /* Within 5 bits of budget: close enough */
    293                 break;
    294             }
    295 
    296             if ( !found_lower && nBits > maxBits ) {
    297                 int j;
    298                 for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
    299                     int sum=0;
    300                     for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
    301                         sum += abs( psEnc->sCmn.pulses[j] );
    302                     }
    303                     if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
    304                         best_sum[i] = sum;
    305                         best_gain_mult[i] = gainMult_Q8;
    306                     } else {
    307                         gain_lock[i] = 1;
    308                     }
    309                 }
    310             }
    311             if( ( found_lower & found_upper ) == 0 ) {
    312                 /* Adjust gain according to high-rate rate/distortion curve */
    313                 if( nBits > maxBits ) {
    314                     if (gainMult_Q8 < 16384) {
    315                         gainMult_Q8 *= 2;
    316                     } else {
    317                         gainMult_Q8 = 32767;
    318                     }
    319                 } else {
    320                     opus_int32 gain_factor_Q16;
    321                     gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
    322                     gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
    323                 }
    324 
    325             } else {
    326                 /* Adjust gain by interpolating */
    327                 gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower );
    328                 /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
    329                 if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
    330                     gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
    331                 } else
    332                 if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
    333                     gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
    334                 }
    335             }
    336 
    337             for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
    338                 opus_int16 tmp;
    339                 if ( gain_lock[i] ) {
    340                     tmp = best_gain_mult[i];
    341                 } else {
    342                     tmp = gainMult_Q8;
    343                 }
    344                 sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
    345             }
    346 
    347             /* Quantize gains */
    348             psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
    349             silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16,
    350                   &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
    351 
    352             /* Unique identifier of gains vector */
    353             gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
    354         }
    355     }
    356 
    357     /* Update input buffer */
    358     silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
    359         ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) );
    360 
    361     /* Exit without entropy coding */
    362     if( psEnc->sCmn.prefillFlag ) {
    363         /* No payload */
    364         *pnBytesOut = 0;
    365         RESTORE_STACK;
    366         return ret;
    367     }
    368 
    369     /* Parameters needed for next frame */
    370     psEnc->sCmn.prevLag        = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ];
    371     psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType;
    372 
    373     /****************************************/
    374     /* Finalize payload                     */
    375     /****************************************/
    376     psEnc->sCmn.first_frame_after_reset = 0;
    377     /* Payload size */
    378     *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
    379 
    380     RESTORE_STACK;
    381     return ret;
    382 }
    383 
    384 /* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate  */
    385 static OPUS_INLINE void silk_LBRR_encode_FIX(
    386     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
    387     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
    388     const opus_int16                x16[],                                  /* I    Input signal                                                                */
    389     opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
    390 )
    391 {
    392     opus_int32   TempGains_Q16[ MAX_NB_SUBFR ];
    393     SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ];
    394     silk_nsq_state sNSQ_LBRR;
    395 
    396     /*******************************************/
    397     /* Control use of inband LBRR              */
    398     /*******************************************/
    399     if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) {
    400         psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
    401 
    402         /* Copy noise shaping quantizer state and quantization indices from regular encoding */
    403         silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
    404         silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) );
    405 
    406         /* Save original gains */
    407         silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
    408 
    409         if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) {
    410             /* First frame in packet or previous frame not LBRR coded */
    411             psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
    412 
    413             /* Increase Gains to get target LBRR rate */
    414             psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases;
    415             psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 );
    416         }
    417 
    418         /* Decode to get gains in sync with decoder         */
    419         /* Overwrite unquantized gains with quantized gains */
    420         silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices,
    421             &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
    422 
    423         /*****************************************/
    424         /* Noise shaping quantization            */
    425         /*****************************************/
    426         if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
    427             silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
    428                 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
    429                 psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
    430                 psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
    431         } else {
    432             silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
    433                 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
    434                 psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
    435                 psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
    436         }
    437 
    438         /* Restore original gains */
    439         silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
    440     }
    441 }
    442