1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/*********************************************************************** 2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCopyright (c) 2006-2011, Skype Limited. All rights reserved. 3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgRedistribution and use in source and binary forms, with or without 4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgmodification, are permitted provided that the following conditions 5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgare met: 6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org- Redistributions of source code must retain the above copyright notice, 7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgthis list of conditions and the following disclaimer. 8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org- Redistributions in binary form must reproduce the above copyright 9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnotice, this list of conditions and the following disclaimer in the 10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgdocumentation and/or other materials provided with the distribution. 11e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org- Neither the name of Internet Society, IETF or IETF Trust, nor the 12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnames of specific contributors, may be used to endorse or promote 13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgproducts derived from this software without specific prior written 14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgpermission. 15e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgPOSSIBILITY OF SUCH DAMAGE. 26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org***********************************************************************/ 27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef HAVE_CONFIG_H 29885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "config.h" 30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "main_FLP.h" 33885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "tuning_parameters.h" 34885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 35885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ 363c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.comstatic OPUS_INLINE void silk_LBRR_encode_FLP( 37885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ 38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ 39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const silk_float xfw[], /* I Input signal */ 40885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int condCoding /* I The type of conditional coding used so far for this frame */ 41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org); 42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid silk_encode_do_VAD_FLP( 44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */ 45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 47885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************/ 48885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Voice Activity Detection */ 49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************/ 50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1 ); 51885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /**************************************************/ 53885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Convert speech activity into VAD and DTX flags */ 54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /**************************************************/ 55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { 56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; 57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.noSpeechCounter++; 58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) { 59885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.inDTX = 0; 60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { 61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; 62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.inDTX = 0; 63885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; 65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.noSpeechCounter = 0; 67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.inDTX = 0; 68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.indices.signalType = TYPE_UNVOICED; 69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; 70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 72885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 73885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/****************/ 74885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Encode frame */ 75885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/****************/ 76885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgopus_int silk_encode_frame_FLP( 77885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ 78885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *pnBytesOut, /* O Number of payload bytes; */ 79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ec_enc *psRangeEnc, /* I/O compressor data structure */ 80885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int condCoding, /* I The type of conditional coding to use */ 81885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int maxBits, /* I If > 0: maximum number of output bits */ 82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int useCBR /* I Flag to force constant-bitrate operation */ 83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_control_FLP sEncCtrl; 86885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int i, iter, maxIter, found_upper, found_lower, ret = 0; 87885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_float *x_frame, *res_pitch_frame; 88885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_float xfw[ MAX_FRAME_LENGTH ]; 89885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; 90885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ec_enc sRangeEnc_copy, sRangeEnc_copy2; 91885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_nsq_state sNSQ_copy, sNSQ_copy2; 92885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper; 93885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 gainsID, gainsID_lower, gainsID_upper; 94885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int16 gainMult_Q8; 95885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int16 ec_prevLagIndex_copy; 96885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int ec_prevSignalType_copy; 97885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int8 LastGainIndex_copy2; 98885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 pGains_Q16[ MAX_NB_SUBFR ]; 99885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_uint8 ec_buf_copy[ 1275 ]; 100885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 101885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */ 102885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0; 103885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 104885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; 105885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 106885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /**************************************************************/ 107885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Set up Input Pointers, and insert frame in input buffer */ 108885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /**************************************************************/ 109885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* pointers aligned with start of frame to encode */ 110885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */ 111885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; /* start of pitch LPC residual frame */ 112885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 113885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /***************************************/ 114885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Ensure smooth bandwidth transitions */ 115885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /***************************************/ 116885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length ); 117885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 118885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*******************************************/ 119885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Copy new frame to front of input buffer */ 120885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*******************************************/ 121885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length ); 122885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 123885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */ 124885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( i = 0; i < 8; i++ ) { 125885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + i * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( i & 2 ) ) * 1e-6f; 126885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 127885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 128885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( !psEnc->sCmn.prefillFlag ) { 129885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*****************************************/ 130885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Find pitch lags, initial LPC analysis */ 131885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*****************************************/ 1323c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch ); 133885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 134885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /************************/ 135885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Noise shape analysis */ 136885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /************************/ 137885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame ); 138885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 139885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /***************************************************/ 140885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Find linear prediction coefficients (LPC + LTP) */ 141885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /***************************************************/ 142885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding ); 143885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 144885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 145885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Process gains */ 146885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 147885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding ); 148885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 149885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*****************************************/ 150885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Prefiltering for noise shaper */ 151885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*****************************************/ 152885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame ); 153885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 154885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 155885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Low Bitrate Redundant Encoding */ 156885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 157885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding ); 158885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 159885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Loop over quantizer and entroy coding to control bitrate */ 160885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org maxIter = 6; 161885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); 162885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org found_lower = 0; 163885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org found_upper = 0; 164885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr ); 165885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainsID_lower = -1; 166885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainsID_upper = -1; 167885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Copy part of the input state */ 168885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) ); 169885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); 170885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org seed_copy = psEnc->sCmn.indices.Seed; 171885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex; 172885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType; 173885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( iter = 0; ; iter++ ) { 174885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( gainsID == gainsID_lower ) { 175885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nBits = nBits_lower; 176885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else if( gainsID == gainsID_upper ) { 177885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nBits = nBits_upper; 178885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 179885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Restore part of the input state */ 180885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( iter > 0 ) { 181885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) ); 182885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) ); 183885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.indices.Seed = seed_copy; 184885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy; 185885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy; 186885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 187885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 188885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*****************************************/ 189885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Noise shaping quantization */ 190885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*****************************************/ 191885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw ); 192885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 193885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 194885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Encode Parameters */ 195885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 196885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding ); 197885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 198885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 199885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Encode Excitation Signal */ 200885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 201885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, 202885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); 203885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 204885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nBits = ec_tell( psRangeEnc ); 205885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 206885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( useCBR == 0 && iter == 0 && nBits <= maxBits ) { 207885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 208885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 209885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 210885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 211885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( iter == maxIter ) { 212885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) { 213885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Restore output state from earlier iteration that did meet the bitrate budget */ 214885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) ); 215885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_assert( sRangeEnc_copy2.offs <= 1275 ); 216885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs ); 217885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) ); 218885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sShape.LastGainIndex = LastGainIndex_copy2; 219885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 220885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 221885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 222885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 223885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( nBits > maxBits ) { 224885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( found_lower == 0 && iter >= 2 ) { 225885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */ 226885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org sEncCtrl.Lambda *= 1.5f; 227885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org found_upper = 0; 228885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainsID_upper = -1; 229885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 230885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org found_upper = 1; 231885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nBits_upper = nBits; 232885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainMult_upper = gainMult_Q8; 233885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainsID_upper = gainsID; 234885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 235885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else if( nBits < maxBits - 5 ) { 236885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org found_lower = 1; 237885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nBits_lower = nBits; 238885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainMult_lower = gainMult_Q8; 239885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( gainsID != gainsID_lower ) { 240885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainsID_lower = gainsID; 241885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Copy part of the output state */ 242885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) ); 243885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_assert( psRangeEnc->offs <= 1275 ); 244885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs ); 245885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); 246885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; 247885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 248885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 249885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Within 5 bits of budget: close enough */ 250885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 251885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 252885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 253885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( ( found_lower & found_upper ) == 0 ) { 254885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Adjust gain according to high-rate rate/distortion curve */ 255885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 gain_factor_Q16; 256885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) ); 257885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) ); 258885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( nBits > maxBits ) { 259885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) ); 260885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 261885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 ); 262885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 263885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Adjust gain by interpolating */ 264885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower ); 265885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */ 266885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) { 267885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ); 268885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else 269885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) { 270885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ); 271885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 272885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 273885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 274885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { 275885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 ); 276885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 277885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 278885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Quantize gains */ 279885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev; 280885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16, 281885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); 282885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 283885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Unique identifier of gains vector */ 284885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr ); 285885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 286885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ 287885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { 288885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org sEncCtrl.Gains[ i ] = pGains_Q16[ i ] / 65536.0f; 289885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 290885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 291885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 292885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 293885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Update input buffer */ 294885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], 295885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( silk_float ) ); 296885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 297885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Exit without entropy coding */ 298885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( psEnc->sCmn.prefillFlag ) { 299885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* No payload */ 300885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *pnBytesOut = 0; 301885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return ret; 302885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 303885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 3043c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com /* Parameters needed for next frame */ 3053c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ]; 3063c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; 3073c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com 308885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 309885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Finalize payload */ 310885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /****************************************/ 311885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.first_frame_after_reset = 0; 312885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Payload size */ 313885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); 314885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 315885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return ret; 316885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 317885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 318885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ 3193c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.comstatic OPUS_INLINE void silk_LBRR_encode_FLP( 320885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ 321885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ 322885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const silk_float xfw[], /* I Input signal */ 323885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int condCoding /* I The type of conditional coding used so far for this frame */ 324885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 325885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 326885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int k; 327885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; 328885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_float TempGains[ MAX_NB_SUBFR ]; 329885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; 330885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_nsq_state sNSQ_LBRR; 331885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 332885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*******************************************/ 333885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Control use of inband LBRR */ 334885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*******************************************/ 335885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { 336885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; 337885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 338885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Copy noise shaping quantizer state and quantization indices from regular encoding */ 339885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); 340885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); 341885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 342885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Save original gains */ 343885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( TempGains, psEncCtrl->Gains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) ); 344885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 345885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { 346885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* First frame in packet or previous frame not LBRR coded */ 347885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; 348885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 349885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Increase Gains to get target LBRR rate */ 350885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psIndices_LBRR->GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases; 351885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); 352885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 353885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 354885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Decode to get gains in sync with decoder */ 355885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_gains_dequant( Gains_Q16, psIndices_LBRR->GainsIndices, 356885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); 357885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 358885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ 359885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { 360885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEncCtrl->Gains[ k ] = Gains_Q16[ k ] * ( 1.0f / 65536.0f ); 361885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 362885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 363885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*****************************************/ 364885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Noise shaping quantization */ 365885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*****************************************/ 366885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, psIndices_LBRR, &sNSQ_LBRR, 367885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw ); 368885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 369885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Restore original gains */ 370885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) ); 371885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 372885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 373