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