audioconvert: make the quantizer a reusable object
authorWim Taymans <wtaymans@redhat.com>
Tue, 27 Oct 2015 16:28:06 +0000 (17:28 +0100)
committerWim Taymans <wtaymans@redhat.com>
Wed, 28 Oct 2015 10:36:18 +0000 (11:36 +0100)
Turn the quantizer into a reusable object.

gst/audioconvert/audioconvert.c
gst/audioconvert/audioconvert.h
gst/audioconvert/gstaudioconvert.c
gst/audioconvert/gstaudioconvert.h
gst/audioconvert/gstaudioquantize.c
gst/audioconvert/gstaudioquantize.h

index cf21516..247c2e4 100644 (file)
  *  - (channel mix F64)
  *  - pack from F64
  */
-#define DOUBLE_INTERMEDIATE_FORMAT(ctx)                     \
-    (!GST_AUDIO_FORMAT_INFO_IS_INTEGER (ctx->in.finfo) ||   \
-     !GST_AUDIO_FORMAT_INFO_IS_INTEGER (ctx->out.finfo) ||  \
-     (ctx->ns != NOISE_SHAPING_NONE))
-
-static inline gboolean
-check_default (AudioConvertCtx * ctx, const GstAudioFormatInfo * fmt)
-{
-  if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
-    return GST_AUDIO_FORMAT_INFO_FORMAT (fmt) == GST_AUDIO_FORMAT_S32;
-  } else {
-    return GST_AUDIO_FORMAT_INFO_FORMAT (fmt) == GST_AUDIO_FORMAT_F64;
-  }
-}
-
 gboolean
 audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in,
-    GstAudioInfo * out, GstAudioConvertDithering dither,
-    GstAudioConvertNoiseShaping ns)
+    GstAudioInfo * out, GstAudioDitherMethod dither,
+    GstAudioNoiseShapingMethod ns)
 {
   gint in_depth, out_depth;
   GstChannelMixFlags flags;
@@ -104,19 +89,19 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in,
    * source depth. */
   if (out_depth <= 20 && (!GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo)
           || in_depth >= out_depth)) {
-    ctx->dither = dither;
-    ctx->ns = ns;
+    dither = dither;
+    ns = ns;
     GST_INFO ("using dither %d and noise shaping %d", dither, ns);
   } else {
-    ctx->dither = DITHER_NONE;
-    ctx->ns = NOISE_SHAPING_NONE;
+    dither = GST_AUDIO_DITHER_NONE;
+    ns = GST_AUDIO_NOISE_SHAPING_NONE;
     GST_INFO ("using no dither and noise shaping");
   }
 
   /* Use simple error feedback when output sample rate is smaller than
    * 32000 as the other methods might move the noise to audible ranges */
-  if (ctx->ns > NOISE_SHAPING_ERROR_FEEDBACK && out->rate < 32000)
-    ctx->ns = NOISE_SHAPING_ERROR_FEEDBACK;
+  if (ns > GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK && out->rate < 32000)
+    ns = GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK;
 
   flags =
       GST_AUDIO_INFO_IS_UNPOSITIONED (in) ?
@@ -128,11 +113,17 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in,
   ctx->mix = gst_channel_mix_new (flags, in->channels, in->position,
       out->channels, out->position);
 
+  if (!GST_AUDIO_FORMAT_INFO_IS_INTEGER (ctx->in.finfo) ||
+      !GST_AUDIO_FORMAT_INFO_IS_INTEGER (ctx->out.finfo) ||
+      (ns != GST_AUDIO_NOISE_SHAPING_NONE))
+    ctx->mix_format = GST_AUDIO_FORMAT_F64;
+  else
+    ctx->mix_format = GST_AUDIO_FORMAT_S32;
+
   /* if one formats is float/double or we use noise shaping use double as
    * intermediate format and switch mixing */
-  if (DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
+  if (ctx->mix_format == GST_AUDIO_FORMAT_F64) {
     GST_INFO ("use float mixing");
-    ctx->mix_format = GST_AUDIO_FORMAT_F64;
     if (ctx->in.finfo->unpack_format != GST_AUDIO_FORMAT_F64) {
       ctx->convert = audio_convert_orc_s32_to_double;
       GST_INFO ("convert input to F64");
@@ -151,7 +142,6 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in,
     }
   } else {
     GST_INFO ("use int mixing");
-    ctx->mix_format = GST_AUDIO_FORMAT_S32;
     /* check if input needs to be unpacked to intermediate format */
     ctx->in_default =
         GST_AUDIO_FORMAT_INFO_FORMAT (in->finfo) == GST_AUDIO_FORMAT_S32;
@@ -164,7 +154,8 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in,
 
   /* check if channel mixer is passthrough */
   ctx->mix_passthrough = gst_channel_mix_is_passthrough (ctx->mix);
-  ctx->quant_default = check_default (ctx, out->finfo);
+  ctx->quant_default =
+      GST_AUDIO_FORMAT_INFO_FORMAT (out->finfo) == ctx->mix_format;
 
   GST_INFO ("in default %d, mix passthrough %d, out default %d",
       ctx->in_default, ctx->mix_passthrough, ctx->out_default);
@@ -174,7 +165,8 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in,
 
   GST_INFO ("scale out %d", ctx->out_scale);
 
-  gst_audio_quantize_setup (ctx);
+  ctx->quant = gst_audio_quantize_new (dither, ns, 0, ctx->mix_format,
+      out->channels, ctx->out_scale);
 
   return TRUE;
 
@@ -191,7 +183,8 @@ audio_convert_clean_context (AudioConvertCtx * ctx)
 {
   g_return_val_if_fail (ctx != NULL, FALSE);
 
-  gst_audio_quantize_free (ctx);
+  if (ctx->quant)
+    gst_audio_quantize_free (ctx->quant);
   if (ctx->mix)
     gst_channel_mix_free (ctx->mix);
   ctx->mix = NULL;
@@ -244,7 +237,7 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
   out_width = GST_AUDIO_FORMAT_INFO_WIDTH (ctx->out.finfo);
 
   /* find biggest temp buffer size */
-  size = (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? sizeof (gdouble)
+  size = (ctx->mix_format == GST_AUDIO_FORMAT_F64) ? sizeof (gdouble)
       : sizeof (gint32);
 
   if (!ctx->in_default)
@@ -314,7 +307,9 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
     else
       outbuf = tmpbuf;
 
-    ctx->quantize (ctx, src, outbuf, samples);
+    gst_audio_quantize_samples (ctx->quant, src, samples);
+
+    outbuf = src;
   }
 
   if (!ctx->out_default) {
index 5a0f540..6b5e712 100644 (file)
 #include <gst/audio/audio.h>
 
 #include "gstchannelmix.h"
+#include "gstaudioquantize.h"
 
 GST_DEBUG_CATEGORY_EXTERN (audio_convert_debug);
 #define GST_CAT_DEFAULT (audio_convert_debug)
 
-/**
- * GstAudioConvertDithering:
- * @DITHER_NONE: No dithering
- * @DITHER_RPDF: Rectangular dithering
- * @DITHER_TPDF: Triangular dithering (default)
- * @DITHER_TPDF_HF: High frequency triangular dithering
- *
- * Set of available dithering methods when converting audio.
- */
-typedef enum
-{
-  DITHER_NONE = 0,
-  DITHER_RPDF,
-  DITHER_TPDF,
-  DITHER_TPDF_HF
-} GstAudioConvertDithering;
-
-/**
- * GstAudioConvertNoiseShaping:
- * @NOISE_SHAPING_NONE: No noise shaping (default)
- * @NOISE_SHAPING_ERROR_FEEDBACK: Error feedback
- * @NOISE_SHAPING_SIMPLE: Simple 2-pole noise shaping
- * @NOISE_SHAPING_MEDIUM: Medium 5-pole noise shaping
- * @NOISE_SHAPING_HIGH: High 8-pole noise shaping
- *
- * Set of available noise shaping methods
- */
-typedef enum
-{
-  NOISE_SHAPING_NONE = 0,
-  NOISE_SHAPING_ERROR_FEEDBACK,
-  NOISE_SHAPING_SIMPLE,
-  NOISE_SHAPING_MEDIUM,
-  NOISE_SHAPING_HIGH
-} GstAudioConvertNoiseShaping;
-
 typedef struct _AudioConvertCtx AudioConvertCtx;
-#if 0
-typedef struct _AudioConvertFmt AudioConvertFmt;
-
-struct _AudioConvertFmt
-{
-  /* general caps */
-  gboolean is_int;
-  gint endianness;
-  gint width;
-  gint rate;
-  gint channels;
-  GstAudioChannelPosition *pos;
-  gboolean unpositioned_layout;
-
-  /* int audio caps */
-  gboolean sign;
-  gint depth;
-
-  gint unit_size;
-};
-#endif
 
-typedef void (*AudioConvertQuantize) (AudioConvertCtx * ctx, gpointer src,
-    gpointer dst, gint count);
 typedef void (*AudioConvertToF64) (gdouble *dst, const gint32 *src, gint count);
 
 struct _AudioConvertCtx
@@ -98,7 +40,9 @@ struct _AudioConvertCtx
   GstAudioInfo in;
   GstAudioInfo out;
 
+  GstAudioFormat mix_format;
   GstChannelMix *mix;
+  GstAudioQuantize *quant;
 
   gboolean in_default;
   gboolean mix_passthrough;
@@ -109,22 +53,13 @@ struct _AudioConvertCtx
   gint tmpbufsize;
 
   gint out_scale;
-  GstAudioFormat mix_format;
 
   AudioConvertToF64 convert;
-  AudioConvertQuantize quantize;
-
-  GstAudioConvertDithering dither;
-  GstAudioConvertNoiseShaping ns;
-  /* last random number generated per channel for hifreq TPDF dither */
-  gpointer last_random;
-  /* contains the past quantization errors, error[out_channels][count] */
-  gdouble *error_buf;
 };
 
 gboolean audio_convert_prepare_context (AudioConvertCtx * ctx,
     GstAudioInfo * in, GstAudioInfo * out,
-    GstAudioConvertDithering dither, GstAudioConvertNoiseShaping ns);
+    GstAudioDitherMethod dither, GstAudioNoiseShapingMethod ns);
 gboolean audio_convert_get_sizes (AudioConvertCtx * ctx, gint samples,
     gint * srcsize, gint * dstsize);
 
index 634fd46..59c427e 100644 (file)
@@ -140,11 +140,12 @@ gst_audio_convert_dithering_get_type (void)
 
   if (gtype == 0) {
     static const GEnumValue values[] = {
-      {DITHER_NONE, "No dithering",
+      {GST_AUDIO_DITHER_NONE, "No dithering",
           "none"},
-      {DITHER_RPDF, "Rectangular dithering", "rpdf"},
-      {DITHER_TPDF, "Triangular dithering (default)", "tpdf"},
-      {DITHER_TPDF_HF, "High frequency triangular dithering", "tpdf-hf"},
+      {GST_AUDIO_DITHER_RPDF, "Rectangular dithering", "rpdf"},
+      {GST_AUDIO_DITHER_TPDF, "Triangular dithering (default)", "tpdf"},
+      {GST_AUDIO_DITHER_TPDF_HF, "High frequency triangular dithering",
+          "tpdf-hf"},
       {0, NULL, NULL}
     };
 
@@ -161,12 +162,13 @@ gst_audio_convert_ns_get_type (void)
 
   if (gtype == 0) {
     static const GEnumValue values[] = {
-      {NOISE_SHAPING_NONE, "No noise shaping (default)",
+      {GST_AUDIO_NOISE_SHAPING_NONE, "No noise shaping (default)",
           "none"},
-      {NOISE_SHAPING_ERROR_FEEDBACK, "Error feedback", "error-feedback"},
-      {NOISE_SHAPING_SIMPLE, "Simple 2-pole noise shaping", "simple"},
-      {NOISE_SHAPING_MEDIUM, "Medium 5-pole noise shaping", "medium"},
-      {NOISE_SHAPING_HIGH, "High 8-pole noise shaping", "high"},
+      {GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK, "Error feedback",
+          "error-feedback"},
+      {GST_AUDIO_NOISE_SHAPING_SIMPLE, "Simple 2-pole noise shaping", "simple"},
+      {GST_AUDIO_NOISE_SHAPING_MEDIUM, "Medium 5-pole noise shaping", "medium"},
+      {GST_AUDIO_NOISE_SHAPING_HIGH, "High 8-pole noise shaping", "high"},
       {0, NULL, NULL}
     };
 
@@ -191,13 +193,13 @@ gst_audio_convert_class_init (GstAudioConvertClass * klass)
   g_object_class_install_property (gobject_class, PROP_DITHERING,
       g_param_spec_enum ("dithering", "Dithering",
           "Selects between different dithering methods.",
-          GST_TYPE_AUDIO_CONVERT_DITHERING, DITHER_TPDF,
+          GST_TYPE_AUDIO_CONVERT_DITHERING, GST_AUDIO_DITHER_TPDF,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_NOISE_SHAPING,
       g_param_spec_enum ("noise-shaping", "Noise shaping",
           "Selects between different noise shaping methods.",
-          GST_TYPE_AUDIO_CONVERT_NOISE_SHAPING, NOISE_SHAPING_NONE,
+          GST_TYPE_AUDIO_CONVERT_NOISE_SHAPING, GST_AUDIO_NOISE_SHAPING_NONE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gst_element_class_add_pad_template (element_class,
@@ -227,8 +229,8 @@ gst_audio_convert_class_init (GstAudioConvertClass * klass)
 static void
 gst_audio_convert_init (GstAudioConvert * this)
 {
-  this->dither = DITHER_TPDF;
-  this->ns = NOISE_SHAPING_NONE;
+  this->dither = GST_AUDIO_DITHER_TPDF;
+  this->ns = GST_AUDIO_NOISE_SHAPING_NONE;
   memset (&this->ctx, 0, sizeof (AudioConvertCtx));
 
   gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (this), TRUE);
index 6ff4374..f52845f 100644 (file)
@@ -48,8 +48,8 @@ struct _GstAudioConvert
 
   AudioConvertCtx ctx;
 
-  GstAudioConvertDithering dither;
-  GstAudioConvertNoiseShaping ns;
+  GstAudioDitherMethod dither;
+  GstAudioNoiseShapingMethod ns;
 };
 
 struct _GstAudioConvertClass
index 1759250..8f7d1ec 100644 (file)
 #include <gst/gst.h>
 #include <string.h>
 #include <math.h>
-#include "audioconvert.h"
 #include "gstaudioconvertorc.h"
 #include "gstaudioquantize.h"
 
 #include "gstfastrandom.h"
 
+typedef void (*QuantizeFunc) (GstAudioQuantize * quant, gpointer src,
+    gpointer dst, gint count);
+
+struct _GstAudioQuantize
+{
+  GstAudioDitherMethod dither;
+  GstAudioNoiseShapingMethod ns;
+  GstAudioQuantizeFlags flags;
+  GstAudioFormat format;
+  guint channels;
+  guint quantizer;
+
+  /* last random number generated per channel for hifreq TPDF dither */
+  gpointer last_random;
+  /* contains the past quantization errors, error[out_channels][count] */
+  gdouble *error_buf;
+
+  QuantizeFunc quantize;
+};
+
 #define MAKE_QUANTIZE_FUNC_NAME(name)                                   \
 gst_audio_quantize_quantize_##name
 
@@ -48,11 +67,11 @@ gst_audio_quantize_quantize_##name
 #define MAKE_QUANTIZE_FUNC_I(name, DITHER_INIT_FUNC, ADD_DITHER_FUNC,   \
                              ROUND_FUNC)                                \
 static void                                                             \
-MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gint32 *src,      \
+MAKE_QUANTIZE_FUNC_NAME (name) (GstAudioQuantize *quant, gint32 *src,   \
                                 gint32 *dst, gint count)                \
 {                                                                       \
-  gint scale = ctx->out_scale;                                          \
-  gint channels = ctx->out.channels;                                    \
+  gint scale = quant->quantizer;                                        \
+  gint channels = quant->channels;                                      \
   gint chan_pos;                                                        \
                                                                         \
   if (scale > 0) {                                                      \
@@ -83,11 +102,11 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gint32 *src,      \
                              ADD_NS_FUNC, ADD_DITHER_FUNC,              \
                              UPDATE_ERROR_FUNC)                         \
 static void                                                             \
-MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
+MAKE_QUANTIZE_FUNC_NAME (name) (GstAudioQuantize *quant, gdouble *src,  \
                                 gint32 *dst, gint count)                \
 {                                                                       \
-  gint scale = ctx->out_scale;                                          \
-  gint channels = ctx->out.channels;                                    \
+  gint scale = quant->quantizer;                                        \
+  gint channels = quant->channels;                                      \
   gint chan_pos;                                                        \
   gdouble tmp, d, factor = (1U<<(32-scale-1));                          \
                                                                         \
@@ -180,7 +199,7 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
 #define INIT_DITHER_TPDF_HF_I()                                         \
   gint32 rand;                                                          \
   gint32 dither = (1<<(scale-1));                                       \
-  gint32 *last_random = (gint32 *) ctx->last_random, tmp_rand;
+  gint32 *last_random = (gint32 *) quant->last_random, tmp_rand;
 
 #define ADD_DITHER_TPDF_HF_I()                                          \
         tmp_rand = RANDOM_INT_DITHER(dither);                           \
@@ -199,7 +218,7 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
 #define INIT_DITHER_TPDF_HF_F()                                         \
   gdouble rand;                                                         \
   gdouble dither = 1.0/(1U<<(32 - scale));                              \
-  gdouble *last_random = (gdouble *) ctx->last_random, tmp_rand;
+  gdouble *last_random = (gdouble *) quant->last_random, tmp_rand;
 
 #define ADD_DITHER_TPDF_HF_F()                                          \
         tmp_rand = gst_fast_random_double_range (- dither, dither);     \
@@ -216,7 +235,7 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
 
 #define INIT_NS_ERROR_FEEDBACK()                                        \
   gdouble orig;                                                         \
-  gdouble *errors = ctx->error_buf;
+  gdouble *errors = quant->error_buf;
 
 #define ADD_NS_ERROR_FEEDBACK()                                         \
         orig = tmp;                                                     \
@@ -230,7 +249,7 @@ MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src,     \
 
 #define INIT_NS_SIMPLE()                                                \
   gdouble orig;                                                         \
-  gdouble *errors = ctx->error_buf, cur_error;
+  gdouble *errors = quant->error_buf, cur_error;
 
 #define ADD_NS_SIMPLE()                                                 \
         cur_error = errors[chan_pos*2] - 0.5 * errors[chan_pos*2 + 1];  \
@@ -256,7 +275,7 @@ static const gdouble ns_medium_coeffs[] = {
 
 #define INIT_NS_MEDIUM()                                                \
   gdouble orig;                                                         \
-  gdouble *errors = ctx->error_buf, cur_error;                          \
+  gdouble *errors = quant->error_buf, cur_error;                        \
   int j;
 
 #define ADD_NS_MEDIUM()                                                 \
@@ -280,7 +299,7 @@ static const gdouble ns_high_coeffs[] = {
 
 #define INIT_NS_HIGH()                                                  \
   gdouble orig;                                                         \
-  gdouble *errors = ctx->error_buf, cur_error;                          \
+  gdouble *errors = quant->error_buf, cur_error;                        \
   int j;
 
 #define ADD_NS_HIGH()                                                   \
@@ -352,142 +371,149 @@ MAKE_QUANTIZE_FUNC_F (float_tpdf_hf_medium, INIT_DITHER_TPDF_HF_F,
 MAKE_QUANTIZE_FUNC_F (float_tpdf_hf_high, INIT_DITHER_TPDF_HF_F, INIT_NS_HIGH,
     ADD_NS_HIGH, ADD_DITHER_TPDF_HF_F, UPDATE_ERROR_HIGH);
 
-static const AudioConvertQuantize quantize_funcs[] = {
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (int_none_none),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (int_rpdf_none),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (int_tpdf_none),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (int_tpdf_hf_none),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_none),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_error_feedback),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_simple),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_medium),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_high),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_none),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_error_feedback),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_simple),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_medium),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_high),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_none),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_error_feedback),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_simple),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_medium),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_high),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_none),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_error_feedback),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_simple),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_medium),
-  (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_high)
+static const QuantizeFunc quantize_funcs[] = {
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (int_none_none),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (int_rpdf_none),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (int_tpdf_none),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (int_tpdf_hf_none),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_none_none),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_none_error_feedback),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_none_simple),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_none_medium),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_none_high),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_none),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_error_feedback),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_simple),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_medium),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_high),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_none),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_error_feedback),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_simple),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_medium),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_high),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_none),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_error_feedback),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_simple),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_medium),
+  (QuantizeFunc) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_high)
 };
 
 static void
-gst_audio_quantize_setup_noise_shaping (AudioConvertCtx * ctx)
+gst_audio_quantize_setup_noise_shaping (GstAudioQuantize * quant)
 {
-  switch (ctx->ns) {
-    case NOISE_SHAPING_HIGH:{
-      ctx->error_buf = g_new0 (gdouble, ctx->out.channels * 8);
+  switch (quant->ns) {
+    case GST_AUDIO_NOISE_SHAPING_HIGH:{
+      quant->error_buf = g_new0 (gdouble, quant->channels * 8);
       break;
     }
-    case NOISE_SHAPING_MEDIUM:{
-      ctx->error_buf = g_new0 (gdouble, ctx->out.channels * 5);
+    case GST_AUDIO_NOISE_SHAPING_MEDIUM:{
+      quant->error_buf = g_new0 (gdouble, quant->channels * 5);
       break;
     }
-    case NOISE_SHAPING_SIMPLE:{
-      ctx->error_buf = g_new0 (gdouble, ctx->out.channels * 2);
+    case GST_AUDIO_NOISE_SHAPING_SIMPLE:{
+      quant->error_buf = g_new0 (gdouble, quant->channels * 2);
       break;
     }
-    case NOISE_SHAPING_ERROR_FEEDBACK:
-      ctx->error_buf = g_new0 (gdouble, ctx->out.channels);
+    case GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK:
+      quant->error_buf = g_new0 (gdouble, quant->channels);
       break;
-    case NOISE_SHAPING_NONE:
+    case GST_AUDIO_NOISE_SHAPING_NONE:
     default:
-      ctx->error_buf = NULL;
+      quant->error_buf = NULL;
       break;
   }
   return;
 }
 
 static void
-gst_audio_quantize_free_noise_shaping (AudioConvertCtx * ctx)
+gst_audio_quantize_setup_dither (GstAudioQuantize * quant)
 {
-  switch (ctx->ns) {
-    case NOISE_SHAPING_HIGH:
-    case NOISE_SHAPING_MEDIUM:
-    case NOISE_SHAPING_SIMPLE:
-    case NOISE_SHAPING_ERROR_FEEDBACK:
-    case NOISE_SHAPING_NONE:
-    default:
+  switch (quant->dither) {
+    case GST_AUDIO_DITHER_TPDF_HF:
+      quant->last_random = g_new0 (gdouble, quant->channels);
       break;
-  }
-
-  g_free (ctx->error_buf);
-  ctx->error_buf = NULL;
-  return;
-}
-
-static void
-gst_audio_quantize_setup_dither (AudioConvertCtx * ctx)
-{
-  switch (ctx->dither) {
-    case DITHER_TPDF_HF:
-      if (GST_AUDIO_FORMAT_INFO_IS_INTEGER (ctx->out.finfo))
-        ctx->last_random = g_new0 (gint32, ctx->out.channels);
-      else
-        ctx->last_random = g_new0 (gdouble, ctx->out.channels);
+    case GST_AUDIO_DITHER_RPDF:
+    case GST_AUDIO_DITHER_TPDF:
+      quant->last_random = NULL;
       break;
-    case DITHER_RPDF:
-    case DITHER_TPDF:
-      ctx->last_random = NULL;
-      break;
-    case DITHER_NONE:
+    case GST_AUDIO_DITHER_NONE:
     default:
-      ctx->last_random = NULL;
+      quant->last_random = NULL;
       break;
   }
   return;
 }
 
 static void
-gst_audio_quantize_free_dither (AudioConvertCtx * ctx)
+gst_audio_quantize_setup_quantize_func (GstAudioQuantize * quant)
 {
-  g_free (ctx->last_random);
+  gint index = 0;
 
-  return;
+  if (quant->ns == GST_AUDIO_NOISE_SHAPING_NONE
+      && quant->format == GST_AUDIO_FORMAT_S32) {
+    index += quant->dither;
+  } else {
+    g_assert (quant->format == GST_AUDIO_FORMAT_F64);
+
+    index += 4 + (5 * quant->dither);
+    index += quant->ns;
+  }
+  quant->quantize = quantize_funcs[index];
 }
 
-static void
-gst_audio_quantize_setup_quantize_func (AudioConvertCtx * ctx)
+/**
+ * gst_audio_quantize_new:
+ * @dither: a #GstAudioDitherMethod
+ * @ns: a #GstAudioNoiseShapingMethod
+ * @flags: #GstAudioQuantizeFlags
+ * @format: the #GstAudioFormat of the samples
+ * @channels: the amount of channels in the samples
+ * @quantizer: the quantizer to use
+ *
+ * Create a new quantizer object with the given parameters.
+ *
+ * Returns: a new #GstAudioQuantize. Free with gst_audio_quantize_free().
+ */
+GstAudioQuantize *
+gst_audio_quantize_new (GstAudioDitherMethod dither,
+    GstAudioNoiseShapingMethod ns, GstAudioQuantizeFlags flags,
+    GstAudioFormat format, guint channels, guint quantizer)
 {
-  gint index = 0;
+  GstAudioQuantize *quant;
 
-  if (!GST_AUDIO_FORMAT_INFO_IS_INTEGER (ctx->out.finfo)) {
-    ctx->quantize = NULL;
-    return;
-  }
+  quant = g_slice_new0 (GstAudioQuantize);
+  quant->dither = dither;
+  quant->ns = ns;
+  quant->flags = flags;
+  quant->format = format;
+  quant->channels = channels;
+  quant->quantizer = quantizer;
 
-  if (ctx->ns == NOISE_SHAPING_NONE
-      && GST_AUDIO_FORMAT_INFO_IS_INTEGER (ctx->in.finfo)) {
-    index += ctx->dither;
-  } else {
-    index += 4 + (5 * ctx->dither);
-    index += ctx->ns;
-  }
+  gst_audio_quantize_setup_dither (quant);
+  gst_audio_quantize_setup_noise_shaping (quant);
+  gst_audio_quantize_setup_quantize_func (quant);
 
-  ctx->quantize = quantize_funcs[index];
+  return quant;
 }
 
-gboolean
-gst_audio_quantize_setup (AudioConvertCtx * ctx)
+/**
+ * gst_audio_quantize_free:
+ * @quant: a #GstAudioQuantize
+ *
+ * Free a #GstAudioQuantize.
+ */
+void
+gst_audio_quantize_free (GstAudioQuantize * quant)
 {
-  gst_audio_quantize_setup_dither (ctx);
-  gst_audio_quantize_setup_noise_shaping (ctx);
-  gst_audio_quantize_setup_quantize_func (ctx);
+  g_free (quant->error_buf);
+  g_free (quant->last_random);
 
-  return TRUE;
+  g_slice_free (GstAudioQuantize, quant);
 }
 
 void
-gst_audio_quantize_free (AudioConvertCtx * ctx)
+gst_audio_quantize_samples (GstAudioQuantize * quant,
+    gpointer data, guint samples)
 {
-  gst_audio_quantize_free_dither (ctx);
-  gst_audio_quantize_free_noise_shaping (ctx);
+  quant->quantize (quant, data, data, samples);
 }
index e5d0708..bb5ccf4 100644 (file)
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *           (C) 2015 Wim Taymans <wim.taymans@gmail.com>
  *
  * gstaudioquantize.h: quantizes audio to the target format and optionally
  *                     applies dithering and noise shaping.
  */
 
 #include <gst/gst.h>
-#include "audioconvert.h"
+
+#include <gst/audio/audio.h>
+
 
 #ifndef __GST_AUDIO_QUANTIZE_H__
 #define __GST_AUDIO_QUANTIZE_H__
 
-gboolean gst_audio_quantize_setup (AudioConvertCtx * ctx);
-void gst_audio_quantize_reset (AudioConvertCtx * ctx);
-void gst_audio_quantize_free (AudioConvertCtx * ctx);
+/**
+ * GstAudioDitherMethod:
+ * @GST_AUDIO_DITHER_NONE: No dithering
+ * @GST_AUDIO_DITHER_RPDF: Rectangular dithering
+ * @GST_AUDIO_DITHER_TPDF: Triangular dithering (default)
+ * @GST_AUDIO_DITHER_TPDF_HF: High frequency triangular dithering
+ *
+ * Set of available dithering methods.
+ */
+typedef enum
+{
+  GST_AUDIO_DITHER_NONE = 0,
+  GST_AUDIO_DITHER_RPDF,
+  GST_AUDIO_DITHER_TPDF,
+  GST_AUDIO_DITHER_TPDF_HF
+} GstAudioDitherMethod;
+
+/**
+ * GstAudioNoiseShapingMethod:
+ * @GST_AUDIO_NOISE_SHAPING_NONE: No noise shaping (default)
+ * @GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK: Error feedback
+ * @GST_AUDIO_NOISE_SHAPING_SIMPLE: Simple 2-pole noise shaping
+ * @GST_AUDIO_NOISE_SHAPING_MEDIUM: Medium 5-pole noise shaping
+ * @GST_AUDIO_NOISE_SHAPING_HIGH: High 8-pole noise shaping
+ *
+ * Set of available noise shaping methods
+ */
+typedef enum
+{
+  GST_AUDIO_NOISE_SHAPING_NONE = 0,
+  GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK,
+  GST_AUDIO_NOISE_SHAPING_SIMPLE,
+  GST_AUDIO_NOISE_SHAPING_MEDIUM,
+  GST_AUDIO_NOISE_SHAPING_HIGH
+} GstAudioNoiseShapingMethod;
+
+
+typedef enum
+{
+  GST_AUDIO_QUANTIZE_FLAG_NONE = 0
+} GstAudioQuantizeFlags;
+
+
+typedef struct _GstAudioQuantize GstAudioQuantize;
+
+GstAudioQuantize *  gst_audio_quantize_new      (GstAudioDitherMethod dither,
+                                                 GstAudioNoiseShapingMethod ns,
+                                                 GstAudioQuantizeFlags flags,
+                                                 GstAudioFormat format,
+                                                 guint channels,
+                                                 guint quantizer);
+
+void                gst_audio_quantize_free     (GstAudioQuantize * quant);
 
+void                gst_audio_quantize_samples  (GstAudioQuantize * quant,
+                                                 gpointer data, guint samples);
 
 #endif /* __GST_AUDIO_QUANTIZE_H__ */