3 * Copyright (C) 2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
28 #include <gst/base/gstbasetransform.h>
29 #include <gst/audio/audio.h>
30 #include <gst/audio/gstaudiofilter.h>
34 #include "audiofxbaseiirfilter.h"
36 #define GST_CAT_DEFAULT gst_audio_fx_base_iir_filter_debug
37 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
39 #define ALLOWED_CAPS \
41 " format=(string){"GST_AUDIO_NE(F32)","GST_AUDIO_NE(F64)"}," \
42 " rate = (int) [ 1, MAX ]," \
43 " channels = (int) [ 1, MAX ]," \
44 " layout=(string) interleaved"
46 #define gst_audio_fx_base_iir_filter_parent_class parent_class
47 G_DEFINE_TYPE (GstAudioFXBaseIIRFilter,
48 gst_audio_fx_base_iir_filter, GST_TYPE_AUDIO_FILTER);
50 static gboolean gst_audio_fx_base_iir_filter_setup (GstAudioFilter * filter,
51 const GstAudioInfo * info);
53 gst_audio_fx_base_iir_filter_transform_ip (GstBaseTransform * base,
55 static gboolean gst_audio_fx_base_iir_filter_stop (GstBaseTransform * base);
57 static void process_64 (GstAudioFXBaseIIRFilter * filter,
58 gdouble * data, guint num_samples);
59 static void process_32 (GstAudioFXBaseIIRFilter * filter,
60 gfloat * data, guint num_samples);
62 /* GObject vmethod implementations */
65 gst_audio_fx_base_iir_filter_finalize (GObject * object)
67 GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (object);
79 if (filter->channels) {
80 GstAudioFXBaseIIRFilterChannelCtx *ctx;
83 for (i = 0; i < filter->nchannels; i++) {
84 ctx = &filter->channels[i];
89 g_free (filter->channels);
90 filter->channels = NULL;
92 g_mutex_clear (&filter->lock);
94 G_OBJECT_CLASS (parent_class)->finalize (object);
98 gst_audio_fx_base_iir_filter_class_init (GstAudioFXBaseIIRFilterClass * klass)
100 GObjectClass *gobject_class = (GObjectClass *) klass;
101 GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
102 GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
105 GST_DEBUG_CATEGORY_INIT (gst_audio_fx_base_iir_filter_debug,
106 "audiofxbaseiirfilter", 0, "Audio IIR Filter Base Class");
108 gobject_class->finalize = gst_audio_fx_base_iir_filter_finalize;
110 caps = gst_caps_from_string (ALLOWED_CAPS);
111 gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
113 gst_caps_unref (caps);
115 filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_setup);
117 trans_class->transform_ip =
118 GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_transform_ip);
119 trans_class->stop = GST_DEBUG_FUNCPTR (gst_audio_fx_base_iir_filter_stop);
123 gst_audio_fx_base_iir_filter_init (GstAudioFXBaseIIRFilter * filter)
125 gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
131 filter->channels = NULL;
132 filter->nchannels = 0;
134 g_mutex_init (&filter->lock);
137 /* Evaluate the transfer function that corresponds to the IIR
138 * coefficients at (zr + zi*I)^-1 and return the magnitude */
140 gst_audio_fx_base_iir_filter_calculate_gain (gdouble * a, guint na, gdouble * b,
141 guint nb, gdouble zr, gdouble zi)
143 gdouble sum_ar, sum_ai;
144 gdouble sum_br, sum_bi;
145 gdouble gain_r, gain_i;
154 for (i = na - 2; i >= 0; i--) {
158 sum_ar = (sum_r_old * zr - sum_i_old * zi) + a[i];
159 sum_ai = (sum_r_old * zi + sum_i_old * zr) + 0.0;
164 for (i = nb - 2; i >= 0; i--) {
168 sum_br = (sum_r_old * zr - sum_i_old * zi) + b[i];
169 sum_bi = (sum_r_old * zi + sum_i_old * zr) + 0.0;
173 (sum_br * sum_ar + sum_bi * sum_ai) / (sum_ar * sum_ar + sum_ai * sum_ai);
175 (sum_bi * sum_ar - sum_br * sum_ai) / (sum_ar * sum_ar + sum_ai * sum_ai);
177 return (sqrt (gain_r * gain_r + gain_i * gain_i));
181 gst_audio_fx_base_iir_filter_set_coefficients (GstAudioFXBaseIIRFilter * filter,
182 gdouble * a, guint na, gdouble * b, guint nb)
186 g_return_if_fail (GST_IS_AUDIO_FX_BASE_IIR_FILTER (filter));
188 g_mutex_lock (&filter->lock);
193 filter->a = filter->b = NULL;
195 if (filter->channels) {
196 GstAudioFXBaseIIRFilterChannelCtx *ctx;
197 gboolean free = (na != filter->na || nb != filter->nb);
199 for (i = 0; i < filter->nchannels; i++) {
200 ctx = &filter->channels[i];
205 memset (ctx->x, 0, filter->nb * sizeof (gdouble));
210 memset (ctx->y, 0, filter->na * sizeof (gdouble));
213 g_free (filter->channels);
214 filter->channels = NULL;
223 if (filter->nchannels && !filter->channels) {
224 GstAudioFXBaseIIRFilterChannelCtx *ctx;
227 g_new0 (GstAudioFXBaseIIRFilterChannelCtx, filter->nchannels);
228 for (i = 0; i < filter->nchannels; i++) {
229 ctx = &filter->channels[i];
231 ctx->x = g_new0 (gdouble, filter->nb);
232 ctx->y = g_new0 (gdouble, filter->na);
236 g_mutex_unlock (&filter->lock);
239 /* GstAudioFilter vmethod implementations */
242 gst_audio_fx_base_iir_filter_setup (GstAudioFilter * base,
243 const GstAudioInfo * info)
245 GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (base);
249 g_mutex_lock (&filter->lock);
250 switch (GST_AUDIO_INFO_FORMAT (info)) {
251 case GST_AUDIO_FORMAT_F32:
252 filter->process = (GstAudioFXBaseIIRFilterProcessFunc)
255 case GST_AUDIO_FORMAT_F64:
256 filter->process = (GstAudioFXBaseIIRFilterProcessFunc)
264 channels = GST_AUDIO_INFO_CHANNELS (info);
266 if (channels != filter->nchannels) {
268 GstAudioFXBaseIIRFilterChannelCtx *ctx;
270 if (filter->channels) {
271 for (i = 0; i < filter->nchannels; i++) {
272 ctx = &filter->channels[i];
277 g_free (filter->channels);
280 filter->channels = g_new0 (GstAudioFXBaseIIRFilterChannelCtx, channels);
281 for (i = 0; i < channels; i++) {
282 ctx = &filter->channels[i];
284 ctx->x = g_new0 (gdouble, filter->nb);
285 ctx->y = g_new0 (gdouble, filter->na);
287 filter->nchannels = channels;
289 g_mutex_unlock (&filter->lock);
294 static inline gdouble
295 process (GstAudioFXBaseIIRFilter * filter,
296 GstAudioFXBaseIIRFilterChannelCtx * ctx, gdouble x0)
298 gdouble val = filter->b[0] * x0;
301 for (i = 1, j = ctx->x_pos; i < filter->nb; i++) {
302 val += filter->b[i] * ctx->x[j];
308 for (i = 1, j = ctx->y_pos; i < filter->na; i++) {
309 val -= filter->a[i] * ctx->y[j];
318 if (ctx->x_pos >= filter->nb)
320 ctx->x[ctx->x_pos] = x0;
324 if (ctx->y_pos >= filter->na)
327 ctx->y[ctx->y_pos] = val;
333 #define DEFINE_PROCESS_FUNC(width,ctype) \
335 process_##width (GstAudioFXBaseIIRFilter * filter, \
336 g##ctype * data, guint num_samples) \
338 gint i, j, channels = filter->nchannels; \
341 for (i = 0; i < num_samples / channels; i++) { \
342 for (j = 0; j < channels; j++) { \
343 val = process (filter, &filter->channels[j], *data); \
349 DEFINE_PROCESS_FUNC (32, float);
350 DEFINE_PROCESS_FUNC (64, double);
352 #undef DEFINE_PROCESS_FUNC
354 /* GstBaseTransform vmethod implementations */
356 gst_audio_fx_base_iir_filter_transform_ip (GstBaseTransform * base,
359 GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (base);
361 GstClockTime timestamp, stream_time;
364 timestamp = GST_BUFFER_TIMESTAMP (buf);
366 gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
368 GST_DEBUG_OBJECT (filter, "sync to %" GST_TIME_FORMAT,
369 GST_TIME_ARGS (timestamp));
371 if (GST_CLOCK_TIME_IS_VALID (stream_time))
372 gst_object_sync_values (GST_OBJECT (filter), stream_time);
374 if (gst_base_transform_is_passthrough (base))
377 g_return_val_if_fail (filter->a != NULL, GST_FLOW_ERROR);
379 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
380 num_samples = map.size / GST_AUDIO_FILTER_BPS (filter);
382 g_mutex_lock (&filter->lock);
383 filter->process (filter, map.data, num_samples);
384 g_mutex_unlock (&filter->lock);
386 gst_buffer_unmap (buf, &map);
393 gst_audio_fx_base_iir_filter_stop (GstBaseTransform * base)
395 GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (base);
396 guint channels = filter->nchannels;
397 GstAudioFXBaseIIRFilterChannelCtx *ctx;
400 /* Reset the history of input and output values if
401 * already existing */
402 if (channels && filter->channels) {
403 for (i = 0; i < channels; i++) {
404 ctx = &filter->channels[i];
408 g_free (filter->channels);
410 filter->channels = NULL;
411 filter->nchannels = 0;