Commit e6acfe07 authored by Jean-Marc Valin's avatar Jean-Marc Valin
Browse files

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

parent 86da2c8b
......@@ -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<<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);
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;
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<<BITRES;
effectiveBytes = vbr_rate>>(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<<LM==frame_size)
break;
if (LM>st->mode->maxLM)
return CELT_BAD_ARG;
M=1<<LM;
c=0; do {
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;
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;
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;j<C*N;j++)
if (ret>0)
for (j=0;j<C*ret;j++)
pcm[j]=out[j]*(1.f/32768.f);
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);
if (ret==0)
for (j=0;j<C*N;j++)
if (ret>0)
for (j=0;j<C*ret;j++)
pcm[j] = FLOAT2INT16 (out[j]);
RESTORE_STACK;
......@@ -2616,6 +2659,11 @@ int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
goto bad_arg;
st->stream_channels = value;
}
case CELT_SET_SIGNALLING_REQUEST:
{
celt_int32 value = va_arg(ap, celt_int32);
st->signalling = value;
}
break;
case CELT_RESET_STATE:
{
......
......@@ -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 */
......
......@@ -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 */
......
......@@ -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<atoi(argv[argc-3]))
/*if (errors && (errors%2==0))*/
err = celt_decode(dec, NULL, len, out, frame_size);
ret = celt_decode(dec, NULL, len, out, frame_size);
else
err = celt_decode(dec, data, len, out, frame_size);
if (err != 0)
fprintf(stderr, "celt_decode() failed: %s\n", celt_strerror(err));
ret = celt_decode(dec, data, len, out, frame_size);
if (ret < 0)
fprintf(stderr, "celt_decode() failed: %s\n", celt_strerror(ret));
#else
for (i=0;i<frame_size*channels;i++)
for (i=0;i<ret*channels;i++)
out[i] = in[i];
#endif
#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]);
/*out[i] -= in[i];*/
}
#endif
count++;
fwrite(out+skip*channels, sizeof(short), (frame_size-skip)*channels, fout);
fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
skip = 0;
}
PRINT_MIPS(stderr);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment