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 == 24 ) {\r
282             psEnc->sCmn.mu_LTP_Q9 = SKP_FIX_CONST( MU_LTP_QUANT_SWB, 9 );\r
283             psEnc->sCmn.bitrate_threshold_up    = SKP_int32_MAX;\r
284             psEnc->sCmn.bitrate_threshold_down  = SWB2WB_BITRATE_BPS; \r
285             psEnc->sCmn.pitch_lag_low_bits_iCDF = SKP_Silk_uniform12_iCDF;\r
286         } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
287             psEnc->sCmn.mu_LTP_Q9 = SKP_FIX_CONST( MU_LTP_QUANT_WB, 9 );\r
288             psEnc->sCmn.bitrate_threshold_up    = WB2SWB_BITRATE_BPS;\r
289             psEnc->sCmn.bitrate_threshold_down  = WB2MB_BITRATE_BPS; \r
290             psEnc->sCmn.pitch_lag_low_bits_iCDF = SKP_Silk_uniform8_iCDF;\r
291         } else if( psEnc->sCmn.fs_kHz == 12 ) {\r
292             psEnc->sCmn.mu_LTP_Q9 = SKP_FIX_CONST( MU_LTP_QUANT_MB, 9 );\r
293             psEnc->sCmn.bitrate_threshold_up    = MB2WB_BITRATE_BPS;\r
294             psEnc->sCmn.bitrate_threshold_down  = MB2NB_BITRATE_BPS;\r
295             psEnc->sCmn.pitch_lag_low_bits_iCDF = SKP_Silk_uniform6_iCDF;\r
296         } else if( psEnc->sCmn.fs_kHz == 8 ) {\r
297             psEnc->sCmn.mu_LTP_Q9 = SKP_FIX_CONST( MU_LTP_QUANT_NB, 9 );\r
298             psEnc->sCmn.bitrate_threshold_up    = NB2MB_BITRATE_BPS;\r
299             psEnc->sCmn.bitrate_threshold_down  = 0;\r
300             psEnc->sCmn.pitch_lag_low_bits_iCDF = SKP_Silk_uniform4_iCDF;\r
301         } else {\r
302             /* unsupported sampling rate */\r
303             SKP_assert( 0 );\r
304         }\r
305         psEnc->sCmn.fs_kHz_changed = 1;\r
306     }\r
307 \r
308     /* Check that settings are valid */\r
309     SKP_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );\r
310  \r
311     return( ret );\r
312 }\r
313 \r
314 SKP_INLINE SKP_int SKP_Silk_setup_rate(\r
315     SKP_Silk_encoder_state_FIX      *psEnc,             /* I/O                      */\r
316     SKP_int                         TargetRate_bps      /* I                        */\r
317 )\r
318 {\r
319     SKP_int k, ret = SKP_SILK_NO_ERROR;\r
320     SKP_int32 frac_Q6;\r
321     const SKP_uint16 *rateTable;\r
322 \r
323     /* Set bitrate/coding quality */\r
324     if( TargetRate_bps != psEnc->sCmn.TargetRate_bps ) {\r
325         psEnc->sCmn.TargetRate_bps = TargetRate_bps;\r
326 \r
327         /* If new TargetRate_bps, translate to SNR_dB value */\r
328         if( psEnc->sCmn.fs_kHz == 8 ) {\r
329             rateTable = TargetRate_table_NB;\r
330         } else if( psEnc->sCmn.fs_kHz == 12 ) {\r
331             rateTable = TargetRate_table_MB;\r
332         } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
333             rateTable = TargetRate_table_WB;\r
334         } else {\r
335             rateTable = TargetRate_table_SWB;\r
336         }\r
337         for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {\r
338             /* Find bitrate interval in table and interpolate */\r
339             if( TargetRate_bps < rateTable[ k ] ) {\r
340                 frac_Q6 = SKP_DIV32( SKP_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), \r
341                                                  rateTable[ k ] - rateTable[ k - 1 ] );\r
342                 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
343                 break;\r
344             }\r
345         }\r
346     }\r
347     return( ret );\r
348 }\r
349 \r
350 SKP_INLINE SKP_int SKP_Silk_setup_LBRR(\r
351     SKP_Silk_encoder_state_FIX      *psEnc             /* I/O                      */\r
352 )\r
353 {\r
354     SKP_int   ret = SKP_SILK_NO_ERROR;\r
355 \r
356 #if USE_LBRR\r
357     SKP_int32 LBRRRate_thres_bps;\r
358 \r
359     if( psEnc->sCmn.useInBandFEC < 0 || psEnc->sCmn.useInBandFEC > 1 ) {\r
360         ret = SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING;\r
361     }\r
362     \r
363     psEnc->sCmn.LBRR_enabled = psEnc->sCmn.useInBandFEC;\r
364     if( psEnc->sCmn.fs_kHz == 8 ) {\r
365         LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 9000;\r
366     } else if( psEnc->sCmn.fs_kHz == 12 ) {\r
367         LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 6000;;\r
368     } else if( psEnc->sCmn.fs_kHz == 16 ) {\r
369         LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 3000;\r
370     } else {\r
371         LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS;\r
372     }\r
373 \r
374     if( psEnc->sCmn.TargetRate_bps >= LBRRRate_thres_bps ) {\r
375         /* Set gain increase / rate reduction for LBRR usage */\r
376         /* Coarsely tuned with PESQ for now. */\r
377         /* Linear regression coefs G = 8 - 0.5 * loss */\r
378         /* Meaning that at 16% loss main rate and redundant rate is the same, -> G = 0 */\r
379         psEnc->sCmn.LBRR_GainIncreases = SKP_max_int( 8 - SKP_RSHIFT( psEnc->sCmn.PacketLoss_perc, 1 ), 0 );\r
380 \r
381         /* Set main stream rate compensation */\r
382         if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.PacketLoss_perc > LBRR_LOSS_THRES ) {\r
383             /* Tuned to give approx same mean / weighted bitrate as no inband FEC */\r
384             psEnc->inBandFEC_SNR_comp_Q8 = SKP_FIX_CONST( 6.0f, 8 ) - SKP_LSHIFT( psEnc->sCmn.LBRR_GainIncreases, 7 );\r
385         } else {\r
386             psEnc->inBandFEC_SNR_comp_Q8 = 0;\r
387             psEnc->sCmn.LBRR_enabled     = 0;\r
388         }\r
389     } else {\r
390         psEnc->inBandFEC_SNR_comp_Q8     = 0;\r
391         psEnc->sCmn.LBRR_enabled         = 0;\r
392     }\r
393 #else\r
394     if( psEnc->sCmn.LBRR_enabled != 0 ) {\r
395         ret = SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING;\r
396         psEnc->sCmn.LBRR_enabled = 0;\r
397     }\r
398 #endif\r
399     return ret;\r
400 }\r