1/***********************************************************************
2Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions
5are met:
6- Redistributions of source code must retain the above copyright notice,
7this list of conditions and the following disclaimer.
8- Redistributions in binary form must reproduce the above copyright
9notice, this list of conditions and the following disclaimer in the
10documentation and/or other materials provided with the distribution.
11- Neither the name of Internet Society, IETF or IETF Trust, nor the
12names of specific contributors, may be used to endorse or promote
13products derived from this software without specific prior written
14permission.
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25POSSIBILITY OF SUCH DAMAGE.
26***********************************************************************/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31#ifdef FIXED_POINT
32#include "main_FIX.h"
33#define silk_encoder_state_Fxx      silk_encoder_state_FIX
34#else
35#include "main_FLP.h"
36#define silk_encoder_state_Fxx      silk_encoder_state_FLP
37#endif
38#include "stack_alloc.h"
39#include "tuning_parameters.h"
40#include "pitch_est_defines.h"
41
42static opus_int silk_setup_resamplers(
43    silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
44    opus_int                        fs_kHz              /* I                        */
45);
46
47static opus_int silk_setup_fs(
48    silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
49    opus_int                        fs_kHz,             /* I                        */
50    opus_int                        PacketSize_ms       /* I                        */
51);
52
53static opus_int silk_setup_complexity(
54    silk_encoder_state              *psEncC,            /* I/O                      */
55    opus_int                        Complexity          /* I                        */
56);
57
58static OPUS_INLINE opus_int silk_setup_LBRR(
59    silk_encoder_state              *psEncC,            /* I/O                      */
60    const opus_int32                TargetRate_bps      /* I                        */
61);
62
63
64/* Control encoder */
65opus_int silk_control_encoder(
66    silk_encoder_state_Fxx          *psEnc,                                 /* I/O  Pointer to Silk encoder state                                               */
67    silk_EncControlStruct           *encControl,                            /* I    Control structure                                                           */
68    const opus_int32                TargetRate_bps,                         /* I    Target max bitrate (bps)                                                    */
69    const opus_int                  allow_bw_switch,                        /* I    Flag to allow switching audio bandwidth                                     */
70    const opus_int                  channelNb,                              /* I    Channel number                                                              */
71    const opus_int                  force_fs_kHz
72)
73{
74    opus_int   fs_kHz, ret = 0;
75
76    psEnc->sCmn.useDTX                 = encControl->useDTX;
77    psEnc->sCmn.useCBR                 = encControl->useCBR;
78    psEnc->sCmn.API_fs_Hz              = encControl->API_sampleRate;
79    psEnc->sCmn.maxInternal_fs_Hz      = encControl->maxInternalSampleRate;
80    psEnc->sCmn.minInternal_fs_Hz      = encControl->minInternalSampleRate;
81    psEnc->sCmn.desiredInternal_fs_Hz  = encControl->desiredInternalSampleRate;
82    psEnc->sCmn.useInBandFEC           = encControl->useInBandFEC;
83    psEnc->sCmn.nChannelsAPI           = encControl->nChannelsAPI;
84    psEnc->sCmn.nChannelsInternal      = encControl->nChannelsInternal;
85    psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch;
86    psEnc->sCmn.channelNb              = channelNb;
87
88    if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) {
89        if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) {
90            /* Change in API sampling rate in the middle of encoding a packet */
91            ret += silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz );
92        }
93        return ret;
94    }
95
96    /* Beyond this point we know that there are no previously coded frames in the payload buffer */
97
98    /********************************************/
99    /* Determine internal sampling rate         */
100    /********************************************/
101    fs_kHz = silk_control_audio_bandwidth( &psEnc->sCmn, encControl );
102    if( force_fs_kHz ) {
103       fs_kHz = force_fs_kHz;
104    }
105    /********************************************/
106    /* Prepare resampler and buffered data      */
107    /********************************************/
108    ret += silk_setup_resamplers( psEnc, fs_kHz );
109
110    /********************************************/
111    /* Set internal sampling frequency          */
112    /********************************************/
113    ret += silk_setup_fs( psEnc, fs_kHz, encControl->payloadSize_ms );
114
115    /********************************************/
116    /* Set encoding complexity                  */
117    /********************************************/
118    ret += silk_setup_complexity( &psEnc->sCmn, encControl->complexity  );
119
120    /********************************************/
121    /* Set packet loss rate measured by farend  */
122    /********************************************/
123    psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage;
124
125    /********************************************/
126    /* Set LBRR usage                           */
127    /********************************************/
128    ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps );
129
130    psEnc->sCmn.controlled_since_last_payload = 1;
131
132    return ret;
133}
134
135static opus_int silk_setup_resamplers(
136    silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
137    opus_int                         fs_kHz              /* I                        */
138)
139{
140    opus_int   ret = SILK_NO_ERROR;
141    SAVE_STACK;
142
143    if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz )
144    {
145        if( psEnc->sCmn.fs_kHz == 0 ) {
146            /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
147            ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 );
148        } else {
149            VARDECL( opus_int16, x_buf_API_fs_Hz );
150            VARDECL( silk_resampler_state_struct, temp_resampler_state );
151#ifdef FIXED_POINT
152            opus_int16 *x_bufFIX = psEnc->x_buf;
153#else
154            VARDECL( opus_int16, x_bufFIX );
155            opus_int32 new_buf_samples;
156#endif
157            opus_int32 api_buf_samples;
158            opus_int32 old_buf_samples;
159            opus_int32 buf_length_ms;
160
161            buf_length_ms = silk_LSHIFT( psEnc->sCmn.nb_subfr * 5, 1 ) + LA_SHAPE_MS;
162            old_buf_samples = buf_length_ms * psEnc->sCmn.fs_kHz;
163
164#ifndef FIXED_POINT
165            new_buf_samples = buf_length_ms * fs_kHz;
166            ALLOC( x_bufFIX, silk_max( old_buf_samples, new_buf_samples ),
167                   opus_int16 );
168            silk_float2short_array( x_bufFIX, psEnc->x_buf, old_buf_samples );
169#endif
170
171            /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */
172            ALLOC( temp_resampler_state, 1, silk_resampler_state_struct );
173            ret += silk_resampler_init( temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 );
174
175            /* Calculate number of samples to temporarily upsample */
176            api_buf_samples = buf_length_ms * silk_DIV32_16( psEnc->sCmn.API_fs_Hz, 1000 );
177
178            /* Temporary resampling of x_buf data to API_fs_Hz */
179            ALLOC( x_buf_API_fs_Hz, api_buf_samples, opus_int16 );
180            ret += silk_resampler( temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, old_buf_samples );
181
182            /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
183            ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 );
184
185            /* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */
186            ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, api_buf_samples );
187
188#ifndef FIXED_POINT
189            silk_short2float_array( psEnc->x_buf, x_bufFIX, new_buf_samples);
190#endif
191        }
192    }
193
194    psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz;
195
196    RESTORE_STACK;
197    return ret;
198}
199
200static opus_int silk_setup_fs(
201    silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
202    opus_int                        fs_kHz,             /* I                        */
203    opus_int                        PacketSize_ms       /* I                        */
204)
205{
206    opus_int ret = SILK_NO_ERROR;
207
208    /* Set packet size */
209    if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) {
210        if( ( PacketSize_ms !=  10 ) &&
211            ( PacketSize_ms !=  20 ) &&
212            ( PacketSize_ms !=  40 ) &&
213            ( PacketSize_ms !=  60 ) ) {
214            ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
215        }
216        if( PacketSize_ms <= 10 ) {
217            psEnc->sCmn.nFramesPerPacket = 1;
218            psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1;
219            psEnc->sCmn.frame_length = silk_SMULBB( PacketSize_ms, fs_kHz );
220            psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
221            if( psEnc->sCmn.fs_kHz == 8 ) {
222                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
223            } else {
224                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
225            }
226        } else {
227            psEnc->sCmn.nFramesPerPacket = silk_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS );
228            psEnc->sCmn.nb_subfr = MAX_NB_SUBFR;
229            psEnc->sCmn.frame_length = silk_SMULBB( 20, fs_kHz );
230            psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );
231            if( psEnc->sCmn.fs_kHz == 8 ) {
232                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
233            } else {
234                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF;
235            }
236        }
237        psEnc->sCmn.PacketSize_ms  = PacketSize_ms;
238        psEnc->sCmn.TargetRate_bps = 0;         /* trigger new SNR computation */
239    }
240
241    /* Set internal sampling frequency */
242    silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
243    silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
244    if( psEnc->sCmn.fs_kHz != fs_kHz ) {
245        /* reset part of the state */
246        silk_memset( &psEnc->sShape,               0, sizeof( psEnc->sShape ) );
247        silk_memset( &psEnc->sPrefilt,             0, sizeof( psEnc->sPrefilt ) );
248        silk_memset( &psEnc->sCmn.sNSQ,            0, sizeof( psEnc->sCmn.sNSQ ) );
249        silk_memset( psEnc->sCmn.prev_NLSFq_Q15,   0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
250        silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) );
251        psEnc->sCmn.inputBufIx                  = 0;
252        psEnc->sCmn.nFramesEncoded              = 0;
253        psEnc->sCmn.TargetRate_bps              = 0;     /* trigger new SNR computation */
254
255        /* Initialize non-zero parameters */
256        psEnc->sCmn.prevLag                     = 100;
257        psEnc->sCmn.first_frame_after_reset     = 1;
258        psEnc->sPrefilt.lagPrev                 = 100;
259        psEnc->sShape.LastGainIndex             = 10;
260        psEnc->sCmn.sNSQ.lagPrev                = 100;
261        psEnc->sCmn.sNSQ.prev_gain_Q16          = 65536;
262        psEnc->sCmn.prevSignalType              = TYPE_NO_VOICE_ACTIVITY;
263
264        psEnc->sCmn.fs_kHz = fs_kHz;
265        if( psEnc->sCmn.fs_kHz == 8 ) {
266            if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
267                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
268            } else {
269                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
270            }
271        } else {
272            if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
273                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF;
274            } else {
275                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
276            }
277        }
278        if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) {
279            psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER;
280            psEnc->sCmn.psNLSF_CB  = &silk_NLSF_CB_NB_MB;
281        } else {
282            psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER;
283            psEnc->sCmn.psNLSF_CB  = &silk_NLSF_CB_WB;
284        }
285        psEnc->sCmn.subfr_length   = SUB_FRAME_LENGTH_MS * fs_kHz;
286        psEnc->sCmn.frame_length   = silk_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );
287        psEnc->sCmn.ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz );
288        psEnc->sCmn.la_pitch       = silk_SMULBB( LA_PITCH_MS, fs_kHz );
289        psEnc->sCmn.max_pitch_lag  = silk_SMULBB( 18, fs_kHz );
290        if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
291            psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );
292        } else {
293            psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
294        }
295        if( psEnc->sCmn.fs_kHz == 16 ) {
296            psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 );
297            psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
298        } else if( psEnc->sCmn.fs_kHz == 12 ) {
299            psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 );
300            psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
301        } else {
302            psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 );
303            psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
304        }
305    }
306
307    /* Check that settings are valid */
308    silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
309
310    return ret;
311}
312
313static opus_int silk_setup_complexity(
314    silk_encoder_state              *psEncC,            /* I/O                      */
315    opus_int                        Complexity          /* I                        */
316)
317{
318    opus_int ret = 0;
319
320    /* Set encoding complexity */
321    silk_assert( Complexity >= 0 && Complexity <= 10 );
322    if( Complexity < 2 ) {
323        psEncC->pitchEstimationComplexity       = SILK_PE_MIN_COMPLEX;
324        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.8, 16 );
325        psEncC->pitchEstimationLPCOrder         = 6;
326        psEncC->shapingLPCOrder                 = 8;
327        psEncC->la_shape                        = 3 * psEncC->fs_kHz;
328        psEncC->nStatesDelayedDecision          = 1;
329        psEncC->useInterpolatedNLSFs            = 0;
330        psEncC->LTPQuantLowComplexity           = 1;
331        psEncC->NLSF_MSVQ_Survivors             = 2;
332        psEncC->warping_Q16                     = 0;
333    } else if( Complexity < 4 ) {
334        psEncC->pitchEstimationComplexity       = SILK_PE_MID_COMPLEX;
335        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.76, 16 );
336        psEncC->pitchEstimationLPCOrder         = 8;
337        psEncC->shapingLPCOrder                 = 10;
338        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
339        psEncC->nStatesDelayedDecision          = 1;
340        psEncC->useInterpolatedNLSFs            = 0;
341        psEncC->LTPQuantLowComplexity           = 0;
342        psEncC->NLSF_MSVQ_Survivors             = 4;
343        psEncC->warping_Q16                     = 0;
344    } else if( Complexity < 6 ) {
345        psEncC->pitchEstimationComplexity       = SILK_PE_MID_COMPLEX;
346        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.74, 16 );
347        psEncC->pitchEstimationLPCOrder         = 10;
348        psEncC->shapingLPCOrder                 = 12;
349        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
350        psEncC->nStatesDelayedDecision          = 2;
351        psEncC->useInterpolatedNLSFs            = 1;
352        psEncC->LTPQuantLowComplexity           = 0;
353        psEncC->NLSF_MSVQ_Survivors             = 8;
354        psEncC->warping_Q16                     = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
355    } else if( Complexity < 8 ) {
356        psEncC->pitchEstimationComplexity       = SILK_PE_MID_COMPLEX;
357        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.72, 16 );
358        psEncC->pitchEstimationLPCOrder         = 12;
359        psEncC->shapingLPCOrder                 = 14;
360        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
361        psEncC->nStatesDelayedDecision          = 3;
362        psEncC->useInterpolatedNLSFs            = 1;
363        psEncC->LTPQuantLowComplexity           = 0;
364        psEncC->NLSF_MSVQ_Survivors             = 16;
365        psEncC->warping_Q16                     = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
366    } else {
367        psEncC->pitchEstimationComplexity       = SILK_PE_MAX_COMPLEX;
368        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.7, 16 );
369        psEncC->pitchEstimationLPCOrder         = 16;
370        psEncC->shapingLPCOrder                 = 16;
371        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
372        psEncC->nStatesDelayedDecision          = MAX_DEL_DEC_STATES;
373        psEncC->useInterpolatedNLSFs            = 1;
374        psEncC->LTPQuantLowComplexity           = 0;
375        psEncC->NLSF_MSVQ_Survivors             = 32;
376        psEncC->warping_Q16                     = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
377    }
378
379    /* Do not allow higher pitch estimation LPC order than predict LPC order */
380    psEncC->pitchEstimationLPCOrder = silk_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder );
381    psEncC->shapeWinLength          = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape;
382    psEncC->Complexity              = Complexity;
383
384    silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
385    silk_assert( psEncC->shapingLPCOrder         <= MAX_SHAPE_LPC_ORDER      );
386    silk_assert( psEncC->nStatesDelayedDecision  <= MAX_DEL_DEC_STATES       );
387    silk_assert( psEncC->warping_Q16             <= 32767                    );
388    silk_assert( psEncC->la_shape                <= LA_SHAPE_MAX             );
389    silk_assert( psEncC->shapeWinLength          <= SHAPE_LPC_WIN_MAX        );
390    silk_assert( psEncC->NLSF_MSVQ_Survivors     <= NLSF_VQ_MAX_SURVIVORS    );
391
392    return ret;
393}
394
395static OPUS_INLINE opus_int silk_setup_LBRR(
396    silk_encoder_state          *psEncC,            /* I/O                      */
397    const opus_int32            TargetRate_bps      /* I                        */
398)
399{
400    opus_int   ret = SILK_NO_ERROR;
401    opus_int32 LBRR_rate_thres_bps;
402
403    psEncC->LBRR_enabled = 0;
404    if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
405        if( psEncC->fs_kHz == 8 ) {
406            LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
407        } else if( psEncC->fs_kHz == 12 ) {
408            LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
409        } else {
410            LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS;
411        }
412        LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
413
414        if( TargetRate_bps > LBRR_rate_thres_bps ) {
415            /* Set gain increase for coding LBRR excitation */
416            psEncC->LBRR_enabled = 1;
417            psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
418        }
419    }
420
421    return ret;
422}
423