Adds in-band signalling of the CELT frame size and bandwidth

This commit is contained in:
Jean-Marc Valin 2011-03-11 16:31:24 -05:00
parent 86da2c8b19
commit e6acfe07cb
4 changed files with 86 additions and 31 deletions

View file

@ -108,6 +108,7 @@ struct CELTEncoder {
celt_int32 bitrate; celt_int32 bitrate;
int vbr; int vbr;
int signalling;
int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */
/* Everything beyond this point gets cleared on a reset */ /* 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->upsample = 1;
st->start = 0; st->start = 0;
st->end = st->mode->effEBands; st->end = st->mode->effEBands;
st->signalling = 1;
st->constrained_vbr = 1; st->constrained_vbr = 1;
st->clip = 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) if (nbCompressedBytes<2 || pcm==NULL)
return CELT_BAD_ARG; return CELT_BAD_ARG;
/* Can't produce more than 1275 output bytes */
nbCompressedBytes = IMIN(nbCompressedBytes,1275);
frame_size *= st->upsample; frame_size *= st->upsample;
for (LM=0;LM<=st->mode->maxLM;LM++) for (LM=0;LM<=st->mode->maxLM;LM++)
if (st->mode->shortMdctSize<<LM==frame_size) if (st->mode->shortMdctSize<<LM==frame_size)
@ -947,12 +948,28 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
tell=ec_tell(enc); tell=ec_tell(enc);
nbFilledBytes=(tell+4)>>3; nbFilledBytes=(tell+4)>>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; nbAvailableBytes = nbCompressedBytes - nbFilledBytes;
if (st->vbr) if (st->vbr)
{ {
celt_int32 den=st->mode->Fs>>BITRES; celt_int32 den=st->mode->Fs>>BITRES;
vbr_rate=(st->bitrate*frame_size+(den>>1))/den; vbr_rate=(st->bitrate*frame_size+(den>>1))/den;
if (st->signalling)
vbr_rate -= 8<<BITRES;
effectiveBytes = vbr_rate>>(3+BITRES); effectiveBytes = vbr_rate>>(3+BITRES);
} else { } else {
celt_int32 tmp; celt_int32 tmp;
@ -961,7 +978,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
if (tell>1) if (tell>1)
tmp += tell; tmp += tell;
nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes, 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; 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 */ it's already filled with zeros */
ec_enc_done(enc); ec_enc_done(enc);
if (st->signalling)
nbCompressedBytes++;
RESTORE_STACK; RESTORE_STACK;
if (ec_get_error(enc)) if (ec_get_error(enc))
return CELT_CORRUPTED_DATA; return CELT_CORRUPTED_DATA;
@ -1759,6 +1779,11 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
st->stream_channels = value; st->stream_channels = value;
} }
break; break;
case CELT_SET_SIGNALLING_REQUEST:
{
celt_int32 value = va_arg(ap, celt_int32);
st->signalling = value;
}
case CELT_RESET_STATE: case CELT_RESET_STATE:
{ {
CELT_MEMSET((char*)&st->ENCODER_RESET_START, 0, CELT_MEMSET((char*)&st->ENCODER_RESET_START, 0,
@ -1807,6 +1832,7 @@ struct CELTDecoder {
int downsample; int downsample;
int start, end; int start, end;
int signalling;
/* Everything beyond this point gets cleared on a reset */ /* Everything beyond this point gets cleared on a reset */
#define DECODER_RESET_START rng #define DECODER_RESET_START rng
@ -1907,6 +1933,7 @@ CELTDecoder *celt_decoder_init_custom(CELTDecoder *st, const CELTMode *mode, int
st->downsample = 1; st->downsample = 1;
st->start = 0; st->start = 0;
st->end = st->mode->effEBands; st->end = st->mode->effEBands;
st->signalling = 1;
st->loss_count = 0; 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_rsv;
int anti_collapse_on=0; int anti_collapse_on=0;
int silence; int silence;
const int C = CHANNELS(st->stream_channels); int C = CHANNELS(st->stream_channels);
ALLOC_STACK; ALLOC_STACK;
SAVE_STACK; SAVE_STACK;
if (len<0 || len>1275 || pcm==NULL)
return CELT_BAD_ARG;
frame_size *= st->downsample; frame_size *= st->downsample;
for (LM=0;LM<=st->mode->maxLM;LM++)
if (st->mode->shortMdctSize<<LM==frame_size)
break;
if (LM>st->mode->maxLM)
return CELT_BAD_ARG;
M=1<<LM;
c=0; do { c=0; do {
decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap); decode_mem[c] = st->_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; oldLogE2 = oldLogE + CC*st->mode->nbEBands;
backgroundLogE = oldLogE2 + 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<<LM)
return CELT_BAD_ARG;
else
frame_size = st->mode->shortMdctSize<<LM;
} else {
for (LM=0;LM<=st->mode->maxLM;LM++)
if (st->mode->shortMdctSize<<LM==frame_size)
break;
if (LM>st->mode->maxLM)
return CELT_BAD_ARG;
}
M=1<<LM;
if (len<0 || len>1275 || pcm==NULL)
return CELT_BAD_ARG;
N = M*st->mode->shortMdctSize; N = M*st->mode->shortMdctSize;
effEnd = st->end; effEnd = st->end;
@ -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)) if (ec_tell(dec) > 8*len || ec_get_error(dec))
return CELT_CORRUPTED_DATA; return CELT_CORRUPTED_DATA;
else else
return CELT_OK; return frame_size/st->downsample;
} }
#ifdef FIXED_POINT #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); ALLOC(out, C*N, celt_int16);
ret=celt_decode_with_ec(st, data, len, out, frame_size, dec); ret=celt_decode_with_ec(st, data, len, out, frame_size, dec);
if (ret==0) if (ret>0)
for (j=0;j<C*N;j++) for (j=0;j<C*ret;j++)
pcm[j]=out[j]*(1.f/32768.f); pcm[j]=out[j]*(1.f/32768.f);
RESTORE_STACK; RESTORE_STACK;
@ -2557,8 +2600,8 @@ int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, in
ret=celt_decode_with_ec_float(st, data, len, out, frame_size, dec); ret=celt_decode_with_ec_float(st, data, len, out, frame_size, dec);
if (ret==0) if (ret>0)
for (j=0;j<C*N;j++) for (j=0;j<C*ret;j++)
pcm[j] = FLOAT2INT16 (out[j]); pcm[j] = FLOAT2INT16 (out[j]);
RESTORE_STACK; RESTORE_STACK;
@ -2616,6 +2659,11 @@ int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
goto bad_arg; goto bad_arg;
st->stream_channels = value; st->stream_channels = value;
} }
case CELT_SET_SIGNALLING_REQUEST:
{
celt_int32 value = va_arg(ap, celt_int32);
st->signalling = value;
}
break; break;
case CELT_RESET_STATE: case CELT_RESET_STATE:
{ {

View file

@ -113,6 +113,9 @@ extern "C" {
#define CELT_SET_CHANNELS_REQUEST 10002 #define CELT_SET_CHANNELS_REQUEST 10002
#define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, _celt_check_int(x) #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 */ /** GET the lookahead used in the current mode */
#define CELT_GET_LOOKAHEAD 1001 #define CELT_GET_LOOKAHEAD 1001
/** GET the sample rate used in the current mode */ /** GET the sample rate used in the current mode */

View file

@ -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) void kiss_fft_free(const kiss_fft_state *cfg)
{ {
if (cfg)
{
celt_free((celt_int16*)cfg->bitrev); celt_free((celt_int16*)cfg->bitrev);
if (cfg->shift < 0) if (cfg->shift < 0)
celt_free((kiss_twiddle_cpx*)cfg->twiddles); celt_free((kiss_twiddle_cpx*)cfg->twiddles);
celt_free((kiss_fft_state*)cfg); celt_free((kiss_fft_state*)cfg);
}
} }
#endif /* CUSTOM_MODES */ #endif /* CUSTOM_MODES */

View file

@ -53,7 +53,7 @@ int main(int argc, char *argv[])
unsigned char data[MAX_PACKET]; unsigned char data[MAX_PACKET];
int rate; int rate;
int complexity; int complexity;
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) #if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
int i; int i;
double rmsd = 0; double rmsd = 0;
#endif #endif
@ -126,6 +126,7 @@ int main(int argc, char *argv[])
while (!feof(fin)) while (!feof(fin))
{ {
int ret;
err = fread(in, sizeof(short), frame_size*channels, fin); err = fread(in, sizeof(short), frame_size*channels, fin);
if (feof(fin)) if (feof(fin))
break; break;
@ -160,24 +161,24 @@ int main(int argc, char *argv[])
/* This is to simulate packet loss */ /* This is to simulate packet loss */
if (argc==9 && rand()%1000<atoi(argv[argc-3])) if (argc==9 && rand()%1000<atoi(argv[argc-3]))
/*if (errors && (errors%2==0))*/ /*if (errors && (errors%2==0))*/
err = celt_decode(dec, NULL, len, out, frame_size); ret = celt_decode(dec, NULL, len, out, frame_size);
else else
err = celt_decode(dec, data, len, out, frame_size); ret = celt_decode(dec, data, len, out, frame_size);
if (err != 0) if (ret < 0)
fprintf(stderr, "celt_decode() failed: %s\n", celt_strerror(err)); fprintf(stderr, "celt_decode() failed: %s\n", celt_strerror(ret));
#else #else
for (i=0;i<frame_size*channels;i++) for (i=0;i<ret*channels;i++)
out[i] = in[i]; out[i] = in[i];
#endif #endif
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) #if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
for (i=0;i<frame_size*channels;i++) for (i=0;i<ret*channels;i++)
{ {
rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]); rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
/*out[i] -= in[i];*/ /*out[i] -= in[i];*/
} }
#endif #endif
count++; count++;
fwrite(out+skip*channels, sizeof(short), (frame_size-skip)*channels, fout); fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
skip = 0; skip = 0;
} }
PRINT_MIPS(stderr); PRINT_MIPS(stderr);