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