Adds in-band signalling of the CELT frame size and bandwidth
authorJean-Marc Valin <jean-marc.valin@octasic.com>
Fri, 11 Mar 2011 21:31:24 +0000 (16:31 -0500)
committerJean-Marc Valin <jean-marc.valin@octasic.com>
Fri, 11 Mar 2011 21:38:49 +0000 (16:38 -0500)
libcelt/celt.c
libcelt/celt.h
libcelt/kiss_fft.c
libcelt/testcelt.c

index 545fd48..fba7113 100644 (file)
@@ -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:
       {
index eaa2622..008e525 100644 (file)
@@ -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 */
index adc617a..4909231 100644 (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)
 {
-   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 */
index 96b0a0d..72b70ba 100644 (file)
@@ -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);