b2a90375245ed130ebd7873a44b4a5c4fca91560
[opus.git] / src_FLP / SKP_Silk_encode_frame_FLP.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_FLP.h"\r
29 #include "SKP_Silk_tuning_parameters.h"\r
30 \r
31 /****************/\r
32 /* Encode frame */\r
33 /****************/\r
34 SKP_int SKP_Silk_encode_frame_FLP( \r
35     SKP_Silk_encoder_state_FLP      *psEnc,             /* I/O  Encoder state FLP                       */\r
36     SKP_int32                       *pnBytesOut,        /*   O  Number of payload bytes                 */\r
37     ec_enc                          *psRangeEnc,        /* I/O  compressor data structure               */\r
38     const SKP_int16                 *pIn                /* I    Input speech frame                      */\r
39 )\r
40 {\r
41     SKP_Silk_encoder_control_FLP sEncCtrl;\r
42     SKP_int     k, i, nBytes, ret = 0;\r
43     SKP_float   *x_frame, *res_pitch_frame;\r
44     SKP_int16   pIn_HP[    MAX_FRAME_LENGTH ];\r
45     SKP_int16   pIn_HP_LP[ MAX_FRAME_LENGTH ];\r
46     SKP_float   xfw[       MAX_FRAME_LENGTH ];\r
47     SKP_float   res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];\r
48     SKP_int     frame_terminator;\r
49 \r
50 TIC(ENCODE_FRAME)\r
51 \r
52     sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3;\r
53     /**************************************************************/\r
54     /* Setup Input Pointers, and insert frame in input buffer    */\r
55     /*************************************************************/\r
56     /* pointers aligned with start of frame to encode */\r
57     x_frame         = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;    /* start of frame to encode */\r
58     res_pitch_frame = res_pitch    + psEnc->sCmn.ltp_mem_length;    /* start of pitch LPC residual frame */\r
59 \r
60     /****************************/\r
61     /* Voice Activity Detection */\r
62     /****************************/\r
63 TIC(VAD)\r
64     SKP_Silk_VAD_FLP( psEnc, &sEncCtrl, pIn );\r
65 TOC(VAD)\r
66 \r
67     /**************************************************/\r
68     /* Convert speech activity into VAD and DTX flags */\r
69     /**************************************************/\r
70     if( psEnc->speech_activity < SPEECH_ACTIVITY_DTX_THRES ) {\r
71         sEncCtrl.sCmn.signalType = TYPE_NO_VOICE_ACTIVITY;\r
72         psEnc->sCmn.noSpeechCounter++;\r
73         if( psEnc->sCmn.noSpeechCounter > NO_SPEECH_FRAMES_BEFORE_DTX ) {\r
74             psEnc->sCmn.inDTX = 1;\r
75         }\r
76         if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX ) {\r
77             psEnc->sCmn.noSpeechCounter = 0;\r
78             psEnc->sCmn.inDTX           = 0;\r
79         }\r
80     } else {\r
81         psEnc->sCmn.noSpeechCounter = 0;\r
82         psEnc->sCmn.inDTX           = 0;\r
83         sEncCtrl.sCmn.signalType    = TYPE_UNVOICED;\r
84     }\r
85 \r
86     /*******************************************/\r
87     /* High-pass filtering of the input signal */\r
88     /*******************************************/\r
89 TIC(HP_IN)\r
90 #if HIGH_PASS_INPUT\r
91     /* Variable high-pass filter */\r
92     SKP_Silk_HP_variable_cutoff_FLP( psEnc, &sEncCtrl, pIn_HP, pIn );\r
93 #else\r
94     SKP_memcpy( pIn_HP, pIn, psEnc->sCmn.frame_length * sizeof( SKP_int16 ) );\r
95 #endif\r
96 TOC(HP_IN)\r
97 \r
98 #if SWITCH_TRANSITION_FILTERING\r
99     /* Ensure smooth bandwidth transitions */\r
100     SKP_Silk_LP_variable_cutoff( &psEnc->sCmn.sLP, pIn_HP_LP, pIn_HP, psEnc->sCmn.frame_length );\r
101 #else\r
102     SKP_memcpy( pIn_HP_LP, pIn_HP, psEnc->sCmn.frame_length * sizeof( SKP_int16 ) );\r
103 #endif\r
104 \r
105     /*******************************************/\r
106     /* Copy new frame to front of input buffer */\r
107     /*******************************************/\r
108     SKP_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, pIn_HP_LP, psEnc->sCmn.frame_length );\r
109 \r
110     /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */\r
111     for( k = 0; k < 8; k++ ) {\r
112         x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + k * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( k & 2 ) ) * 1e-6f;\r
113     }\r
114 \r
115     /*****************************************/\r
116     /* Find pitch lags, initial LPC analysis */\r
117     /*****************************************/\r
118 TIC(FIND_PITCH)\r
119     SKP_Silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame );\r
120 TOC(FIND_PITCH)\r
121 \r
122     /************************/\r
123     /* Noise shape analysis */\r
124     /************************/\r
125 TIC(NOISE_SHAPE_ANALYSIS)\r
126     SKP_Silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame );\r
127 TOC(NOISE_SHAPE_ANALYSIS)\r
128 \r
129     /*****************************************/\r
130     /* Prefiltering for noise shaper         */\r
131     /*****************************************/\r
132 TIC(PREFILTER)\r
133     SKP_Silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame );\r
134 TOC(PREFILTER)\r
135 \r
136     /***************************************************/\r
137     /* Find linear prediction coefficients (LPC + LTP) */\r
138     /***************************************************/\r
139 TIC(FIND_PRED_COEF)\r
140     SKP_Silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame );\r
141 TOC(FIND_PRED_COEF)\r
142 \r
143     /****************************************/\r
144     /* Process gains                        */\r
145     /****************************************/\r
146 TIC(PROCESS_GAINS)\r
147     SKP_Silk_process_gains_FLP( psEnc, &sEncCtrl );\r
148 TOC(PROCESS_GAINS)\r
149     \r
150     psEnc->sCmn.quantOffsetType[ psEnc->sCmn.nFramesInPayloadBuf ] = sEncCtrl.sCmn.quantOffsetType;\r
151     psEnc->sCmn.signalType[      psEnc->sCmn.nFramesInPayloadBuf ] = sEncCtrl.sCmn.signalType;\r
152 \r
153     /****************************************/\r
154     /* Low Bitrate Redundant Encoding       */\r
155     /****************************************/\r
156     psEnc->sCmn.LBRR_nBytes = MAX_ARITHM_BYTES;\r
157 TIC(LBRR)\r
158     //SKP_Silk_LBRR_encode_FLP( psEnc, &sEncCtrl, psEnc->sCmn.LBRR_payload, &psEnc->sCmn.LBRR_nBytes, xfw );\r
159 TOC(LBRR)\r
160 \r
161     /*****************************************/\r
162     /* Noise shaping quantization            */\r
163     /*****************************************/\r
164 TIC(NSQ)\r
165     SKP_Silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, xfw, &psEnc->sCmn.q[ psEnc->sCmn.nFramesInPayloadBuf * MAX_FRAME_LENGTH ], 0 );\r
166 TOC(NSQ)\r
167 \r
168     /****************************************/\r
169     /* Initialize range coder               */\r
170     /****************************************/\r
171     if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {\r
172         psEnc->sCmn.nBytesInPayloadBuf = 0;\r
173     }\r
174 \r
175     /****************************************/\r
176     /* Encode Parameters                    */\r
177     /****************************************/\r
178 TIC(ENCODE_PARAMS)\r
179     SKP_Silk_encode_indices( &psEnc->sCmn, &sEncCtrl.sCmn, psRangeEnc );\r
180 TOC(ENCODE_PARAMS)\r
181 \r
182     /****************************************/\r
183     /* Update Buffers and State             */\r
184     /****************************************/\r
185     /* Update input buffer */\r
186     SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], \r
187         ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( SKP_float ) );\r
188     \r
189     /* Parameters needed for next frame */\r
190     psEnc->sCmn.prevSignalType          = sEncCtrl.sCmn.signalType;\r
191     psEnc->sCmn.prevLag                 = sEncCtrl.sCmn.pitchL[ psEnc->sCmn.nb_subfr - 1 ];\r
192     psEnc->sCmn.first_frame_after_reset = 0;\r
193     psEnc->sCmn.nFramesInPayloadBuf++;\r
194 \r
195     /****************************************/\r
196     /* Finalize payload and copy to output  */\r
197     /****************************************/\r
198     if( psEnc->sCmn.nFramesInPayloadBuf * SUB_FRAME_LENGTH_MS * psEnc->sCmn.nb_subfr >= psEnc->sCmn.PacketSize_ms ) {\r
199 \r
200         /* Check if FEC information should be added */\r
201         //frame_terminator = psEnc->sCmn.LBRR_usage;\r
202         frame_terminator = SKP_SILK_NO_LBRR;\r
203 \r
204         /* Add the frame termination info to stream */\r
205         ec_enc_icdf( psRangeEnc, frame_terminator, SKP_Silk_LBRR_Present_iCDF, 8 );\r
206 \r
207         /* Code excitation signal */\r
208         for( i = 0; i < psEnc->sCmn.nFramesInPayloadBuf; i++ ) {\r
209             SKP_Silk_encode_pulses( psRangeEnc, psEnc->sCmn.signalType[ i ], psEnc->sCmn.quantOffsetType[ i ], \r
210                 &psEnc->sCmn.q[ i * MAX_FRAME_LENGTH ], psEnc->sCmn.frame_length );\r
211         }\r
212 \r
213         /* Payload length so far */\r
214         nBytes = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );\r
215         *pnBytesOut = nBytes;\r
216 \r
217         /* Reset the number of frames in payload buffer */\r
218         psEnc->sCmn.nFramesInPayloadBuf = 0;\r
219     } else {\r
220         /* No payload this time */\r
221         *pnBytesOut = 0;\r
222 \r
223         /* Payload length so far */\r
224         nBytes = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );\r
225 \r
226         /* Take into account the q signal that isn't in the bitstream yet */\r
227         nBytes += SKP_Silk_pulses_to_bytes( &psEnc->sCmn, \r
228             &psEnc->sCmn.q[ psEnc->sCmn.nFramesInPayloadBuf * MAX_FRAME_LENGTH ] );\r
229     }\r
230 \r
231     /* Simulate number of ms buffered in channel because of exceeding TargetRate */\r
232     psEnc->BufferedInChannel_ms   += ( 8.0f * 1000.0f * ( nBytes - psEnc->sCmn.nBytesInPayloadBuf ) ) / psEnc->sCmn.TargetRate_bps;\r
233     psEnc->BufferedInChannel_ms   -= SKP_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr );\r
234     psEnc->BufferedInChannel_ms    = SKP_LIMIT_float( psEnc->BufferedInChannel_ms, 0.0f, 100.0f );\r
235     psEnc->sCmn.nBytesInPayloadBuf = nBytes;\r
236 \r
237 TOC(ENCODE_FRAME)\r
238 #ifdef SAVE_ALL_INTERNAL_DATA\r
239     //DEBUG_STORE_DATA( xf.dat,                   pIn_HP_LP,                           psEnc->sCmn.frame_length * sizeof( SKP_int16 ) );\r
240     //DEBUG_STORE_DATA( xfw.dat,                  xfw,                                 psEnc->sCmn.frame_length * sizeof( SKP_float ) );\r
241     DEBUG_STORE_DATA( pitchL.dat,               sEncCtrl.sCmn.pitchL,                            MAX_NB_SUBFR * sizeof( SKP_int   ) );\r
242     DEBUG_STORE_DATA( pitchG_quantized.dat,     sEncCtrl.LTPCoef,            psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( SKP_float ) );\r
243     DEBUG_STORE_DATA( pitch_freq_low_Hz.dat,    &sEncCtrl.pitch_freq_low_Hz,                                    sizeof( SKP_float ) );\r
244     DEBUG_STORE_DATA( LTPcorr.dat,              &psEnc->LTPCorr,                                                sizeof( SKP_float ) );\r
245     DEBUG_STORE_DATA( tilt.dat,                 &sEncCtrl.input_tilt,                                           sizeof( SKP_float ) );\r
246     DEBUG_STORE_DATA( gains.dat,                sEncCtrl.Gains,                          psEnc->sCmn.nb_subfr * sizeof( SKP_float ) );\r
247     DEBUG_STORE_DATA( gains_indices.dat,        &sEncCtrl.sCmn.GainsIndices,             psEnc->sCmn.nb_subfr * sizeof( SKP_int   ) );\r
248     DEBUG_STORE_DATA( nBytes.dat,               &nBytes,                                                        sizeof( SKP_int   ) );\r
249     DEBUG_STORE_DATA( current_SNR_db.dat,       &sEncCtrl.current_SNR_dB,                                       sizeof( SKP_float ) );\r
250     DEBUG_STORE_DATA( quantOffsetType.dat,      &sEncCtrl.sCmn.quantOffsetType,                                 sizeof( SKP_int   ) );\r
251     DEBUG_STORE_DATA( speech_activity.dat,      &psEnc->speech_activity,                                        sizeof( SKP_float ) );\r
252     DEBUG_STORE_DATA( input_quality_bands.dat,  sEncCtrl.input_quality_bands,                     VAD_N_BANDS * sizeof( SKP_float ) );\r
253     DEBUG_STORE_DATA( signalType.dat,           &sEncCtrl.sCmn.signalType,                                      sizeof( SKP_int   ) ); \r
254     DEBUG_STORE_DATA( ratelevel.dat,            &sEncCtrl.sCmn.RateLevelIndex,                                  sizeof( SKP_int   ) ); \r
255     DEBUG_STORE_DATA( lag_index.dat,            &sEncCtrl.sCmn.lagIndex,                                        sizeof( SKP_int   ) ); \r
256     DEBUG_STORE_DATA( contour_index.dat,        &sEncCtrl.sCmn.contourIndex,                                    sizeof( SKP_int   ) ); \r
257     DEBUG_STORE_DATA( per_index.dat,            &sEncCtrl.sCmn.PERIndex,                                        sizeof( SKP_int   ) );\r
258     DEBUG_STORE_DATA( PredCoef.dat,             &sEncCtrl.PredCoef[ 1 ],          psEnc->sCmn.predictLPCOrder * sizeof( SKP_float ) );\r
259     DEBUG_STORE_DATA( ltp_scale_idx.dat,        &sEncCtrl.sCmn.LTP_scaleIndex,                                  sizeof( SKP_int   ) );\r
260 //  DEBUG_STORE_DATA( xq.dat,                   psEnc->sNSQ.xqBuf,                   psEnc->sCmn.frame_length * sizeof( SKP_float ) );\r
261 #endif\r
262     return( ret );\r
263 }\r
264 \r
265 #if 0\r
266 /* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate           */\r
267 void SKP_Silk_LBRR_encode_FLP(\r
268     SKP_Silk_encoder_state_FLP      *psEnc,             /* I/O  Encoder state FLP                       */\r
269     SKP_Silk_encoder_control_FLP    *psEncCtrl,         /* I/O  Encoder control FLP                     */\r
270           SKP_uint8                 *pCode,             /* O    Payload                                 */\r
271           SKP_int16                 *pnBytesOut,        /* I/O  Payload bytes; in: max; out: used       */\r
272     const SKP_float                 xfw[]               /* I    Input signal                            */\r
273 )\r
274 {\r
275     SKP_int32   Gains_Q16[ MAX_NB_SUBFR ];\r
276     SKP_int     i, k, TempGainsIndices[ MAX_NB_SUBFR ], frame_terminator;\r
277     SKP_int     nBytes, nFramesInPayloadBuf;\r
278     SKP_float   TempGains[ MAX_NB_SUBFR ];\r
279     SKP_int     typeOffset, LTP_scaleIndex, Rate_only_parameters = 0;\r
280     ec_byte_buffer range_enc_celt_buf;\r
281 \r
282     /*******************************************/\r
283     /* Control use of inband LBRR              */\r
284     /*******************************************/\r
285     psEnc->sCmn.LBRR_usage = SKP_SILK_NO_LBRR;\r
286     if( psEnc->sCmn.LBRR_enabled ) {\r
287         /* Control LBRR based on sensitivity and packet loss caracteristics */\r
288         if( psEnc->speech_activity > LBRR_SPEECH_ACTIVITY_THRES && psEnc->sCmn.PacketLoss_perc > LBRR_LOSS_THRES ) {\r
289             psEnc->sCmn.LBRR_usage = SKP_SILK_LBRR;\r
290         }\r
291 \r
292         /* Save original gains */\r
293         SKP_memcpy( TempGainsIndices, psEncCtrl->sCmn.GainsIndices, MAX_NB_SUBFR * sizeof( SKP_int   ) );\r
294         SKP_memcpy( TempGains,        psEncCtrl->Gains,             MAX_NB_SUBFR * sizeof( SKP_float ) );\r
295 \r
296         typeOffset     = psEnc->sCmn.typeOffsetPrev; // Temp save as cannot be overwritten\r
297         LTP_scaleIndex = psEncCtrl->sCmn.LTP_scaleIndex;\r
298 \r
299         /* Set max rate where quant signal is encoded */\r
300         if( psEnc->sCmn.fs_kHz == 8 ) {\r
301             Rate_only_parameters = 13500;\r
302         } else if( psEnc->sCmn.fs_kHz == 12 ) {\r
303             Rate_only_parameters = 15500;\r
304         } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
305             Rate_only_parameters = 17500;\r
306         } else {\r
307             SKP_assert( 0 );\r
308         }\r
309 \r
310         if( psEnc->sCmn.Complexity >= 4 && psEnc->sCmn.TargetRate_bps > Rate_only_parameters ) {\r
311             if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {\r
312                 /* First frame in packet copy everything */\r
313                 SKP_memcpy( &psEnc->sNSQ_LBRR, &psEnc->sNSQ, sizeof( SKP_Silk_nsq_state ) );\r
314                 psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;\r
315                 /* Increase Gains to get target LBRR rate */\r
316                 psEncCtrl->sCmn.GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases;\r
317                 psEncCtrl->sCmn.GainsIndices[ 0 ]  = SKP_LIMIT_int( psEncCtrl->sCmn.GainsIndices[ 0 ], 0, N_LEVELS_QGAIN - 1 );\r
318             }\r
319             /* Decode to get gains in sync with decoder */\r
320             SKP_Silk_gains_dequant( Gains_Q16, psEncCtrl->sCmn.GainsIndices, \r
321                 &psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesInPayloadBuf, psEnc->sCmn.nb_subfr );\r
322 \r
323             /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */\r
324             for( k = 0; k <  psEnc->sCmn.nb_subfr; k++ ) {\r
325                 psEncCtrl->Gains[ k ] = Gains_Q16[ k ] / 65536.0f;\r
326             }\r
327 \r
328             /*****************************************/\r
329             /* Noise shaping quantization            */\r
330             /*****************************************/\r
331             SKP_Silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, xfw, &psEnc->sCmn.q_LBRR[ psEnc->sCmn.nFramesInPayloadBuf * MAX_FRAME_LENGTH ], 1 );\r
332         } else {\r
333             SKP_memset( &psEnc->sCmn.q_LBRR[ psEnc->sCmn.nFramesInPayloadBuf * MAX_FRAME_LENGTH ], 0, psEnc->sCmn.frame_length * sizeof( SKP_int8 ) );\r
334             psEncCtrl->sCmn.LTP_scaleIndex = 0;\r
335         }\r
336         /****************************************/\r
337         /* Initialize arithmetic coder          */\r
338         /****************************************/\r
339         if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {\r
340             ec_enc_init( &psEnc->sCmn.sRC_LBRR.range_enc_celt_state, psEnc->sCmn.sRC_LBRR.buffer, MAX_ARITHM_BYTES );\r
341 \r
342             SKP_Silk_range_enc_init( &psEnc->sCmn.sRC_LBRR );\r
343             psEnc->sCmn.nBytesInPayloadBuf = 0;\r
344         }\r
345 \r
346         /****************************************/\r
347         /* Encode Parameters                    */\r
348         /****************************************/\r
349         SKP_Silk_encode_indices( &psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sRC_LBRR );\r
350 \r
351         if( psEnc->sCmn.sRC_LBRR.error ) {\r
352             /* Encoder returned error: Clear payload buffer */\r
353             nFramesInPayloadBuf = 0;\r
354         } else {\r
355             nFramesInPayloadBuf = psEnc->sCmn.nFramesInPayloadBuf + 1;\r
356         }\r
357 \r
358         /****************************************/\r
359         /* Finalize payload and copy to output  */\r
360         /****************************************/\r
361         if( psEnc->sCmn.nFramesInPayloadBuf * SUB_FRAME_LENGTH_MS * psEnc->sCmn.nb_subfr >= psEnc->sCmn.PacketSize_ms ) {\r
362 \r
363             /* Check if FEC information should be added */\r
364             frame_terminator = SKP_SILK_LAST_FRAME;\r
365 \r
366             /* Add the frame termination info to stream */\r
367             ec_encode_bin( psRangeEnc_LBRR, FrameTermination_CDF[ frame_terminator ], \r
368                 FrameTermination_CDF[ frame_terminator + 1 ], 16 );\r
369 \r
370             /*********************************************/\r
371             /* Encode quantization indices of excitation */\r
372             /*********************************************/\r
373             for( i = 0; i < nFramesInPayloadBuf; i++ ) {\r
374                 SKP_Silk_encode_pulses( &psEnc->sCmn.sRC_LBRR, psEnc->sCmn.signalType[ i ], psEnc->sCmn.quantOffsetType[ i ],\r
375                     &psEnc->sCmn.q_LBRR[ i * MAX_FRAME_LENGTH ], psEnc->sCmn.frame_length );\r
376             }\r
377 \r
378             /* Payload length so far */\r
379             nBytes = SKP_RSHIFT( ec_tell( psRangeEnc_LBRR ) + 7, 3 );\r
380 \r
381             /* Check that there is enough space in external output buffer and move data */\r
382             if( *pnBytesOut >= nBytes ) {\r
383                 SKP_int bits_in_stream, mask;\r
384                 bits_in_stream = ec_tell( &psEnc->sCmn.sRC_LBRR.range_enc_celt_state );\r
385                 ec_enc_done( &psEnc->sCmn.sRC_LBRR.range_enc_celt_state );\r
386 \r
387                 /* Fill up any remaining bits in the last byte with 1s */\r
388                 if( bits_in_stream & 7 ) {\r
389                     mask = SKP_RSHIFT( 0xFF, bits_in_stream & 7 );\r
390                     if( nBytes - 1 < *pnBytesOut ) {\r
391                         psEnc->sCmn.sRC_LBRR.range_enc_celt_state.buf->buf[ nBytes - 1 ] |= mask;\r
392                     }\r
393                 }\r
394                 SKP_memcpy( pCode, psEnc->sCmn.sRC_LBRR.range_enc_celt_state.buf->buf, nBytes * sizeof( SKP_uint8 ) );\r
395 \r
396                 *pnBytesOut = nBytes;               \r
397             } else {\r
398                 /* Not enough space: payload will be discarded */\r
399                 *pnBytesOut = 0;\r
400                 SKP_assert( 0 );\r
401             }\r
402         } else {\r
403             /* No payload this time */\r
404             *pnBytesOut = 0;\r
405 \r
406             /* Encode that more frames follows */\r
407             frame_terminator = SKP_SILK_MORE_FRAMES;\r
408             ec_encode_bin( psRangeEnc_LBRR, FrameTermination_CDF[ frame_terminator ], \r
409                 FrameTermination_CDF[ frame_terminator + 1 ], 16 );\r
410         }\r
411 \r
412         /* Restore original Gains */\r
413         SKP_memcpy( psEncCtrl->sCmn.GainsIndices, TempGainsIndices, psEnc->sCmn.nb_subfr * sizeof( SKP_int   ) );\r
414         SKP_memcpy( psEncCtrl->Gains,             TempGains,        psEnc->sCmn.nb_subfr * sizeof( SKP_float ) );\r
415     \r
416         /* Restore LTP scale index and typeoffset */\r
417         psEncCtrl->sCmn.LTP_scaleIndex = LTP_scaleIndex;\r
418         psEnc->sCmn.typeOffsetPrev     = typeOffset;\r
419     }\r
420 }\r
421 #endif\r