"Fossies" - the Fresh Open Source Software Archive 
Member "gst-plugins-good-1.20.3/gst/audiofx/audioiirfilter.c" (15 Jun 2022, 8701 Bytes) of package /linux/misc/gst-plugins-good-1.20.3.tar.xz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "audioiirfilter.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.18.6_vs_1.20.0.
1 /*
2 * GStreamer
3 * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
4 *
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.
9 *
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.
14 *
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., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22 /**
23 * SECTION:element-audioiirfilter
24 * @title: audioiirfilter
25 *
26 * audioiirfilter implements a generic audio
27 * [IIR filter](http://en.wikipedia.org/wiki/Infinite_impulse_response).
28 * Before usage the "a" and "b" properties have to be set to the filter
29 * coefficients that should be used.
30 *
31 * The filter coefficients describe the numerator and denominator of the
32 * transfer function.
33 *
34 * To change the filter coefficients whenever the sampling rate changes the
35 * "rate-changed" signal can be used. This should be done for most
36 * IIR filters as they're depending on the sampling rate.
37 *
38 * ## Example application
39 * <programlisting language="C">
40 * <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" parse="text" href="../../../../tests/examples/audiofx/iirfilter-example.c" />
41 * ]|
42 *
43 */
44
45 /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
46 * with newer GLib versions (>= 2.31.0) */
47 #define GLIB_DISABLE_DEPRECATION_WARNINGS
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <string.h>
54 #include <math.h>
55 #include <gst/gst.h>
56 #include <gst/audio/gstaudiofilter.h>
57
58 #include "audioiirfilter.h"
59
60 #include "gst/glib-compat-private.h"
61
62 #define GST_CAT_DEFAULT gst_audio_iir_filter_debug
63 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
64
65 enum
66 {
67 SIGNAL_RATE_CHANGED,
68 LAST_SIGNAL
69 };
70
71 enum
72 {
73 PROP_0,
74 PROP_A,
75 PROP_B
76 };
77
78 static guint gst_audio_iir_filter_signals[LAST_SIGNAL] = { 0, };
79
80 #define gst_audio_iir_filter_parent_class parent_class
81 G_DEFINE_TYPE (GstAudioIIRFilter, gst_audio_iir_filter,
82 GST_TYPE_AUDIO_FX_BASE_IIR_FILTER);
83 GST_ELEMENT_REGISTER_DEFINE (audioiirfilter, "audioiirfilter",
84 GST_RANK_NONE, GST_TYPE_AUDIO_IIR_FILTER);
85
86 static void gst_audio_iir_filter_set_property (GObject * object, guint prop_id,
87 const GValue * value, GParamSpec * pspec);
88 static void gst_audio_iir_filter_get_property (GObject * object, guint prop_id,
89 GValue * value, GParamSpec * pspec);
90 static void gst_audio_iir_filter_finalize (GObject * object);
91
92 static gboolean gst_audio_iir_filter_setup (GstAudioFilter * base,
93 const GstAudioInfo * info);
94
95 static void
96 gst_audio_iir_filter_class_init (GstAudioIIRFilterClass * klass)
97 {
98 GObjectClass *gobject_class = (GObjectClass *) klass;
99 GstElementClass *gstelement_class = (GstElementClass *) klass;
100 GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
101
102 GST_DEBUG_CATEGORY_INIT (gst_audio_iir_filter_debug, "audioiirfilter", 0,
103 "Generic audio IIR filter plugin");
104
105 gobject_class->set_property = gst_audio_iir_filter_set_property;
106 gobject_class->get_property = gst_audio_iir_filter_get_property;
107 gobject_class->finalize = gst_audio_iir_filter_finalize;
108
109 g_object_class_install_property (gobject_class, PROP_A,
110 g_param_spec_value_array ("a", "A",
111 "Filter coefficients (denominator of transfer function)",
112 g_param_spec_double ("Coefficient", "Filter Coefficient",
113 "Filter coefficient", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
114 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
115 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
116 g_object_class_install_property (gobject_class, PROP_B,
117 g_param_spec_value_array ("b", "B",
118 "Filter coefficients (numerator of transfer function)",
119 g_param_spec_double ("Coefficient", "Filter Coefficient",
120 "Filter coefficient", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
121 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
122 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
123
124 filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_iir_filter_setup);
125
126 /**
127 * GstAudioIIRFilter::rate-changed:
128 * @filter: the filter on which the signal is emitted
129 * @rate: the new sampling rate
130 *
131 * Will be emitted when the sampling rate changes. The callbacks
132 * will be called from the streaming thread and processing will
133 * stop until the event is handled.
134 */
135 gst_audio_iir_filter_signals[SIGNAL_RATE_CHANGED] =
136 g_signal_new ("rate-changed", G_TYPE_FROM_CLASS (klass),
137 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAudioIIRFilterClass, rate_changed),
138 NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
139
140 gst_element_class_set_static_metadata (gstelement_class,
141 "Audio IIR filter", "Filter/Effect/Audio",
142 "Generic audio IIR filter with custom filter kernel",
143 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
144 }
145
146 static void
147 gst_audio_iir_filter_update_coefficients (GstAudioIIRFilter * self,
148 GValueArray * va, GValueArray * vb)
149 {
150 gdouble *a = NULL, *b = NULL;
151 guint i;
152
153 if (va) {
154 if (self->a)
155 g_value_array_free (self->a);
156
157 self->a = va;
158 }
159 if (vb) {
160 if (self->b)
161 g_value_array_free (self->b);
162
163 self->b = vb;
164 }
165
166 if (self->a && self->a->n_values > 0) {
167 a = g_new (gdouble, self->a->n_values);
168
169 for (i = 0; i < self->a->n_values; i++) {
170 GValue *v = g_value_array_get_nth (self->a, i);
171 a[i] = g_value_get_double (v);
172 }
173 }
174
175 if (self->b && self->b->n_values > 0) {
176 b = g_new (gdouble, self->b->n_values);
177 for (i = 0; i < self->b->n_values; i++) {
178 GValue *v = g_value_array_get_nth (self->b, i);
179 b[i] = g_value_get_double (v);
180 }
181 }
182
183 gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
184 (self), a, (self->a) ? self->a->n_values : 0, b,
185 (self->b) ? self->b->n_values : 0);
186 }
187
188 static void
189 gst_audio_iir_filter_init (GstAudioIIRFilter * self)
190 {
191 GValue v = { 0, };
192 GValueArray *a;
193
194 a = g_value_array_new (1);
195
196 g_value_init (&v, G_TYPE_DOUBLE);
197 g_value_set_double (&v, 1.0);
198 g_value_array_append (a, &v);
199 g_value_unset (&v);
200
201 gst_audio_iir_filter_update_coefficients (self, a, g_value_array_copy (a));
202
203 g_mutex_init (&self->lock);
204 }
205
206 /* GstAudioFilter vmethod implementations */
207
208 /* get notified of caps and plug in the correct process function */
209 static gboolean
210 gst_audio_iir_filter_setup (GstAudioFilter * base, const GstAudioInfo * info)
211 {
212 GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (base);
213 gint new_rate = GST_AUDIO_INFO_RATE (info);
214
215 if (GST_AUDIO_FILTER_RATE (self) != new_rate) {
216 g_signal_emit (G_OBJECT (self),
217 gst_audio_iir_filter_signals[SIGNAL_RATE_CHANGED], 0, new_rate);
218 }
219
220 return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, info);
221 }
222
223 static void
224 gst_audio_iir_filter_finalize (GObject * object)
225 {
226 GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
227
228 g_mutex_clear (&self->lock);
229
230 if (self->a)
231 g_value_array_free (self->a);
232 self->a = NULL;
233 if (self->b)
234 g_value_array_free (self->b);
235 self->b = NULL;
236
237 G_OBJECT_CLASS (parent_class)->finalize (object);
238 }
239
240 static void
241 gst_audio_iir_filter_set_property (GObject * object, guint prop_id,
242 const GValue * value, GParamSpec * pspec)
243 {
244 GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
245
246 g_return_if_fail (GST_IS_AUDIO_IIR_FILTER (self));
247
248 switch (prop_id) {
249 case PROP_A:
250 g_mutex_lock (&self->lock);
251 gst_audio_iir_filter_update_coefficients (self, g_value_dup_boxed (value),
252 NULL);
253 g_mutex_unlock (&self->lock);
254 break;
255 case PROP_B:
256 g_mutex_lock (&self->lock);
257 gst_audio_iir_filter_update_coefficients (self, NULL,
258 g_value_dup_boxed (value));
259 g_mutex_unlock (&self->lock);
260 break;
261 default:
262 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
263 break;
264 }
265 }
266
267 static void
268 gst_audio_iir_filter_get_property (GObject * object, guint prop_id,
269 GValue * value, GParamSpec * pspec)
270 {
271 GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
272
273 switch (prop_id) {
274 case PROP_A:
275 g_value_set_boxed (value, self->a);
276 break;
277 case PROP_B:
278 g_value_set_boxed (value, self->b);
279 break;
280 default:
281 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
282 break;
283 }
284 }