shithub: opus

Download patch

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;