[CELT-dev] Updated MDCT callback patch

Thorvald Natvig thorvald at natvig.com
Thu Jun 4 13:41:13 PDT 2009


Here's an updated version of the MDCT callback patch.

-------------- next part --------------
From 2f58af665858906d70c3d5450be2b7ceb70d98ea Mon Sep 17 00:00:00 2001
From: Thorvald Natvig <slicer at users.sourceforge.net>
Date: Wed, 3 Jun 2009 16:48:30 +0200
Subject: [PATCH] Add callback for twiddling DCT data

---
 libcelt/celt.c |   33 +++++++++++++++++++++++++++++++++
 libcelt/celt.h |   45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/libcelt/celt.c b/libcelt/celt.c
index 72045d9..5a274b6 100644
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -93,6 +93,8 @@ struct CELTEncoder {
    celt_word16_t *psy_mem;
    struct PsyDecay psy;
 #endif
+   _celt_post_mdct_callback post_mdct_callback;
+   void *post_mdct_userdata;
 };
 
 CELTEncoder *celt_encoder_create(const CELTMode *mode)
@@ -132,6 +134,9 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode)
    psydecay_init(&st->psy, MAX_PERIOD/2, st->mode->Fs);
 #endif
 
+   st->post_mdct_callback = NULL;
+   st->post_mdct_userdata = NULL;
+
    return st;
 }
 
@@ -549,6 +554,24 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si
    ALLOC(bandE,st->mode->nbEBands*C, celt_ener_t);
    /* Compute MDCTs */
    compute_mdcts(st->mode, shortBlocks, in, freq);
+
+   if (st->post_mdct_callback) {
+#ifdef FIXED_POINT
+     const celt_int32_t format = CELT_DATAFORMAT_INT32;
+     const celt_int32_t shift = SIG_SHIFT;
+#else
+     const celt_int32_t format = CELT_DATAFORMAT_FLOAT;
+     const celt_int32_t shift = 0;
+#endif
+     if(st->post_mdct_callback(st, freq, format, shift, shortBlocks ? st->mode->nbShortMdcts : 1, st->post_mdct_userdata) == 0) {
+       if (st->pitch_available > 0) st->pitch_available = 1;
+       st->delayedIntra = 1;
+
+       RESTORE_STACK;
+       return CELT_POST_MDCT_CALLBACK_ABORT;
+     }
+   }
+
    if (shortBlocks && !transient_shift) 
    {
       celt_word32_t sum[4]={1,1,1,1};
@@ -980,6 +1003,16 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
          st->delayedIntra = 1;
       }
       break;
+      case CELT_SET_POST_MDCT_CALLBACK_REQUEST:
+      {
+          _celt_post_mdct_callback cb = va_arg(ap, _celt_post_mdct_callback);
+          void *data = va_arg(ap, void *);
+          if (cb == NULL)
+            data = NULL;
+          st->post_mdct_callback = cb;
+          st->post_mdct_userdata = data;
+      }
+      break;
       default:
          goto bad_request;
    }
diff --git a/libcelt/celt.h b/libcelt/celt.h
index 8ed67f3..70847ec 100644
--- a/libcelt/celt.h
+++ b/libcelt/celt.h
@@ -51,8 +51,11 @@ extern "C" {
 #define EXPORT
 #endif
 
+
 #define _celt_check_int(x) (((void)((x) == (celt_int32_t)0)), (celt_int32_t)(x))
 #define _celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (CELTMode**)(ptr)))
+#define _celt_check_post_mdct_callback(x) (((void)((_celt_post_mdct_callback)NULL == (x))), (_celt_post_mdct_callback)(x))
+#define _celt_check_voidptr(x) (((void)((void *)NULL == (x))), (void *)(x))
 
 /* Error codes */
 /** No error */
@@ -67,6 +70,8 @@ extern "C" {
 #define CELT_CORRUPTED_DATA   -4
 /** Invalid/unsupported request number */
 #define CELT_UNIMPLEMENTED    -5
+/** Encoding aborted by post-MDCT callback */
+#define CELT_POST_MDCT_CALLBACK_ABORT -6
 
 /* Requests */
 #define CELT_GET_MODE_REQUEST    1
@@ -97,6 +102,31 @@ extern "C" {
 /** GET the bit-stream version for compatibility check */
 #define CELT_GET_BITSTREAM_VERSION 2000
 
+#define CELT_SET_POST_MDCT_CALLBACK_REQUEST 3000
+
+/** Set the post-MDCT callback.
+    The callback will be called immediately after MDCT of the input block, and can change the MDCT data and/or
+    abort further processing.
+ @param fptr Pointer to a #_celt_post_mdct_callback function.
+ @param userdata Data pointer that will be passed to the callback.
+ @see celt_encoder_ctl
+*/
+#define CELT_SET_POST_MDCT_CALLBACK(fptr,userdata) CELT_SET_POST_MDCT_CALLBACK_REQUEST, _celt_check_post_mdct_callback(fptr), _celt_check_voidptr(userdata)
+
+/** Dataformat is float *
+ @see _celt_post_mdct_callback
+*/
+#define CELT_DATAFORMAT_FLOAT 0
+
+/** Dataformat is celt_int32_t *
+ @see _celt_post_mdct_callback
+*/
+#define CELT_DATAFORMAT_INT32 1
+
+/** Dataformat is celt_int16_t *
+ @see _celt_post_mdct_callback
+*/
+#define CELT_DATAFORMAT_INT16 2
 
 /** Contains the state of an encoder. One encoder state is needed for each 
     stream. It is initialised once at the beginning of the stream. Do *not*
@@ -115,6 +145,21 @@ typedef struct CELTDecoder CELTDecoder;
     otherwise the quality will be very bad */
 typedef struct CELTMode CELTMode;
 
+/** Callback function for twiddling MDCT data.
+    You need to fetch the block length, channels and sample rate either from the encoder state or
+    have in the user_data.
+ @param st Encoder state called back from
+ @param freq Block to be encoded, in MDCT frequency domain. The type of data can be determined from scale. The callback can modify freq.
+ @param format Datatype of freq.
+ @param scale Number of bits shifted for fixed point.
+ @param numMdcts Number of interleaved MDCTs in freq.
+ @param user_data User data pointer.
+ @return Abort state. If the callback returns 0, encoding will be aborted, and the encoder call will
+         return #CELT_POST_MDCT_CALLBACK_ABORT. You can therefore do encoding decisions in this callback.
+ @see celt_encoder_ctl
+ @see CELT_SET_POST_MDCT_CALLBACK
+*/
+typedef celt_int32_t (* _celt_post_mdct_callback)(CELTEncoder *st, void *freq, celt_int32_t format, celt_int32_t scale, celt_int32_t numMdcts, void *user_data);
 
 /** \defgroup codec Encoding and decoding */
 /*  @{ */
-- 
1.6.1.3



More information about the celt-dev mailing list