xref: /aosp_15_r20/external/libopus/silk/fixed/encode_frame_FIX.c (revision a58d3d2adb790c104798cd88c8a3aff4fa8b82cc)
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 
silk_encode_do_VAD_FIX(silk_encoder_state_FIX * psEnc,opus_int activity)45 void silk_encode_do_VAD_FIX(
46     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
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 /****************/
silk_encode_frame_FIX(silk_encoder_state_FIX * psEnc,opus_int32 * pnBytesOut,ec_enc * psRangeEnc,opus_int condCoding,opus_int maxBits,opus_int useCBR)85 opus_int silk_encode_frame_FIX(
86     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
87     opus_int32                      *pnBytesOut,                            /* O    Pointer to 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_FIX sEncCtrl;
95     opus_int     i, iter, maxIter, found_upper, found_lower, ret = 0;
96     opus_int16   *x_frame;
97     ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
98     silk_nsq_state sNSQ_copy, sNSQ_copy2;
99     opus_int32   seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
100     opus_int32   gainsID, gainsID_lower, gainsID_upper;
101     opus_int16   gainMult_Q8;
102     opus_int16   ec_prevLagIndex_copy;
103     opus_int     ec_prevSignalType_copy;
104     opus_int8    LastGainIndex_copy2;
105     opus_int     gain_lock[ MAX_NB_SUBFR ] = {0};
106     opus_int16   best_gain_mult[ MAX_NB_SUBFR ];
107     opus_int     best_sum[ MAX_NB_SUBFR ];
108     opus_int     bits_margin;
109     SAVE_STACK;
110 
111     /* For CBR, 5 bits below budget is close enough. For VBR, allow up to 25% below the cap if we initially busted the budget. */
112     bits_margin = useCBR ? 5 : maxBits/4;
113     /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
114     LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
115 
116     psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
117 
118     /**************************************************************/
119     /* Set up Input Pointers, and insert frame in input buffer   */
120     /*************************************************************/
121     /* start of frame to encode */
122     x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;
123 
124     /***************************************/
125     /* Ensure smooth bandwidth transitions */
126     /***************************************/
127     silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
128 
129     /*******************************************/
130     /* Copy new frame to front of input buffer */
131     /*******************************************/
132     silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );
133 
134     if( !psEnc->sCmn.prefillFlag ) {
135         VARDECL( opus_int16, res_pitch );
136         VARDECL( opus_uint8, ec_buf_copy );
137         opus_int16 *res_pitch_frame;
138 
139         ALLOC( res_pitch,
140                psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length
141                    + psEnc->sCmn.ltp_mem_length, opus_int16 );
142         /* start of pitch LPC residual frame */
143         res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length;
144 
145         /*****************************************/
146         /* Find pitch lags, initial LPC analysis */
147         /*****************************************/
148         silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame - psEnc->sCmn.ltp_mem_length, psEnc->sCmn.arch );
149 
150         /************************/
151         /* Noise shape analysis */
152         /************************/
153         silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch );
154 
155         /***************************************************/
156         /* Find linear prediction coefficients (LPC + LTP) */
157         /***************************************************/
158         silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
159 
160         /****************************************/
161         /* Process gains                        */
162         /****************************************/
163         silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding );
164 
165         /****************************************/
166         /* Low Bitrate Redundant Encoding       */
167         /****************************************/
168         silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding );
169 
170         /* Loop over quantizer and entropy coding to control bitrate */
171         maxIter = 6;
172         gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
173         found_lower = 0;
174         found_upper = 0;
175         gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
176         gainsID_lower = -1;
177         gainsID_upper = -1;
178         /* Copy part of the input state */
179         silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
180         silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
181         seed_copy = psEnc->sCmn.indices.Seed;
182         ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
183         ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
184         ALLOC( ec_buf_copy, 1275, opus_uint8 );
185         for( iter = 0; ; iter++ ) {
186             if( gainsID == gainsID_lower ) {
187                 nBits = nBits_lower;
188             } else if( gainsID == gainsID_upper ) {
189                 nBits = nBits_upper;
190             } else {
191                 /* Restore part of the input state */
192                 if( iter > 0 ) {
193                     silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
194                     silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) );
195                     psEnc->sCmn.indices.Seed = seed_copy;
196                     psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
197                     psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
198                 }
199 
200                 /*****************************************/
201                 /* Noise shaping quantization            */
202                 /*****************************************/
203                 if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
204                     silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
205                            sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
206                            sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
207                            psEnc->sCmn.arch );
208                 } else {
209                     silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
210                             sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
211                             sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
212                             psEnc->sCmn.arch);
213                 }
214 
215                 if ( iter == maxIter && !found_lower ) {
216                     silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
217                 }
218 
219                 /****************************************/
220                 /* Encode Parameters                    */
221                 /****************************************/
222                 silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
223 
224                 /****************************************/
225                 /* Encode Excitation Signal             */
226                 /****************************************/
227                 silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
228                     psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
229 
230                 nBits = ec_tell( psRangeEnc );
231 
232                 /* If we still bust after the last iteration, do some damage control. */
233                 if ( iter == maxIter && !found_lower && nBits > maxBits ) {
234                     silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
235 
236                     /* Keep gains the same as the last frame. */
237                     psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
238                     for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
239                         psEnc->sCmn.indices.GainsIndices[ i ] = 4;
240                     }
241                     if (condCoding != CODE_CONDITIONALLY) {
242                        psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
243                     }
244                     psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
245                     psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
246                     /* Clear all pulses. */
247                     for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
248                         psEnc->sCmn.pulses[ i ] = 0;
249                     }
250 
251                     silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
252 
253                     silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
254                         psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
255 
256                     nBits = ec_tell( psRangeEnc );
257                 }
258 
259                 if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
260                     break;
261                 }
262             }
263 
264             if( iter == maxIter ) {
265                 if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
266                     /* Restore output state from earlier iteration that did meet the bitrate budget */
267                     silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
268                     celt_assert( sRangeEnc_copy2.offs <= 1275 );
269                     silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
270                     silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
271                     psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
272                 }
273                 break;
274             }
275 
276             if( nBits > maxBits ) {
277                 if( found_lower == 0 && iter >= 2 ) {
278                     /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
279                     sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 );
280                     found_upper = 0;
281                     gainsID_upper = -1;
282                 } else {
283                     found_upper = 1;
284                     nBits_upper = nBits;
285                     gainMult_upper = gainMult_Q8;
286                     gainsID_upper = gainsID;
287                 }
288             } else if( nBits < maxBits - bits_margin ) {
289                 found_lower = 1;
290                 nBits_lower = nBits;
291                 gainMult_lower = gainMult_Q8;
292                 if( gainsID != gainsID_lower ) {
293                     gainsID_lower = gainsID;
294                     /* Copy part of the output state */
295                     silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
296                     celt_assert( psRangeEnc->offs <= 1275 );
297                     silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
298                     silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
299                     LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
300                 }
301             } else {
302                 /* Close enough */
303                 break;
304             }
305 
306             if ( !found_lower && nBits > maxBits ) {
307                 int j;
308                 for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
309                     int sum=0;
310                     for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
311                         sum += abs( psEnc->sCmn.pulses[j] );
312                     }
313                     if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
314                         best_sum[i] = sum;
315                         best_gain_mult[i] = gainMult_Q8;
316                     } else {
317                         gain_lock[i] = 1;
318                     }
319                 }
320             }
321             if( ( found_lower & found_upper ) == 0 ) {
322                 /* Adjust gain according to high-rate rate/distortion curve */
323                 if( nBits > maxBits ) {
324                     gainMult_Q8 = silk_min_32( 1024, gainMult_Q8*3/2 );
325                 } else {
326                     gainMult_Q8 = silk_max_32( 64, gainMult_Q8*4/5 );
327                 }
328             } else {
329                 /* Adjust gain by interpolating */
330                 gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower );
331                 /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
332                 if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
333                     gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
334                 } else
335                 if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
336                     gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
337                 }
338             }
339 
340             for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
341                 opus_int16 tmp;
342                 if ( gain_lock[i] ) {
343                     tmp = best_gain_mult[i];
344                 } else {
345                     tmp = gainMult_Q8;
346                 }
347                 sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
348             }
349 
350             /* Quantize gains */
351             psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
352             silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16,
353                   &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
354 
355             /* Unique identifier of gains vector */
356             gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
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( opus_int16 ) );
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  */
silk_LBRR_encode_FIX(silk_encoder_state_FIX * psEnc,silk_encoder_control_FIX * psEncCtrl,const opus_int16 x16[],opus_int condCoding)388 static OPUS_INLINE void silk_LBRR_encode_FIX(
389     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
390     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
391     const opus_int16                x16[],                                  /* I    Input signal                                                                */
392     opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
393 )
394 {
395     opus_int32   TempGains_Q16[ MAX_NB_SUBFR ];
396     SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ];
397     silk_nsq_state sNSQ_LBRR;
398 
399     /*******************************************/
400     /* Control use of inband LBRR              */
401     /*******************************************/
402     if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) {
403         psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
404 
405         /* Copy noise shaping quantizer state and quantization indices from regular encoding */
406         silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
407         silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) );
408 
409         /* Save original gains */
410         silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
411 
412         if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) {
413             /* First frame in packet or previous frame not LBRR coded */
414             psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
415 
416             /* Increase Gains to get target LBRR rate */
417             psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases;
418             psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 );
419         }
420 
421         /* Decode to get gains in sync with decoder         */
422         /* Overwrite unquantized gains with quantized gains */
423         silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices,
424             &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
425 
426         /*****************************************/
427         /* Noise shaping quantization            */
428         /*****************************************/
429         if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
430             silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
431                 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
432                 psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
433                 psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
434         } else {
435             silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
436                 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
437                 psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
438                 psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
439         }
440 
441         /* Restore original gains */
442         silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
443     }
444 }
445