From e6acfe07cbf7193305f1a9eef43f44f1ee207235 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Fri, 11 Mar 2011 16:31:24 -0500 Subject: Adds in-band signalling of the CELT frame size and bandwidth --- libcelt/celt.c | 86 ++++++++++++++++++++++++++++++++++++++++++------------ libcelt/celt.h | 3 ++ libcelt/kiss_fft.c | 11 ++++--- libcelt/testcelt.c | 17 ++++++----- 4 files changed, 86 insertions(+), 31 deletions(-) diff --git a/libcelt/celt.c b/libcelt/celt.c index 545fd48..fba7113 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -108,6 +108,7 @@ struct CELTEncoder { celt_int32 bitrate; int vbr; + int signalling; int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ /* Everything beyond this point gets cleared on a reset */ @@ -226,6 +227,8 @@ CELTEncoder *celt_encoder_init_custom(CELTEncoder *st, const CELTMode *mode, int st->upsample = 1; st->start = 0; st->end = st->mode->effEBands; + st->signalling = 1; + st->constrained_vbr = 1; st->clip = 1; @@ -921,8 +924,6 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i if (nbCompressedBytes<2 || pcm==NULL) return CELT_BAD_ARG; - /* Can't produce more than 1275 output bytes */ - nbCompressedBytes = IMIN(nbCompressedBytes,1275); frame_size *= st->upsample; for (LM=0;LM<=st->mode->maxLM;LM++) if (st->mode->shortMdctSize<>3; } + + if (st->signalling && enc==NULL) + { + int tmp = (st->mode->effEBands-st->end)>>1; + st->end = IMAX(1, st->mode->effEBands-tmp); + compressed[0] = tmp<<5; + compressed[0] |= LM<<3; + compressed[0] |= (C==2)<<2; + compressed++; + nbCompressedBytes--; + } + + /* Can't produce more than 1275 output bytes */ + nbCompressedBytes = IMIN(nbCompressedBytes,1275); nbAvailableBytes = nbCompressedBytes - nbFilledBytes; if (st->vbr) { celt_int32 den=st->mode->Fs>>BITRES; vbr_rate=(st->bitrate*frame_size+(den>>1))/den; + if (st->signalling) + vbr_rate -= 8<>(3+BITRES); } else { celt_int32 tmp; @@ -961,7 +978,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i if (tell>1) tmp += tell; nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes, - (tmp+4*st->mode->Fs)/(8*st->mode->Fs))); + (tmp+4*st->mode->Fs)/(8*st->mode->Fs)-!!st->signalling)); effectiveBytes = nbCompressedBytes; } @@ -1604,6 +1621,9 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i it's already filled with zeros */ ec_enc_done(enc); + if (st->signalling) + nbCompressedBytes++; + RESTORE_STACK; if (ec_get_error(enc)) return CELT_CORRUPTED_DATA; @@ -1759,6 +1779,11 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...) st->stream_channels = value; } break; + case CELT_SET_SIGNALLING_REQUEST: + { + celt_int32 value = va_arg(ap, celt_int32); + st->signalling = value; + } case CELT_RESET_STATE: { CELT_MEMSET((char*)&st->ENCODER_RESET_START, 0, @@ -1807,6 +1832,7 @@ struct CELTDecoder { int downsample; int start, end; + int signalling; /* Everything beyond this point gets cleared on a reset */ #define DECODER_RESET_START rng @@ -1907,6 +1933,7 @@ CELTDecoder *celt_decoder_init_custom(CELTDecoder *st, const CELTMode *mode, int st->downsample = 1; st->start = 0; st->end = st->mode->effEBands; + st->signalling = 1; st->loss_count = 0; @@ -2204,20 +2231,11 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da int anti_collapse_rsv; int anti_collapse_on=0; int silence; - const int C = CHANNELS(st->stream_channels); + int C = CHANNELS(st->stream_channels); ALLOC_STACK; SAVE_STACK; - if (len<0 || len>1275 || pcm==NULL) - return CELT_BAD_ARG; - frame_size *= st->downsample; - for (LM=0;LM<=st->mode->maxLM;LM++) - if (st->mode->shortMdctSize<st->mode->maxLM) - return CELT_BAD_ARG; - M=1<_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap); @@ -2230,6 +2248,31 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da oldLogE2 = oldLogE + CC*st->mode->nbEBands; backgroundLogE = oldLogE2 + CC*st->mode->nbEBands; + if (st->signalling && data!=NULL) + { + st->end = IMAX(1, st->mode->effEBands-2*(data[0]>>5)); + LM = (data[0]>>3)&0x3; + C = 1 + ((data[0]>>2)&0x1); + data++; + len--; + if (LM>st->mode->maxLM) + return CELT_CORRUPTED_DATA; + if (frame_size < st->mode->shortMdctSize<mode->shortMdctSize<mode->maxLM;LM++) + if (st->mode->shortMdctSize<st->mode->maxLM) + return CELT_BAD_ARG; + } + M=1<1275 || pcm==NULL) + return CELT_BAD_ARG; + N = M*st->mode->shortMdctSize; effEnd = st->end; @@ -2258,7 +2301,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da RESTORE_STACK; return CELT_BAD_ARG; } - + if (dec == NULL) { ec_dec_init(&_dec,(unsigned char*)data,len); @@ -2510,7 +2553,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da if (ec_tell(dec) > 8*len || ec_get_error(dec)) return CELT_CORRUPTED_DATA; else - return CELT_OK; + return frame_size/st->downsample; } #ifdef FIXED_POINT @@ -2531,8 +2574,8 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da ALLOC(out, C*N, celt_int16); ret=celt_decode_with_ec(st, data, len, out, frame_size, dec); - if (ret==0) - for (j=0;j0) + for (j=0;j0) + for (j=0;jstream_channels = value; } + case CELT_SET_SIGNALLING_REQUEST: + { + celt_int32 value = va_arg(ap, celt_int32); + st->signalling = value; + } break; case CELT_RESET_STATE: { diff --git a/libcelt/celt.h b/libcelt/celt.h index eaa2622..008e525 100644 --- a/libcelt/celt.h +++ b/libcelt/celt.h @@ -113,6 +113,9 @@ extern "C" { #define CELT_SET_CHANNELS_REQUEST 10002 #define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, _celt_check_int(x) +#define CELT_SET_SIGNALLING_REQUEST 10003 +#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, _celt_check_int(x) + /** GET the lookahead used in the current mode */ #define CELT_GET_LOOKAHEAD 1001 /** GET the sample rate used in the current mode */ diff --git a/libcelt/kiss_fft.c b/libcelt/kiss_fft.c index adc617a..4909231 100644 --- a/libcelt/kiss_fft.c +++ b/libcelt/kiss_fft.c @@ -644,10 +644,13 @@ kiss_fft_state *kiss_fft_alloc(int nfft,void * mem,size_t * lenmem ) void kiss_fft_free(const kiss_fft_state *cfg) { - celt_free((celt_int16*)cfg->bitrev); - if (cfg->shift < 0) - celt_free((kiss_twiddle_cpx*)cfg->twiddles); - celt_free((kiss_fft_state*)cfg); + if (cfg) + { + celt_free((celt_int16*)cfg->bitrev); + if (cfg->shift < 0) + celt_free((kiss_twiddle_cpx*)cfg->twiddles); + celt_free((kiss_fft_state*)cfg); + } } #endif /* CUSTOM_MODES */ diff --git a/libcelt/testcelt.c b/libcelt/testcelt.c index 96b0a0d..72b70ba 100644 --- a/libcelt/testcelt.c +++ b/libcelt/testcelt.c @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) unsigned char data[MAX_PACKET]; int rate; int complexity; -#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) +#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) int i; double rmsd = 0; #endif @@ -126,6 +126,7 @@ int main(int argc, char *argv[]) while (!feof(fin)) { + int ret; err = fread(in, sizeof(short), frame_size*channels, fin); if (feof(fin)) break; @@ -160,24 +161,24 @@ int main(int argc, char *argv[]) /* This is to simulate packet loss */ if (argc==9 && rand()%1000