ref: e2a09db92b5e9de9375100fe639d032b1edced54
parent: 60d59c872fd0c9f8c265ff5643a97a7c9ec48455
author: Jean-Marc Valin <[email protected]>
date: Wed Mar 2 12:54:43 EST 2011
Implementing decoder-side support for redundant mode switching (bemasc's idea)
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -83,6 +83,8 @@
int audiosize;
int mode;
int transition=0;
+ int start_band;
+ int redundancy;
/* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
if (len<=2)
@@ -130,7 +132,8 @@
&& !(mode == MODE_HYBRID && st->prev_mode == MODE_SILK_ONLY))
{
transition = 1;
- opus_decode(st, NULL, 0, pcm_transition, IMAX(480, audiosize), 0);
+ if (mode == MODE_CELT_ONLY && !st->prev_redundancy)
+ opus_decode(st, NULL, 0, pcm_transition, IMAX(480, audiosize), 0);
}
if (audiosize > frame_size)
{
@@ -185,14 +188,22 @@
pcm[i] = 0;
}
+ start_band = 0;
if (mode == MODE_HYBRID)
{
- /* This should be adjusted based on the SILK bandwidth */
- celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(17));
- } else {
- celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(0));
+ /* Check if we have a redundant 0-8 kHz band */
+ redundancy = ec_dec_bit_logp(&dec, 12);
+ if (!redundancy)
+ 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)
{
int endband;
@@ -242,6 +253,7 @@
#endif
st->prev_mode = mode;
+ st->prev_redundancy = redundancy;
return celt_ret<0 ? celt_ret : audiosize;
}
--- a/src/opus_decoder.h
+++ b/src/opus_decoder.h
@@ -41,6 +41,7 @@
/* Sampling rate (at the API level) */
int Fs;
int prev_mode;
+ int prev_redundancy;
#ifdef OPUS_TEST_RANGE_CODER_STATE
int rangeFinal;
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -95,6 +95,8 @@
int silk_internal_bandwidth;
int bytes_target;
int prefill=0;
+ int start_band;
+ int redundancy = 0;
bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1;
@@ -213,6 +215,17 @@
} else {
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)
{
int len;