annotate src/opus-1.3/silk/float/encode_frame_FLP.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 7aeed7906520
children
rev   line source
Chris@69 1 /***********************************************************************
Chris@69 2 Copyright (c) 2006-2011, Skype Limited. All rights reserved.
Chris@69 3 Redistribution and use in source and binary forms, with or without
Chris@69 4 modification, are permitted provided that the following conditions
Chris@69 5 are met:
Chris@69 6 - Redistributions of source code must retain the above copyright notice,
Chris@69 7 this list of conditions and the following disclaimer.
Chris@69 8 - Redistributions in binary form must reproduce the above copyright
Chris@69 9 notice, this list of conditions and the following disclaimer in the
Chris@69 10 documentation and/or other materials provided with the distribution.
Chris@69 11 - Neither the name of Internet Society, IETF or IETF Trust, nor the
Chris@69 12 names of specific contributors, may be used to endorse or promote
Chris@69 13 products derived from this software without specific prior written
Chris@69 14 permission.
Chris@69 15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Chris@69 16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Chris@69 17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Chris@69 18 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Chris@69 19 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Chris@69 20 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Chris@69 21 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Chris@69 22 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Chris@69 23 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Chris@69 24 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Chris@69 25 POSSIBILITY OF SUCH DAMAGE.
Chris@69 26 ***********************************************************************/
Chris@69 27
Chris@69 28 #ifdef HAVE_CONFIG_H
Chris@69 29 #include "config.h"
Chris@69 30 #endif
Chris@69 31
Chris@69 32 #include <stdlib.h>
Chris@69 33 #include "main_FLP.h"
Chris@69 34 #include "tuning_parameters.h"
Chris@69 35
Chris@69 36 /* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */
Chris@69 37 static OPUS_INLINE void silk_LBRR_encode_FLP(
Chris@69 38 silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
Chris@69 39 silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
Chris@69 40 const silk_float xfw[], /* I Input signal */
Chris@69 41 opus_int condCoding /* I The type of conditional coding used so far for this frame */
Chris@69 42 );
Chris@69 43
Chris@69 44 void silk_encode_do_VAD_FLP(
Chris@69 45 silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
Chris@69 46 opus_int activity /* I Decision of Opus voice activity detector */
Chris@69 47 )
Chris@69 48 {
Chris@69 49 const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
Chris@69 50
Chris@69 51 /****************************/
Chris@69 52 /* Voice Activity Detection */
Chris@69 53 /****************************/
Chris@69 54 silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
Chris@69 55 /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
Chris@69 56 if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
Chris@69 57 psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
Chris@69 58 }
Chris@69 59
Chris@69 60 /**************************************************/
Chris@69 61 /* Convert speech activity into VAD and DTX flags */
Chris@69 62 /**************************************************/
Chris@69 63 if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
Chris@69 64 psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
Chris@69 65 psEnc->sCmn.noSpeechCounter++;
Chris@69 66 if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
Chris@69 67 psEnc->sCmn.inDTX = 0;
Chris@69 68 } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
Chris@69 69 psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
Chris@69 70 psEnc->sCmn.inDTX = 0;
Chris@69 71 }
Chris@69 72 psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0;
Chris@69 73 } else {
Chris@69 74 psEnc->sCmn.noSpeechCounter = 0;
Chris@69 75 psEnc->sCmn.inDTX = 0;
Chris@69 76 psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
Chris@69 77 psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
Chris@69 78 }
Chris@69 79 }
Chris@69 80
Chris@69 81 /****************/
Chris@69 82 /* Encode frame */
Chris@69 83 /****************/
Chris@69 84 opus_int silk_encode_frame_FLP(
Chris@69 85 silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
Chris@69 86 opus_int32 *pnBytesOut, /* O Number of payload bytes; */
Chris@69 87 ec_enc *psRangeEnc, /* I/O compressor data structure */
Chris@69 88 opus_int condCoding, /* I The type of conditional coding to use */
Chris@69 89 opus_int maxBits, /* I If > 0: maximum number of output bits */
Chris@69 90 opus_int useCBR /* I Flag to force constant-bitrate operation */
Chris@69 91 )
Chris@69 92 {
Chris@69 93 silk_encoder_control_FLP sEncCtrl;
Chris@69 94 opus_int i, iter, maxIter, found_upper, found_lower, ret = 0;
Chris@69 95 silk_float *x_frame, *res_pitch_frame;
Chris@69 96 silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
Chris@69 97 ec_enc sRangeEnc_copy, sRangeEnc_copy2;
Chris@69 98 silk_nsq_state sNSQ_copy, sNSQ_copy2;
Chris@69 99 opus_int32 seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
Chris@69 100 opus_int32 gainsID, gainsID_lower, gainsID_upper;
Chris@69 101 opus_int16 gainMult_Q8;
Chris@69 102 opus_int16 ec_prevLagIndex_copy;
Chris@69 103 opus_int ec_prevSignalType_copy;
Chris@69 104 opus_int8 LastGainIndex_copy2;
Chris@69 105 opus_int32 pGains_Q16[ MAX_NB_SUBFR ];
Chris@69 106 opus_uint8 ec_buf_copy[ 1275 ];
Chris@69 107 opus_int gain_lock[ MAX_NB_SUBFR ] = {0};
Chris@69 108 opus_int16 best_gain_mult[ MAX_NB_SUBFR ];
Chris@69 109 opus_int best_sum[ MAX_NB_SUBFR ];
Chris@69 110
Chris@69 111 /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
Chris@69 112 LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
Chris@69 113
Chris@69 114 psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
Chris@69 115
Chris@69 116 /**************************************************************/
Chris@69 117 /* Set up Input Pointers, and insert frame in input buffer */
Chris@69 118 /**************************************************************/
Chris@69 119 /* pointers aligned with start of frame to encode */
Chris@69 120 x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */
Chris@69 121 res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; /* start of pitch LPC residual frame */
Chris@69 122
Chris@69 123 /***************************************/
Chris@69 124 /* Ensure smooth bandwidth transitions */
Chris@69 125 /***************************************/
Chris@69 126 silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
Chris@69 127
Chris@69 128 /*******************************************/
Chris@69 129 /* Copy new frame to front of input buffer */
Chris@69 130 /*******************************************/
Chris@69 131 silk_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
Chris@69 132
Chris@69 133 /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */
Chris@69 134 for( i = 0; i < 8; i++ ) {
Chris@69 135 x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + i * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( i & 2 ) ) * 1e-6f;
Chris@69 136 }
Chris@69 137
Chris@69 138 if( !psEnc->sCmn.prefillFlag ) {
Chris@69 139 /*****************************************/
Chris@69 140 /* Find pitch lags, initial LPC analysis */
Chris@69 141 /*****************************************/
Chris@69 142 silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch );
Chris@69 143
Chris@69 144 /************************/
Chris@69 145 /* Noise shape analysis */
Chris@69 146 /************************/
Chris@69 147 silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame );
Chris@69 148
Chris@69 149 /***************************************************/
Chris@69 150 /* Find linear prediction coefficients (LPC + LTP) */
Chris@69 151 /***************************************************/
Chris@69 152 silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
Chris@69 153
Chris@69 154 /****************************************/
Chris@69 155 /* Process gains */
Chris@69 156 /****************************************/
Chris@69 157 silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding );
Chris@69 158
Chris@69 159 /****************************************/
Chris@69 160 /* Low Bitrate Redundant Encoding */
Chris@69 161 /****************************************/
Chris@69 162 silk_LBRR_encode_FLP( psEnc, &sEncCtrl, x_frame, condCoding );
Chris@69 163
Chris@69 164 /* Loop over quantizer and entroy coding to control bitrate */
Chris@69 165 maxIter = 6;
Chris@69 166 gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
Chris@69 167 found_lower = 0;
Chris@69 168 found_upper = 0;
Chris@69 169 gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
Chris@69 170 gainsID_lower = -1;
Chris@69 171 gainsID_upper = -1;
Chris@69 172 /* Copy part of the input state */
Chris@69 173 silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
Chris@69 174 silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
Chris@69 175 seed_copy = psEnc->sCmn.indices.Seed;
Chris@69 176 ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
Chris@69 177 ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
Chris@69 178 for( iter = 0; ; iter++ ) {
Chris@69 179 if( gainsID == gainsID_lower ) {
Chris@69 180 nBits = nBits_lower;
Chris@69 181 } else if( gainsID == gainsID_upper ) {
Chris@69 182 nBits = nBits_upper;
Chris@69 183 } else {
Chris@69 184 /* Restore part of the input state */
Chris@69 185 if( iter > 0 ) {
Chris@69 186 silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
Chris@69 187 silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) );
Chris@69 188 psEnc->sCmn.indices.Seed = seed_copy;
Chris@69 189 psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
Chris@69 190 psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
Chris@69 191 }
Chris@69 192
Chris@69 193 /*****************************************/
Chris@69 194 /* Noise shaping quantization */
Chris@69 195 /*****************************************/
Chris@69 196 silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, x_frame );
Chris@69 197
Chris@69 198 if ( iter == maxIter && !found_lower ) {
Chris@69 199 silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
Chris@69 200 }
Chris@69 201
Chris@69 202 /****************************************/
Chris@69 203 /* Encode Parameters */
Chris@69 204 /****************************************/
Chris@69 205 silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
Chris@69 206
Chris@69 207 /****************************************/
Chris@69 208 /* Encode Excitation Signal */
Chris@69 209 /****************************************/
Chris@69 210 silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
Chris@69 211 psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
Chris@69 212
Chris@69 213 nBits = ec_tell( psRangeEnc );
Chris@69 214
Chris@69 215 /* If we still bust after the last iteration, do some damage control. */
Chris@69 216 if ( iter == maxIter && !found_lower && nBits > maxBits ) {
Chris@69 217 silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
Chris@69 218
Chris@69 219 /* Keep gains the same as the last frame. */
Chris@69 220 psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
Chris@69 221 for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
Chris@69 222 psEnc->sCmn.indices.GainsIndices[ i ] = 4;
Chris@69 223 }
Chris@69 224 if (condCoding != CODE_CONDITIONALLY) {
Chris@69 225 psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
Chris@69 226 }
Chris@69 227 psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
Chris@69 228 psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
Chris@69 229 /* Clear all pulses. */
Chris@69 230 for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
Chris@69 231 psEnc->sCmn.pulses[ i ] = 0;
Chris@69 232 }
Chris@69 233
Chris@69 234 silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
Chris@69 235
Chris@69 236 silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
Chris@69 237 psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
Chris@69 238
Chris@69 239 nBits = ec_tell( psRangeEnc );
Chris@69 240 }
Chris@69 241
Chris@69 242 if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
Chris@69 243 break;
Chris@69 244 }
Chris@69 245 }
Chris@69 246
Chris@69 247 if( iter == maxIter ) {
Chris@69 248 if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
Chris@69 249 /* Restore output state from earlier iteration that did meet the bitrate budget */
Chris@69 250 silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
Chris@69 251 celt_assert( sRangeEnc_copy2.offs <= 1275 );
Chris@69 252 silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
Chris@69 253 silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
Chris@69 254 psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
Chris@69 255 }
Chris@69 256 break;
Chris@69 257 }
Chris@69 258
Chris@69 259 if( nBits > maxBits ) {
Chris@69 260 if( found_lower == 0 && iter >= 2 ) {
Chris@69 261 /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
Chris@69 262 sEncCtrl.Lambda = silk_max_float(sEncCtrl.Lambda*1.5f, 1.5f);
Chris@69 263 /* Reducing dithering can help us hit the target. */
Chris@69 264 psEnc->sCmn.indices.quantOffsetType = 0;
Chris@69 265 found_upper = 0;
Chris@69 266 gainsID_upper = -1;
Chris@69 267 } else {
Chris@69 268 found_upper = 1;
Chris@69 269 nBits_upper = nBits;
Chris@69 270 gainMult_upper = gainMult_Q8;
Chris@69 271 gainsID_upper = gainsID;
Chris@69 272 }
Chris@69 273 } else if( nBits < maxBits - 5 ) {
Chris@69 274 found_lower = 1;
Chris@69 275 nBits_lower = nBits;
Chris@69 276 gainMult_lower = gainMult_Q8;
Chris@69 277 if( gainsID != gainsID_lower ) {
Chris@69 278 gainsID_lower = gainsID;
Chris@69 279 /* Copy part of the output state */
Chris@69 280 silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
Chris@69 281 celt_assert( psRangeEnc->offs <= 1275 );
Chris@69 282 silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
Chris@69 283 silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
Chris@69 284 LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
Chris@69 285 }
Chris@69 286 } else {
Chris@69 287 /* Within 5 bits of budget: close enough */
Chris@69 288 break;
Chris@69 289 }
Chris@69 290
Chris@69 291 if ( !found_lower && nBits > maxBits ) {
Chris@69 292 int j;
Chris@69 293 for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
Chris@69 294 int sum=0;
Chris@69 295 for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
Chris@69 296 sum += abs( psEnc->sCmn.pulses[j] );
Chris@69 297 }
Chris@69 298 if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
Chris@69 299 best_sum[i] = sum;
Chris@69 300 best_gain_mult[i] = gainMult_Q8;
Chris@69 301 } else {
Chris@69 302 gain_lock[i] = 1;
Chris@69 303 }
Chris@69 304 }
Chris@69 305 }
Chris@69 306 if( ( found_lower & found_upper ) == 0 ) {
Chris@69 307 /* Adjust gain according to high-rate rate/distortion curve */
Chris@69 308 if( nBits > maxBits ) {
Chris@69 309 if (gainMult_Q8 < 16384) {
Chris@69 310 gainMult_Q8 *= 2;
Chris@69 311 } else {
Chris@69 312 gainMult_Q8 = 32767;
Chris@69 313 }
Chris@69 314 } else {
Chris@69 315 opus_int32 gain_factor_Q16;
Chris@69 316 gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
Chris@69 317 gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
Chris@69 318 }
Chris@69 319 } else {
Chris@69 320 /* Adjust gain by interpolating */
Chris@69 321 gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
Chris@69 322 /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
Chris@69 323 if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
Chris@69 324 gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
Chris@69 325 } else
Chris@69 326 if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
Chris@69 327 gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
Chris@69 328 }
Chris@69 329 }
Chris@69 330
Chris@69 331 for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
Chris@69 332 opus_int16 tmp;
Chris@69 333 if ( gain_lock[i] ) {
Chris@69 334 tmp = best_gain_mult[i];
Chris@69 335 } else {
Chris@69 336 tmp = gainMult_Q8;
Chris@69 337 }
Chris@69 338 pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
Chris@69 339 }
Chris@69 340
Chris@69 341 /* Quantize gains */
Chris@69 342 psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
Chris@69 343 silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
Chris@69 344 &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
Chris@69 345
Chris@69 346 /* Unique identifier of gains vector */
Chris@69 347 gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
Chris@69 348
Chris@69 349 /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
Chris@69 350 for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
Chris@69 351 sEncCtrl.Gains[ i ] = pGains_Q16[ i ] / 65536.0f;
Chris@69 352 }
Chris@69 353 }
Chris@69 354 }
Chris@69 355
Chris@69 356 /* Update input buffer */
Chris@69 357 silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
Chris@69 358 ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( silk_float ) );
Chris@69 359
Chris@69 360 /* Exit without entropy coding */
Chris@69 361 if( psEnc->sCmn.prefillFlag ) {
Chris@69 362 /* No payload */
Chris@69 363 *pnBytesOut = 0;
Chris@69 364 return ret;
Chris@69 365 }
Chris@69 366
Chris@69 367 /* Parameters needed for next frame */
Chris@69 368 psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ];
Chris@69 369 psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType;
Chris@69 370
Chris@69 371 /****************************************/
Chris@69 372 /* Finalize payload */
Chris@69 373 /****************************************/
Chris@69 374 psEnc->sCmn.first_frame_after_reset = 0;
Chris@69 375 /* Payload size */
Chris@69 376 *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
Chris@69 377
Chris@69 378 return ret;
Chris@69 379 }
Chris@69 380
Chris@69 381 /* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */
Chris@69 382 static OPUS_INLINE void silk_LBRR_encode_FLP(
Chris@69 383 silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
Chris@69 384 silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
Chris@69 385 const silk_float xfw[], /* I Input signal */
Chris@69 386 opus_int condCoding /* I The type of conditional coding used so far for this frame */
Chris@69 387 )
Chris@69 388 {
Chris@69 389 opus_int k;
Chris@69 390 opus_int32 Gains_Q16[ MAX_NB_SUBFR ];
Chris@69 391 silk_float TempGains[ MAX_NB_SUBFR ];
Chris@69 392 SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ];
Chris@69 393 silk_nsq_state sNSQ_LBRR;
Chris@69 394
Chris@69 395 /*******************************************/
Chris@69 396 /* Control use of inband LBRR */
Chris@69 397 /*******************************************/
Chris@69 398 if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) {
Chris@69 399 psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
Chris@69 400
Chris@69 401 /* Copy noise shaping quantizer state and quantization indices from regular encoding */
Chris@69 402 silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
Chris@69 403 silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) );
Chris@69 404
Chris@69 405 /* Save original gains */
Chris@69 406 silk_memcpy( TempGains, psEncCtrl->Gains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) );
Chris@69 407
Chris@69 408 if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) {
Chris@69 409 /* First frame in packet or previous frame not LBRR coded */
Chris@69 410 psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
Chris@69 411
Chris@69 412 /* Increase Gains to get target LBRR rate */
Chris@69 413 psIndices_LBRR->GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases;
Chris@69 414 psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 );
Chris@69 415 }
Chris@69 416
Chris@69 417 /* Decode to get gains in sync with decoder */
Chris@69 418 silk_gains_dequant( Gains_Q16, psIndices_LBRR->GainsIndices,
Chris@69 419 &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
Chris@69 420
Chris@69 421 /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
Chris@69 422 for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
Chris@69 423 psEncCtrl->Gains[ k ] = Gains_Q16[ k ] * ( 1.0f / 65536.0f );
Chris@69 424 }
Chris@69 425
Chris@69 426 /*****************************************/
Chris@69 427 /* Noise shaping quantization */
Chris@69 428 /*****************************************/
Chris@69 429 silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, psIndices_LBRR, &sNSQ_LBRR,
Chris@69 430 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw );
Chris@69 431
Chris@69 432 /* Restore original gains */
Chris@69 433 silk_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) );
Chris@69 434 }
Chris@69 435 }