Adds a generic CELT_SET_BITRATE() ctl() API for CBR and VBR
authorJean-Marc Valin <jean-marc.valin@octasic.com>
Tue, 1 Feb 2011 22:04:27 +0000 (17:04 -0500)
committerJean-Marc Valin <jean-marc.valin@octasic.com>
Tue, 1 Feb 2011 22:04:27 +0000 (17:04 -0500)
libcelt/celt.c
libcelt/celt.h
tools/celtenc.c

index c170c48..eb3cf3f 100644 (file)
@@ -103,7 +103,8 @@ struct CELTEncoder {
    int upsample;
    int start, end;
 
-   celt_int32 vbr_rate_norm; /* Target number of 8th bits per frame */
+   celt_int32 bitrate;
+   int vbr;
    int constrained_vbr;      /* If zero, VBR can do whatever it likes with the rate */
 
    /* Everything beyond this point gets cleared on a reset */
@@ -224,7 +225,8 @@ CELTEncoder *celt_encoder_init_custom(CELTEncoder *st, const CELTMode *mode, int
    st->end = st->mode->effEBands;
    st->constrained_vbr = 1;
 
-   st->vbr_rate_norm = 0;
+   st->bitrate = 255000*channels;
+   st->vbr = 0;
    st->vbr_offset = 0;
    st->force_intra  = 0;
    st->delayedIntra = 1;
@@ -909,6 +911,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
    if (LM>=MAX_CONFIG_SIZES)
       return CELT_BAD_ARG;
    M=1<<LM;
+   N = M*st->mode->shortMdctSize;
 
    prefilter_mem = st->in_mem+CC*(st->overlap);
    _overlap_mem = prefilter_mem+CC*COMBFILTER_MAXPERIOD;
@@ -919,9 +922,6 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
 
    if (enc==NULL)
    {
-      ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
-      ec_enc_init(&_enc,&buf);
-      enc = &_enc;
       tell=1;
       nbFilledBytes=0;
    } else {
@@ -930,10 +930,30 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
    }
    nbAvailableBytes = nbCompressedBytes - nbFilledBytes;
 
-   vbr_rate = st->vbr_rate_norm<<LM;
+   if (st->vbr)
+   {
+      vbr_rate = ((2*st->bitrate*frame_size<<BITRES)+st->mode->Fs)/(2*st->mode->Fs);
+      effectiveBytes = vbr_rate>>3;
+   } else {
+      celt_int32 tmp;
+      vbr_rate = 0;
+      tmp = st->bitrate*frame_size;
+      if (tell>1)
+         tmp += tell;
+      nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes,
+            (tmp+4*st->mode->Fs)/(8*st->mode->Fs)));
+      effectiveBytes = nbCompressedBytes;
+   }
+
+   if (enc==NULL)
+   {
+      ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
+      ec_enc_init(&_enc,&buf);
+      enc = &_enc;
+   }
+
    if (vbr_rate>0)
    {
-      effectiveBytes = st->vbr_rate_norm>>BITRES<<LM>>3;
       /* Computes the max bit-rate allowed in VBR mode to avoid violating the
           target rate and buffering.
          We must do this up front so that bust-prevention logic triggers
@@ -954,18 +974,16 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
          {
             nbCompressedBytes = nbFilledBytes+max_allowed;
             nbAvailableBytes = max_allowed;
-            ec_byte_shrink(&buf, nbCompressedBytes);
+            ec_byte_shrink(enc->buf, nbCompressedBytes);
          }
       }
-   } else
-      effectiveBytes = nbCompressedBytes;
+   }
    total_bits = nbCompressedBytes*8;
 
    effEnd = st->end;
    if (effEnd > st->mode->effEBands)
       effEnd = st->mode->effEBands;
 
-   N = M*st->mode->shortMdctSize;
    ALLOC(in, CC*(N+st->overlap), celt_sig);
 
    /* Find pitch period and gain */
@@ -1021,7 +1039,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
             effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2);
             total_bits=nbCompressedBytes*8;
             nbAvailableBytes=2;
-            ec_byte_shrink(&buf, nbCompressedBytes);
+            ec_byte_shrink(enc->buf, nbCompressedBytes);
          }
          /* Pretend we've filled all the remaining bits with zeros
             (that's what the initialiser did anyway) */
@@ -1357,7 +1375,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
      }
      nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
      /* This moves the raw bits to take into account the new compressed size */
-     ec_byte_shrink(&buf, nbCompressedBytes);
+     ec_byte_shrink(enc->buf, nbCompressedBytes);
    }
    if (C==2)
    {
@@ -1688,17 +1706,18 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
          st->constrained_vbr = value;
       }
       break;
-      case CELT_SET_VBR_RATE_REQUEST:
+      case CELT_SET_VBR_REQUEST:
+      {
+         celt_int32 value = va_arg(ap, celt_int32);
+         st->vbr = value;
+      }
+      break;
+      case CELT_SET_BITRATE_REQUEST:
       {
          celt_int32 value = va_arg(ap, celt_int32);
-         int frame_rate;
-         int N = st->mode->shortMdctSize;
-         if (value<0)
+         if (value<=500)
             goto bad_arg;
-         if (value>3072000)
-            value = 3072000;
-         frame_rate = ((st->mode->Fs<<3)+(N>>1))/N;
-         st->vbr_rate_norm = value>0?IMAX(1,((value<<(BITRES+3))+(frame_rate>>1))/frame_rate):0;
+         st->bitrate = value;
       }
       break;
       case CELT_SET_CHANNELS_REQUEST:
index e83b9f5..d99b0ab 100644 (file)
@@ -78,9 +78,11 @@ extern "C" {
 #define CELT_GET_MODE_REQUEST    1
 /** Get the CELTMode used by an encoder or decoder */
 #define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, _celt_check_mode_ptr_ptr(x)
+
 #define CELT_SET_COMPLEXITY_REQUEST    2
 /** Controls the complexity from 0-10 (int) */
 #define CELT_SET_COMPLEXITY(x) CELT_SET_COMPLEXITY_REQUEST, _celt_check_int(x)
+
 #define CELT_SET_PREDICTION_REQUEST    4
 /** Controls the use of interframe prediction.
     0=Independent frames
@@ -88,9 +90,11 @@ extern "C" {
     2=Long term prediction allowed
  */
 #define CELT_SET_PREDICTION(x) CELT_SET_PREDICTION_REQUEST, _celt_check_int(x)
-#define CELT_SET_VBR_RATE_REQUEST    6
+
+#define CELT_SET_BITRATE_REQUEST    6
 /** Set the target VBR rate in bits per second(int); 0=CBR (default) */
-#define CELT_SET_VBR_RATE(x) CELT_SET_VBR_RATE_REQUEST, _celt_check_int(x)
+#define CELT_SET_BITRATE(x) CELT_SET_BITRATE_REQUEST, _celt_check_int(x)
+
 /** Reset the encoder/decoder memories to zero*/
 #define CELT_RESET_STATE_REQUEST        8
 #define CELT_RESET_STATE       CELT_RESET_STATE_REQUEST
@@ -98,6 +102,9 @@ extern "C" {
 #define CELT_SET_VBR_CONSTRAINT_REQUEST 10
 #define CELT_SET_VBR_CONSTRAINT(x)       CELT_SET_VBR_CONSTRAINT_REQUEST, _celt_check_int(x)
 
+#define CELT_SET_VBR_REQUEST 12
+#define CELT_SET_VBR(x)       CELT_SET_VBR_REQUEST, _celt_check_int(x)
+
 #define CELT_SET_START_BAND_REQUEST    10000
 #define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, _celt_check_int(x)
 
index 5a8be45..c07ed74 100644 (file)
@@ -482,20 +482,7 @@ int main(int argc, char **argv)
      else
        bitrate=128.0;
      
-   bytes_per_packet = (bitrate*1000*frame_size/rate+4)/8;
-   
-   if (bytes_per_packet > MAX_FRAME_BYTES) {
-      bytes_per_packet=MAX_FRAME_BYTES;
-      fprintf (stderr, "Warning: Requested bitrate (%0.3fkbit/sec) is too high. Setting CELT to %d bytes/frame.\n",bitrate,MAX_FRAME_BYTES);      
-   }
-
-   if (with_cbr)
-   {
-     bitrate = ((rate/(float)frame_size)*8*bytes_per_packet)/1000.0;
-   } else {
-     /*In VBR mode the bytes_per_packet argument becomes a hard maximum. 3x the average rate is just a random choice.*/
-     bytes_per_packet=IMIN(bytes_per_packet*3,MAX_FRAME_BYTES);
-   }
+   bytes_per_packet = MAX_FRAME_BYTES;
    
    mode = celt_mode_create(rate, frame_size, NULL);
    if (!mode)
@@ -527,10 +514,17 @@ int main(int argc, char **argv)
    /*Initialize CELT encoder*/
    st = celt_encoder_create_custom(mode, chan, NULL);
 
+   {
+      int tmp = (bitrate*1000);
+      if (celt_encoder_ctl(st, CELT_SET_BITRATE(tmp)) != CELT_OK)
+      {
+         fprintf (stderr, "bitrate request failed\n");
+         return 1;
+      }
+   }
    if (!with_cbr)
    {
-     int tmp = (bitrate*1000);
-     if (celt_encoder_ctl(st, CELT_SET_VBR_RATE(tmp)) != CELT_OK)
+     if (celt_encoder_ctl(st, CELT_SET_VBR(1)) != CELT_OK)
      {
         fprintf (stderr, "VBR request failed\n");
         return 1;