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