tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

encode_frame_FLP.c (22671B)


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