"Fossies" - the Fresh Open Source Software Archive 
Member "gst-plugins-good-1.20.3/gst/audiofx/audiochebband.c" (15 Jun 2022, 21657 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 "audiochebband.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) 2007-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 * Chebyshev type 1 filter design based on
23 * "The Scientist and Engineer's Guide to DSP", Chapter 20.
24 * http://www.dspguide.com/
25 *
26 * For type 2 and Chebyshev filters in general read
27 * http://en.wikipedia.org/wiki/Chebyshev_filter
28 *
29 * Transformation from lowpass to bandpass/bandreject:
30 * http://docs.dewresearch.com/DspHelp/html/IDH_LinearSystems_LowpassToBandPassZ.htm
31 * http://docs.dewresearch.com/DspHelp/html/IDH_LinearSystems_LowpassToBandStopZ.htm
32 *
33 */
34
35 /**
36 * SECTION:element-audiochebband
37 * @title: audiochebband
38 *
39 * Attenuates all frequencies outside (bandpass) or inside (bandreject) of a frequency
40 * band. The number of poles and the ripple parameter control the rolloff.
41 *
42 * This element has the advantage over the windowed sinc bandpass and bandreject filter that it is
43 * much faster and produces almost as good results. It's only disadvantages are the highly
44 * non-linear phase and the slower rolloff compared to a windowed sinc filter with a large kernel.
45 *
46 * For type 1 the ripple parameter specifies how much ripple in dB is allowed in the passband, i.e.
47 * some frequencies in the passband will be amplified by that value. A higher ripple value will allow
48 * a faster rolloff.
49 *
50 * For type 2 the ripple parameter specifies the stopband attenuation. In the stopband the gain will
51 * be at most this value. A lower ripple value will allow a faster rolloff.
52 *
53 * As a special case, a Chebyshev type 1 filter with no ripple is a Butterworth filter.
54 *
55 * > Be warned that a too large number of poles can produce noise. The most poles are possible with
56 * > a cutoff frequency at a quarter of the sampling rate.
57 *
58 * ## Example launch line
59 * |[
60 * gst-launch-1.0 audiotestsrc freq=1500 ! audioconvert ! audiochebband mode=band-pass lower-frequency=1000 upper-frequency=6000 poles=4 ! audioconvert ! alsasink
61 * gst-launch-1.0 filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audiochebband mode=band-reject lower-frequency=1000 upper-frequency=4000 ripple=0.2 ! audioconvert ! alsasink
62 * gst-launch-1.0 audiotestsrc wave=white-noise ! audioconvert ! audiochebband mode=band-pass lower-frequency=1000 upper-frequency=4000 type=2 ! audioconvert ! alsasink
63 * ]|
64 *
65 */
66
67 #ifdef HAVE_CONFIG_H
68 #include "config.h"
69 #endif
70
71 #include <string.h>
72
73 #include <gst/gst.h>
74 #include <gst/base/gstbasetransform.h>
75 #include <gst/audio/audio.h>
76 #include <gst/audio/gstaudiofilter.h>
77
78 #include <math.h>
79
80 #include "math_compat.h"
81
82 #include "audiochebband.h"
83
84 #include "gst/glib-compat-private.h"
85
86 #define GST_CAT_DEFAULT gst_audio_cheb_band_debug
87 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
88
89 enum
90 {
91 PROP_0,
92 PROP_MODE,
93 PROP_TYPE,
94 PROP_LOWER_FREQUENCY,
95 PROP_UPPER_FREQUENCY,
96 PROP_RIPPLE,
97 PROP_POLES
98 };
99
100 #define gst_audio_cheb_band_parent_class parent_class
101 G_DEFINE_TYPE (GstAudioChebBand, gst_audio_cheb_band,
102 GST_TYPE_AUDIO_FX_BASE_IIR_FILTER);
103 GST_ELEMENT_REGISTER_DEFINE (audiochebband, "audiochebband",
104 GST_RANK_NONE, GST_TYPE_AUDIO_CHEB_BAND);
105
106 static void gst_audio_cheb_band_set_property (GObject * object,
107 guint prop_id, const GValue * value, GParamSpec * pspec);
108 static void gst_audio_cheb_band_get_property (GObject * object,
109 guint prop_id, GValue * value, GParamSpec * pspec);
110 static void gst_audio_cheb_band_finalize (GObject * object);
111
112 static gboolean gst_audio_cheb_band_setup (GstAudioFilter * filter,
113 const GstAudioInfo * info);
114
115 enum
116 {
117 MODE_BAND_PASS = 0,
118 MODE_BAND_REJECT
119 };
120
121 #define GST_TYPE_AUDIO_CHEBYSHEV_FREQ_BAND_MODE (gst_audio_cheb_band_mode_get_type ())
122 static GType
123 gst_audio_cheb_band_mode_get_type (void)
124 {
125 static GType gtype = 0;
126
127 if (gtype == 0) {
128 static const GEnumValue values[] = {
129 {MODE_BAND_PASS, "Band pass (default)",
130 "band-pass"},
131 {MODE_BAND_REJECT, "Band reject",
132 "band-reject"},
133 {0, NULL, NULL}
134 };
135
136 gtype = g_enum_register_static ("GstAudioChebBandMode", values);
137 }
138 return gtype;
139 }
140
141 /* GObject vmethod implementations */
142
143 static void
144 gst_audio_cheb_band_class_init (GstAudioChebBandClass * klass)
145 {
146 GObjectClass *gobject_class = (GObjectClass *) klass;
147 GstElementClass *gstelement_class = (GstElementClass *) klass;
148 GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
149
150 GST_DEBUG_CATEGORY_INIT (gst_audio_cheb_band_debug, "audiochebband", 0,
151 "audiochebband element");
152
153 gobject_class->set_property = gst_audio_cheb_band_set_property;
154 gobject_class->get_property = gst_audio_cheb_band_get_property;
155 gobject_class->finalize = gst_audio_cheb_band_finalize;
156
157 g_object_class_install_property (gobject_class, PROP_MODE,
158 g_param_spec_enum ("mode", "Mode",
159 "Low pass or high pass mode", GST_TYPE_AUDIO_CHEBYSHEV_FREQ_BAND_MODE,
160 MODE_BAND_PASS,
161 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
162 g_object_class_install_property (gobject_class, PROP_TYPE,
163 g_param_spec_int ("type", "Type", "Type of the chebychev filter", 1, 2, 1,
164 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
165
166 /* FIXME: Don't use the complete possible range but restrict the upper boundary
167 * so automatically generated UIs can use a slider without */
168 g_object_class_install_property (gobject_class, PROP_LOWER_FREQUENCY,
169 g_param_spec_float ("lower-frequency", "Lower frequency",
170 "Start frequency of the band (Hz)", 0.0, 100000.0,
171 0.0,
172 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
173 g_object_class_install_property (gobject_class, PROP_UPPER_FREQUENCY,
174 g_param_spec_float ("upper-frequency", "Upper frequency",
175 "Stop frequency of the band (Hz)", 0.0, 100000.0, 0.0,
176 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
177 g_object_class_install_property (gobject_class, PROP_RIPPLE,
178 g_param_spec_float ("ripple", "Ripple", "Amount of ripple (dB)", 0.0,
179 200.0, 0.25,
180 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
181 /* FIXME: What to do about this upper boundary? With a frequencies near
182 * rate/4 32 poles are completely possible, with frequencies very low
183 * or very high 16 poles already produces only noise */
184 g_object_class_install_property (gobject_class, PROP_POLES,
185 g_param_spec_int ("poles", "Poles",
186 "Number of poles to use, will be rounded up to the next multiply of four",
187 4, 32, 4,
188 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
189
190 gst_element_class_set_static_metadata (gstelement_class,
191 "Band pass & band reject filter", "Filter/Effect/Audio",
192 "Chebyshev band pass and band reject filter",
193 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
194
195 filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_cheb_band_setup);
196
197 gst_type_mark_as_plugin_api (GST_TYPE_AUDIO_CHEBYSHEV_FREQ_BAND_MODE, 0);
198 }
199
200 static void
201 gst_audio_cheb_band_init (GstAudioChebBand * filter)
202 {
203 filter->lower_frequency = filter->upper_frequency = 0.0;
204 filter->mode = MODE_BAND_PASS;
205 filter->type = 1;
206 filter->poles = 4;
207 filter->ripple = 0.25;
208
209 g_mutex_init (&filter->lock);
210 }
211
212 static void
213 generate_biquad_coefficients (GstAudioChebBand * filter,
214 gint p, gint rate, gdouble * b0, gdouble * b1, gdouble * b2, gdouble * b3,
215 gdouble * b4, gdouble * a1, gdouble * a2, gdouble * a3, gdouble * a4)
216 {
217 gint np = filter->poles / 2;
218 gdouble ripple = filter->ripple;
219
220 /* pole location in s-plane */
221 gdouble rp, ip;
222
223 /* zero location in s-plane */
224 gdouble iz = 0.0;
225
226 /* transfer function coefficients for the z-plane */
227 gdouble x0, x1, x2, y1, y2;
228 gint type = filter->type;
229
230 /* Calculate pole location for lowpass at frequency 1 */
231 {
232 gdouble angle = (G_PI / 2.0) * (2.0 * p - 1) / np;
233
234 rp = -sin (angle);
235 ip = cos (angle);
236 }
237
238 /* If we allow ripple, move the pole from the unit
239 * circle to an ellipse and keep cutoff at frequency 1 */
240 if (ripple > 0 && type == 1) {
241 gdouble es, vx;
242
243 es = sqrt (pow (10.0, ripple / 10.0) - 1.0);
244
245 vx = (1.0 / np) * asinh (1.0 / es);
246 rp = rp * sinh (vx);
247 ip = ip * cosh (vx);
248 } else if (type == 2) {
249 gdouble es, vx;
250
251 es = sqrt (pow (10.0, ripple / 10.0) - 1.0);
252 vx = (1.0 / np) * asinh (es);
253 rp = rp * sinh (vx);
254 ip = ip * cosh (vx);
255 }
256
257 /* Calculate inverse of the pole location to move from
258 * type I to type II */
259 if (type == 2) {
260 gdouble mag2 = rp * rp + ip * ip;
261
262 rp /= mag2;
263 ip /= mag2;
264 }
265
266 /* Calculate zero location for frequency 1 on the
267 * unit circle for type 2 */
268 if (type == 2) {
269 gdouble angle = G_PI / (np * 2.0) + ((p - 1) * G_PI) / (np);
270 gdouble mag2;
271
272 iz = cos (angle);
273 mag2 = iz * iz;
274 iz /= mag2;
275 }
276
277 /* Convert from s-domain to z-domain by
278 * using the bilinear Z-transform, i.e.
279 * substitute s by (2/t)*((z-1)/(z+1))
280 * with t = 2 * tan(0.5).
281 */
282 if (type == 1) {
283 gdouble t, m, d;
284
285 t = 2.0 * tan (0.5);
286 m = rp * rp + ip * ip;
287 d = 4.0 - 4.0 * rp * t + m * t * t;
288
289 x0 = (t * t) / d;
290 x1 = 2.0 * x0;
291 x2 = x0;
292 y1 = (8.0 - 2.0 * m * t * t) / d;
293 y2 = (-4.0 - 4.0 * rp * t - m * t * t) / d;
294 } else {
295 gdouble t, m, d;
296
297 t = 2.0 * tan (0.5);
298 m = rp * rp + ip * ip;
299 d = 4.0 - 4.0 * rp * t + m * t * t;
300
301 x0 = (t * t * iz * iz + 4.0) / d;
302 x1 = (-8.0 + 2.0 * iz * iz * t * t) / d;
303 x2 = x0;
304 y1 = (8.0 - 2.0 * m * t * t) / d;
305 y2 = (-4.0 - 4.0 * rp * t - m * t * t) / d;
306 }
307
308 /* Convert from lowpass at frequency 1 to either bandpass
309 * or band reject.
310 *
311 * For bandpass substitute z^(-1) with:
312 *
313 * -2 -1
314 * -z + alpha * z - beta
315 * ----------------------------
316 * -2 -1
317 * beta * z - alpha * z + 1
318 *
319 * alpha = (2*a*b)/(1+b)
320 * beta = (b-1)/(b+1)
321 * a = cos((w1 + w0)/2) / cos((w1 - w0)/2)
322 * b = tan(1/2) * cot((w1 - w0)/2)
323 *
324 * For bandreject substitute z^(-1) with:
325 *
326 * -2 -1
327 * z - alpha * z + beta
328 * ----------------------------
329 * -2 -1
330 * beta * z - alpha * z + 1
331 *
332 * alpha = (2*a)/(1+b)
333 * beta = (1-b)/(1+b)
334 * a = cos((w1 + w0)/2) / cos((w1 - w0)/2)
335 * b = tan(1/2) * tan((w1 - w0)/2)
336 *
337 */
338 {
339 gdouble a, b, d;
340 gdouble alpha, beta;
341 gdouble w0 = 2.0 * G_PI * (filter->lower_frequency / rate);
342 gdouble w1 = 2.0 * G_PI * (filter->upper_frequency / rate);
343
344 if (filter->mode == MODE_BAND_PASS) {
345 a = cos ((w1 + w0) / 2.0) / cos ((w1 - w0) / 2.0);
346 b = tan (1.0 / 2.0) / tan ((w1 - w0) / 2.0);
347
348 alpha = (2.0 * a * b) / (1.0 + b);
349 beta = (b - 1.0) / (b + 1.0);
350
351 d = 1.0 + beta * (y1 - beta * y2);
352
353 *b0 = (x0 + beta * (-x1 + beta * x2)) / d;
354 *b1 = (alpha * (-2.0 * x0 + x1 + beta * x1 - 2.0 * beta * x2)) / d;
355 *b2 =
356 (-x1 - beta * beta * x1 + 2.0 * beta * (x0 + x2) +
357 alpha * alpha * (x0 - x1 + x2)) / d;
358 *b3 = (alpha * (x1 + beta * (-2.0 * x0 + x1) - 2.0 * x2)) / d;
359 *b4 = (beta * (beta * x0 - x1) + x2) / d;
360 *a1 = (alpha * (2.0 + y1 + beta * y1 - 2.0 * beta * y2)) / d;
361 *a2 =
362 (-y1 - beta * beta * y1 - alpha * alpha * (1.0 + y1 - y2) +
363 2.0 * beta * (-1.0 + y2)) / d;
364 *a3 = (alpha * (y1 + beta * (2.0 + y1) - 2.0 * y2)) / d;
365 *a4 = (-beta * beta - beta * y1 + y2) / d;
366 } else {
367 a = cos ((w1 + w0) / 2.0) / cos ((w1 - w0) / 2.0);
368 b = tan (1.0 / 2.0) * tan ((w1 - w0) / 2.0);
369
370 alpha = (2.0 * a) / (1.0 + b);
371 beta = (1.0 - b) / (1.0 + b);
372
373 d = -1.0 + beta * (beta * y2 + y1);
374
375 *b0 = (-x0 - beta * x1 - beta * beta * x2) / d;
376 *b1 = (alpha * (2.0 * x0 + x1 + beta * x1 + 2.0 * beta * x2)) / d;
377 *b2 =
378 (-x1 - beta * beta * x1 - 2.0 * beta * (x0 + x2) -
379 alpha * alpha * (x0 + x1 + x2)) / d;
380 *b3 = (alpha * (x1 + beta * (2.0 * x0 + x1) + 2.0 * x2)) / d;
381 *b4 = (-beta * beta * x0 - beta * x1 - x2) / d;
382 *a1 = (alpha * (-2.0 + y1 + beta * y1 + 2.0 * beta * y2)) / d;
383 *a2 =
384 -(y1 + beta * beta * y1 + 2.0 * beta * (-1.0 + y2) +
385 alpha * alpha * (-1.0 + y1 + y2)) / d;
386 *a3 = (alpha * (beta * (-2.0 + y1) + y1 + 2.0 * y2)) / d;
387 *a4 = -(-beta * beta + beta * y1 + y2) / d;
388 }
389 }
390 }
391
392 static void
393 generate_coefficients (GstAudioChebBand * filter, const GstAudioInfo * info)
394 {
395 gint rate;
396
397 if (info) {
398 rate = GST_AUDIO_INFO_RATE (info);
399 } else {
400 rate = GST_AUDIO_FILTER_RATE (filter);
401 }
402
403 if (rate == 0) {
404 gdouble *a = g_new0 (gdouble, 1);
405 gdouble *b = g_new0 (gdouble, 1);
406
407 a[0] = 1.0;
408 b[0] = 1.0;
409 gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
410 (filter), a, 1, b, 1);
411 GST_LOG_OBJECT (filter, "rate was not set yet");
412 return;
413 }
414
415 if (filter->upper_frequency <= filter->lower_frequency) {
416 gdouble *a = g_new0 (gdouble, 1);
417 gdouble *b = g_new0 (gdouble, 1);
418
419 a[0] = 1.0;
420 b[0] = (filter->mode == MODE_BAND_PASS) ? 0.0 : 1.0;
421 gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
422 (filter), a, 1, b, 1);
423
424 GST_LOG_OBJECT (filter, "frequency band had no or negative dimension");
425 return;
426 }
427
428 if (filter->upper_frequency > rate / 2) {
429 filter->upper_frequency = rate / 2;
430 GST_LOG_OBJECT (filter, "clipped upper frequency to nyquist frequency");
431 }
432
433 if (filter->lower_frequency < 0.0) {
434 filter->lower_frequency = 0.0;
435 GST_LOG_OBJECT (filter, "clipped lower frequency to 0.0");
436 }
437
438 /* Calculate coefficients for the chebyshev filter */
439 {
440 gint np = filter->poles;
441 gdouble *a, *b;
442 gint i, p;
443
444 a = g_new0 (gdouble, np + 5);
445 b = g_new0 (gdouble, np + 5);
446
447 /* Calculate transfer function coefficients */
448 a[4] = 1.0;
449 b[4] = 1.0;
450
451 for (p = 1; p <= np / 4; p++) {
452 gdouble b0, b1, b2, b3, b4, a1, a2, a3, a4;
453 gdouble *ta = g_new0 (gdouble, np + 5);
454 gdouble *tb = g_new0 (gdouble, np + 5);
455
456 generate_biquad_coefficients (filter, p, rate,
457 &b0, &b1, &b2, &b3, &b4, &a1, &a2, &a3, &a4);
458
459 memcpy (ta, a, sizeof (gdouble) * (np + 5));
460 memcpy (tb, b, sizeof (gdouble) * (np + 5));
461
462 /* add the new coefficients for the new two poles
463 * to the cascade by multiplication of the transfer
464 * functions */
465 for (i = 4; i < np + 5; i++) {
466 b[i] =
467 b0 * tb[i] + b1 * tb[i - 1] + b2 * tb[i - 2] + b3 * tb[i - 3] +
468 b4 * tb[i - 4];
469 a[i] =
470 ta[i] - a1 * ta[i - 1] - a2 * ta[i - 2] - a3 * ta[i - 3] -
471 a4 * ta[i - 4];
472 }
473 g_free (ta);
474 g_free (tb);
475 }
476
477 /* Move coefficients to the beginning of the array to move from
478 * the transfer function's coefficients to the difference
479 * equation's coefficients */
480 for (i = 0; i <= np; i++) {
481 a[i] = a[i + 4];
482 b[i] = b[i + 4];
483 }
484
485 /* Normalize to unity gain at frequency 0 and frequency
486 * 0.5 for bandreject and unity gain at band center frequency
487 * for bandpass */
488 if (filter->mode == MODE_BAND_REJECT) {
489 /* gain is sqrt(H(0)*H(0.5)) */
490
491 gdouble gain1 =
492 gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
493 1.0, 0.0);
494 gdouble gain2 =
495 gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
496 -1.0, 0.0);
497
498 gain1 = sqrt (gain1 * gain2);
499
500 for (i = 0; i <= np; i++) {
501 b[i] /= gain1;
502 }
503 } else {
504 /* gain is H(wc), wc = center frequency */
505
506 gdouble w1 = 2.0 * G_PI * (filter->lower_frequency / rate);
507 gdouble w2 = 2.0 * G_PI * (filter->upper_frequency / rate);
508 gdouble w0 = (w2 + w1) / 2.0;
509 gdouble zr = cos (w0), zi = sin (w0);
510 gdouble gain =
511 gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1, zr,
512 zi);
513
514 for (i = 0; i <= np; i++) {
515 b[i] /= gain;
516 }
517 }
518
519 gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
520 (filter), a, np + 1, b, np + 1);
521
522 GST_LOG_OBJECT (filter,
523 "Generated IIR coefficients for the Chebyshev filter");
524 GST_LOG_OBJECT (filter,
525 "mode: %s, type: %d, poles: %d, lower-frequency: %.2f Hz, upper-frequency: %.2f Hz, ripple: %.2f dB",
526 (filter->mode == MODE_BAND_PASS) ? "band-pass" : "band-reject",
527 filter->type, filter->poles, filter->lower_frequency,
528 filter->upper_frequency, filter->ripple);
529
530 GST_LOG_OBJECT (filter, "%.2f dB gain @ 0Hz",
531 20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
532 np + 1, 1.0, 0.0)));
533 {
534 gdouble w1 = 2.0 * G_PI * (filter->lower_frequency / rate);
535 gdouble w2 = 2.0 * G_PI * (filter->upper_frequency / rate);
536 gdouble w0 = (w2 + w1) / 2.0;
537 gdouble zr, zi;
538
539 zr = cos (w1);
540 zi = sin (w1);
541 GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
542 20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
543 b, np + 1, zr, zi)), (int) filter->lower_frequency);
544 zr = cos (w0);
545 zi = sin (w0);
546 GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
547 20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
548 b, np + 1, zr, zi)),
549 (int) ((filter->lower_frequency + filter->upper_frequency) / 2.0));
550 zr = cos (w2);
551 zi = sin (w2);
552 GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
553 20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
554 b, np + 1, zr, zi)), (int) filter->upper_frequency);
555 }
556 GST_LOG_OBJECT (filter, "%.2f dB gain @ %dHz",
557 20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
558 np + 1, -1.0, 0.0)), rate / 2);
559 }
560 }
561
562 static void
563 gst_audio_cheb_band_finalize (GObject * object)
564 {
565 GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (object);
566
567 g_mutex_clear (&filter->lock);
568
569 G_OBJECT_CLASS (parent_class)->finalize (object);
570 }
571
572 static void
573 gst_audio_cheb_band_set_property (GObject * object, guint prop_id,
574 const GValue * value, GParamSpec * pspec)
575 {
576 GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (object);
577
578 switch (prop_id) {
579 case PROP_MODE:
580 g_mutex_lock (&filter->lock);
581 filter->mode = g_value_get_enum (value);
582 generate_coefficients (filter, NULL);
583 g_mutex_unlock (&filter->lock);
584 break;
585 case PROP_TYPE:
586 g_mutex_lock (&filter->lock);
587 filter->type = g_value_get_int (value);
588 generate_coefficients (filter, NULL);
589 g_mutex_unlock (&filter->lock);
590 break;
591 case PROP_LOWER_FREQUENCY:
592 g_mutex_lock (&filter->lock);
593 filter->lower_frequency = g_value_get_float (value);
594 generate_coefficients (filter, NULL);
595 g_mutex_unlock (&filter->lock);
596 break;
597 case PROP_UPPER_FREQUENCY:
598 g_mutex_lock (&filter->lock);
599 filter->upper_frequency = g_value_get_float (value);
600 generate_coefficients (filter, NULL);
601 g_mutex_unlock (&filter->lock);
602 break;
603 case PROP_RIPPLE:
604 g_mutex_lock (&filter->lock);
605 filter->ripple = g_value_get_float (value);
606 generate_coefficients (filter, NULL);
607 g_mutex_unlock (&filter->lock);
608 break;
609 case PROP_POLES:
610 g_mutex_lock (&filter->lock);
611 filter->poles = GST_ROUND_UP_4 (g_value_get_int (value));
612 generate_coefficients (filter, NULL);
613 g_mutex_unlock (&filter->lock);
614 break;
615 default:
616 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
617 break;
618 }
619 }
620
621 static void
622 gst_audio_cheb_band_get_property (GObject * object, guint prop_id,
623 GValue * value, GParamSpec * pspec)
624 {
625 GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (object);
626
627 switch (prop_id) {
628 case PROP_MODE:
629 g_value_set_enum (value, filter->mode);
630 break;
631 case PROP_TYPE:
632 g_value_set_int (value, filter->type);
633 break;
634 case PROP_LOWER_FREQUENCY:
635 g_value_set_float (value, filter->lower_frequency);
636 break;
637 case PROP_UPPER_FREQUENCY:
638 g_value_set_float (value, filter->upper_frequency);
639 break;
640 case PROP_RIPPLE:
641 g_value_set_float (value, filter->ripple);
642 break;
643 case PROP_POLES:
644 g_value_set_int (value, filter->poles);
645 break;
646 default:
647 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
648 break;
649 }
650 }
651
652 /* GstAudioFilter vmethod implementations */
653
654 static gboolean
655 gst_audio_cheb_band_setup (GstAudioFilter * base, const GstAudioInfo * info)
656 {
657 GstAudioChebBand *filter = GST_AUDIO_CHEB_BAND (base);
658
659 generate_coefficients (filter, info);
660
661 return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, info);
662 }