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