Initial Skype commit taken from FreeSwitch, which got it from the IETF draft.
[opus.git] / src / SKP_Silk_encode_frame_FIX.c
1 /***********************************************************************\r
2 Copyright (c) 2006-2010, Skype Limited. All rights reserved. \r
3 Redistribution and use in source and binary forms, with or without \r
4 modification, (subject to the limitations in the disclaimer below) \r
5 are permitted provided that the following conditions are met:\r
6 - Redistributions of source code must retain the above copyright notice,\r
7 this list of conditions and the following disclaimer.\r
8 - Redistributions in binary form must reproduce the above copyright \r
9 notice, this list of conditions and the following disclaimer in the \r
10 documentation and/or other materials provided with the distribution.\r
11 - Neither the name of Skype Limited, nor the names of specific \r
12 contributors, may be used to endorse or promote products derived from \r
13 this software without specific prior written permission.\r
14 NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED \r
15 BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \r
16 CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\r
17 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \r
18 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
19 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, \r
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
22 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
23 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
26 ***********************************************************************/\r
27 \r
28 #include "SKP_Silk_main_FIX.h"\r
29 /****************/\r
30 /* Encode frame */\r
31 /****************/\r
32 SKP_int SKP_Silk_encode_frame_FIX( \r
33     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O  Pointer to Silk FIX encoder state           */\r
34     SKP_uint8                       *pCode,             /* O    Pointer to payload                          */\r
35     SKP_int16                       *pnBytesOut,        /* I/O  Pointer to number of payload bytes          */\r
36                                                         /*      input: max length; output: used             */\r
37     const SKP_int16                 *pIn                /* I    Pointer to input speech frame               */\r
38 )\r
39 {\r
40     SKP_Silk_encoder_control_FIX sEncCtrl;\r
41     SKP_int     i, nBytes, ret = 0;\r
42     SKP_int16   *x_frame, *res_pitch_frame;\r
43     SKP_int16   xfw[ MAX_FRAME_LENGTH ];\r
44     SKP_int16   pIn_HP[ MAX_FRAME_LENGTH ];\r
45     SKP_int16   res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];\r
46     SKP_int     LBRR_idx, frame_terminator, SNR_dB_Q7;\r
47     const SKP_uint16 *FrameTermination_CDF;\r
48 \r
49     /* Low bitrate redundancy parameters */\r
50     SKP_uint8   LBRRpayload[ MAX_ARITHM_BYTES ];\r
51     SKP_int16   nBytesLBRR;\r
52 \r
53     //SKP_int32   Seed[ MAX_LAYERS ];\r
54     sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3;\r
55 \r
56 \r
57     /**************************************************************/\r
58     /* Setup Input Pointers, and insert frame in input buffer    */\r
59     /*************************************************************/\r
60     x_frame         = psEnc->x_buf + psEnc->sCmn.frame_length; /* start of frame to encode */\r
61     res_pitch_frame = res_pitch    + psEnc->sCmn.frame_length; /* start of pitch LPC residual frame */\r
62 \r
63     /****************************/\r
64     /* Voice Activity Detection */\r
65     /****************************/\r
66     ret = SKP_Silk_VAD_GetSA_Q8( &psEnc->sCmn.sVAD, &psEnc->speech_activity_Q8, &SNR_dB_Q7, \r
67                                  sEncCtrl.input_quality_bands_Q15, &sEncCtrl.input_tilt_Q15,\r
68                                  pIn,psEnc->sCmn.frame_length );\r
69 \r
70     /*******************************************/\r
71     /* High-pass filtering of the input signal */\r
72     /*******************************************/\r
73 #if HIGH_PASS_INPUT\r
74     /* Variable high-pass filter */\r
75     SKP_Silk_HP_variable_cutoff_FIX( psEnc, &sEncCtrl, pIn_HP, pIn );\r
76 #else\r
77     SKP_memcpy( pIn_HP, pIn,psEnc->sCmn.frame_length * sizeof( SKP_int16 ) );\r
78 #endif\r
79 \r
80 #if SWITCH_TRANSITION_FILTERING\r
81     /* Ensure smooth bandwidth transitions */\r
82     SKP_Silk_LP_variable_cutoff( &psEnc->sCmn.sLP, x_frame + psEnc->sCmn.la_shape, pIn_HP, psEnc->sCmn.frame_length );\r
83 #else\r
84     SKP_memcpy( x_frame + psEnc->sCmn.la_shape, pIn_HP,psEnc->sCmn.frame_length * sizeof( SKP_int16 ) );\r
85 #endif\r
86     \r
87     /*****************************************/\r
88     /* Find pitch lags, initial LPC analysis */\r
89     /*****************************************/\r
90     SKP_Silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame );\r
91 \r
92     /************************/\r
93     /* Noise shape analysis */\r
94     /************************/\r
95     SKP_Silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame );    \r
96 \r
97     /*****************************************/\r
98     /* Prefiltering for noise shaper         */\r
99     /*****************************************/\r
100     SKP_Silk_prefilter_FIX( psEnc, &sEncCtrl, xfw, x_frame );\r
101 \r
102 \r
103     /***************************************************/\r
104     /* Find linear prediction coefficients (LPC + LTP) */\r
105     /***************************************************/\r
106     SKP_Silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch );\r
107 \r
108     /****************************************/\r
109     /* Process gains                        */\r
110     /****************************************/\r
111     SKP_Silk_process_gains_FIX( psEnc, &sEncCtrl );\r
112  \r
113     psEnc->sCmn.sigtype[         psEnc->sCmn.nFramesInPayloadBuf ] = sEncCtrl.sCmn.sigtype;\r
114     psEnc->sCmn.QuantOffsetType[ psEnc->sCmn.nFramesInPayloadBuf ] = sEncCtrl.sCmn.QuantOffsetType;\r
115 \r
116     /****************************************/\r
117     /* Low Bitrate Redundant Encoding       */\r
118     /****************************************/\r
119     nBytesLBRR = MAX_ARITHM_BYTES;\r
120     SKP_Silk_LBRR_encode_FIX( psEnc, &sEncCtrl, LBRRpayload, &nBytesLBRR, xfw );\r
121 \r
122     /*****************************************/\r
123     /* Noise shaping quantization            */\r
124     /*****************************************/\r
125     psEnc->NoiseShapingQuantizer( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sNSQ, xfw, \r
126         &psEnc->sCmn.q[ psEnc->sCmn.nFramesInPayloadBuf *psEnc->sCmn.frame_length ], sEncCtrl.sCmn.NLSFInterpCoef_Q2, \r
127         sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, \r
128         sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.Lambda_Q10, \r
129         sEncCtrl.LTP_scale_Q14 );\r
130 \r
131     /**************************************************/\r
132     /* Convert speech activity into VAD and DTX flags */\r
133     /**************************************************/\r
134     if( psEnc->speech_activity_Q8 < SPEECH_ACTIVITY_DTX_THRES_Q8 ) {\r
135         psEnc->sCmn.vadFlag = NO_VOICE_ACTIVITY;\r
136         psEnc->sCmn.noSpeechCounter++;\r
137         if( psEnc->sCmn.noSpeechCounter > NO_SPEECH_FRAMES_BEFORE_DTX ) {\r
138             psEnc->sCmn.inDTX = 1;\r
139         }\r
140         if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX ) {\r
141             psEnc->sCmn.noSpeechCounter = 0;\r
142             psEnc->sCmn.inDTX           = 0;\r
143         }\r
144     } else {\r
145         psEnc->sCmn.noSpeechCounter = 0;\r
146         psEnc->sCmn.inDTX           = 0;\r
147         psEnc->sCmn.vadFlag         = VOICE_ACTIVITY;\r
148     }\r
149 \r
150     /****************************************/\r
151     /* Initialize arithmetic coder          */\r
152     /****************************************/\r
153     if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {\r
154         SKP_Silk_range_enc_init( &psEnc->sCmn.sRC );\r
155         psEnc->sCmn.nBytesInPayloadBuf = 0;\r
156     }\r
157 \r
158     /****************************************/\r
159     /* Encode Parameters                    */\r
160     /****************************************/\r
161     if( psEnc->sCmn.bitstream_v == BIT_STREAM_V4 ) {\r
162         SKP_Silk_encode_parameters_v4( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC );\r
163         FrameTermination_CDF = SKP_Silk_FrameTermination_v4_CDF;\r
164     } else {\r
165         SKP_Silk_encode_parameters( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC, \r
166             &psEnc->sCmn.q[ psEnc->sCmn.nFramesInPayloadBuf *psEnc->sCmn.frame_length ] );\r
167         FrameTermination_CDF = SKP_Silk_FrameTermination_CDF;\r
168     }\r
169 \r
170     /****************************************/\r
171     /* Update Buffers and State             */\r
172     /****************************************/\r
173     /* Update Input buffer */\r
174     SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], ( psEnc->sCmn.frame_length + psEnc->sCmn.la_shape ) * sizeof( SKP_int16 ) );\r
175     \r
176     /* parameters needed for next frame */\r
177     psEnc->sCmn.prev_sigtype            = sEncCtrl.sCmn.sigtype;\r
178     psEnc->sCmn.prevLag                 = sEncCtrl.sCmn.pitchL[ NB_SUBFR - 1];\r
179     psEnc->sCmn.first_frame_after_reset = 0;\r
180 \r
181     if( psEnc->sCmn.sRC.error ) {\r
182         /* encoder returned error: clear payload buffer */\r
183         psEnc->sCmn.nFramesInPayloadBuf = 0;\r
184     } else {\r
185         psEnc->sCmn.nFramesInPayloadBuf++;\r
186     }\r
187 \r
188     /****************************************/\r
189     /* finalize payload and copy to output  */\r
190     /****************************************/\r
191     if( psEnc->sCmn.nFramesInPayloadBuf * FRAME_LENGTH_MS >= psEnc->sCmn.PacketSize_ms ) {\r
192 \r
193         LBRR_idx = ( psEnc->sCmn.oldest_LBRR_idx + 1 ) & LBRR_IDX_MASK;\r
194 \r
195         /* Check if FEC information should be added */\r
196         frame_terminator = SKP_SILK_LAST_FRAME;\r
197         if( psEnc->sCmn.LBRR_buffer[ LBRR_idx ].usage == SKP_SILK_ADD_LBRR_TO_PLUS1 ) {\r
198             frame_terminator = SKP_SILK_LBRR_VER1;\r
199         }\r
200         if( psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].usage == SKP_SILK_ADD_LBRR_TO_PLUS2 ) {\r
201             frame_terminator = SKP_SILK_LBRR_VER2;\r
202             LBRR_idx = psEnc->sCmn.oldest_LBRR_idx;\r
203         }\r
204         /* Add the frame termination info to stream */\r
205         SKP_Silk_range_encoder( &psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF );\r
206 \r
207         if( psEnc->sCmn.bitstream_v == BIT_STREAM_V4 ) {\r
208             /* Code excitation signal */\r
209             for( i = 0; i <psEnc->sCmn.nFramesInPayloadBuf; i++ ) {\r
210                 SKP_Silk_encode_pulses( &psEnc->sCmn.sRC, psEnc->sCmn.sigtype[ i ],psEnc->sCmn.QuantOffsetType[ i ], \r
211                     &psEnc->sCmn.q[ i * psEnc->sCmn.frame_length],psEnc->sCmn.frame_length );\r
212             }\r
213         }\r
214         /* payload length so far */\r
215         SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC, &nBytes );\r
216 \r
217         /* check that there is enough space in external output buffer, and move data */\r
218         if( *pnBytesOut >= nBytes ) {\r
219             SKP_Silk_range_enc_wrap_up( &psEnc->sCmn.sRC );\r
220             SKP_memcpy( pCode, psEnc->sCmn.sRC.buffer, nBytes * sizeof( SKP_uint8 ) );\r
221             \r
222             if( frame_terminator > SKP_SILK_MORE_FRAMES && \r
223                     *pnBytesOut >= nBytes + psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes ) {\r
224                 /* Get old packet and add to payload. */\r
225                 SKP_memcpy( &pCode[ nBytes ],\r
226                     psEnc->sCmn.LBRR_buffer[ LBRR_idx ].payload,\r
227                     psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes * sizeof( SKP_uint8 ) );\r
228                 nBytes += psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes;\r
229             }\r
230                         \r
231             *pnBytesOut = nBytes;\r
232         \r
233             /* Update FEC buffer */\r
234             SKP_memcpy( psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].payload, LBRRpayload, \r
235                 nBytesLBRR * sizeof( SKP_uint8 ) );\r
236             psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].nBytes = nBytesLBRR;\r
237             /* This line tells describes how FEC should be used */\r
238             psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].usage = sEncCtrl.sCmn.LBRR_usage;\r
239             psEnc->sCmn.oldest_LBRR_idx = ( psEnc->sCmn.oldest_LBRR_idx + 1 ) & LBRR_IDX_MASK;\r
240 \r
241             /* Reset number of frames in payload buffer */\r
242             psEnc->sCmn.nFramesInPayloadBuf = 0;\r
243         } else {\r
244             /* Not enough space: Payload will be discarded */\r
245             *pnBytesOut = 0;\r
246             nBytes      = 0;\r
247             psEnc->sCmn.nFramesInPayloadBuf = 0;\r
248             ret = SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT;\r
249         }\r
250     } else {\r
251         /* no payload for you this time */\r
252         *pnBytesOut = 0;\r
253 \r
254         /* Encode that more frames follows */\r
255         frame_terminator = SKP_SILK_MORE_FRAMES;\r
256         SKP_Silk_range_encoder( &psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF );\r
257 \r
258         /* payload length so far */\r
259         SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC, &nBytes );\r
260         \r
261         if( psEnc->sCmn.bitstream_v == BIT_STREAM_V4 ) {\r
262             /* Take into account the q signal that isnt in the bitstream yet */\r
263             nBytes +=  SKP_Silk_pulses_to_bytes( &psEnc->sCmn, \r
264                 &psEnc->sCmn.q[ (psEnc->sCmn.nFramesInPayloadBuf - 1) * psEnc->sCmn.frame_length ] );\r
265         }\r
266     }\r
267 \r
268     /* Check for arithmetic coder errors */\r
269     if( psEnc->sCmn.sRC.error ) {\r
270         ret = SKP_SILK_ENC_INTERNAL_ERROR;\r
271     }\r
272 \r
273     /* simulate number of ms buffered in channel because of exceeding TargetRate */\r
274     SKP_assert(  ( 8 * 1000 * ( (SKP_int64)nBytes - (SKP_int64)psEnc->sCmn.nBytesInPayloadBuf ) ) == \r
275         SKP_SAT32( 8 * 1000 * ( (SKP_int64)nBytes - (SKP_int64)psEnc->sCmn.nBytesInPayloadBuf ) ) );\r
276     SKP_assert( psEnc->sCmn.TargetRate_bps > 0 );\r
277     psEnc->BufferedInChannel_ms   += SKP_DIV32( 8 * 1000 * ( nBytes -psEnc->sCmn.nBytesInPayloadBuf ),psEnc->sCmn.TargetRate_bps );\r
278     psEnc->BufferedInChannel_ms   -= FRAME_LENGTH_MS;\r
279     psEnc->BufferedInChannel_ms    = SKP_LIMIT( psEnc->BufferedInChannel_ms, 0, 100 );\r
280     psEnc->sCmn.nBytesInPayloadBuf = nBytes;\r
281 \r
282     if( psEnc->speech_activity_Q8 > WB_DETECT_ACTIVE_SPEECH_LEVEL_THRES_Q8 ) {\r
283         psEnc->sCmn.sSWBdetect.ActiveSpeech_ms = SKP_ADD_POS_SAT32( psEnc->sCmn.sSWBdetect.ActiveSpeech_ms, FRAME_LENGTH_MS ); \r
284     }\r
285 \r
286 \r
287     return( ret );\r
288 }\r
289 \r
290 /* Low BitRate Redundancy encoding functionality. Reuse all parameters but encode residual with lower bitrate */\r
291 void SKP_Silk_LBRR_encode_FIX(\r
292     SKP_Silk_encoder_state_FIX      *psEnc,         /* I/O  Pointer to Silk encoder state           */\r
293     SKP_Silk_encoder_control_FIX    *psEncCtrl,     /* I/O  Pointer to Silk encoder control struct  */\r
294     SKP_uint8                       *pCode,         /* O    Pointer to payload                      */\r
295     SKP_int16                       *pnBytesOut,    /* I/O  Pointer to number of payload bytes      */\r
296     SKP_int16                       xfw[]           /* I    Input signal                            */\r
297 )\r
298 {\r
299     SKP_int     i, TempGainsIndices[ NB_SUBFR ], frame_terminator;\r
300     SKP_int     nBytes, nFramesInPayloadBuf;\r
301     SKP_int32   TempGains_Q16[ NB_SUBFR ];\r
302     SKP_int     typeOffset, LTP_scaleIndex, Rate_only_parameters = 0;\r
303     /*******************************************/\r
304     /* Control use of inband LBRR              */\r
305     /*******************************************/\r
306     SKP_Silk_LBRR_ctrl_FIX( psEnc, psEncCtrl );\r
307 \r
308     if( psEnc->sCmn.LBRR_enabled ) {\r
309         /* Save original Gains */\r
310         SKP_memcpy( TempGainsIndices, psEncCtrl->sCmn.GainsIndices, NB_SUBFR * sizeof( SKP_int   ) );\r
311         SKP_memcpy( TempGains_Q16,    psEncCtrl->Gains_Q16,    NB_SUBFR * sizeof( SKP_int32 ) );\r
312 \r
313         typeOffset     = psEnc->sCmn.typeOffsetPrev; // Temp save as cannot be overwritten\r
314         LTP_scaleIndex = psEncCtrl->sCmn.LTP_scaleIndex;\r
315 \r
316         /* Set max rate where quant signal is encoded */\r
317         if( psEnc->sCmn.fs_kHz == 8 ) {\r
318             Rate_only_parameters = 13500;\r
319         } else if( psEnc->sCmn.fs_kHz == 12 ) {\r
320             Rate_only_parameters = 15500;\r
321         } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
322             Rate_only_parameters = 17500;\r
323         } else if( psEnc->sCmn.fs_kHz == 24 ) {\r
324             Rate_only_parameters = 19500;\r
325         } else {\r
326             SKP_assert( 0 );\r
327         }\r
328 \r
329         if( psEnc->sCmn.Complexity > 0 && psEnc->sCmn.TargetRate_bps > Rate_only_parameters ) {\r
330             if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {\r
331                 /* First frame in packet copy Everything */\r
332                 SKP_memcpy( &psEnc->sNSQ_LBRR, &psEnc->sNSQ, sizeof( SKP_Silk_nsq_state ) );\r
333             \r
334                 psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;\r
335                 /* Increase Gains to get target LBRR rate */\r
336                 psEncCtrl->sCmn.GainsIndices[ 0 ] = psEncCtrl->sCmn.GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases;\r
337                 psEncCtrl->sCmn.GainsIndices[ 0 ] = SKP_LIMIT( psEncCtrl->sCmn.GainsIndices[ 0 ], 0, N_LEVELS_QGAIN - 1 );\r
338             }\r
339             /* Decode to get Gains in sync with decoder         */\r
340             /* Overwrite unquantized gains with quantized gains */\r
341             SKP_Silk_gains_dequant( psEncCtrl->Gains_Q16, psEncCtrl->sCmn.GainsIndices, \r
342                 &psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesInPayloadBuf );\r
343             /*****************************************/\r
344             /* Noise shaping quantization            */\r
345             /*****************************************/\r
346             psEnc->NoiseShapingQuantizer( &psEnc->sCmn, &psEncCtrl->sCmn,\r
347                 &psEnc->sNSQ_LBRR, xfw, &psEnc->sCmn.q_LBRR[ psEnc->sCmn.nFramesInPayloadBuf * psEnc->sCmn.frame_length ], \r
348                 psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, \r
349                 psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, \r
350                 psEncCtrl->Gains_Q16, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 );\r
351         } else {\r
352             SKP_memset( &psEnc->sCmn.q_LBRR[ psEnc->sCmn.nFramesInPayloadBuf *psEnc->sCmn.frame_length ], 0,\r
353                 psEnc->sCmn.frame_length * sizeof( SKP_int ) );\r
354             psEncCtrl->sCmn.LTP_scaleIndex = 0;\r
355         }\r
356         /****************************************/\r
357         /* Initialize arithmetic coder          */\r
358         /****************************************/\r
359         if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {\r
360             SKP_Silk_range_enc_init( &psEnc->sCmn.sRC_LBRR );\r
361             psEnc->sCmn.nBytesInPayloadBuf = 0;\r
362         }\r
363 \r
364         /****************************************/\r
365         /* Encode Parameters                    */\r
366         /****************************************/\r
367         if( psEnc->sCmn.bitstream_v == BIT_STREAM_V4 ) {\r
368             SKP_Silk_encode_parameters_v4( &psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sRC_LBRR );\r
369         } else {\r
370             SKP_Silk_encode_parameters( &psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sRC_LBRR, \r
371                 &psEnc->sCmn.q_LBRR[ psEnc->sCmn.nFramesInPayloadBuf * psEnc->sCmn.frame_length] );\r
372         }\r
373 \r
374         if( psEnc->sCmn.sRC_LBRR.error ) {\r
375             /* encoder returned error: clear payload buffer */\r
376             nFramesInPayloadBuf = 0;\r
377         } else {\r
378             nFramesInPayloadBuf = psEnc->sCmn.nFramesInPayloadBuf + 1;\r
379         }\r
380 \r
381         /****************************************/\r
382         /* finalize payload and copy to output  */\r
383         /****************************************/\r
384         if( SKP_SMULBB( nFramesInPayloadBuf, FRAME_LENGTH_MS ) >= psEnc->sCmn.PacketSize_ms ) {\r
385 \r
386             /* Check if FEC information should be added */\r
387             frame_terminator = SKP_SILK_LAST_FRAME;\r
388 \r
389             /* Add the frame termination info to stream */\r
390             SKP_Silk_range_encoder( &psEnc->sCmn.sRC_LBRR, frame_terminator, SKP_Silk_FrameTermination_CDF );\r
391             \r
392             if( psEnc->sCmn.bitstream_v == BIT_STREAM_V4 ) {\r
393                 /*********************************************/\r
394                 /* Encode quantization indices of excitation */\r
395                 /*********************************************/\r
396                 for( i = 0; i < nFramesInPayloadBuf; i++ ) {\r
397                     SKP_Silk_encode_pulses( &psEnc->sCmn.sRC_LBRR, psEnc->sCmn.sigtype[ i ], psEnc->sCmn.QuantOffsetType[ i ],\r
398                         &psEnc->sCmn.q_LBRR[ i * psEnc->sCmn.frame_length ], psEnc->sCmn.frame_length );\r
399                 }\r
400             }\r
401             /* payload length so far */\r
402             SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC_LBRR, &nBytes );\r
403 \r
404             /* check that there is enough space in external output buffer, and move data */\r
405             if( *pnBytesOut >= nBytes ) {\r
406                 SKP_Silk_range_enc_wrap_up( &psEnc->sCmn.sRC_LBRR );\r
407                 SKP_memcpy( pCode, psEnc->sCmn.sRC_LBRR.buffer, nBytes * sizeof( SKP_uint8 ) );\r
408                 \r
409                 *pnBytesOut = nBytes;\r
410             } else {\r
411                 /* not enough space: payload will be discarded */\r
412                 *pnBytesOut = 0;\r
413                 SKP_assert( 0 );\r
414             }\r
415         } else {\r
416             /* no payload for you this time */\r
417             *pnBytesOut = 0;\r
418 \r
419             /* Encode that more frames follows */\r
420             frame_terminator = SKP_SILK_MORE_FRAMES;\r
421             SKP_Silk_range_encoder( &psEnc->sCmn.sRC_LBRR, frame_terminator, SKP_Silk_FrameTermination_CDF );\r
422         }\r
423 \r
424         /* Restore original Gains */\r
425         SKP_memcpy( psEncCtrl->sCmn.GainsIndices, TempGainsIndices, NB_SUBFR * sizeof( SKP_int   ) );\r
426         SKP_memcpy( psEncCtrl->Gains_Q16,  TempGains_Q16,    NB_SUBFR * sizeof( SKP_int32 ) );\r
427     \r
428         /* Restore LTP scale index and typeoffset */\r
429         psEncCtrl->sCmn.LTP_scaleIndex = LTP_scaleIndex;\r
430         psEnc->sCmn.typeOffsetPrev = typeOffset;\r
431     }\r
432 }\r