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 }