SILK update
[opus.git] / src_FIX / SKP_Silk_control_codec_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 #include "SKP_Silk_setup_complexity.h"\r
30 \r
31 /* ToDo: Move the functions belowto common to be able to use them in FLP control codec also */\r
32 SKP_INLINE SKP_int SKP_Silk_setup_resamplers(\r
33     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O                      */\r
34     SKP_int                         fs_kHz              /* I                        */\r
35 );\r
36 \r
37 SKP_INLINE SKP_int SKP_Silk_setup_fs(\r
38     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O                      */\r
39     SKP_int                         fs_kHz,             /* I                        */\r
40     SKP_int                         PacketSize_ms       /* I                        */\r
41 );\r
42 \r
43 SKP_INLINE SKP_int SKP_Silk_setup_rate(\r
44     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O                      */\r
45     SKP_int                         TargetRate_bps      /* I                        */\r
46 );\r
47 \r
48 SKP_INLINE SKP_int SKP_Silk_setup_LBRR(\r
49     SKP_Silk_encoder_state_FIX      *psEnc              /* I/O                      */\r
50 );\r
51 \r
52 /* Control encoder SNR */\r
53 SKP_int SKP_Silk_control_encoder_FIX( \r
54     SKP_Silk_encoder_state_FIX  *psEnc,                 /* I/O  Pointer to Silk encoder state           */\r
55     const SKP_int               PacketSize_ms,          /* I    Packet length (ms)                      */\r
56     const SKP_int32             TargetRate_bps,         /* I    Target max bitrate (bps)                */\r
57     const SKP_int               PacketLoss_perc,        /* I    Packet loss rate (in percent)           */\r
58     const SKP_int               Complexity              /* I    Complexity (0-10)                       */\r
59 )\r
60 {\r
61     SKP_int   fs_kHz, ret = 0;\r
62 \r
63     if( psEnc->sCmn.controlled_since_last_payload != 0 ) {\r
64         if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) {\r
65             /* Change in API sampling rate in the middle of encoding a packet */\r
66             ret += SKP_Silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz );\r
67         }\r
68         return ret;\r
69     }\r
70 \r
71     /* Beyond this point we know that there are no previously coded frames in the payload buffer */\r
72 \r
73     /********************************************/\r
74     /* Determine internal sampling rate         */\r
75     /********************************************/\r
76     fs_kHz = SKP_Silk_control_audio_bandwidth( &psEnc->sCmn, TargetRate_bps );\r
77 \r
78     /********************************************/\r
79     /* Prepare resampler and buffered data      */\r
80     /********************************************/\r
81     ret += SKP_Silk_setup_resamplers( psEnc, fs_kHz );\r
82 \r
83     /********************************************/\r
84     /* Set internal sampling frequency          */\r
85     /********************************************/\r
86     ret += SKP_Silk_setup_fs( psEnc, fs_kHz, PacketSize_ms );\r
87 \r
88     /********************************************/\r
89     /* Set encoding complexity                  */\r
90     /********************************************/\r
91     ret += SKP_Silk_setup_complexity( &psEnc->sCmn, Complexity );\r
92 \r
93     /********************************************/\r
94     /* Set bitrate/coding quality               */\r
95     /********************************************/\r
96     ret += SKP_Silk_setup_rate( psEnc, TargetRate_bps );\r
97 \r
98     /********************************************/\r
99     /* Set packet loss rate measured by farend  */\r
100     /********************************************/\r
101     if( ( PacketLoss_perc < 0 ) || ( PacketLoss_perc > 100 ) ) {\r
102         ret = SKP_SILK_ENC_INVALID_LOSS_RATE;\r
103     }\r
104     psEnc->sCmn.PacketLoss_perc = PacketLoss_perc;\r
105 \r
106     /********************************************/\r
107     /* Set LBRR usage                           */\r
108     /********************************************/\r
109     ret += SKP_Silk_setup_LBRR( psEnc );\r
110 \r
111     psEnc->sCmn.controlled_since_last_payload = 1;\r
112 \r
113     return ret;\r
114 }\r
115 \r
116 SKP_INLINE SKP_int SKP_Silk_setup_resamplers(\r
117     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O                      */\r
118     SKP_int                         fs_kHz              /* I                        */\r
119 )\r
120 {\r
121     SKP_int ret = SKP_SILK_NO_ERROR;\r
122     \r
123     if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) {\r
124 \r
125         if( psEnc->sCmn.fs_kHz == 0 ) {\r
126             /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */\r
127             ret += SKP_Silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000 );\r
128         } else {\r
129             /* Allocate space for worst case temporary upsampling, 8 to 48 kHz, so a factor 6 */\r
130             SKP_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * ( MAX_API_FS_KHZ / 8 ) ];\r
131 \r
132             SKP_int32 nSamples_temp = SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz;\r
133 \r
134             if( SKP_SMULBB( fs_kHz, 1000 ) < psEnc->sCmn.API_fs_Hz && psEnc->sCmn.fs_kHz != 0 ) {\r
135                 /* Resample buffered data in x_buf to API_fs_Hz */\r
136 \r
137                 SKP_Silk_resampler_state_struct  temp_resampler_state;\r
138 \r
139                 /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */\r
140                 ret += SKP_Silk_resampler_init( &temp_resampler_state, SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz );\r
141 \r
142                 /* Temporary resampling of x_buf data to API_fs_Hz */\r
143                 ret += SKP_Silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, psEnc->x_buf, nSamples_temp );\r
144 \r
145                 /* Calculate number of samples that has been temporarily upsampled */\r
146                 nSamples_temp = SKP_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) );\r
147 \r
148                 /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */\r
149                 ret += SKP_Silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, SKP_SMULBB( fs_kHz, 1000 ) );\r
150 \r
151             } else {\r
152                 /* Copy data */\r
153                 SKP_memcpy( x_buf_API_fs_Hz, psEnc->x_buf, nSamples_temp * sizeof( SKP_int16 ) );\r
154             }\r
155 \r
156             if( 1000 * fs_kHz != psEnc->sCmn.API_fs_Hz ) {\r
157                 /* Correct resampler state (unless resampling by a factor 1) by resampling buffered data from API_fs_Hz to fs_kHz */\r
158                 ret += SKP_Silk_resampler( &psEnc->sCmn.resampler_state, psEnc->x_buf, x_buf_API_fs_Hz, nSamples_temp );\r
159             }\r
160         }\r
161     }\r
162 \r
163     psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz;\r
164 \r
165     return(ret);\r
166 }\r
167 \r
168 SKP_INLINE SKP_int SKP_Silk_setup_fs(\r
169     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O                      */\r
170     SKP_int                         fs_kHz,             /* I                        */\r
171     SKP_int                         PacketSize_ms       /* I                        */\r
172 )\r
173 {\r
174     SKP_int ret = SKP_SILK_NO_ERROR;\r
175 \r
176     /* Set packet size */\r
177     if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) {\r
178         if( ( PacketSize_ms !=  10 ) &&\r
179             ( PacketSize_ms !=  20 ) &&\r
180             ( PacketSize_ms !=  40 ) && \r
181             ( PacketSize_ms !=  60 ) ) {\r
182             ret = SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;\r
183         }\r
184         if( PacketSize_ms == 10 ) {\r
185             /* Only allowed when the payload buffer is empty */\r
186             psEnc->sCmn.nb_subfr = MAX_NB_SUBFR >> 1;\r
187             psEnc->sPred.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );\r
188             if( psEnc->sCmn.fs_kHz == 8 ) {\r
189                 psEnc->sCmn.pitch_contour_iCDF = SKP_Silk_pitch_contour_10_ms_NB_iCDF;\r
190             } else {\r
191                 psEnc->sCmn.pitch_contour_iCDF = SKP_Silk_pitch_contour_10_ms_iCDF;\r
192             }\r
193         } else {\r
194             psEnc->sCmn.nb_subfr = MAX_NB_SUBFR;\r
195             psEnc->sPred.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );\r
196             if( psEnc->sCmn.fs_kHz == 8 ) {\r
197                 psEnc->sCmn.pitch_contour_iCDF = SKP_Silk_pitch_contour_NB_iCDF;\r
198             } else {\r
199                 psEnc->sCmn.pitch_contour_iCDF = SKP_Silk_pitch_contour_iCDF; \r
200             }\r
201         }\r
202         psEnc->sCmn.PacketSize_ms = PacketSize_ms;\r
203         psEnc->sCmn.LBRR_nBytes = 0;\r
204     }\r
205 \r
206     /* Set internal sampling frequency */\r
207     if( psEnc->sCmn.fs_kHz != fs_kHz ) {\r
208         /* reset part of the state */\r
209         SKP_memset( &psEnc->sShape,              0,                        sizeof( SKP_Silk_shape_state_FIX ) );\r
210         SKP_memset( &psEnc->sPrefilt,            0,                        sizeof( SKP_Silk_prefilter_state_FIX ) );\r
211         SKP_memset( &psEnc->sNSQ,                0,                        sizeof( SKP_Silk_nsq_state ) );\r
212         SKP_memset( &psEnc->sPred,               0,                        sizeof( SKP_Silk_predict_state_FIX ) );\r
213         SKP_memset( psEnc->sNSQ.xq,              0, 2 * MAX_FRAME_LENGTH * sizeof( SKP_int16 ) );\r
214         SKP_memset( psEnc->sNSQ_LBRR.xq,         0, 2 * MAX_FRAME_LENGTH * sizeof( SKP_int16 ) );\r
215         SKP_memset( psEnc->sPred.prev_NLSFq_Q15, 0,        MAX_LPC_ORDER * sizeof( SKP_int ) );\r
216 #if SWITCH_TRANSITION_FILTERING\r
217         SKP_memset( psEnc->sCmn.sLP.In_LP_State, 0, 2 * sizeof( SKP_int32 ) );\r
218         if( psEnc->sCmn.sLP.mode == 1 ) {\r
219             /* Begin transition phase */\r
220             psEnc->sCmn.sLP.transition_frame_no = 1;\r
221         } else {\r
222             /* End transition phase */\r
223             psEnc->sCmn.sLP.transition_frame_no = 0;\r
224         }\r
225 #endif\r
226         psEnc->sCmn.LBRR_nBytes         = 0;\r
227         psEnc->sCmn.inputBufIx          = 0;\r
228         psEnc->sCmn.nFramesInPayloadBuf = 0;\r
229         psEnc->sCmn.nBytesInPayloadBuf  = 0;\r
230         psEnc->sCmn.TargetRate_bps      = 0; /* Ensures that psEnc->SNR_dB is recomputed */\r
231 \r
232         /* Initialize non-zero parameters */\r
233         psEnc->sCmn.prevLag                 = 100;\r
234         psEnc->sCmn.first_frame_after_reset = 1;\r
235         psEnc->sPrefilt.lagPrev             = 100;\r
236         psEnc->sShape.LastGainIndex         = 1;\r
237         psEnc->sNSQ.lagPrev                 = 100;\r
238         psEnc->sNSQ.prev_inv_gain_Q16       = 65536;\r
239         psEnc->sNSQ_LBRR.prev_inv_gain_Q16  = 65536;\r
240 \r
241         psEnc->sCmn.fs_kHz = fs_kHz;\r
242         if( psEnc->sCmn.fs_kHz == 8 ) {\r
243             psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER;\r
244             psEnc->sCmn.psNLSF_CB[ 0 ]  = &SKP_Silk_NLSF_CB0_10;\r
245             psEnc->sCmn.psNLSF_CB[ 1 ]  = &SKP_Silk_NLSF_CB1_10;\r
246             if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ){\r
247                 psEnc->sCmn.pitch_contour_iCDF = SKP_Silk_pitch_contour_NB_iCDF; \r
248             } else if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR / 2 ){\r
249                 psEnc->sCmn.pitch_contour_iCDF = SKP_Silk_pitch_contour_10_ms_NB_iCDF;\r
250             } else {\r
251                 /* Unsupported number of frames */\r
252                 SKP_assert( 0 );\r
253             }\r
254         } else {\r
255             psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER;\r
256             psEnc->sCmn.psNLSF_CB[ 0 ]  = &SKP_Silk_NLSF_CB0_16;\r
257             psEnc->sCmn.psNLSF_CB[ 1 ]  = &SKP_Silk_NLSF_CB1_16;\r
258             if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ){\r
259                 psEnc->sCmn.pitch_contour_iCDF = SKP_Silk_pitch_contour_iCDF; \r
260             } else if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR / 2 ){\r
261                 psEnc->sCmn.pitch_contour_iCDF = SKP_Silk_pitch_contour_10_ms_iCDF;\r
262             } else {\r
263                 /* Unsupported number of frames */\r
264                 SKP_assert( 0 );\r
265             }\r
266         }\r
267         psEnc->sCmn.subfr_length   = SUB_FRAME_LENGTH_MS * fs_kHz;\r
268         psEnc->sCmn.frame_length   = SKP_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );\r
269         psEnc->sCmn.ltp_mem_length = SKP_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); \r
270         psEnc->sCmn.la_pitch       = SKP_SMULBB( LA_PITCH_MS, fs_kHz );\r
271         psEnc->sPred.min_pitch_lag = SKP_SMULBB(  3, fs_kHz );\r
272         psEnc->sPred.max_pitch_lag = SKP_SMULBB( 18, fs_kHz );\r
273         if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ){\r
274             psEnc->sPred.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );\r
275         } else if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR / 2 ){\r
276             psEnc->sPred.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );\r
277         } else {\r
278             /* Unsupported number of frames */\r
279             SKP_assert( 0 );\r
280         }\r
281         if( psEnc->sCmn.fs_kHz == 16 ) {\r
282             psEnc->sCmn.mu_LTP_Q9 = SKP_FIX_CONST( MU_LTP_QUANT_WB, 9 );\r
283             psEnc->sCmn.bitrate_threshold_up    = SKP_int32_MAX;\r
284             psEnc->sCmn.bitrate_threshold_down  = WB2MB_BITRATE_BPS; \r
285             psEnc->sCmn.pitch_lag_low_bits_iCDF = SKP_Silk_uniform8_iCDF;\r
286         } else if( psEnc->sCmn.fs_kHz == 12 ) {\r
287             psEnc->sCmn.mu_LTP_Q9 = SKP_FIX_CONST( MU_LTP_QUANT_MB, 9 );\r
288             psEnc->sCmn.bitrate_threshold_up    = MB2WB_BITRATE_BPS;\r
289             psEnc->sCmn.bitrate_threshold_down  = MB2NB_BITRATE_BPS;\r
290             psEnc->sCmn.pitch_lag_low_bits_iCDF = SKP_Silk_uniform6_iCDF;\r
291         } else if( psEnc->sCmn.fs_kHz == 8 ) {\r
292             psEnc->sCmn.mu_LTP_Q9 = SKP_FIX_CONST( MU_LTP_QUANT_NB, 9 );\r
293             psEnc->sCmn.bitrate_threshold_up    = NB2MB_BITRATE_BPS;\r
294             psEnc->sCmn.bitrate_threshold_down  = 0;\r
295             psEnc->sCmn.pitch_lag_low_bits_iCDF = SKP_Silk_uniform4_iCDF;\r
296         } else {\r
297             /* unsupported sampling rate */\r
298             SKP_assert( 0 );\r
299         }\r
300         psEnc->sCmn.fs_kHz_changed = 1;\r
301     }\r
302 \r
303     /* Check that settings are valid */\r
304     SKP_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );\r
305  \r
306     return( ret );\r
307 }\r
308 \r
309 SKP_INLINE SKP_int SKP_Silk_setup_rate(\r
310     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O                      */\r
311     SKP_int                         TargetRate_bps      /* I                        */\r
312 )\r
313 {\r
314     SKP_int k, ret = SKP_SILK_NO_ERROR;\r
315     SKP_int32 frac_Q6;\r
316     const SKP_uint16 *rateTable;\r
317 \r
318     /* Set bitrate/coding quality */\r
319     if( TargetRate_bps != psEnc->sCmn.TargetRate_bps ) {\r
320         psEnc->sCmn.TargetRate_bps = TargetRate_bps;\r
321 \r
322         /* If new TargetRate_bps, translate to SNR_dB value */\r
323         if( psEnc->sCmn.fs_kHz == 8 ) {\r
324             rateTable = TargetRate_table_NB;\r
325         } else if( psEnc->sCmn.fs_kHz == 12 ) {\r
326             rateTable = TargetRate_table_MB;\r
327         } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
328             rateTable = TargetRate_table_WB;\r
329         } else {\r
330             SKP_assert( 0 );\r
331         }\r
332         /* Reduce bitrate for 10 ms modes in these calculations */\r
333         if( psEnc->sCmn.nb_subfr == 2 ) {\r
334             TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;\r
335         }\r
336         for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {\r
337             /* Find bitrate interval in table and interpolate */\r
338             if( TargetRate_bps < rateTable[ k ] ) {\r
339                 frac_Q6 = SKP_DIV32( SKP_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), \r
340                                                  rateTable[ k ] - rateTable[ k - 1 ] );\r
341                 psEnc->SNR_dB_Q7 = SKP_LSHIFT( SNR_table_Q1[ k - 1 ], 6 ) + SKP_MUL( frac_Q6, SNR_table_Q1[ k ] - SNR_table_Q1[ k - 1 ] );\r
342                 break;\r
343             }\r
344         }\r
345     }\r
346     return( ret );\r
347 }\r
348 \r
349 SKP_INLINE SKP_int SKP_Silk_setup_LBRR(\r
350     SKP_Silk_encoder_state_FIX      *psEnc             /* I/O                      */\r
351 )\r
352 {\r
353     SKP_int   ret = SKP_SILK_NO_ERROR;\r
354 \r
355 #if USE_LBRR\r
356     SKP_int32 LBRRRate_thres_bps;\r
357 \r
358     if( psEnc->sCmn.useInBandFEC < 0 || psEnc->sCmn.useInBandFEC > 1 ) {\r
359         ret = SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING;\r
360     }\r
361     \r
362     psEnc->sCmn.LBRR_enabled = psEnc->sCmn.useInBandFEC;\r
363     if( psEnc->sCmn.fs_kHz == 8 ) {\r
364         LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 9000;\r
365     } else if( psEnc->sCmn.fs_kHz == 12 ) {\r
366         LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 6000;;\r
367     } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
368         LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 3000;\r
369     } else {\r
370         LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS;\r
371     }\r
372 \r
373     if( psEnc->sCmn.TargetRate_bps >= LBRRRate_thres_bps ) {\r
374         /* Set gain increase / rate reduction for LBRR usage */\r
375         /* Coarsely tuned with PESQ for now. */\r
376         /* Linear regression coefs G = 8 - 0.5 * loss */\r
377         /* Meaning that at 16% loss main rate and redundant rate is the same, -> G = 0 */\r
378         psEnc->sCmn.LBRR_GainIncreases = SKP_max_int( 8 - SKP_RSHIFT( psEnc->sCmn.PacketLoss_perc, 1 ), 0 );\r
379 \r
380         /* Set main stream rate compensation */\r
381         if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.PacketLoss_perc > LBRR_LOSS_THRES ) {\r
382             /* Tuned to give approx same mean / weighted bitrate as no inband FEC */\r
383             psEnc->inBandFEC_SNR_comp_Q8 = SKP_FIX_CONST( 6.0f, 8 ) - SKP_LSHIFT( psEnc->sCmn.LBRR_GainIncreases, 7 );\r
384         } else {\r
385             psEnc->inBandFEC_SNR_comp_Q8 = 0;\r
386             psEnc->sCmn.LBRR_enabled     = 0;\r
387         }\r
388     } else {\r
389         psEnc->inBandFEC_SNR_comp_Q8     = 0;\r
390         psEnc->sCmn.LBRR_enabled         = 0;\r
391     }\r
392 #else\r
393     if( psEnc->sCmn.LBRR_enabled != 0 ) {\r
394         ret = SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING;\r
395         psEnc->sCmn.LBRR_enabled = 0;\r
396     }\r
397 #endif\r
398     return ret;\r
399 }\r