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