diff --git a/libcelt/celt.c b/libcelt/celt.c index dfa72e14ebd2b610a7c40c8697d217be9e8650f4..5131d3d3e96a48084f2c2a7fffd000d6bc6c84fe 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -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; diff --git a/libcelt/celt.h b/libcelt/celt.h index 7a3064dd65256291f7b143f19e4375ecd074fe1f..21ac728c1a938052d2fcdad6cf205fb44f7228de 100644 --- a/libcelt/celt.h +++ b/libcelt/celt.h @@ -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. diff --git a/src/opus_decoder.c b/src/opus_decoder.c index dea50e29900de1ff29e1ed624db0f1896218bb7d..55b8eea265811c0cfed1d2a8825a7fcaac44d7d5 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -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; diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 0d4d78bf10664ff0a7b58465596559fc329520e7..e457a047e7f60b384caeae1b490c07e1d802fa15 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -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;