[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