2010-03-17 16:16:27 +00:00
/***********************************************************************
2011-08-25 17:24:46 -05:00
Copyright ( c ) 2006 - 2011 , Skype Limited . All rights reserved .
2010-03-17 16:16:27 +00:00
Redistribution and use in source and binary forms , with or without
modification , ( subject to the limitations in the disclaimer below )
are permitted provided that the following conditions are met :
- Redistributions of source code must retain the above copyright notice ,
this list of conditions and the following disclaimer .
- Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
- Neither the name of Skype Limited , nor the names of specific
contributors , may be used to endorse or promote products derived from
this software without specific prior written permission .
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY ' S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE . THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ' ' AS IS ' ' AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING ,
BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF
USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "SKP_Silk_main_FIX.h"
2011-08-25 17:24:46 -05:00
# include "SKP_Silk_setup_complexity.h"
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_resamplers_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state FIX */
SKP_int fs_kHz /* I Internal sampling rate (kHz) */
) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_packetsize_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state FIX */
SKP_int PacketSize_ms /* I Packet length (ms) */
) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_fs_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state FIX */
SKP_int fs_kHz /* I Internal sampling rate (kHz) */
) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_rate_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state FIX */
SKP_int TargetRate_bps /* I Target max bitrate (if SNR_dB == 0) */
) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_LBRR_FIX (
SKP_Silk_encoder_state_FIX * psEnc /* I/O Pointer to Silk encoder state FIX */
) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/* Control encoder */
SKP_int SKP_Silk_control_encoder_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state */
const SKP_int PacketSize_ms , /* I Packet length (ms) */
const SKP_int32 TargetRate_bps , /* I Target max bitrate (bps) */
const SKP_int PacketLoss_perc , /* I Packet loss rate (in percent) */
const SKP_int DTX_enabled , /* I Enable / disable DTX */
const SKP_int Complexity /* I Complexity (0->low; 1->medium; 2->high) */
)
{
SKP_int fs_kHz , ret = 0 ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
if ( psEnc - > sCmn . controlled_since_last_payload ! = 0 ) {
if ( psEnc - > sCmn . API_fs_Hz ! = psEnc - > sCmn . prev_API_fs_Hz & & psEnc - > sCmn . fs_kHz > 0 ) {
/* Change in API sampling rate in the middle of encoding a packet */
ret + = SKP_Silk_setup_resamplers_FIX ( psEnc , psEnc - > sCmn . fs_kHz ) ;
}
return ret ;
}
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/* Beyond this point we know that there are no previously coded frames in the payload buffer */
/********************************************/
/* Determine internal sampling rate */
/********************************************/
fs_kHz = SKP_Silk_control_audio_bandwidth ( & psEnc - > sCmn , TargetRate_bps ) ;
/********************************************/
/* Prepare resampler and buffered data */
/********************************************/
ret + = SKP_Silk_setup_resamplers_FIX ( psEnc , fs_kHz ) ;
/********************************************/
/* Set packet size */
/********************************************/
ret + = SKP_Silk_setup_packetsize_FIX ( psEnc , PacketSize_ms ) ;
/********************************************/
/* Set internal sampling frequency */
/********************************************/
ret + = SKP_Silk_setup_fs_FIX ( psEnc , fs_kHz ) ;
/********************************************/
/* Set encoding complexity */
/********************************************/
ret + = SKP_Silk_setup_complexity ( & psEnc - > sCmn , Complexity ) ;
/********************************************/
/* Set bitrate/coding quality */
/********************************************/
ret + = SKP_Silk_setup_rate_FIX ( psEnc , TargetRate_bps ) ;
/********************************************/
/* Set packet loss rate measured by farend */
/********************************************/
if ( ( PacketLoss_perc < 0 ) | | ( PacketLoss_perc > 100 ) ) {
ret = SKP_SILK_ENC_INVALID_LOSS_RATE ;
}
psEnc - > sCmn . PacketLoss_perc = PacketLoss_perc ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/********************************************/
/* Set LBRR usage */
/********************************************/
ret + = SKP_Silk_setup_LBRR_FIX ( psEnc ) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/********************************************/
/* Set DTX mode */
/********************************************/
if ( DTX_enabled < 0 | | DTX_enabled > 1 ) {
ret = SKP_SILK_ENC_INVALID_DTX_SETTING ;
}
psEnc - > sCmn . useDTX = DTX_enabled ;
psEnc - > sCmn . controlled_since_last_payload = 1 ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
return ret ;
}
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/* Control low bitrate redundancy usage */
void SKP_Silk_LBRR_ctrl_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I Encoder state FIX */
SKP_Silk_encoder_control * psEncCtrlC /* I/O Encoder control */
)
{
SKP_int LBRR_usage ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
if ( psEnc - > sCmn . LBRR_enabled ) {
/* Control LBRR */
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/* Usage Control based on sensitivity and packet loss caracteristics */
/* For now only enable adding to next for active frames. Make more complex later */
LBRR_usage = SKP_SILK_NO_LBRR ;
if ( psEnc - > speech_activity_Q8 > SKP_FIX_CONST ( LBRR_SPEECH_ACTIVITY_THRES , 8 ) & & psEnc - > sCmn . PacketLoss_perc > LBRR_LOSS_THRES ) { // nb! maybe multiply loss prob and speech activity
LBRR_usage = SKP_SILK_ADD_LBRR_TO_PLUS1 ;
}
psEncCtrlC - > LBRR_usage = LBRR_usage ;
} else {
psEncCtrlC - > LBRR_usage = SKP_SILK_NO_LBRR ;
}
}
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_resamplers_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state FIX */
SKP_int fs_kHz /* I Internal sampling rate (kHz) */
)
{
SKP_int ret = SKP_SILK_NO_ERROR ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
if ( psEnc - > sCmn . fs_kHz ! = fs_kHz | | psEnc - > sCmn . prev_API_fs_Hz ! = psEnc - > sCmn . API_fs_Hz ) {
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
if ( psEnc - > sCmn . fs_kHz = = 0 ) {
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
ret + = SKP_Silk_resampler_init ( & psEnc - > sCmn . resampler_state , psEnc - > sCmn . API_fs_Hz , fs_kHz * 1000 ) ;
} else {
/* Allocate space for worst case temporary upsampling, 8 to 48 kHz, so a factor 6 */
SKP_int16 x_buf_API_fs_Hz [ ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * ( MAX_API_FS_KHZ / 8 ) ] ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_int32 nSamples_temp = SKP_LSHIFT ( psEnc - > sCmn . frame_length , 1 ) + LA_SHAPE_MS * psEnc - > sCmn . fs_kHz ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
if ( SKP_SMULBB ( fs_kHz , 1000 ) < psEnc - > sCmn . API_fs_Hz & & psEnc - > sCmn . fs_kHz ! = 0 ) {
/* Resample buffered data in x_buf to API_fs_Hz */
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_Silk_resampler_state_struct temp_resampler_state ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */
ret + = SKP_Silk_resampler_init ( & temp_resampler_state , SKP_SMULBB ( psEnc - > sCmn . fs_kHz , 1000 ) , psEnc - > sCmn . API_fs_Hz ) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/* Temporary resampling of x_buf data to API_fs_Hz */
ret + = SKP_Silk_resampler ( & temp_resampler_state , x_buf_API_fs_Hz , psEnc - > x_buf , nSamples_temp ) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/* Calculate number of samples that has been temporarily upsampled */
nSamples_temp = SKP_DIV32_16 ( nSamples_temp * psEnc - > sCmn . API_fs_Hz , SKP_SMULBB ( psEnc - > sCmn . fs_kHz , 1000 ) ) ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
ret + = SKP_Silk_resampler_init ( & psEnc - > sCmn . resampler_state , psEnc - > sCmn . API_fs_Hz , SKP_SMULBB ( fs_kHz , 1000 ) ) ;
} else {
/* Copy data */
SKP_memcpy ( x_buf_API_fs_Hz , psEnc - > x_buf , nSamples_temp * sizeof ( SKP_int16 ) ) ;
2010-03-17 16:16:27 +00:00
}
2011-08-25 17:24:46 -05:00
if ( 1000 * fs_kHz ! = psEnc - > sCmn . API_fs_Hz ) {
/* Correct resampler state (unless resampling by a factor 1) by resampling buffered data from API_fs_Hz to fs_kHz */
ret + = SKP_Silk_resampler ( & psEnc - > sCmn . resampler_state , psEnc - > x_buf , x_buf_API_fs_Hz , nSamples_temp ) ;
}
2010-03-17 16:16:27 +00:00
}
}
2011-08-25 17:24:46 -05:00
psEnc - > sCmn . prev_API_fs_Hz = psEnc - > sCmn . API_fs_Hz ;
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
return ( ret ) ;
}
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_packetsize_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state FIX */
SKP_int PacketSize_ms /* I Packet length (ms) */
)
{
SKP_int ret = SKP_SILK_NO_ERROR ;
/* Set packet size */
if ( ( PacketSize_ms ! = 20 ) & &
( PacketSize_ms ! = 40 ) & &
( PacketSize_ms ! = 60 ) & &
( PacketSize_ms ! = 80 ) & &
( PacketSize_ms ! = 100 ) ) {
ret = SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED ;
} else {
if ( PacketSize_ms ! = psEnc - > sCmn . PacketSize_ms ) {
psEnc - > sCmn . PacketSize_ms = PacketSize_ms ;
/* Packet length changes. Reset LBRR buffer */
SKP_Silk_LBRR_reset ( & psEnc - > sCmn ) ;
}
}
return ( ret ) ;
}
SKP_INLINE SKP_int SKP_Silk_setup_fs_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state FIX */
SKP_int fs_kHz /* I Internal sampling rate (kHz) */
)
{
SKP_int ret = SKP_SILK_NO_ERROR ;
2010-03-17 16:16:27 +00:00
/* Set internal sampling frequency */
if ( psEnc - > sCmn . fs_kHz ! = fs_kHz ) {
/* reset part of the state */
2011-08-25 17:24:46 -05:00
SKP_memset ( & psEnc - > sShape , 0 , sizeof ( SKP_Silk_shape_state_FIX ) ) ;
SKP_memset ( & psEnc - > sPrefilt , 0 , sizeof ( SKP_Silk_prefilter_state_FIX ) ) ;
SKP_memset ( & psEnc - > sNSQ , 0 , sizeof ( SKP_Silk_nsq_state ) ) ;
SKP_memset ( & psEnc - > sPred , 0 , sizeof ( SKP_Silk_predict_state_FIX ) ) ;
2010-03-17 16:16:27 +00:00
SKP_memset ( psEnc - > sNSQ . xq , 0 , ( 2 * MAX_FRAME_LENGTH ) * sizeof ( SKP_int16 ) ) ;
SKP_memset ( psEnc - > sNSQ_LBRR . xq , 0 , ( 2 * MAX_FRAME_LENGTH ) * sizeof ( SKP_int16 ) ) ;
2011-08-25 17:24:46 -05:00
SKP_memset ( psEnc - > sCmn . LBRR_buffer , 0 , MAX_LBRR_DELAY * sizeof ( SKP_SILK_LBRR_struct ) ) ;
2010-03-17 16:16:27 +00:00
# if SWITCH_TRANSITION_FILTERING
SKP_memset ( psEnc - > sCmn . sLP . In_LP_State , 0 , 2 * sizeof ( SKP_int32 ) ) ;
if ( psEnc - > sCmn . sLP . mode = = 1 ) {
/* Begin transition phase */
psEnc - > sCmn . sLP . transition_frame_no = 1 ;
} else {
/* End transition phase */
psEnc - > sCmn . sLP . transition_frame_no = 0 ;
}
# endif
psEnc - > sCmn . inputBufIx = 0 ;
psEnc - > sCmn . nFramesInPayloadBuf = 0 ;
psEnc - > sCmn . nBytesInPayloadBuf = 0 ;
psEnc - > sCmn . oldest_LBRR_idx = 0 ;
2011-08-25 17:24:46 -05:00
psEnc - > sCmn . TargetRate_bps = 0 ; /* Ensures that psEnc->SNR_dB is recomputed */
2010-03-17 16:16:27 +00:00
SKP_memset ( psEnc - > sPred . prev_NLSFq_Q15 , 0 , MAX_LPC_ORDER * sizeof ( SKP_int ) ) ;
/* Initialize non-zero parameters */
psEnc - > sCmn . prevLag = 100 ;
psEnc - > sCmn . prev_sigtype = SIG_TYPE_UNVOICED ;
psEnc - > sCmn . first_frame_after_reset = 1 ;
psEnc - > sPrefilt . lagPrev = 100 ;
2011-08-25 17:24:46 -05:00
psEnc - > sShape . LastGainIndex = 1 ;
psEnc - > sNSQ . lagPrev = 100 ;
psEnc - > sNSQ . prev_inv_gain_Q16 = 65536 ;
psEnc - > sNSQ_LBRR . prev_inv_gain_Q16 = 65536 ;
2010-03-17 16:16:27 +00:00
psEnc - > sCmn . fs_kHz = fs_kHz ;
if ( psEnc - > sCmn . fs_kHz = = 8 ) {
psEnc - > sCmn . predictLPCOrder = MIN_LPC_ORDER ;
psEnc - > sCmn . psNLSF_CB [ 0 ] = & SKP_Silk_NLSF_CB0_10 ;
psEnc - > sCmn . psNLSF_CB [ 1 ] = & SKP_Silk_NLSF_CB1_10 ;
} else {
psEnc - > sCmn . predictLPCOrder = MAX_LPC_ORDER ;
psEnc - > sCmn . psNLSF_CB [ 0 ] = & SKP_Silk_NLSF_CB0_16 ;
psEnc - > sCmn . psNLSF_CB [ 1 ] = & SKP_Silk_NLSF_CB1_16 ;
}
psEnc - > sCmn . frame_length = SKP_SMULBB ( FRAME_LENGTH_MS , fs_kHz ) ;
psEnc - > sCmn . subfr_length = SKP_DIV32_16 ( psEnc - > sCmn . frame_length , NB_SUBFR ) ;
psEnc - > sCmn . la_pitch = SKP_SMULBB ( LA_PITCH_MS , fs_kHz ) ;
psEnc - > sPred . min_pitch_lag = SKP_SMULBB ( 3 , fs_kHz ) ;
psEnc - > sPred . max_pitch_lag = SKP_SMULBB ( 18 , fs_kHz ) ;
psEnc - > sPred . pitch_LPC_win_length = SKP_SMULBB ( FIND_PITCH_LPC_WIN_MS , fs_kHz ) ;
if ( psEnc - > sCmn . fs_kHz = = 24 ) {
2011-08-25 17:24:46 -05:00
psEnc - > mu_LTP_Q8 = SKP_FIX_CONST ( MU_LTP_QUANT_SWB , 8 ) ;
psEnc - > sCmn . bitrate_threshold_up = SKP_int32_MAX ;
psEnc - > sCmn . bitrate_threshold_down = SWB2WB_BITRATE_BPS ;
2010-03-17 16:16:27 +00:00
} else if ( psEnc - > sCmn . fs_kHz = = 16 ) {
2011-08-25 17:24:46 -05:00
psEnc - > mu_LTP_Q8 = SKP_FIX_CONST ( MU_LTP_QUANT_WB , 8 ) ;
psEnc - > sCmn . bitrate_threshold_up = WB2SWB_BITRATE_BPS ;
psEnc - > sCmn . bitrate_threshold_down = WB2MB_BITRATE_BPS ;
2010-03-17 16:16:27 +00:00
} else if ( psEnc - > sCmn . fs_kHz = = 12 ) {
2011-08-25 17:24:46 -05:00
psEnc - > mu_LTP_Q8 = SKP_FIX_CONST ( MU_LTP_QUANT_MB , 8 ) ;
psEnc - > sCmn . bitrate_threshold_up = MB2WB_BITRATE_BPS ;
psEnc - > sCmn . bitrate_threshold_down = MB2NB_BITRATE_BPS ;
2010-03-17 16:16:27 +00:00
} else {
2011-08-25 17:24:46 -05:00
psEnc - > mu_LTP_Q8 = SKP_FIX_CONST ( MU_LTP_QUANT_NB , 8 ) ;
psEnc - > sCmn . bitrate_threshold_up = NB2MB_BITRATE_BPS ;
psEnc - > sCmn . bitrate_threshold_down = 0 ;
2010-03-17 16:16:27 +00:00
}
psEnc - > sCmn . fs_kHz_changed = 1 ;
2011-08-25 17:24:46 -05:00
2010-03-17 16:16:27 +00:00
/* Check that settings are valid */
SKP_assert ( ( psEnc - > sCmn . subfr_length * NB_SUBFR ) = = psEnc - > sCmn . frame_length ) ;
}
2011-08-25 17:24:46 -05:00
return ( ret ) ;
}
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_rate_FIX (
SKP_Silk_encoder_state_FIX * psEnc , /* I/O Pointer to Silk encoder state FIX */
SKP_int TargetRate_bps /* I Target max bitrate (if SNR_dB == 0) */
)
{
SKP_int k , ret = SKP_SILK_NO_ERROR ;
SKP_int32 frac_Q6 ;
const SKP_int32 * rateTable ;
2010-03-17 16:16:27 +00:00
/* Set bitrate/coding quality */
if ( TargetRate_bps ! = psEnc - > sCmn . TargetRate_bps ) {
psEnc - > sCmn . TargetRate_bps = TargetRate_bps ;
2011-08-25 17:24:46 -05:00
/* If new TargetRate_bps, translate to SNR_dB value */
2010-03-17 16:16:27 +00:00
if ( psEnc - > sCmn . fs_kHz = = 8 ) {
rateTable = TargetRate_table_NB ;
} else if ( psEnc - > sCmn . fs_kHz = = 12 ) {
rateTable = TargetRate_table_MB ;
} else if ( psEnc - > sCmn . fs_kHz = = 16 ) {
rateTable = TargetRate_table_WB ;
} else {
rateTable = TargetRate_table_SWB ;
}
for ( k = 1 ; k < TARGET_RATE_TAB_SZ ; k + + ) {
2011-08-25 17:24:46 -05:00
/* Find bitrate interval in table and interpolate */
2010-03-17 16:16:27 +00:00
if ( TargetRate_bps < rateTable [ k ] ) {
2011-08-25 17:24:46 -05:00
frac_Q6 = SKP_DIV32 ( SKP_LSHIFT ( TargetRate_bps - rateTable [ k - 1 ] , 6 ) ,
rateTable [ k ] - rateTable [ k - 1 ] ) ;
2010-03-17 16:16:27 +00:00
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 ] ) ;
break ;
}
}
}
2011-08-25 17:24:46 -05:00
return ( ret ) ;
}
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
SKP_INLINE SKP_int SKP_Silk_setup_LBRR_FIX (
SKP_Silk_encoder_state_FIX * psEnc /* I/O Pointer to Silk encoder state FIX */
)
{
SKP_int ret = SKP_SILK_NO_ERROR ;
2010-03-17 16:16:27 +00:00
# if USE_LBRR
2011-08-25 17:24:46 -05:00
SKP_int32 LBRRRate_thres_bps ;
if ( psEnc - > sCmn . useInBandFEC < 0 | | psEnc - > sCmn . useInBandFEC > 1 ) {
ret = SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING ;
2010-03-17 16:16:27 +00:00
}
2011-08-25 17:24:46 -05:00
psEnc - > sCmn . LBRR_enabled = psEnc - > sCmn . useInBandFEC ;
if ( psEnc - > sCmn . fs_kHz = = 8 ) {
LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 9000 ;
} else if ( psEnc - > sCmn . fs_kHz = = 12 ) {
LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 6000 ; ;
} else if ( psEnc - > sCmn . fs_kHz = = 16 ) {
LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 3000 ;
} else {
LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS ;
}
2010-03-17 16:16:27 +00:00
2011-08-25 17:24:46 -05:00
if ( psEnc - > sCmn . TargetRate_bps > = LBRRRate_thres_bps ) {
/* Set gain increase / rate reduction for LBRR usage */
/* Coarsely tuned with PESQ for now. */
/* Linear regression coefs G = 8 - 0.5 * loss */
/* Meaning that at 16% loss main rate and redundant rate is the same, -> G = 0 */
psEnc - > sCmn . LBRR_GainIncreases = SKP_max_int ( 8 - SKP_RSHIFT ( psEnc - > sCmn . PacketLoss_perc , 1 ) , 0 ) ;
/* Set main stream rate compensation */
if ( psEnc - > sCmn . LBRR_enabled & & psEnc - > sCmn . PacketLoss_perc > LBRR_LOSS_THRES ) {
/* Tuned to give approx same mean / weighted bitrate as no inband FEC */
psEnc - > inBandFEC_SNR_comp_Q8 = SKP_FIX_CONST ( 6.0f , 8 ) - SKP_LSHIFT ( psEnc - > sCmn . LBRR_GainIncreases , 7 ) ;
2010-03-17 16:16:27 +00:00
} else {
2011-08-25 17:24:46 -05:00
psEnc - > inBandFEC_SNR_comp_Q8 = 0 ;
psEnc - > sCmn . LBRR_enabled = 0 ;
2010-03-17 16:16:27 +00:00
}
2011-08-25 17:24:46 -05:00
} else {
psEnc - > inBandFEC_SNR_comp_Q8 = 0 ;
psEnc - > sCmn . LBRR_enabled = 0 ;
2010-03-17 16:16:27 +00:00
}
# else
2011-08-25 17:24:46 -05:00
if ( INBandFEC_enabled ! = 0 ) {
ret = SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING ;
}
2010-03-17 16:16:27 +00:00
psEnc - > sCmn . LBRR_enabled = 0 ;
# endif
return ret ;
}