Including redundant frames in the final range coder state
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Fri, 19 Aug 2011 20:11:41 +0000 (16:11 -0400)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Fri, 19 Aug 2011 20:21:42 +0000 (16:21 -0400)
libcelt/celt.c
libcelt/celt.h
src/opus_decoder.c
src/opus_encoder.c

index dfa72e1..5131d3d 100644 (file)
@@ -1838,6 +1838,14 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
          *value=st->mode;
       }
       break;
+      case CELT_GET_RANGE_REQUEST:
+      {
+         opus_uint32 * value = va_arg(ap, opus_uint32 *);
+         if (value==0)
+            goto bad_arg;
+         *value=st->rng;
+      }
+      break;
 #endif
       default:
          goto bad_request;
@@ -2741,6 +2749,14 @@ int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
          st->signalling = value;
       }
       break;
+      case CELT_GET_RANGE_REQUEST:
+      {
+         opus_uint32 * value = va_arg(ap, opus_uint32 *);
+         if (value==0)
+            goto bad_arg;
+         *value=st->rng;
+      }
+      break;
 #endif
       default:
          goto bad_request;
index 7a3064d..21ac728 100644 (file)
@@ -51,7 +51,8 @@ extern "C" {
 
 #define _celt_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
 #define _celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
-#define _celt_check_int_ptr(ptr) ((ptr) + ((ptr) - (int*)(ptr)))
+#define _celt_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
+#define _celt_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
 
 /* Error codes */
 /** No error */
@@ -121,6 +122,9 @@ extern "C" {
 #define CELT_SET_END_BAND_REQUEST    10001
 #define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, _celt_check_int(x)
 
+#define CELT_GET_RANGE_REQUEST    10002
+#define CELT_GET_RANGE(x) CELT_GET_RANGE_REQUEST, _celt_check_uint_ptr(x)
+
 /** Contains the state of an encoder. One encoder state is needed
     for each stream. It is initialised once at the beginning of the
     stream. Do *not* re-initialise the state for every frame.
index dea50e2..55b8eea 100644 (file)
@@ -196,6 +196,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     int c;
     int F2_5, F5, F10, F20;
     const opus_val16 *window;
+    opus_uint32 redundant_rng = 0;
     ALLOC_STACK;
 
     silk_dec = (char*)st+st->silk_dec_offset;
@@ -373,6 +374,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     {
         celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
         celt_decode_native(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
+        celt_decoder_ctl(celt_dec, CELT_GET_RANGE(&redundant_rng));
         celt_decoder_ctl(celt_dec, CELT_RESET_STATE);
     }
 
@@ -416,6 +418,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
         celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
 
         celt_decode_native(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
+        celt_decoder_ctl(celt_dec, CELT_GET_RANGE(&redundant_rng));
         smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
                        pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
     }
@@ -439,7 +442,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
                    st->channels, window, st->Fs);
     }
 
-    st->rangeFinal = dec.rng;
+    st->rangeFinal = dec.rng ^ redundant_rng;
 
     st->prev_mode = mode;
     st->prev_redundancy = redundancy;
index 0d4d78b..e457a04 100644 (file)
@@ -258,6 +258,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
     int nb_compr_bytes;
     int to_celt = 0;
     opus_int32 mono_rate;
+    opus_uint32 redundant_rng = 0;
     ALLOC_STACK;
 
     if (400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs &&
@@ -685,6 +686,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
         celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
         celt_encoder_ctl(celt_enc, CELT_SET_VBR(0));
         celt_encode_native(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes);
+        celt_encoder_ctl(celt_enc, CELT_GET_RANGE(&redundant_rng));
         celt_encoder_ctl(celt_enc, CELT_RESET_STATE);
     }
 
@@ -710,6 +712,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
         celt_encode_native(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, data+nb_compr_bytes, redundancy_bytes);
 
         celt_encode_native(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes);
+        celt_encoder_ctl(celt_enc, CELT_GET_RANGE(&redundant_rng));
     }
 
 
@@ -729,7 +732,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
     data--;
     data[0] = gen_toc(st->mode, st->Fs/frame_size, st->bandwidth, st->stream_channels);
 
-    st->rangeFinal = enc.rng;
+    st->rangeFinal = enc.rng ^ redundant_rng;
 
     if (to_celt)
         st->prev_mode = MODE_CELT_ONLY;