Implementing decoder-side support for redundant mode switching (bemasc's idea)
authorJean-Marc Valin <jean-marc.valin@octasic.com>
Wed, 2 Mar 2011 22:54:43 +0000 (17:54 -0500)
committerJean-Marc Valin <jean-marc.valin@octasic.com>
Wed, 2 Mar 2011 22:54:43 +0000 (17:54 -0500)
src/opus_decoder.c
src/opus_decoder.h
src/opus_encoder.c

index 41671eb..1ebc3ea 100644 (file)
@@ -83,6 +83,8 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
     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 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
                && !(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,13 +188,21 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
             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)
     {
@@ -242,6 +253,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
 #endif
 
     st->prev_mode = mode;
+    st->prev_redundancy = redundancy;
        return celt_ret<0 ? celt_ret : audiosize;
 
 }
index 1b0569c..037c87b 100644 (file)
@@ -41,6 +41,7 @@ struct OpusDecoder {
     /* Sampling rate (at the API level) */
     int          Fs;
     int          prev_mode;
+    int          prev_redundancy;
 
 #ifdef OPUS_TEST_RANGE_CODER_STATE
     int          rangeFinal;
index 2334aa2..2c2e589 100644 (file)
@@ -95,6 +95,8 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
     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 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
         } 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;