Implementing decoder-side support for redundant mode switching (bemasc's idea)

This commit is contained in:
Jean-Marc Valin 2011-03-02 17:54:43 -05:00
parent 60d59c872f
commit e2a09db92b
3 changed files with 31 additions and 5 deletions

View file

@ -83,6 +83,8 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
int audiosize; int audiosize;
int mode; int mode;
int transition=0; int transition=0;
int start_band;
int redundancy;
/* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */ /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
if (len<=2) if (len<=2)
@ -130,6 +132,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
&& !(mode == MODE_HYBRID && st->prev_mode == MODE_SILK_ONLY)) && !(mode == MODE_HYBRID && st->prev_mode == MODE_SILK_ONLY))
{ {
transition = 1; transition = 1;
if (mode == MODE_CELT_ONLY && !st->prev_redundancy)
opus_decode(st, NULL, 0, pcm_transition, IMAX(480, audiosize), 0); opus_decode(st, NULL, 0, pcm_transition, IMAX(480, audiosize), 0);
} }
if (audiosize > frame_size) if (audiosize > frame_size)
@ -185,13 +188,21 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
pcm[i] = 0; pcm[i] = 0;
} }
start_band = 0;
if (mode == MODE_HYBRID) if (mode == MODE_HYBRID)
{ {
/* This should be adjusted based on the SILK bandwidth */ /* Check if we have a redundant 0-8 kHz band */
celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(17)); redundancy = ec_dec_bit_logp(&dec, 12);
} else { if (!redundancy)
celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(0)); start_band = 17;
} }
celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(start_band));
if (redundancy)
transition = 0;
if (transition && mode != MODE_CELT_ONLY)
opus_decode(st, NULL, 0, pcm_transition, IMAX(480, audiosize), 0);
if (mode != MODE_SILK_ONLY) if (mode != MODE_SILK_ONLY)
{ {
@ -242,6 +253,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
#endif #endif
st->prev_mode = mode; st->prev_mode = mode;
st->prev_redundancy = redundancy;
return celt_ret<0 ? celt_ret : audiosize; return celt_ret<0 ? celt_ret : audiosize;
} }

View file

@ -41,6 +41,7 @@ struct OpusDecoder {
/* Sampling rate (at the API level) */ /* Sampling rate (at the API level) */
int Fs; int Fs;
int prev_mode; int prev_mode;
int prev_redundancy;
#ifdef OPUS_TEST_RANGE_CODER_STATE #ifdef OPUS_TEST_RANGE_CODER_STATE
int rangeFinal; int rangeFinal;

View file

@ -95,6 +95,8 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
int silk_internal_bandwidth; int silk_internal_bandwidth;
int bytes_target; int bytes_target;
int prefill=0; int prefill=0;
int start_band;
int redundancy = 0;
bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1; bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1;
@ -213,6 +215,17 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
} else { } else {
celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(2)); celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(2));
} }
start_band = 0;
if (st->mode == MODE_HYBRID)
{
/* Check if we have a redundant 0-8 kHz band */
ec_enc_bit_logp(&enc, redundancy, 12);
if (!redundancy)
start_band = 17;
}
celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(start_band));
if (st->mode == MODE_HYBRID) if (st->mode == MODE_HYBRID)
{ {
int len; int len;