slomo gst-plugins-good: gst-plugins-good/ gst-plugins-good/gst/audiofx/
[email protected] Mon, 5 Jan 2009 02:13:43 -0800 (PST)
| Newsgroups | gmane.comp.video.gstreamer.cvs |
|---|---|
| Message-ID | <[email protected]> |
CVS Root: /cvs/gstreamer
Module: gst-plugins-good
Changes by: slomo
Date: Mon Jan 05 2009 10:13:43 UTC
Log message:
* gst/audiofx/Makefile.am:
* gst/audiofx/audiofxbaseiirfilter.c:
(gst_audio_fx_base_iir_filter_base_init),
(gst_audio_fx_base_iir_filter_dispose),
(gst_audio_fx_base_iir_filter_class_init),
(gst_audio_fx_base_iir_filter_init),
(gst_audio_fx_base_iir_filter_calculate_gain),
(gst_audio_fx_base_iir_filter_set_coefficients),
(gst_audio_fx_base_iir_filter_setup), (process),
(gst_audio_fx_base_iir_filter_transform_ip),
(gst_audio_fx_base_iir_filter_stop):
* gst/audiofx/audiofxbaseiirfilter.h:
Implement a base class for IIR filters.
* gst/audiofx/audiochebband.c: (gst_audio_cheb_band_base_init),
(gst_audio_cheb_band_class_init), (gst_audio_cheb_band_init),
(generate_coefficients), (gst_audio_cheb_band_set_property),
(gst_audio_cheb_band_setup):
* gst/audiofx/audiochebband.h:
* gst/audiofx/audiocheblimit.c: (gst_audio_cheb_limit_base_init),
(gst_audio_cheb_limit_class_init), (gst_audio_cheb_limit_init),
(generate_coefficients), (gst_audio_cheb_limit_set_property),
(gst_audio_cheb_limit_setup):
* gst/audiofx/audiocheblimit.h:
Use the IIR filter base class for the chebyshev filters.
Modified files:
. : ChangeLog
gst/audiofx : Makefile.am audiochebband.c audiochebband.h
audiocheblimit.c audiocheblimit.h
Added files:
gst/audiofx : audiofxbaseiirfilter.c audiofxbaseiirfilter.h
Links:
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/ChangeLog.diff?r1=1.3879&r2=1.3880
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/audiofx/Makefile.am.diff?r1=1.15&r2=1.16
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/audiofx/audiochebband.c.diff?r1=1.8&r2=1.9
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/audiofx/audiochebband.h.diff?r1=1.2&r2=1.3
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/audiofx/audiocheblimit.c.diff?r1=1.9&r2=1.10
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/audiofx/audiocheblimit.h.diff?r1=1.2&r2=1.3
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/audiofx/audiofxbaseiirfilter.c?rev=1.1&content-type=text/vnd.viewcvs-markup
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/audiofx/audiofxbaseiirfilter.h?rev=1.1&content-type=text/vnd.viewcvs-markup
====Begin Diffs====
Index: ChangeLog
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-good/ChangeLog,v
retrieving revision 1.3879
retrieving revision 1.3880
diff -u -d -r1.3879 -r1.3880
--- ChangeLog 2 Jan 2009 20:39:32 -0000 1.3879
+++ ChangeLog 5 Jan 2009 10:13:26 -0000 1.3880
@@ -1,3 +1,31 @@
+2009-01-05 Sebastian Dröge <[email protected]>
+
+ * gst/audiofx/Makefile.am:
+ * gst/audiofx/audiofxbaseiirfilter.c:
+ (gst_audio_fx_base_iir_filter_base_init),
+ (gst_audio_fx_base_iir_filter_dispose),
+ (gst_audio_fx_base_iir_filter_class_init),
+ (gst_audio_fx_base_iir_filter_init),
+ (gst_audio_fx_base_iir_filter_calculate_gain),
+ (gst_audio_fx_base_iir_filter_set_coefficients),
+ (gst_audio_fx_base_iir_filter_setup), (process),
+ (gst_audio_fx_base_iir_filter_transform_ip),
+ (gst_audio_fx_base_iir_filter_stop):
+ * gst/audiofx/audiofxbaseiirfilter.h:
+ Implement a base class for IIR filters.
+ * gst/audiofx/audiochebband.c: (gst_audio_cheb_band_base_init),
+ (gst_audio_cheb_band_class_init), (gst_audio_cheb_band_init),
+ (generate_coefficients), (gst_audio_cheb_band_set_property),
+ (gst_audio_cheb_band_setup):
+ * gst/audiofx/audiochebband.h:
+ * gst/audiofx/audiocheblimit.c: (gst_audio_cheb_limit_base_init),
+ (gst_audio_cheb_limit_class_init), (gst_audio_cheb_limit_init),
+ (generate_coefficients), (gst_audio_cheb_limit_set_property),
+ (gst_audio_cheb_limit_setup):
+ * gst/audiofx/audiocheblimit.h:
+ Use the IIR filter base class for the chebyshev filters.
2009-01-02 Michael Smith <[email protected]>
Patch by: Justin Karnegas <[email protected]> and
Index: Makefile.am
RCS file: /cvs/gstreamer/gst-plugins-good/gst/audiofx/Makefile.am,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- Makefile.am 4 Nov 2008 12:28:23 -0000 1.15
+++ Makefile.am 5 Jan 2009 10:13:28 -0000 1.16
@@ -9,6 +9,7 @@
audioamplify.c \
audiodynamic.c \
audiokaraoke.c \
+ audiofxbaseiirfilter.c \
audiocheblimit.c \
audiochebband.c \
audiowsincband.c \
@@ -34,6 +35,7 @@
audioamplify.h \
audiodynamic.h \
audiokaraoke.h \
+ audiofxbaseiirfilter.h \
audiocheblimit.h \
audiochebband.h \
audiowsincband.h \
Index: audiochebband.c
RCS file: /cvs/gstreamer/gst-plugins-good/gst/audiofx/audiochebband.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- audiochebband.c 7 Mar 2008 13:08:40 -0000 1.8
+++ audiochebband.c 5 Jan 2009 10:13:28 -0000 1.9
@@ -1,6 +1,6 @@
/*
* GStreamer
- * Copyright (C) 2007 Sebastian Dröge <[email protected]>
+ * Copyright (C) 2007-2009 Sebastian Dröge <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -92,19 +92,6 @@
#define GST_CAT_DEFAULT gst_audio_cheb_band_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-static const GstElementDetails element_details =
-GST_ELEMENT_DETAILS ("Band pass & band reject filter",
- "Filter/Effect/Audio",
- "Chebyshev band pass and band reject filter",
- "Sebastian Dröge <[email protected]>");
-
-/* Filter signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
enum
{
PROP_0,
@@ -116,18 +103,11 @@
PROP_POLES
};
-#define ALLOWED_CAPS \
- "audio/x-raw-float," \
- " width = (int) { 32, 64 }, " \
- " endianness = (int) BYTE_ORDER," \
- " rate = (int) [ 1, MAX ]," \
- " channels = (int) [ 1, MAX ]"
#define DEBUG_INIT(bla) \
GST_DEBUG_CATEGORY_INIT (gst_audio_cheb_band_debug, "audiochebband", 0, "audiochebband element");
GST_BOILERPLATE_FULL (GstAudioChebBand, gst_audio_cheb_band,
- GstAudioFilter, GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+ GstAudioFXBaseIIRFilter, GST_TYPE_AUDIO_FX_BASE_IIR_FILTER, DEBUG_INIT);
static void gst_audio_cheb_band_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -136,14 +116,6 @@
static gboolean gst_audio_cheb_band_setup (GstAudioFilter * filter,
GstRingBufferSpec * format);
-static GstFlowReturn
-gst_audio_cheb_band_transform_ip (GstBaseTransform * base, GstBuffer * buf);
-static gboolean gst_audio_cheb_band_start (GstBaseTransform * base);
-static void process_64 (GstAudioChebBand * filter,
- gdouble * data, guint num_samples);
-static void process_32 (GstAudioChebBand * filter,
- gfloat * data, guint num_samples);
@@ -177,98 +149,56 @@
gst_audio_cheb_band_base_init (gpointer klass)
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- GstCaps *caps;
- gst_element_class_set_details (element_class, &element_details);
- caps = gst_caps_from_string (ALLOWED_CAPS);
- gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
- caps);
- gst_caps_unref (caps);
-}
-static void
-gst_audio_cheb_band_dispose (GObject * object)
- GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (object);
- if (filter->a) {
- g_free (filter->a);
- filter->a = NULL;
- }
- if (filter->b) {
- g_free (filter->b);
- filter->b = NULL;
- if (filter->channels) {
- GstAudioChebBandChannelCtx *ctx;
- gint i, channels = GST_AUDIO_FILTER (filter)->format.channels;
- for (i = 0; i < channels; i++) {
- ctx = &filter->channels[i];
- g_free (ctx->x);
- g_free (ctx->y);
- }
- g_free (filter->channels);
- filter->channels = NULL;
- G_OBJECT_CLASS (parent_class)->dispose (object);
+ gst_element_class_set_details_simple (element_class,
+ "Band pass & band reject filter", "Filter/Effect/Audio",
+ "Chebyshev band pass and band reject filter",
+ "Sebastian Dröge <[email protected]>");
}
static void
gst_audio_cheb_band_class_init (GstAudioChebBandClass * klass)
- GObjectClass *gobject_class;
- GstBaseTransformClass *trans_class;
- GstAudioFilterClass *filter_class;
- gobject_class = (GObjectClass *) klass;
- trans_class = (GstBaseTransformClass *) klass;
- filter_class = (GstAudioFilterClass *) klass;
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
gobject_class->set_property = gst_audio_cheb_band_set_property;
gobject_class->get_property = gst_audio_cheb_band_get_property;
- gobject_class->dispose = gst_audio_cheb_band_dispose;
g_object_class_install_property (gobject_class, PROP_MODE,
g_param_spec_enum ("mode", "Mode",
"Low pass or high pass mode", GST_TYPE_AUDIO_CHEBYSHEV_FREQ_BAND_MODE,
- MODE_BAND_PASS, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+ MODE_BAND_PASS,
+ G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_TYPE,
- g_param_spec_int ("type", "Type",
- "Type of the chebychev filter", 1, 2,
- 1, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+ g_param_spec_int ("type", "Type", "Type of the chebychev filter", 1, 2, 1,
/* FIXME: Don't use the complete possible range but restrict the upper boundary
* so automatically generated UIs can use a slider without */
g_object_class_install_property (gobject_class, PROP_LOWER_FREQUENCY,
g_param_spec_float ("lower-frequency", "Lower frequency",
"Start frequency of the band (Hz)", 0.0, 100000.0,
- 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+ 0.0,
g_object_class_install_property (gobject_class, PROP_UPPER_FREQUENCY,
g_param_spec_float ("upper-frequency", "Upper frequency",
- "Stop frequency of the band (Hz)", 0.0, 100000.0,
+ "Stop frequency of the band (Hz)", 0.0, 100000.0, 0.0,
g_object_class_install_property (gobject_class, PROP_RIPPLE,
- g_param_spec_float ("ripple", "Ripple",
- "Amount of ripple (dB)", 0.0, 200.0,
- 0.25, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+ g_param_spec_float ("ripple", "Ripple", "Amount of ripple (dB)", 0.0,
+ 200.0, 0.25,
/* FIXME: What to do about this upper boundary? With a frequencies near
* rate/4 32 poles are completely possible, with frequencies very low
* or very high 16 poles already produces only noise */
g_object_class_install_property (gobject_class, PROP_POLES,
g_param_spec_int ("poles", "Poles",
"Number of poles to use, will be rounded up to the next multiply of four",
- 4, 32, 4, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+ 4, 32, 4,
filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_cheb_band_setup);
- trans_class->transform_ip =
- GST_DEBUG_FUNCPTR (gst_audio_cheb_band_transform_ip);
- trans_class->start = GST_DEBUG_FUNCPTR (gst_audio_cheb_band_start);
@@ -280,12 +210,6 @@
filter->type = 1;
filter->poles = 4;
filter->ripple = 0.25;
- gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
- filter->have_coeffs = FALSE;
- filter->num_a = 0;
- filter->num_b = 0;
- filter->channels = NULL;
@@ -474,98 +398,26 @@
}
-/* Evaluate the transfer function that corresponds to the IIR
- * coefficients at zr + zi*I and return the magnitude */
-static gdouble
-calculate_gain (gdouble * a, gdouble * b, gint num_a, gint num_b, gdouble zr,
- gdouble zi)
- gdouble sum_ar, sum_ai;
- gdouble sum_br, sum_bi;
- gdouble gain_r, gain_i;
- gdouble sum_r_old;
- gdouble sum_i_old;
- gint i;
- sum_ar = 0.0;
- sum_ai = 0.0;
- for (i = num_a; i >= 0; i--) {
- sum_r_old = sum_ar;
- sum_i_old = sum_ai;
- sum_ar = (sum_r_old * zr - sum_i_old * zi) + a[i];
- sum_ai = (sum_r_old * zi + sum_i_old * zr) + 0.0;
- sum_br = 0.0;
- sum_bi = 0.0;
- for (i = num_b; i >= 0; i--) {
- sum_r_old = sum_br;
- sum_i_old = sum_bi;
- sum_br = (sum_r_old * zr - sum_i_old * zi) - b[i];
- sum_bi = (sum_r_old * zi + sum_i_old * zr) - 0.0;
- sum_br += 1.0;
- sum_bi += 0.0;
- gain_r =
- (sum_ar * sum_br + sum_ai * sum_bi) / (sum_br * sum_br + sum_bi * sum_bi);
- gain_i =
- (sum_ai * sum_br - sum_ar * sum_bi) / (sum_br * sum_br + sum_bi * sum_bi);
- return (sqrt (gain_r * gain_r + gain_i * gain_i));
generate_coefficients (GstAudioChebBand * filter)
- gint channels = GST_AUDIO_FILTER (filter)->format.channels;
- gint i;
if (GST_AUDIO_FILTER (filter)->format.rate == 0) {
- filter->num_a = 1;
- filter->a = g_new0 (gdouble, 1);
- filter->a[0] = 1.0;
- filter->num_b = 0;
- filter->channels = g_new0 (GstAudioChebBandChannelCtx, channels);
+ gdouble *a = g_new0 (gdouble, 1);
+ a[0] = 1.0;
+ gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+ (filter), a, 1, NULL, 0);
GST_LOG_OBJECT (filter, "rate was not set yet");
return;
- filter->have_coeffs = TRUE;
if (filter->upper_frequency <= filter->lower_frequency) {
- filter->a[0] = (filter->mode == MODE_BAND_PASS) ? 0.0 : 1.0;
+ a[0] = (filter->mode == MODE_BAND_PASS) ? 0.0 : 1.0;
GST_LOG_OBJECT (filter, "frequency band had no or negative dimension");
@@ -586,18 +438,8 @@
gdouble *a, *b;
gint i, p;
- filter->num_a = np + 1;
- filter->a = a = g_new0 (gdouble, np + 5);
- filter->num_b = np + 1;
- filter->b = b = g_new0 (gdouble, np + 5);
- GstAudioChebBandChannelCtx *ctx = &filter->channels[i];
- ctx->x = g_new0 (gdouble, np + 1);
- ctx->y = g_new0 (gdouble, np + 1);
+ a = g_new0 (gdouble, np + 5);
+ b = g_new0 (gdouble, np + 5);
/* Calculate transfer function coefficients */
a[4] = 1.0;
@@ -645,8 +487,12 @@
if (filter->mode == MODE_BAND_REJECT) {
/* gain is sqrt(H(0)*H(0.5)) */
- gdouble gain1 = calculate_gain (a, b, np, np, 1.0, 0.0);
- gdouble gain2 = calculate_gain (a, b, np, np, -1.0, 0.0);
+ gdouble gain1 =
+ gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
+ 1.0, 0.0);
+ gdouble gain2 =
+ -1.0, 0.0);
gain1 = sqrt (gain1 * gain2);
@@ -664,13 +510,18 @@
GST_AUDIO_FILTER (filter)->format.rate);
gdouble w0 = (w2 + w1) / 2.0;
gdouble zr = cos (w0), zi = sin (w0);
- gdouble gain = calculate_gain (a, b, np, np, zr, zi);
+ gdouble gain =
+ gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1, zr,
+ zi);
for (i = 0; i <= np; i++) {
a[i] /= gain;
}
}
+ (filter), a, np + 1, b, np + 1);
GST_LOG_OBJECT (filter,
"Generated IIR coefficients for the Chebyshev filter");
@@ -680,7 +531,8 @@
filter->upper_frequency, filter->ripple);
GST_LOG_OBJECT (filter, "%.2f dB gain @ 0Hz",
- 20.0 * log10 (calculate_gain (a, b, np, np, 1.0, 0.0)));
+ 20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
+ np + 1, 1.0, 0.0)));
{
gdouble w1 =
2.0 * M_PI * (filter->lower_frequency /
@@ -694,21 +546,23 @@
zr = cos (w1);
zi = sin (w1);
GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
- 20.0 * log10 (calculate_gain (a, b, np, np, zr, zi)),
- (int) filter->lower_frequency);
+ 20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
+ b, np + 1, zr, zi)), (int) filter->lower_frequency);
zr = cos (w0);
zi = sin (w0);
+ b, np + 1, zr, zi)),
(int) ((filter->lower_frequency + filter->upper_frequency) / 2.0));
zr = cos (w2);
zi = sin (w2);
- (int) filter->upper_frequency);
+ b, np + 1, zr, zi)), (int) filter->upper_frequency);
GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
- 20.0 * log10 (calculate_gain (a, b, np, np, -1.0, 0.0)),
+ np + 1, -1.0, 0.0)),
GST_AUDIO_FILTER (filter)->format.rate / 2);
@@ -721,40 +575,40 @@
switch (prop_id) {
case PROP_MODE:
- GST_BASE_TRANSFORM_LOCK (filter);
+ GST_OBJECT_LOCK (filter);
filter->mode = g_value_get_enum (value);
generate_coefficients (filter);
- GST_BASE_TRANSFORM_UNLOCK (filter);
+ GST_OBJECT_UNLOCK (filter);
break;
case PROP_TYPE:
filter->type = g_value_get_int (value);
case PROP_LOWER_FREQUENCY:
filter->lower_frequency = g_value_get_float (value);
case PROP_UPPER_FREQUENCY:
filter->upper_frequency = g_value_get_float (value);
case PROP_RIPPLE:
filter->ripple = g_value_get_float (value);
case PROP_POLES:
filter->poles = GST_ROUND_UP_4 (g_value_get_int (value));
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -799,122 +653,8 @@
gst_audio_cheb_band_setup (GstAudioFilter * base, GstRingBufferSpec * format)
GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (base);
- gboolean ret = TRUE;
- if (format->width == 32)
- filter->process = (GstAudioChebBandProcessFunc)
- process_32;
- else if (format->width == 64)
- process_64;
- else
- ret = FALSE;
- return ret;
-static inline gdouble
-process (GstAudioChebBand * filter,
- GstAudioChebBandChannelCtx * ctx, gdouble x0)
- gdouble val = filter->a[0] * x0;
- gint i, j;
- for (i = 1, j = ctx->x_pos; i < filter->num_a; i++) {
- val += filter->a[i] * ctx->x[j];
- j--;
- if (j < 0)
- j = filter->num_a - 1;
- for (i = 1, j = ctx->y_pos; i < filter->num_b; i++) {
- val += filter->b[i] * ctx->y[j];
- j = filter->num_b - 1;
- if (ctx->x) {
- ctx->x_pos++;
- if (ctx->x_pos > filter->num_a - 1)
- ctx->x_pos = 0;
- ctx->x[ctx->x_pos] = x0;
- if (ctx->y) {
- ctx->y_pos++;
- if (ctx->y_pos > filter->num_b - 1)
- ctx->y_pos = 0;
- ctx->y[ctx->y_pos] = val;
- return val;
-#define DEFINE_PROCESS_FUNC(width,ctype) \
-static void \
-process_##width (GstAudioChebBand * filter, \
- g##ctype * data, guint num_samples) \
-{ \
- gint i, j, channels = GST_AUDIO_FILTER (filter)->format.channels; \
- gdouble val; \
- \
- for (i = 0; i < num_samples / channels; i++) { \
- for (j = 0; j < channels; j++) { \
- val = process (filter, &filter->channels[j], *data); \
- *data++ = val; \
- } \
- } \
-DEFINE_PROCESS_FUNC (32, float);
-DEFINE_PROCESS_FUNC (64, double);
-#undef DEFINE_PROCESS_FUNC
-/* GstBaseTransform vmethod implementations */
-gst_audio_cheb_band_transform_ip (GstBaseTransform * base, GstBuffer * buf)
- GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (base);
- guint num_samples =
- GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (filter)->format.width / 8);
- if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
- gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (buf));
- if (gst_base_transform_is_passthrough (base))
- return GST_FLOW_OK;
- if (!filter->have_coeffs)
- generate_coefficients (filter);
- filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
- return GST_FLOW_OK;
-static gboolean
-gst_audio_cheb_band_start (GstBaseTransform * base)
- GstAudioChebBandChannelCtx *ctx;
+ generate_coefficients (filter);
- /* Reset the history of input and output values if
- * already existing */
- if (channels && filter->channels) {
- if (ctx->x)
- memset (ctx->x, 0, (filter->poles + 1) * sizeof (gdouble));
- if (ctx->y)
- memset (ctx->y, 0, (filter->poles + 1) * sizeof (gdouble));
- return TRUE;
+ return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
Index: audiochebband.h
RCS file: /cvs/gstreamer/gst-plugins-good/gst/audiofx/audiochebband.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- audiochebband.h 6 Feb 2008 23:44:35 -0000 1.2
+++ audiochebband.h 5 Jan 2009 10:13:28 -0000 1.3
@@ -26,6 +26,8 @@
#include <gst/audio/audio.h>
#include <gst/audio/gstaudiofilter.h>
+#include "audiofxbaseiirfilter.h"
G_BEGIN_DECLS
#define GST_TYPE_AUDIO_CHEB_BAND (gst_audio_cheb_band_get_type())
#define GST_AUDIO_CHEB_BAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_CHEB_BAND,GstAudioChebBand))
@@ -36,19 +38,9 @@
typedef struct _GstAudioChebBand GstAudioChebBand;
typedef struct _GstAudioChebBandClass GstAudioChebBandClass;
-typedef void (*GstAudioChebBandProcessFunc) (GstAudioChebBand *, guint8 *, guint);
-typedef struct
- gdouble *x;
- gint x_pos;
- gdouble *y;
- gint y_pos;
-} GstAudioChebBandChannelCtx;
struct _GstAudioChebBand
- GstAudioFilter audiofilter;
+ GstAudioFXBaseIIRFilter parent;
gint mode;
gint type;
@@ -56,21 +48,11 @@
gfloat lower_frequency;
gfloat upper_frequency;
gfloat ripple;
- /* < private > */
- GstAudioChebBandProcessFunc process;
- gboolean have_coeffs;
- gdouble *a;
- gint num_a;
- gdouble *b;
- gint num_b;
- GstAudioChebBandChannelCtx *channels;
struct _GstAudioChebBandClass
- GstAudioFilterClass parent;
+ GstAudioFXBaseIIRFilterClass parent;
GType gst_audio_cheb_band_get_type (void);
Index: audiocheblimit.c
RCS file: /cvs/gstreamer/gst-plugins-good/gst/audiofx/audiocheblimit.c,v
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- audiocheblimit.c 30 Aug 2008 14:15:02 -0000 1.9
+++ audiocheblimit.c 5 Jan 2009 10:13:29 -0000 1.10
@@ -88,19 +88,6 @@
#define GST_CAT_DEFAULT gst_audio_cheb_limit_debug
-GST_ELEMENT_DETAILS ("Low pass & high pass filter",
- "Chebyshev low pass and high pass filter",
@@ -111,18 +98,12 @@
GST_DEBUG_CATEGORY_INIT (gst_audio_cheb_limit_debug, "audiocheblimit", 0, "audiocheblimit element");
GST_BOILERPLATE_FULL (GstAudioChebLimit,
- gst_audio_cheb_limit, GstAudioFilter, GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+ gst_audio_cheb_limit, GstAudioFXBaseIIRFilter,
+ GST_TYPE_AUDIO_FX_BASE_IIR_FILTER, DEBUG_INIT);
static void gst_audio_cheb_limit_set_property (GObject * object,
@@ -131,14 +112,6 @@
static gboolean gst_audio_cheb_limit_setup (GstAudioFilter * filter,
-gst_audio_cheb_limit_transform_ip (GstBaseTransform * base, GstBuffer * buf);
-static gboolean gst_audio_cheb_limit_start (GstBaseTransform * base);
-static void process_64 (GstAudioChebLimit * filter,
-static void process_32 (GstAudioChebLimit * filter,
@@ -172,80 +145,42 @@
gst_audio_cheb_limit_base_init (gpointer klass)
-gst_audio_cheb_limit_dispose (GObject * object)
- GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (object);
- GstAudioChebLimitChannelCtx *ctx;
+ "Low pass & high pass filter",
+ "Filter/Effect/Audio",
+ "Chebyshev low pass and high pass filter",
gst_audio_cheb_limit_class_init (GstAudioChebLimitClass * klass)
gobject_class->set_property = gst_audio_cheb_limit_set_property;
gobject_class->get_property = gst_audio_cheb_limit_get_property;
- gobject_class->dispose = gst_audio_cheb_limit_dispose;
"Low pass or high pass mode",
GST_TYPE_AUDIO_CHEBYSHEV_FREQ_LIMIT_MODE, MODE_LOW_PASS,
- G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
g_param_spec_int ("type", "Type", "Type of the chebychev filter", 1, 2, 1,
g_object_class_install_property (gobject_class, PROP_CUTOFF,
g_param_spec_float ("cutoff", "Cutoff", "Cut off frequency (Hz)", 0.0,
- 100000.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+ 100000.0, 0.0,
g_param_spec_float ("ripple", "Ripple", "Amount of ripple (dB)", 0.0,
- 200.0, 0.25, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
/* FIXME: What to do about this upper boundary? With a cutoff frequency of
* rate/4 32 poles are completely possible, with a cutoff frequency very low
@@ -253,12 +188,10 @@
"Number of poles to use, will be rounded up to the next even number",
- 2, 32, 4, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+ 2, 32, 4,
filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_cheb_limit_setup);
- GST_DEBUG_FUNCPTR (gst_audio_cheb_limit_transform_ip);
- trans_class->start = GST_DEBUG_FUNCPTR (gst_audio_cheb_limit_start);
@@ -270,12 +203,6 @@
@@ -423,106 +350,34 @@
generate_coefficients (GstAudioChebLimit * filter)
+ if (GST_AUDIO_FILTER (filter)->format.rate == 0) {
- if (GST_AUDIO_FILTER (filter)->format.rate == 0) {
- filter->channels = g_new0 (GstAudioChebLimitChannelCtx, channels);
if (filter->cutoff >= GST_AUDIO_FILTER (filter)->format.rate / 2.0) {
- filter->a[0] = (filter->mode == MODE_LOW_PASS) ? 1.0 : 0.0;
+ a[0] = (filter->mode == MODE_LOW_PASS) ? 1.0 : 0.0;
GST_LOG_OBJECT (filter, "cutoff was higher than nyquist frequency");
} else if (filter->cutoff <= 0.0) {
- filter->a[0] = (filter->mode == MODE_LOW_PASS) ? 0.0 : 1.0;
+ a[0] = (filter->mode == MODE_LOW_PASS) ? 0.0 : 1.0;
GST_LOG_OBJECT (filter, "cutoff is lower than zero");
@@ -533,18 +388,8 @@
- filter->a = a = g_new0 (gdouble, np + 3);
- filter->b = b = g_new0 (gdouble, np + 3);
- GstAudioChebLimitChannelCtx *ctx = &filter->channels[i];
+ a = g_new0 (gdouble, np + 3);
+ b = g_new0 (gdouble, np + 3);
a[2] = 1.0;
@@ -587,15 +432,22 @@
gdouble gain;
if (filter->mode == MODE_LOW_PASS)
- gain = calculate_gain (a, b, np, np, 1.0, 0.0);
+ gain =
+ gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
+ 1.0, 0.0);
else
- gain = calculate_gain (a, b, np, np, -1.0, 0.0);
+ -1.0, 0.0);
@@ -603,7 +455,8 @@
(filter->mode == MODE_LOW_PASS) ? "low-pass" : "high-pass",
filter->type, filter->poles, filter->cutoff, filter->ripple);
GST_LOG_OBJECT (filter, "%.2f dB gain @ 0 Hz",
#ifndef GST_DISABLE_GST_DEBUG
@@ -613,13 +466,14 @@
gdouble zr = cos (wc), zi = sin (wc);
GST_LOG_OBJECT (filter, "%.2f dB gain @ %d Hz",
- (int) filter->cutoff);
+ b, np + 1, zr, zi)), (int) filter->cutoff);
#endif
GST_LOG_OBJECT (filter, "%.2f dB gain @ %d Hz",
@@ -632,34 +486,34 @@
case PROP_CUTOFF:
filter->cutoff = g_value_get_float (value);
filter->poles = GST_ROUND_UP_2 (g_value_get_int (value));
@@ -701,123 +555,8 @@
gst_audio_cheb_limit_setup (GstAudioFilter * base, GstRingBufferSpec * format)
GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (base);
- filter->process = (GstAudioChebLimitProcessFunc)
-process (GstAudioChebLimit * filter,
- GstAudioChebLimitChannelCtx * ctx, gdouble x0)
-process_##width (GstAudioChebLimit * filter, \
-gst_audio_cheb_limit_transform_ip (GstBaseTransform * base, GstBuffer * buf)
- GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (base);
-gst_audio_cheb_limit_start (GstBaseTransform * base)
- GstAudioChebLimitChannelCtx *ctx;
Index: audiocheblimit.h
RCS file: /cvs/gstreamer/gst-plugins-good/gst/audiofx/audiocheblimit.h,v
--- audiocheblimit.h 6 Feb 2008 23:44:35 -0000 1.2
+++ audiocheblimit.h 5 Jan 2009 10:13:29 -0000 1.3
@@ -26,53 +26,38 @@
#define GST_TYPE_AUDIO_CHEB_LIMIT (gst_audio_cheb_limit_get_type())
#define GST_AUDIO_CHEB_LIMIT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_CHEB_LIMIT,GstAudioChebLimit))
#define GST_IS_AUDIO_CHEB_LIMIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_CHEB_LIMIT))
#define GST_AUDIO_CHEB_LIMIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_CHEB_LIMIT,GstAudioChebLimitClass))
#define GST_IS_AUDIO_CHEB_LIMIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_CHEB_LIMIT))
#define GST_AUDIO_CHEB_LIMIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_CHEB_LIMIT,GstAudioChebLimitClass))
typedef struct _GstAudioChebLimit GstAudioChebLimit;
typedef struct _GstAudioChebLimitClass GstAudioChebLimitClass;
-typedef void (*GstAudioChebLimitProcessFunc) (GstAudioChebLimit *, guint8 *, guint);
-} GstAudioChebLimitChannelCtx;
struct _GstAudioChebLimit
gint poles;
gfloat cutoff;
- GstAudioChebLimitProcessFunc process;
- GstAudioChebLimitChannelCtx *channels;
struct _GstAudioChebLimitClass
GType gst_audio_cheb_limit_get_type (void);
G_END_DECLS
#endif /* __GST_AUDIO_CHEB_LIMIT_H__ */
--- NEW FILE: audiofxbaseiirfilter.c ---
/*
* GStreamer
* Copyright (C) 2007-2009 Sebastian Dröge <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
#include <gst/audio/audio.h>
#include <gst/audio/gstaudiofilter.h>
#include <gst/controller/gstcontroller.h>
#include <math.h>
#include "audiofxbaseiirfilter.h"
#define GST_CAT_DEFAULT gst_audio_fx_base_iir_filter_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define ALLOWED_CAPS \
"audio/x-raw-float," \
" width = (int) { 32, 64 }, " \
" endianness = (int) BYTE_ORDER," \
" rate = (int) [ 1, MAX ]," \
" channels = (int) [ 1, MAX ]"
#define DEBUG_INIT(bla) \
GST_DEBUG_CATEGORY_INIT (gst_audio_fx_base_iir_filter_debug, "audiobaseiirfilter", 0, "Audio IIR Filter Base Class");
GST_BOILERPLATE_FULL (GstAudioFXBaseIIRFilter,
gst_audio_fx_base_iir_filter, GstAudioFilter, GST_TYPE_AUDIO_FILTER,
DEBUG_INIT);
static gboolean gst_audio_fx_base_iir_filter_setup (GstAudioFilter * filter,
GstRingBufferSpec * format);
static GstFlowReturn
gst_audio_fx_base_iir_filter_transform_ip (GstBaseTransform * base,
GstBuffer * buf);
static gboolean gst_audio_fx_base_iir_filter_stop (GstBaseTransform * base);
static void process_64 (GstAudioFXBaseIIRFilter * filter,
gdouble * data, guint num_samples);
static void process_32 (GstAudioFXBaseIIRFilter * filter,
gfloat * data, guint num_samples);
/* GObject vmethod implementations */
static void
gst_audio_fx_base_iir_filter_base_init (gpointer klass)
{
GstCaps *caps;
caps = gst_caps_from_string (ALLOWED_CAPS);
gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
caps);
gst_caps_unref (caps);
}
gst_audio_fx_base_iir_filter_dispose (GObject * object)
GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (object);
if (filter->a) {
g_free (filter->a);
filter->a = NULL;
}
if (filter->b) {
g_free (filter->b);
filter->b = NULL;
if (filter->channels) {
GstAudioFXBaseIIRFilterChannelCtx *ctx;
guint i;
for (i = 0; i < filter->nchannels; i++) {
ctx = &filter->channels[i];
g_free (ctx->x);
g_free (ctx->y);
}
g_free (filter->channels);
filter->channels = NULL;
G_OBJECT_CLASS (parent_class)->dispose (object);
gst_audio_fx_base_iir_filter_class_init (GstAudioFXBaseIIRFilterClass * klass)
GObjectClass *gobject_class = (GObjectClass *) klass;
GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
gobject_class->dispose = gst_audio_fx_base_iir_filter_dispose;
filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_setup);
trans_class->transform_ip =
GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_transform_ip);
trans_class->stop = GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_stop);
gst_audio_fx_base_iir_filter_init (GstAudioFXBaseIIRFilter * filter,
GstAudioFXBaseIIRFilterClass * klass)
gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
filter->a = NULL;
filter->na = 0;
filter->b = NULL;
filter->nb = 0;
filter->channels = NULL;
filter->nchannels = 0;
/* Evaluate the transfer function that corresponds to the IIR
* coefficients at zr + zi*I and return the magnitude */
gdouble
gst_audio_fx_base_iir_filter_calculate_gain (gdouble * a, guint na, gdouble * b,
guint nb, gdouble zr, gdouble zi)
gdouble sum_ar, sum_ai;
gdouble sum_br, sum_bi;
gdouble gain_r, gain_i;
gdouble sum_r_old;
gdouble sum_i_old;
gint i;
sum_ar = 0.0;
sum_ai = 0.0;
for (i = na - 1; i >= 0; i--) {
sum_r_old = sum_ar;
sum_i_old = sum_ai;
sum_ar = (sum_r_old * zr - sum_i_old * zi) + a[i];
sum_ai = (sum_r_old * zi + sum_i_old * zr) + 0.0;
sum_br = 0.0;
sum_bi = 0.0;
for (i = nb - 1; i >= 0; i--) {
sum_r_old = sum_br;
sum_i_old = sum_bi;
sum_br = (sum_r_old * zr - sum_i_old * zi) - b[i];
sum_bi = (sum_r_old * zi + sum_i_old * zr) - 0.0;
sum_br += 1.0;
sum_bi += 0.0;
gain_r =
(sum_ar * sum_br + sum_ai * sum_bi) / (sum_br * sum_br + sum_bi * sum_bi);
gain_i =
(sum_ai * sum_br - sum_ar * sum_bi) / (sum_br * sum_br + sum_bi * sum_bi);
return (sqrt (gain_r * gain_r + gain_i * gain_i));
void
gst_audio_fx_base_iir_filter_set_coefficients (GstAudioFXBaseIIRFilter * filter,
gdouble * a, guint na, gdouble * b, guint nb)
guint i;
g_return_if_fail (GST_IS_AUDIO_FX_BASE_IIR_FILTER (filter));
GST_BASE_TRANSFORM_LOCK (filter);
g_free (filter->a);
g_free (filter->b);
filter->a = filter->b = NULL;
gboolean free = (na != filter->na || nb != filter->nb);
if (free)
g_free (ctx->x);
else
memset (ctx->x, 0, filter->na * sizeof (gdouble));
g_free (ctx->y);
memset (ctx->y, 0, filter->nb * sizeof (gdouble));
filter->na = na;
filter->nb = nb;
filter->a = a;
filter->b = b;
if (filter->nchannels && !filter->channels) {
filter->channels =
g_new0 (GstAudioFXBaseIIRFilterChannelCtx, filter->nchannels);
ctx->x = g_new0 (gdouble, filter->na);
ctx->y = g_new0 (gdouble, filter->nb);
GST_BASE_TRANSFORM_UNLOCK (filter);
/* GstAudioFilter vmethod implementations */
static gboolean
gst_audio_fx_base_iir_filter_setup (GstAudioFilter * base,
GstRingBufferSpec * format)
GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (base);
gboolean ret = TRUE;
if (format->width == 32)
filter->process = (GstAudioFXBaseIIRFilterProcessFunc)
process_32;
else if (format->width == 64)
process_64;
else
ret = FALSE;
if (format->channels != filter->nchannels) {
if (filter->channels) {
for (i = 0; i < filter->nchannels; i++) {
ctx = &filter->channels[i];
}
g_free (filter->channels);
filter->channels = NULL;
filter->nchannels = format->channels;
return ret;
static inline gdouble
process (GstAudioFXBaseIIRFilter * filter,
GstAudioFXBaseIIRFilterChannelCtx * ctx, gdouble x0)
gdouble val = filter->a[0] * x0;
gint i, j;
for (i = 1, j = ctx->x_pos; i < filter->na; i++) {
val += filter->a[i] * ctx->x[j];
j--;
if (j < 0)
j = filter->na - 1;
for (i = 1, j = ctx->y_pos; i < filter->nb; i++) {
val += filter->b[i] * ctx->y[j];
j = filter->nb - 1;
if (ctx->x) {
ctx->x_pos++;
if (ctx->x_pos >= filter->na)
ctx->x_pos = 0;
ctx->x[ctx->x_pos] = x0;
if (ctx->y) {
ctx->y_pos++;
if (ctx->y_pos >= filter->nb)
ctx->y_pos = 0;
ctx->y[ctx->y_pos] = val;
return val;
#define DEFINE_PROCESS_FUNC(width,ctype) \
static void \
process_##width (GstAudioFXBaseIIRFilter * filter, \
g##ctype * data, guint num_samples) \
{ \
gint i, j, channels = GST_AUDIO_FILTER (filter)->format.channels; \
gdouble val; \
\
for (i = 0; i < num_samples / channels; i++) { \
for (j = 0; j < channels; j++) { \
val = process (filter, &filter->channels[j], *data); \
*data++ = val; \
} \
} \
DEFINE_PROCESS_FUNC (32, float);
DEFINE_PROCESS_FUNC (64, double);
#undef DEFINE_PROCESS_FUNC
/* GstBaseTransform vmethod implementations */
GstBuffer * buf)
guint num_samples =
GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (filter)->format.width / 8);
if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (buf));
if (gst_base_transform_is_passthrough (base))
return GST_FLOW_OK;
g_return_val_if_fail (filter->a != NULL, GST_FLOW_ERROR);
filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
return GST_FLOW_OK;
gst_audio_fx_base_iir_filter_stop (GstBaseTransform * base)
guint channels = GST_AUDIO_FILTER (filter)->format.channels;
GstAudioFXBaseIIRFilterChannelCtx *ctx;
/* Reset the history of input and output values if
* already existing */
if (channels && filter->channels) {
for (i = 0; i < channels; i++) {
return TRUE;
--- NEW FILE: audiofxbaseiirfilter.h ---
#ifndef __GST_AUDIO_FX_BASE_IIR_FILTER_H__
#define __GST_AUDIO_FX_BASE_IIR_FILTER_H__
G_BEGIN_DECLS
#define GST_TYPE_AUDIO_FX_BASE_IIR_FILTER (gst_audio_fx_base_iir_filter_get_type())
#define GST_AUDIO_FX_BASE_IIR_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_FX_BASE_IIR_FILTER,GstAudioFXBaseIIRFilter))
#define GST_IS_AUDIO_FX_BASE_IIR_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_FX_BASE_IIR_FILTER))
#define GST_AUDIO_FX_BASE_IIR_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_FX_BASE_IIR_FILTER,GstAudioFXBaseIIRFilterClass))
#define GST_IS_AUDIO_FX_BASE_IIR_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_FX_BASE_IIR_FILTER))
#define GST_AUDIO_FX_BASE_IIR_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_FX_BASE_IIR_FILTER,GstAudioFXBaseIIRFilterClass))
typedef struct _GstAudioFXBaseIIRFilter GstAudioFXBaseIIRFilter;
typedef struct _GstAudioFXBaseIIRFilterClass GstAudioFXBaseIIRFilterClass;
typedef void (*GstAudioFXBaseIIRFilterProcessFunc) (GstAudioFXBaseIIRFilter *, guint8 *, guint);
typedef struct
gdouble *x;
gint x_pos;
gdouble *y;
gint y_pos;
} GstAudioFXBaseIIRFilterChannelCtx;
struct _GstAudioFXBaseIIRFilter
GstAudioFilter audiofilter;
/* < private > */
GstAudioFXBaseIIRFilterProcessFunc process;
gboolean have_coeffs;
gdouble *a;
guint na;
gdouble *b;
guint nb;
GstAudioFXBaseIIRFilterChannelCtx *channels;
guint nchannels;
};
struct _GstAudioFXBaseIIRFilterClass
GstAudioFilterClass parent;
GType gst_audio_fx_base_iir_filter_get_type (void);
void gst_audio_fx_base_iir_filter_set_coefficients (GstAudioFXBaseIIRFilter *filter, gdouble *a, guint na, gdouble *b, guint nb);
gdouble gst_audio_fx_base_iir_filter_calculate_gain (gdouble *a, guint na, gdouble *b, guint nb, gdouble zr, gdouble zi);
G_END_DECLS
#endif /* __GST_AUDIO_FX_BASE_IIR_FILTER_H__ */
------------------------------------------------------------------------------
_______________________________________________
gstreamer-cvs-verbose mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gstreamer-cvs-verbose