Implements hard CBR for SILK
This is achieved by running the encoding process in a loop and padding when we don't reach the exact rate. It also implements VBR-with-cap, which means we no longer need to artificially decrease the SILK bandwidth when it's close to the cap.
This commit is contained in:
parent
dbf2ea841e
commit
294bfec27b
25 changed files with 442 additions and 94 deletions
|
@ -56,7 +56,7 @@ typedef struct {
|
||||||
/* Get size in bytes of the Silk encoder state */
|
/* Get size in bytes of the Silk encoder state */
|
||||||
/***********************************************/
|
/***********************************************/
|
||||||
opus_int silk_Get_Encoder_Size( /* O: Returns error code */
|
opus_int silk_Get_Encoder_Size( /* O: Returns error code */
|
||||||
int *encSizeBytes /* O: Number of bytes in SILK encoder state */
|
opus_int *encSizeBytes /* O: Number of bytes in SILK encoder state */
|
||||||
);
|
);
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
|
@ -98,7 +98,7 @@ opus_int silk_Encode( /* O: Returns error c
|
||||||
/* Get size in bytes of the Silk decoder state */
|
/* Get size in bytes of the Silk decoder state */
|
||||||
/***********************************************/
|
/***********************************************/
|
||||||
opus_int silk_Get_Decoder_Size( /* O: Returns error code */
|
opus_int silk_Get_Decoder_Size( /* O: Returns error code */
|
||||||
int *decSizeBytes /* O: Number of bytes in SILK decoder state */
|
opus_int *decSizeBytes /* O: Number of bytes in SILK decoder state */
|
||||||
);
|
);
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
|
|
|
@ -99,7 +99,7 @@ void silk_biquad_alt(
|
||||||
opus_int32 *S, /* I/O: State vector [2] */
|
opus_int32 *S, /* I/O: State vector [2] */
|
||||||
opus_int16 *out, /* O: output signal */
|
opus_int16 *out, /* O: output signal */
|
||||||
const opus_int32 len, /* I: signal length (must be even) */
|
const opus_int32 len, /* I: signal length (must be even) */
|
||||||
int stride
|
opus_int stride /* I: Operate on interleaved signal if > 1 */
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Variable order MA prediction error filter. */
|
/* Variable order MA prediction error filter. */
|
||||||
|
|
|
@ -47,7 +47,7 @@ void silk_biquad_alt(
|
||||||
opus_int32 *S, /* I/O: State vector [2] */
|
opus_int32 *S, /* I/O: State vector [2] */
|
||||||
opus_int16 *out, /* O: Output signal */
|
opus_int16 *out, /* O: Output signal */
|
||||||
const opus_int32 len, /* I: Signal length (must be even) */
|
const opus_int32 len, /* I: Signal length (must be even) */
|
||||||
int stride
|
opus_int stride /* I: Operate on interleaved signal if > 1 */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
|
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
|
||||||
|
@ -62,7 +62,7 @@ void silk_biquad_alt(
|
||||||
|
|
||||||
for( k = 0; k < len; k++ ) {
|
for( k = 0; k < len; k++ ) {
|
||||||
/* S[ 0 ], S[ 1 ]: Q12 */
|
/* S[ 0 ], S[ 1 ]: Q12 */
|
||||||
inval = in[ k*stride ];
|
inval = in[ k * stride ];
|
||||||
out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
|
out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
|
||||||
|
|
||||||
S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
|
S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
|
||||||
|
@ -74,6 +74,6 @@ void silk_biquad_alt(
|
||||||
S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
|
S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
|
||||||
|
|
||||||
/* Scale back to Q0 and saturate */
|
/* Scale back to Q0 and saturate */
|
||||||
out[ k*stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
|
out[ k * stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,9 @@ typedef struct {
|
||||||
/* I: Flag to use constant bitrate */
|
/* I: Flag to use constant bitrate */
|
||||||
opus_int useCBR;
|
opus_int useCBR;
|
||||||
|
|
||||||
|
/* I: Maximum number of bits allowed for the frame */
|
||||||
|
opus_int maxBits;
|
||||||
|
|
||||||
/* I: Causes a smooth downmix to mono */
|
/* I: Causes a smooth downmix to mono */
|
||||||
opus_int toMono;
|
opus_int toMono;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "tuning_parameters.h"
|
#include "tuning_parameters.h"
|
||||||
|
|
||||||
|
|
||||||
static const int enc_delay_matrix[3][5] = {
|
static const opus_int enc_delay_matrix[3][5] = {
|
||||||
/*SILK API 8 12 16 24 48 */
|
/*SILK API 8 12 16 24 48 */
|
||||||
/* 8 */ {5, 0, 3, 4, 8},
|
/* 8 */ {5, 0, 3, 4, 8},
|
||||||
/*12 */ {0, 6, 0, 0, 0},
|
/*12 */ {0, 6, 0, 0, 0},
|
||||||
|
|
|
@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
/* Encoder functions */
|
/* Encoder functions */
|
||||||
/****************************************/
|
/****************************************/
|
||||||
|
|
||||||
opus_int silk_Get_Encoder_Size( int *encSizeBytes )
|
opus_int silk_Get_Encoder_Size( opus_int *encSizeBytes )
|
||||||
{
|
{
|
||||||
opus_int ret = SILK_NO_ERROR;
|
opus_int ret = SILK_NO_ERROR;
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ opus_int silk_Encode(
|
||||||
opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol;
|
opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol;
|
||||||
silk_encoder *psEnc = ( silk_encoder * )encState;
|
silk_encoder *psEnc = ( silk_encoder * )encState;
|
||||||
opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ + MAX_ENCODER_DELAY];
|
opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ + MAX_ENCODER_DELAY];
|
||||||
opus_int transition, delay;
|
opus_int transition, delay, curr_block, tot_blocks;
|
||||||
|
|
||||||
psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0;
|
psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0;
|
||||||
|
|
||||||
|
@ -172,6 +172,8 @@ opus_int silk_Encode(
|
||||||
psEnc->nChannelsInternal = encControl->nChannelsInternal;
|
psEnc->nChannelsInternal = encControl->nChannelsInternal;
|
||||||
|
|
||||||
nBlocksOf10ms = silk_DIV32( 100 * nSamplesIn, encControl->API_sampleRate );
|
nBlocksOf10ms = silk_DIV32( 100 * nSamplesIn, encControl->API_sampleRate );
|
||||||
|
tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1;
|
||||||
|
curr_block = 0;
|
||||||
if( prefillFlag ) {
|
if( prefillFlag ) {
|
||||||
/* Only accept input length of 10 ms */
|
/* Only accept input length of 10 ms */
|
||||||
if( nBlocksOf10ms != 1 ) {
|
if( nBlocksOf10ms != 1 ) {
|
||||||
|
@ -211,13 +213,12 @@ opus_int silk_Encode(
|
||||||
TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 );
|
TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 );
|
||||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||||
/* JMV: Force the side channel to the same rate as the mid. Is this the right way? */
|
/* JMV: Force the side channel to the same rate as the mid. Is this the right way? */
|
||||||
int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
|
opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
|
||||||
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
|
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
|
||||||
silk_assert( 0 );
|
silk_assert( 0 );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition)
|
if( psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition ) {
|
||||||
{
|
|
||||||
for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) {
|
for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) {
|
||||||
psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] = 0;
|
psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] = 0;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +235,7 @@ opus_int silk_Encode(
|
||||||
nSamplesFromInput = silk_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 );
|
nSamplesFromInput = silk_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 );
|
||||||
/* Resample and write to buffer */
|
/* Resample and write to buffer */
|
||||||
if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) {
|
if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) {
|
||||||
int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
|
opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
|
||||||
for( n = 0; n < nSamplesFromInput; n++ ) {
|
for( n = 0; n < nSamplesFromInput; n++ ) {
|
||||||
buf[ n+delay ] = samplesIn[ 2 * n ];
|
buf[ n+delay ] = samplesIn[ 2 * n ];
|
||||||
}
|
}
|
||||||
|
@ -419,10 +420,33 @@ opus_int silk_Encode(
|
||||||
|
|
||||||
/* Encode */
|
/* Encode */
|
||||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||||
|
opus_int maxBits, useCBR;
|
||||||
|
|
||||||
|
/* Handling rate constraints */
|
||||||
|
maxBits = encControl->maxBits;
|
||||||
|
/*if( encControl->useCBR ) {
|
||||||
|
maxBits = (encControl->bitRate * nBlocksOf10ms / 800) * 8;
|
||||||
|
}*/
|
||||||
|
if( tot_blocks == 2 && curr_block == 0 ) {
|
||||||
|
maxBits = maxBits * 3 / 5;
|
||||||
|
} else if( tot_blocks == 3 ) {
|
||||||
|
if( curr_block == 0 ) {
|
||||||
|
maxBits = maxBits * 2 / 5;
|
||||||
|
} else if( curr_block == 1 ) {
|
||||||
|
maxBits = maxBits * 3 / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
useCBR = encControl->useCBR && curr_block == tot_blocks - 1;
|
||||||
|
|
||||||
if( encControl->nChannelsInternal == 1 ) {
|
if( encControl->nChannelsInternal == 1 ) {
|
||||||
channelRate_bps = TargetRate_bps;
|
channelRate_bps = TargetRate_bps;
|
||||||
} else {
|
} else {
|
||||||
channelRate_bps = MStargetRates_bps[ n ];
|
channelRate_bps = MStargetRates_bps[ n ];
|
||||||
|
if( n == 0 && MStargetRates_bps[ 1 ] > 0 ) {
|
||||||
|
useCBR = 0;
|
||||||
|
/* Give mid up to 1/2 of the max bits for that frame */
|
||||||
|
maxBits -= encControl->maxBits / ( tot_blocks * 2 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( channelRate_bps > 0 ) {
|
if( channelRate_bps > 0 ) {
|
||||||
|
@ -440,7 +464,7 @@ opus_int silk_Encode(
|
||||||
} else {
|
} else {
|
||||||
condCoding = CODE_CONDITIONALLY;
|
condCoding = CODE_CONDITIONALLY;
|
||||||
}
|
}
|
||||||
if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc, condCoding ) ) != 0 ) {
|
if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc, condCoding, maxBits, useCBR ) ) != 0 ) {
|
||||||
silk_assert( 0 );
|
silk_assert( 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,6 +516,7 @@ opus_int silk_Encode(
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
curr_block++;
|
||||||
}
|
}
|
||||||
|
|
||||||
psEnc->nPrevChannelsInternal = encControl->nChannelsInternal;
|
psEnc->nPrevChannelsInternal = encControl->nChannelsInternal;
|
||||||
|
|
|
@ -35,7 +35,6 @@ void silk_LTP_scale_ctrl_FIX(
|
||||||
silk_encoder_state_FIX *psEnc, /* I/O encoder state FIX */
|
silk_encoder_state_FIX *psEnc, /* I/O encoder state FIX */
|
||||||
silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control FIX */
|
silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control FIX */
|
||||||
opus_int condCoding /* I The type of conditional coding to use */
|
opus_int condCoding /* I The type of conditional coding to use */
|
||||||
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
opus_int round_loss;
|
opus_int round_loss;
|
||||||
|
|
|
@ -79,14 +79,23 @@ opus_int silk_encode_frame_FIX(
|
||||||
silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */
|
silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */
|
||||||
opus_int32 *pnBytesOut, /* O Number of payload bytes */
|
opus_int32 *pnBytesOut, /* O Number of payload bytes */
|
||||||
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
||||||
opus_int condCoding /* I The type of conditional coding to use */
|
opus_int condCoding, /* I The type of conditional coding to use */
|
||||||
|
opus_int maxBits, /* I If > 0: maximum number of output bits */
|
||||||
|
opus_int useCBR /* I Flag to force constant-bitrate operation */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
silk_encoder_control_FIX sEncCtrl;
|
silk_encoder_control_FIX sEncCtrl;
|
||||||
opus_int ret = 0;
|
opus_int i, iter, maxIter, found_upper, found_lower, ret = 0;
|
||||||
opus_int16 *x_frame, *res_pitch_frame;
|
opus_int16 *x_frame, *res_pitch_frame;
|
||||||
opus_int16 xfw[ MAX_FRAME_LENGTH ];
|
opus_int16 xfw[ MAX_FRAME_LENGTH ];
|
||||||
opus_int16 res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
|
opus_int16 res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
|
||||||
|
ec_enc sRangeEnc_copy, sRangeEnc_copy2;
|
||||||
|
silk_nsq_state sNSQ_copy, sNSQ_copy2;
|
||||||
|
opus_int32 seed_copy, nBits, nBits_lower, nBits_upper, gainMult_Q10, gainMult_lower, gainMult_upper;
|
||||||
|
opus_int16 ec_prevLagIndex_copy;
|
||||||
|
opus_int ec_prevSignalType_copy;
|
||||||
|
opus_int8 LastGainIndex_copy2;
|
||||||
|
opus_uint8 ec_buf_copy[ 512 ];
|
||||||
|
|
||||||
TIC(ENCODE_FRAME)
|
TIC(ENCODE_FRAME)
|
||||||
|
|
||||||
|
@ -151,21 +160,132 @@ TIC(LBRR)
|
||||||
silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw, condCoding );
|
silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw, condCoding );
|
||||||
TOC(LBRR)
|
TOC(LBRR)
|
||||||
|
|
||||||
/*****************************************/
|
/* Loop over quantizer and entroy coding to control bitrate */
|
||||||
/* Noise shaping quantization */
|
maxIter = 5;
|
||||||
/*****************************************/
|
gainMult_Q10 = SILK_FIX_CONST( 1, 10 );
|
||||||
|
found_lower = 0;
|
||||||
|
found_upper = 0;
|
||||||
|
for( iter = 0; ; iter++ ) {
|
||||||
|
if( maxBits > 0 && !psEnc->sCmn.prefillFlag ) {
|
||||||
|
/* Copy part of the input state */
|
||||||
|
silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
|
||||||
|
silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
|
||||||
|
seed_copy = psEnc->sCmn.indices.Seed;
|
||||||
|
ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
|
||||||
|
ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************/
|
||||||
|
/* Noise shaping quantization */
|
||||||
|
/*****************************************/
|
||||||
TIC(NSQ)
|
TIC(NSQ)
|
||||||
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
|
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
|
||||||
silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
|
silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
|
||||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||||
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
|
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
|
||||||
} else {
|
} else {
|
||||||
silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
|
silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
|
||||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||||
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
|
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
|
||||||
}
|
}
|
||||||
TOC(NSQ)
|
TOC(NSQ)
|
||||||
|
|
||||||
|
if( psEnc->sCmn.prefillFlag ) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/****************************************/
|
||||||
|
/* Encode Parameters */
|
||||||
|
/****************************************/
|
||||||
|
TIC(ENCODE_PARAMS)
|
||||||
|
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
||||||
|
TOC(ENCODE_PARAMS)
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Encode Excitation Signal */
|
||||||
|
/****************************************/
|
||||||
|
TIC(ENCODE_PULSES)
|
||||||
|
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
||||||
|
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
||||||
|
TOC(ENCODE_PULSES)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nBits = ec_tell( psRangeEnc );
|
||||||
|
|
||||||
|
if( maxBits == 0 || ( useCBR == 0 && iter == 0 && nBits <= maxBits ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( iter == maxIter ) {
|
||||||
|
if( nBits > maxBits && found_lower ) {
|
||||||
|
/* Restore output state from earlier iteration that did meet the bitrate budget */
|
||||||
|
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
|
||||||
|
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
|
||||||
|
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
|
||||||
|
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( nBits > maxBits ) {
|
||||||
|
found_upper = 1;
|
||||||
|
nBits_upper = nBits;
|
||||||
|
gainMult_upper = gainMult_Q10;
|
||||||
|
if( found_lower == 0 && iter >= 2 ) {
|
||||||
|
/* Adjust the quantizer's rate/distortion tradeoff */
|
||||||
|
sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 );
|
||||||
|
}
|
||||||
|
} else if( nBits < maxBits - 5 ) {
|
||||||
|
found_lower = 1;
|
||||||
|
nBits_lower = nBits;
|
||||||
|
gainMult_lower = gainMult_Q10;
|
||||||
|
/* Copy part of the output state */
|
||||||
|
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
|
||||||
|
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
|
||||||
|
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
|
||||||
|
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
|
||||||
|
} else {
|
||||||
|
/* Within 5 bits of budget: close enough */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( found_lower & found_upper ) == 0 ) {
|
||||||
|
/* Adjust gain according to high-rate rate/distortion curve */
|
||||||
|
opus_int32 gain_factor_Q16;
|
||||||
|
gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
|
||||||
|
if( nBits > maxBits ) {
|
||||||
|
gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
|
||||||
|
}
|
||||||
|
gainMult_Q10 = silk_SMULWW( gainMult_Q10, gain_factor_Q16 );
|
||||||
|
} else {
|
||||||
|
/* Adjust gain by interpolating */
|
||||||
|
gainMult_Q10 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower );
|
||||||
|
/* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
|
||||||
|
if( gainMult_Q10 > gainMult_lower + silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 ) ) {
|
||||||
|
gainMult_Q10 = gainMult_lower + silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 );
|
||||||
|
} else
|
||||||
|
if( gainMult_Q10 < gainMult_upper - silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 ) ) {
|
||||||
|
gainMult_Q10 = gainMult_upper - silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||||
|
sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWW( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q10 ), 6 );
|
||||||
|
}
|
||||||
|
psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
|
||||||
|
|
||||||
|
/* Noise shaping quantization */
|
||||||
|
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16,
|
||||||
|
&psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
|
||||||
|
|
||||||
|
/* Restore part of the input state */
|
||||||
|
silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
|
||||||
|
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) );
|
||||||
|
psEnc->sCmn.indices.Seed = seed_copy;
|
||||||
|
psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
|
||||||
|
psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
|
||||||
|
}
|
||||||
|
|
||||||
/* Update input buffer */
|
/* Update input buffer */
|
||||||
silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
|
silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
|
||||||
( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) );
|
( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) );
|
||||||
|
@ -181,28 +301,14 @@ TOC(NSQ)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************/
|
|
||||||
/* Encode Parameters */
|
|
||||||
/****************************************/
|
|
||||||
TIC(ENCODE_PARAMS)
|
|
||||||
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
|
||||||
TOC(ENCODE_PARAMS)
|
|
||||||
|
|
||||||
/****************************************/
|
|
||||||
/* Encode Excitation Signal */
|
|
||||||
/****************************************/
|
|
||||||
TIC(ENCODE_PULSES)
|
|
||||||
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
|
||||||
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
|
||||||
TOC(ENCODE_PULSES)
|
|
||||||
|
|
||||||
/****************************************/
|
/****************************************/
|
||||||
/* Finalize payload */
|
/* Finalize payload */
|
||||||
/****************************************/
|
/****************************************/
|
||||||
psEnc->sCmn.first_frame_after_reset = 0;
|
psEnc->sCmn.first_frame_after_reset = 0;
|
||||||
/* Payload size */
|
/* Payload size */
|
||||||
*pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
|
*pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
|
||||||
TOC(ENCODE_FRAME)
|
|
||||||
|
TOC(ENCODE_FRAME)
|
||||||
|
|
||||||
#ifdef SAVE_ALL_INTERNAL_DATA
|
#ifdef SAVE_ALL_INTERNAL_DATA
|
||||||
{
|
{
|
||||||
|
|
|
@ -127,6 +127,6 @@ void silk_find_pred_coefs_FIX(
|
||||||
silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains,
|
silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains,
|
||||||
psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
|
psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
|
||||||
|
|
||||||
/* Copy to prediction struct for use in next frame for fluctuation reduction */
|
/* Copy to prediction struct for use in next frame for interpolation */
|
||||||
silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
|
silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,9 @@ opus_int silk_encode_frame_FIX(
|
||||||
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
|
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
|
||||||
opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */
|
opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */
|
||||||
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
||||||
opus_int condCoding /* I The type of conditional coding to use */
|
opus_int condCoding, /* I The type of conditional coding to use */
|
||||||
|
opus_int maxBits, /* I If > 0: maximum number of output bits */
|
||||||
|
opus_int useCBR /* I Flag to force constant-bitrate operation */
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Initializes the Silk encoder state */
|
/* Initializes the Silk encoder state */
|
||||||
|
|
|
@ -86,6 +86,10 @@ void silk_process_gains_FIX(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save unquantized gains and gain Index */
|
||||||
|
silk_memcpy( psEncCtrl->GainsUnq_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
|
||||||
|
psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex;
|
||||||
|
|
||||||
/* Noise shaping quantization */
|
/* Noise shaping quantization */
|
||||||
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16,
|
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16,
|
||||||
&psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
|
&psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
|
||||||
|
|
|
@ -109,6 +109,9 @@ typedef struct {
|
||||||
opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
|
opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
|
||||||
opus_int ResNrgQ[ MAX_NB_SUBFR ]; /* Q domain for the residual energy > 0 */
|
opus_int ResNrgQ[ MAX_NB_SUBFR ]; /* Q domain for the residual energy > 0 */
|
||||||
|
|
||||||
|
/* Parameters for CBR mode */
|
||||||
|
opus_int32 GainsUnq_Q16[ MAX_NB_SUBFR ];
|
||||||
|
opus_int8 lastGainIndexPrev;
|
||||||
} silk_encoder_control_FIX;
|
} silk_encoder_control_FIX;
|
||||||
|
|
||||||
/************************/
|
/************************/
|
||||||
|
|
|
@ -82,17 +82,31 @@ opus_int silk_encode_frame_FLP(
|
||||||
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
||||||
opus_int32 *pnBytesOut, /* O Number of payload bytes */
|
opus_int32 *pnBytesOut, /* O Number of payload bytes */
|
||||||
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
||||||
opus_int condCoding /* I The type of conditional coding to use */
|
opus_int condCoding, /* I The type of conditional coding to use */
|
||||||
|
opus_int maxBits, /* I If > 0: maximum number of output bits */
|
||||||
|
opus_int useCBR /* I Flag to force constant-bitrate operation */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
silk_encoder_control_FLP sEncCtrl;
|
silk_encoder_control_FLP sEncCtrl;
|
||||||
opus_int i, ret = 0;
|
opus_int i, iter, maxIter, found_upper, found_lower, ret = 0;
|
||||||
silk_float *x_frame, *res_pitch_frame;
|
silk_float *x_frame, *res_pitch_frame;
|
||||||
silk_float xfw[ MAX_FRAME_LENGTH ];
|
silk_float xfw[ MAX_FRAME_LENGTH ];
|
||||||
silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
|
silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
|
||||||
|
ec_enc sRangeEnc_copy, sRangeEnc_copy2;
|
||||||
|
silk_nsq_state sNSQ_copy, sNSQ_copy2;
|
||||||
|
opus_int32 seed_copy, nBits, nBits_lower, nBits_upper, gainMult_Q10, gainMult_lower, gainMult_upper;
|
||||||
|
opus_int16 ec_prevLagIndex_copy;
|
||||||
|
opus_int ec_prevSignalType_copy;
|
||||||
|
opus_int8 LastGainIndex_copy2;
|
||||||
|
opus_int32 pGains_Q16[ MAX_NB_SUBFR ];
|
||||||
|
opus_uint8 ec_buf_copy[ 512 ];
|
||||||
|
|
||||||
TIC(ENCODE_FRAME)
|
TIC(ENCODE_FRAME)
|
||||||
|
|
||||||
|
/* This is totally unnecessary but many compilers (including gcc) are too dumb
|
||||||
|
to realise it */
|
||||||
|
LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
|
||||||
|
|
||||||
psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
|
psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
|
@ -159,12 +173,128 @@ TIC(LBRR)
|
||||||
silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );
|
silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );
|
||||||
TOC(LBRR)
|
TOC(LBRR)
|
||||||
|
|
||||||
/*****************************************/
|
if ( psEnc->sCmn.prefillFlag )
|
||||||
/* Noise shaping quantization */
|
{
|
||||||
/*****************************************/
|
|
||||||
TIC(NSQ)
|
TIC(NSQ)
|
||||||
silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
|
silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
|
||||||
TOC(NSQ)
|
TOC(NSQ)
|
||||||
|
} else {
|
||||||
|
/* Loop over quantizer and entroy coding to control bitrate */
|
||||||
|
maxIter = 5;
|
||||||
|
gainMult_Q10 = SILK_FIX_CONST( 1, 10 );
|
||||||
|
found_lower = 0;
|
||||||
|
found_upper = 0;
|
||||||
|
for( iter = 0; ; iter++ ) {
|
||||||
|
/* Copy part of the input state */
|
||||||
|
silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
|
||||||
|
silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
|
||||||
|
seed_copy = psEnc->sCmn.indices.Seed;
|
||||||
|
ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
|
||||||
|
ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
|
||||||
|
|
||||||
|
/*****************************************/
|
||||||
|
/* Noise shaping quantization */
|
||||||
|
/*****************************************/
|
||||||
|
TIC(NSQ)
|
||||||
|
silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
|
||||||
|
TOC(NSQ)
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Encode Parameters */
|
||||||
|
/****************************************/
|
||||||
|
TIC(ENCODE_PARAMS)
|
||||||
|
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
||||||
|
TOC(ENCODE_PARAMS)
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Encode Excitation Signal */
|
||||||
|
/****************************************/
|
||||||
|
TIC(ENCODE_PULSES)
|
||||||
|
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
||||||
|
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
||||||
|
TOC(ENCODE_PULSES)
|
||||||
|
|
||||||
|
nBits = ec_tell( psRangeEnc );
|
||||||
|
|
||||||
|
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( iter == maxIter ) {
|
||||||
|
if( nBits > maxBits && found_lower ) {
|
||||||
|
/* Restore output state from earlier iteration that did meet the bitrate budget */
|
||||||
|
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
|
||||||
|
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
|
||||||
|
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
|
||||||
|
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( nBits > maxBits ) {
|
||||||
|
found_upper = 1;
|
||||||
|
nBits_upper = nBits;
|
||||||
|
gainMult_upper = gainMult_Q10;
|
||||||
|
if( found_lower == 0 && iter >= 3 ) {
|
||||||
|
/* Adjust the quantizer's rate/distortion tradeoff */
|
||||||
|
sEncCtrl.Lambda *= 1.5f;
|
||||||
|
}
|
||||||
|
} else if( nBits < maxBits - 5 ) {
|
||||||
|
found_lower = 1;
|
||||||
|
nBits_lower = nBits;
|
||||||
|
gainMult_lower = gainMult_Q10;
|
||||||
|
/* Copy part of the output state */
|
||||||
|
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
|
||||||
|
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
|
||||||
|
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
|
||||||
|
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
|
||||||
|
} else {
|
||||||
|
/* Within 5 bits of budget: close enough */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( found_lower & found_upper ) == 0 ) {
|
||||||
|
/* Adjust gain according to high-rate rate/distortion curve */
|
||||||
|
opus_int32 gain_factor_Q16;
|
||||||
|
gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
|
||||||
|
if( nBits > maxBits ) {
|
||||||
|
gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
|
||||||
|
}
|
||||||
|
gainMult_Q10 = silk_SMULWW( gainMult_Q10, gain_factor_Q16 );
|
||||||
|
} else {
|
||||||
|
/* Adjust gain by interpolating */
|
||||||
|
gainMult_Q10 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
|
||||||
|
/* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
|
||||||
|
if( gainMult_Q10 > gainMult_lower + silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 ) ) {
|
||||||
|
gainMult_Q10 = gainMult_lower + silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 );
|
||||||
|
} else
|
||||||
|
if( gainMult_Q10 < gainMult_upper - silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 ) ) {
|
||||||
|
gainMult_Q10 = gainMult_upper - silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||||
|
pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWW( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q10 ), 6 );
|
||||||
|
}
|
||||||
|
psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
|
||||||
|
|
||||||
|
/* Noise shaping quantization */
|
||||||
|
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
|
||||||
|
&psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
|
||||||
|
|
||||||
|
/* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
|
||||||
|
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||||
|
sEncCtrl.Gains[ i ] = pGains_Q16[ i ] / 65536.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore part of the input state */
|
||||||
|
silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
|
||||||
|
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) );
|
||||||
|
psEnc->sCmn.indices.Seed = seed_copy;
|
||||||
|
psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
|
||||||
|
psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Update input buffer */
|
/* Update input buffer */
|
||||||
silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
|
silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
|
||||||
|
@ -181,32 +311,16 @@ TOC(NSQ)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************/
|
|
||||||
/* Encode Parameters */
|
|
||||||
/****************************************/
|
|
||||||
TIC(ENCODE_PARAMS)
|
|
||||||
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
|
||||||
TOC(ENCODE_PARAMS)
|
|
||||||
|
|
||||||
/****************************************/
|
|
||||||
/* Encode Excitation Signal */
|
|
||||||
/****************************************/
|
|
||||||
TIC(ENCODE_PULSES)
|
|
||||||
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
|
||||||
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
|
||||||
TOC(ENCODE_PULSES)
|
|
||||||
|
|
||||||
/****************************************/
|
/****************************************/
|
||||||
/* Finalize payload */
|
/* Finalize payload */
|
||||||
/****************************************/
|
/****************************************/
|
||||||
psEnc->sCmn.first_frame_after_reset = 0;
|
psEnc->sCmn.first_frame_after_reset = 0;
|
||||||
/* Payload size */
|
/* Payload size */
|
||||||
*pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
|
*pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
|
||||||
|
|
||||||
TOC(ENCODE_FRAME)
|
TOC(ENCODE_FRAME)
|
||||||
|
|
||||||
#ifdef SAVE_ALL_INTERNAL_DATA
|
#ifdef SAVE_ALL_INTERNAL_DATA
|
||||||
/*DEBUG_STORE_DATA( xf.dat, pIn_HP_LP, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );*/
|
|
||||||
/*DEBUG_STORE_DATA( xfw.dat, xfw, psEnc->sCmn.frame_length * sizeof( silk_float ) );*/
|
|
||||||
DEBUG_STORE_DATA( pitchL.dat, sEncCtrl.pitchL, MAX_NB_SUBFR * sizeof( opus_int ) );
|
DEBUG_STORE_DATA( pitchL.dat, sEncCtrl.pitchL, MAX_NB_SUBFR * sizeof( opus_int ) );
|
||||||
DEBUG_STORE_DATA( pitchG_quantized.dat, sEncCtrl.LTPCoef, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) );
|
DEBUG_STORE_DATA( pitchG_quantized.dat, sEncCtrl.LTPCoef, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) );
|
||||||
DEBUG_STORE_DATA( LTPcorr.dat, &psEnc->LTPCorr, sizeof( silk_float ) );
|
DEBUG_STORE_DATA( LTPcorr.dat, &psEnc->LTPCorr, sizeof( silk_float ) );
|
||||||
|
@ -220,7 +334,6 @@ TOC(ENCODE_FRAME)
|
||||||
DEBUG_STORE_DATA( per_index.dat, &psEnc->sCmn.indices.PERIndex, sizeof( opus_int8 ) );
|
DEBUG_STORE_DATA( per_index.dat, &psEnc->sCmn.indices.PERIndex, sizeof( opus_int8 ) );
|
||||||
DEBUG_STORE_DATA( PredCoef.dat, &sEncCtrl.PredCoef[ 1 ], psEnc->sCmn.predictLPCOrder * sizeof( silk_float ) );
|
DEBUG_STORE_DATA( PredCoef.dat, &sEncCtrl.PredCoef[ 1 ], psEnc->sCmn.predictLPCOrder * sizeof( silk_float ) );
|
||||||
DEBUG_STORE_DATA( ltp_scale_idx.dat, &psEnc->sCmn.indices.LTP_scaleIndex, sizeof( opus_int8 ) );
|
DEBUG_STORE_DATA( ltp_scale_idx.dat, &psEnc->sCmn.indices.LTP_scaleIndex, sizeof( opus_int8 ) );
|
||||||
/*DEBUG_STORE_DATA( xq.dat, psEnc->sCmn.sNSQ.xqBuf, psEnc->sCmn.frame_length * sizeof( silk_float ) );*/
|
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ TOC(LSF_quant);
|
||||||
silk_residual_energy_FLP( psEncCtrl->ResNrg, LPC_in_pre, psEncCtrl->PredCoef, psEncCtrl->Gains,
|
silk_residual_energy_FLP( psEncCtrl->ResNrg, LPC_in_pre, psEncCtrl->PredCoef, psEncCtrl->Gains,
|
||||||
psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
|
psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
|
||||||
|
|
||||||
/* Copy to prediction struct for use in next frame for fluctuation reduction */
|
/* Copy to prediction struct for use in next frame for interpolation */
|
||||||
silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
|
silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,18 +42,18 @@ double silk_inner_product_FLP( /* O result */
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
/* 4x unrolled loop */
|
/* 4x unrolled loop */
|
||||||
result = 0.0f;
|
result = 0.0;
|
||||||
dataSize4 = dataSize & 0xFFFC;
|
dataSize4 = dataSize & 0xFFFC;
|
||||||
for( i = 0; i < dataSize4; i += 4 ) {
|
for( i = 0; i < dataSize4; i += 4 ) {
|
||||||
result += data1[ i + 0 ] * data2[ i + 0 ] +
|
result += data1[ i + 0 ] * (double)data2[ i + 0 ] +
|
||||||
data1[ i + 1 ] * data2[ i + 1 ] +
|
data1[ i + 1 ] * (double)data2[ i + 1 ] +
|
||||||
data1[ i + 2 ] * data2[ i + 2 ] +
|
data1[ i + 2 ] * (double)data2[ i + 2 ] +
|
||||||
data1[ i + 3 ] * data2[ i + 3 ];
|
data1[ i + 3 ] * (double)data2[ i + 3 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add any remaining products */
|
/* add any remaining products */
|
||||||
for( ; i < dataSize; i++ ) {
|
for( ; i < dataSize; i++ ) {
|
||||||
result += data1[ i ] * data2[ i ];
|
result += data1[ i ] * (double)data2[ i ];
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -64,7 +64,9 @@ opus_int silk_encode_frame_FLP(
|
||||||
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
||||||
opus_int32 *pnBytesOut, /* O Number of payload bytes; */
|
opus_int32 *pnBytesOut, /* O Number of payload bytes; */
|
||||||
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
ec_enc *psRangeEnc, /* I/O compressor data structure */
|
||||||
opus_int condCoding /* I The type of conditional coding to use */
|
opus_int condCoding, /* I The type of conditional coding to use */
|
||||||
|
opus_int maxBits, /* I If > 0: maximum number of output bits */
|
||||||
|
opus_int useCBR /* I Flag to force constant-bitrate operation */
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Initializes the Silk encoder state */
|
/* Initializes the Silk encoder state */
|
||||||
|
|
|
@ -202,8 +202,8 @@ opus_int silk_pitch_analysis_core_FLP( /* O voicing estimate: 0 voiced, 1 unvoic
|
||||||
|
|
||||||
/* Add contribution of new sample and remove contribution from oldest sample */
|
/* Add contribution of new sample and remove contribution from oldest sample */
|
||||||
normalizer +=
|
normalizer +=
|
||||||
basis_ptr[ 0 ] * basis_ptr[ 0 ] -
|
basis_ptr[ 0 ] * (double)basis_ptr[ 0 ] -
|
||||||
basis_ptr[ sf_length_8kHz ] * basis_ptr[ sf_length_8kHz ];
|
basis_ptr[ sf_length_8kHz ] * (double)basis_ptr[ sf_length_8kHz ];
|
||||||
C[ 0 ][ d ] += (silk_float)(cross_corr / sqrt( normalizer ));
|
C[ 0 ][ d ] += (silk_float)(cross_corr / sqrt( normalizer ));
|
||||||
}
|
}
|
||||||
/* Update target pointer */
|
/* Update target pointer */
|
||||||
|
@ -225,7 +225,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O voicing estimate: 0 voiced, 1 unvoic
|
||||||
target_ptr = &frame_4kHz[ silk_SMULBB( sf_length_4kHz, nb_subfr ) ];
|
target_ptr = &frame_4kHz[ silk_SMULBB( sf_length_4kHz, nb_subfr ) ];
|
||||||
energy = 1000.0f;
|
energy = 1000.0f;
|
||||||
for( i = 0; i < silk_LSHIFT( sf_length_4kHz, 2 ); i++ ) {
|
for( i = 0; i < silk_LSHIFT( sf_length_4kHz, 2 ); i++ ) {
|
||||||
energy += target_ptr[i] * target_ptr[i];
|
energy += target_ptr[i] * (double)target_ptr[i];
|
||||||
}
|
}
|
||||||
threshold = Cmax * Cmax;
|
threshold = Cmax * Cmax;
|
||||||
if( energy / 16.0f > threshold ) {
|
if( energy / 16.0f > threshold ) {
|
||||||
|
|
|
@ -67,6 +67,10 @@ void silk_process_gains_FLP(
|
||||||
pGains_Q16[ k ] = ( opus_int32 ) ( psEncCtrl->Gains[ k ] * 65536.0f );
|
pGains_Q16[ k ] = ( opus_int32 ) ( psEncCtrl->Gains[ k ] * 65536.0f );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save unquantized gains and gain Index */
|
||||||
|
silk_memcpy( psEncCtrl->GainsUnq_Q16, pGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
|
||||||
|
psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex;
|
||||||
|
|
||||||
/* Noise shaping quantization */
|
/* Noise shaping quantization */
|
||||||
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
|
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
|
||||||
&psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
|
&psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
|
||||||
|
|
|
@ -107,6 +107,10 @@ typedef struct {
|
||||||
silk_float predGain;
|
silk_float predGain;
|
||||||
silk_float LTPredCodGain;
|
silk_float LTPredCodGain;
|
||||||
silk_float ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
|
silk_float ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
|
||||||
|
|
||||||
|
/* Parameters for CBR mode */
|
||||||
|
opus_int32 GainsUnq_Q16[ MAX_NB_SUBFR ];
|
||||||
|
opus_int8 lastGainIndexPrev;
|
||||||
} silk_encoder_control_FLP;
|
} silk_encoder_control_FLP;
|
||||||
|
|
||||||
/************************/
|
/************************/
|
||||||
|
|
|
@ -54,14 +54,14 @@ void silk_process_NLSFs(
|
||||||
/* Calculate mu values */
|
/* Calculate mu values */
|
||||||
/***********************/
|
/***********************/
|
||||||
/* NLSF_mu = 0.003 - 0.0015 * psEnc->speech_activity; */
|
/* NLSF_mu = 0.003 - 0.0015 * psEnc->speech_activity; */
|
||||||
NLSF_mu_Q20 = silk_SMLAWB( SILK_FIX_CONST( 0.0025, 20 ), SILK_FIX_CONST( -0.001, 28 ), psEncC->speech_activity_Q8 );
|
NLSF_mu_Q20 = silk_SMLAWB( SILK_FIX_CONST( 0.003, 20 ), SILK_FIX_CONST( -0.001, 28 ), psEncC->speech_activity_Q8 );
|
||||||
if( psEncC->nb_subfr == 2 ) {
|
if( psEncC->nb_subfr == 2 ) {
|
||||||
/* Multiply by 1.5 for 10 ms packets */
|
/* Multiply by 1.5 for 10 ms packets */
|
||||||
NLSF_mu_Q20 = silk_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 );
|
NLSF_mu_Q20 = silk_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
silk_assert( NLSF_mu_Q20 > 0 );
|
silk_assert( NLSF_mu_Q20 > 0 );
|
||||||
silk_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.0045, 20 ) );
|
silk_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.005, 20 ) );
|
||||||
|
|
||||||
/* Calculate NLSF weights */
|
/* Calculate NLSF weights */
|
||||||
silk_NLSF_VQ_weights_laroia( pNLSFW_QW, pNLSF_Q15, psEncC->predictLPCOrder );
|
silk_NLSF_VQ_weights_laroia( pNLSFW_QW, pNLSF_Q15, psEncC->predictLPCOrder );
|
||||||
|
|
|
@ -189,7 +189,7 @@ typedef struct {
|
||||||
opus_int8 LBRR_flag;
|
opus_int8 LBRR_flag;
|
||||||
opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ];
|
opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ];
|
||||||
|
|
||||||
SideInfoIndices indices;
|
SideInfoIndices indices;
|
||||||
opus_int8 pulses[ MAX_FRAME_LENGTH ];
|
opus_int8 pulses[ MAX_FRAME_LENGTH ];
|
||||||
|
|
||||||
/* Input/output buffering */
|
/* Input/output buffering */
|
||||||
|
|
|
@ -726,7 +726,7 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data,
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
for (i=0;i<ret*st->channels;i++)
|
for (i=0;i<ret*st->channels;i++)
|
||||||
pcm[i] = (1./32768.)*(out[i]);
|
pcm[i] = (1.f/32768.f)*(out[i]);
|
||||||
}
|
}
|
||||||
RESTORE_STACK;
|
RESTORE_STACK;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -219,6 +219,44 @@ int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int applicat
|
||||||
return OPUS_OK;
|
return OPUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pad_frame(unsigned char *data, int len, int new_len)
|
||||||
|
{
|
||||||
|
if (len == new_len)
|
||||||
|
return 0;
|
||||||
|
if (len > new_len)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ((data[0]&0x3)==0)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int padding, nb_255s;
|
||||||
|
|
||||||
|
padding = new_len - len;
|
||||||
|
if (padding >= 2)
|
||||||
|
{
|
||||||
|
nb_255s = (padding-2)/255;
|
||||||
|
|
||||||
|
for (i=len-1;i>=1;i--)
|
||||||
|
data[i+nb_255s+2] = data[i];
|
||||||
|
data[0] |= 0x3;
|
||||||
|
data[1] = 0x41;
|
||||||
|
for (i=0;i<nb_255s;i++)
|
||||||
|
data[i+2] = 255;
|
||||||
|
data[nb_255s+2] = padding-255*nb_255s-2;
|
||||||
|
for (i=len+3+nb_255s;i<new_len;i++)
|
||||||
|
data[i] = 0;
|
||||||
|
} else {
|
||||||
|
for (i=len-1;i>=1;i--)
|
||||||
|
data[i+1] = data[i];
|
||||||
|
data[0] |= 0x3;
|
||||||
|
data[1] = 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels)
|
static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels)
|
||||||
{
|
{
|
||||||
int period;
|
int period;
|
||||||
|
@ -449,6 +487,15 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
|
||||||
|
|
||||||
st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes);
|
st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes);
|
||||||
|
|
||||||
|
if (!st->use_vbr)
|
||||||
|
{
|
||||||
|
int cbrBytes, frame_rate;
|
||||||
|
frame_rate = st->Fs/frame_size;
|
||||||
|
cbrBytes = IMIN( (st->bitrate_bps + 4*frame_rate)/(8*frame_rate) , max_data_bytes);
|
||||||
|
st->bitrate_bps = cbrBytes * (8*frame_rate);
|
||||||
|
max_data_bytes = cbrBytes;
|
||||||
|
}
|
||||||
|
|
||||||
/* Equivalent 20-ms rate for mode/channel/bandwidth decisions */
|
/* Equivalent 20-ms rate for mode/channel/bandwidth decisions */
|
||||||
equiv_rate = st->bitrate_bps - 60*(st->Fs/frame_size - 50);
|
equiv_rate = st->bitrate_bps - 60*(st->Fs/frame_size - 50);
|
||||||
|
|
||||||
|
@ -614,6 +661,21 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
|
||||||
if (st->user_bandwidth != OPUS_AUTO)
|
if (st->user_bandwidth != OPUS_AUTO)
|
||||||
st->bandwidth = st->user_bandwidth;
|
st->bandwidth = st->user_bandwidth;
|
||||||
|
|
||||||
|
/* This enforces safe rates for CBR SILK */
|
||||||
|
if (!st->use_vbr && st->mode != MODE_CELT_ONLY)
|
||||||
|
{
|
||||||
|
int frame_rate;
|
||||||
|
opus_int32 max_rate;
|
||||||
|
frame_rate = st->Fs/frame_size;
|
||||||
|
max_rate = frame_rate*max_data_bytes;
|
||||||
|
if (max_rate < 15000)
|
||||||
|
st->bandwidth = IMIN(st->bandwidth, OPUS_BANDWIDTH_WIDEBAND);
|
||||||
|
if (max_rate < 12000)
|
||||||
|
st->bandwidth = IMIN(st->bandwidth, OPUS_BANDWIDTH_MEDIUMBAND);
|
||||||
|
if (max_rate < 9000)
|
||||||
|
st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
|
||||||
|
}
|
||||||
|
|
||||||
/* Prevents Opus from wasting bits on frequencies that are above
|
/* Prevents Opus from wasting bits on frequencies that are above
|
||||||
the Nyquist rate of the input signal */
|
the Nyquist rate of the input signal */
|
||||||
if (st->Fs <= 24000 && st->bandwidth > OPUS_BANDWIDTH_SUPERWIDEBAND)
|
if (st->Fs <= 24000 && st->bandwidth > OPUS_BANDWIDTH_SUPERWIDEBAND)
|
||||||
|
@ -625,6 +687,9 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
|
||||||
if (st->Fs <= 8000 && st->bandwidth > OPUS_BANDWIDTH_NARROWBAND)
|
if (st->Fs <= 8000 && st->bandwidth > OPUS_BANDWIDTH_NARROWBAND)
|
||||||
st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
|
st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
|
||||||
|
|
||||||
|
/* If max_data_bytes represents less than 8 kb/s, switch to CELT-only mode */
|
||||||
|
if (max_data_bytes < 8000*frame_size / (st->Fs * 8))
|
||||||
|
st->mode = MODE_CELT_ONLY;
|
||||||
|
|
||||||
/* Can't support higher than wideband for >20 ms frames */
|
/* Can't support higher than wideband for >20 ms frames */
|
||||||
if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
|
if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
|
||||||
|
@ -688,9 +753,6 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
|
||||||
if (st->mode == MODE_HYBRID && st->bandwidth <= OPUS_BANDWIDTH_WIDEBAND)
|
if (st->mode == MODE_HYBRID && st->bandwidth <= OPUS_BANDWIDTH_WIDEBAND)
|
||||||
st->mode = MODE_SILK_ONLY;
|
st->mode = MODE_SILK_ONLY;
|
||||||
|
|
||||||
/* If max_data_bytes represents less than 8 kb/s, switch to CELT-only mode */
|
|
||||||
if (max_data_bytes < 8000*frame_size / (st->Fs * 8))
|
|
||||||
st->mode = MODE_CELT_ONLY;
|
|
||||||
/* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, st->bandwidth); */
|
/* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, st->bandwidth); */
|
||||||
bytes_target = IMIN(max_data_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1;
|
bytes_target = IMIN(max_data_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1;
|
||||||
|
|
||||||
|
@ -756,9 +818,6 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
|
||||||
st->silk_mode.bitRate = ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5;
|
st->silk_mode.bitRate = ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* SILK is not allow to use more than 50% of max_data_bytes */
|
|
||||||
if (max_data_bytes < st->silk_mode.bitRate*frame_size / (st->Fs * 4))
|
|
||||||
st->silk_mode.bitRate = max_data_bytes*st->Fs*4/frame_size;
|
|
||||||
|
|
||||||
st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
|
st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
|
||||||
st->silk_mode.nChannelsAPI = st->channels;
|
st->silk_mode.nChannelsAPI = st->channels;
|
||||||
|
@ -779,8 +838,24 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
|
||||||
}
|
}
|
||||||
st->silk_mode.maxInternalSampleRate = 16000;
|
st->silk_mode.maxInternalSampleRate = 16000;
|
||||||
|
|
||||||
|
st->silk_mode.useCBR = !st->use_vbr;
|
||||||
|
|
||||||
/* Call SILK encoder for the low band */
|
/* Call SILK encoder for the low band */
|
||||||
nBytes = IMIN(1275, max_data_bytes-1);
|
nBytes = IMIN(1275, max_data_bytes-1);
|
||||||
|
|
||||||
|
st->silk_mode.maxBits = nBytes*8;
|
||||||
|
/* Only allow up to 90% of the bits for hybrid mode*/
|
||||||
|
if (st->mode == MODE_HYBRID)
|
||||||
|
st->silk_mode.maxBits = (opus_int32)st->silk_mode.maxBits*9/10;
|
||||||
|
if (st->silk_mode.useCBR)
|
||||||
|
{
|
||||||
|
st->silk_mode.maxBits = (st->silk_mode.bitRate * frame_size / (st->Fs * 8))*8;
|
||||||
|
/* Reduce the initial target to make it easier to reach the CBR rate */
|
||||||
|
st->silk_mode.bitRate = 1;
|
||||||
|
}
|
||||||
|
if (redundancy)
|
||||||
|
st->silk_mode.maxBits -= st->silk_mode.maxBits/(1 + frame_size/(st->Fs/200));
|
||||||
|
|
||||||
if (prefill)
|
if (prefill)
|
||||||
{
|
{
|
||||||
int zero=0;
|
int zero=0;
|
||||||
|
@ -1029,6 +1104,12 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
|
||||||
st->prev_framesize = frame_size;
|
st->prev_framesize = frame_size;
|
||||||
|
|
||||||
st->first = 0;
|
st->first = 0;
|
||||||
|
if (!redundancy && st->mode==MODE_SILK_ONLY && !st->use_vbr && ret >= 2)
|
||||||
|
{
|
||||||
|
nb_compr_bytes = st->bitrate_bps * frame_size / (st->Fs * 8);
|
||||||
|
pad_frame(data, ret+1, nb_compr_bytes);
|
||||||
|
return nb_compr_bytes;
|
||||||
|
}
|
||||||
RESTORE_STACK;
|
RESTORE_STACK;
|
||||||
return ret+1+redundancy_bytes;
|
return ret+1+redundancy_bytes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ int main(int argc, char *argv[])
|
||||||
int stop=0;
|
int stop=0;
|
||||||
short *in, *out;
|
short *in, *out;
|
||||||
int application=OPUS_APPLICATION_AUDIO;
|
int application=OPUS_APPLICATION_AUDIO;
|
||||||
double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
|
double bits=0.0, bits_max=0.0, bits_act=0.0, bits2=0.0, nrg;
|
||||||
int bandwidth=-1;
|
int bandwidth=-1;
|
||||||
const char *bandwidth_string;
|
const char *bandwidth_string;
|
||||||
int lost = 0, lost_prev = 1;
|
int lost = 0, lost_prev = 1;
|
||||||
|
@ -446,6 +446,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
/* count bits */
|
/* count bits */
|
||||||
bits += len[toggle]*8;
|
bits += len[toggle]*8;
|
||||||
|
bits_max = ( len[toggle]*8 > bits_max ) ? len[toggle]*8 : bits_max;
|
||||||
if( count >= use_inbandfec ) {
|
if( count >= use_inbandfec ) {
|
||||||
nrg = 0.0;
|
nrg = 0.0;
|
||||||
if (!decode_only)
|
if (!decode_only)
|
||||||
|
@ -465,6 +466,7 @@ int main(int argc, char *argv[])
|
||||||
toggle = (toggle + use_inbandfec) & 1;
|
toggle = (toggle + use_inbandfec) & 1;
|
||||||
}
|
}
|
||||||
fprintf (stderr, "average bitrate: %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
|
fprintf (stderr, "average bitrate: %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
|
||||||
|
fprintf (stderr, "maximum bitrate: %7.3f bkp/s\n", 1e-3*bits_max*sampling_rate/frame_size);
|
||||||
if (!decode_only)
|
if (!decode_only)
|
||||||
fprintf (stderr, "active bitrate: %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
|
fprintf (stderr, "active bitrate: %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
|
||||||
fprintf (stderr, "bitrate standard deviation: %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
|
fprintf (stderr, "bitrate standard deviation: %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue