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