"Fossies" - the Fresh Open Source Software Archive 
Member "gst-plugins-good-1.20.3/gst/audiofx/audiofirfilter.c" (15 Jun 2022, 8449 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 "audiofirfilter.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-audiofirfilter
24 * @title: audiofirfilter
25 *
26 * audiofirfilter implements a generic audio
27 * [FIR filter](http://en.wikipedia.org/wiki/Finite_impulse_response). Before
28 * usage the "kernel" property has to be set to the filter kernel that should be
29 * used and the "latency" property has to be set to the latency (in samples)
30 * that is introduced by the filter kernel. Setting a latency of n samples
31 * will lead to the first n samples being dropped from the output and
32 * n samples added to the end.
33 *
34 * The filter kernel describes the impulse response of the filter. To
35 * calculate the frequency response of the filter you have to calculate
36 * the Fourier Transform of the impulse response.
37 *
38 * To change the filter kernel whenever the sampling rate changes the
39 * "rate-changed" signal can be used. This should be done for most
40 * FIR filters as they're depending on the sampling rate.
41 *
42 * ## Example application
43 * <programlisting language="C">
44 * <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" parse="text" href="../../../../tests/examples/audiofx/firfilter-example.c" />
45 * ]|
46 *
47 */
48
49 /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
50 * with newer GLib versions (>= 2.31.0) */
51 #define GLIB_DISABLE_DEPRECATION_WARNINGS
52
53 #ifdef HAVE_CONFIG_H
54 #include "config.h"
55 #endif
56
57 #include <string.h>
58 #include <math.h>
59 #include <gst/gst.h>
60 #include <gst/audio/gstaudiofilter.h>
61
62 #include "audiofirfilter.h"
63
64 #include "gst/glib-compat-private.h"
65
66 #define GST_CAT_DEFAULT gst_audio_fir_filter_debug
67 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
68
69 enum
70 {
71 SIGNAL_RATE_CHANGED,
72 LAST_SIGNAL
73 };
74
75 enum
76 {
77 PROP_0,
78 PROP_KERNEL,
79 PROP_LATENCY
80 };
81
82 static guint gst_audio_fir_filter_signals[LAST_SIGNAL] = { 0, };
83
84 #define gst_audio_fir_filter_parent_class parent_class
85 G_DEFINE_TYPE (GstAudioFIRFilter, gst_audio_fir_filter,
86 GST_TYPE_AUDIO_FX_BASE_FIR_FILTER);
87 GST_ELEMENT_REGISTER_DEFINE (audiofirfilter, "audiofirfilter",
88 GST_RANK_NONE, GST_TYPE_AUDIO_FIR_FILTER);
89
90 static void gst_audio_fir_filter_set_property (GObject * object, guint prop_id,
91 const GValue * value, GParamSpec * pspec);
92 static void gst_audio_fir_filter_get_property (GObject * object, guint prop_id,
93 GValue * value, GParamSpec * pspec);
94 static void gst_audio_fir_filter_finalize (GObject * object);
95
96 static gboolean gst_audio_fir_filter_setup (GstAudioFilter * base,
97 const GstAudioInfo * info);
98
99
100 static void
101 gst_audio_fir_filter_class_init (GstAudioFIRFilterClass * klass)
102 {
103 GObjectClass *gobject_class = (GObjectClass *) klass;
104 GstElementClass *gstelement_class = (GstElementClass *) klass;
105 GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
106
107 GST_DEBUG_CATEGORY_INIT (gst_audio_fir_filter_debug, "audiofirfilter", 0,
108 "Generic audio FIR filter plugin");
109
110 gobject_class->set_property = gst_audio_fir_filter_set_property;
111 gobject_class->get_property = gst_audio_fir_filter_get_property;
112 gobject_class->finalize = gst_audio_fir_filter_finalize;
113
114 g_object_class_install_property (gobject_class, PROP_KERNEL,
115 g_param_spec_value_array ("kernel", "Filter Kernel",
116 "Filter kernel for the FIR filter",
117 g_param_spec_double ("Element", "Filter Kernel Element",
118 "Element of the filter kernel", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
119 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
120 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
121 g_object_class_install_property (gobject_class, PROP_LATENCY,
122 g_param_spec_uint64 ("latency", "Latecy",
123 "Filter latency in samples",
124 0, G_MAXUINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
125
126 filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_fir_filter_setup);
127
128 /**
129 * GstAudioFIRFilter::rate-changed:
130 * @filter: the filter on which the signal is emitted
131 * @rate: the new sampling rate
132 *
133 * Will be emitted when the sampling rate changes. The callbacks
134 * will be called from the streaming thread and processing will
135 * stop until the event is handled.
136 */
137 gst_audio_fir_filter_signals[SIGNAL_RATE_CHANGED] =
138 g_signal_new ("rate-changed", G_TYPE_FROM_CLASS (klass),
139 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAudioFIRFilterClass, rate_changed),
140 NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
141
142 gst_element_class_set_static_metadata (gstelement_class,
143 "Audio FIR filter", "Filter/Effect/Audio",
144 "Generic audio FIR filter with custom filter kernel",
145 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
146 }
147
148 static void
149 gst_audio_fir_filter_update_kernel (GstAudioFIRFilter * self, GValueArray * va)
150 {
151 gdouble *kernel;
152 guint i;
153
154 if (va) {
155 if (self->kernel)
156 g_value_array_free (self->kernel);
157
158 self->kernel = va;
159 }
160
161 kernel = g_new (gdouble, self->kernel->n_values);
162
163 for (i = 0; i < self->kernel->n_values; i++) {
164 GValue *v = g_value_array_get_nth (self->kernel, i);
165 kernel[i] = g_value_get_double (v);
166 }
167
168 gst_audio_fx_base_fir_filter_set_kernel (GST_AUDIO_FX_BASE_FIR_FILTER (self),
169 kernel, self->kernel->n_values, self->latency, NULL);
170 }
171
172 static void
173 gst_audio_fir_filter_init (GstAudioFIRFilter * self)
174 {
175 GValue v = { 0, };
176 GValueArray *va;
177
178 self->latency = 0;
179 va = g_value_array_new (1);
180
181 g_value_init (&v, G_TYPE_DOUBLE);
182 g_value_set_double (&v, 1.0);
183 g_value_array_append (va, &v);
184 g_value_unset (&v);
185 gst_audio_fir_filter_update_kernel (self, va);
186
187 g_mutex_init (&self->lock);
188 }
189
190 /* GstAudioFilter vmethod implementations */
191
192 /* get notified of caps and plug in the correct process function */
193 static gboolean
194 gst_audio_fir_filter_setup (GstAudioFilter * base, const GstAudioInfo * info)
195 {
196 GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (base);
197 gint new_rate = GST_AUDIO_INFO_RATE (info);
198
199 if (GST_AUDIO_FILTER_RATE (self) != new_rate) {
200 g_signal_emit (G_OBJECT (self),
201 gst_audio_fir_filter_signals[SIGNAL_RATE_CHANGED], 0, new_rate);
202 }
203
204 return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, info);
205 }
206
207 static void
208 gst_audio_fir_filter_finalize (GObject * object)
209 {
210 GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
211
212 g_mutex_clear (&self->lock);
213
214 if (self->kernel)
215 g_value_array_free (self->kernel);
216 self->kernel = NULL;
217
218 G_OBJECT_CLASS (parent_class)->finalize (object);
219 }
220
221 static void
222 gst_audio_fir_filter_set_property (GObject * object, guint prop_id,
223 const GValue * value, GParamSpec * pspec)
224 {
225 GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
226
227 g_return_if_fail (GST_IS_AUDIO_FIR_FILTER (self));
228
229 switch (prop_id) {
230 case PROP_KERNEL:
231 g_mutex_lock (&self->lock);
232 /* update kernel already pushes residues */
233 gst_audio_fir_filter_update_kernel (self, g_value_dup_boxed (value));
234 g_mutex_unlock (&self->lock);
235 break;
236 case PROP_LATENCY:
237 g_mutex_lock (&self->lock);
238 self->latency = g_value_get_uint64 (value);
239 gst_audio_fir_filter_update_kernel (self, NULL);
240 g_mutex_unlock (&self->lock);
241 break;
242 default:
243 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
244 break;
245 }
246 }
247
248 static void
249 gst_audio_fir_filter_get_property (GObject * object, guint prop_id,
250 GValue * value, GParamSpec * pspec)
251 {
252 GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
253
254 switch (prop_id) {
255 case PROP_KERNEL:
256 g_value_set_boxed (value, self->kernel);
257 break;
258 case PROP_LATENCY:
259 g_value_set_uint64 (value, self->latency);
260 break;
261 default:
262 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
263 break;
264 }
265 }