upload tizen1.0 source
[framework/multimedia/gst-plugins-good0.10.git] / gst / equalizer / gstiirequalizer.c
1 /* GStreamer
2  * Copyright (C) <2004> Benjamin Otte <otte@gnome.org>
3  *               <2007> Stefan Kost <ensonic@users.sf.net>
4  *               <2007> Sebastian Dröge <slomo@circular-chaos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <math.h>
27 #include <string.h>
28
29 #include "gstiirequalizer.h"
30 #include "gstiirequalizernbands.h"
31 #include "gstiirequalizer3bands.h"
32 #include "gstiirequalizer10bands.h"
33
34 GST_DEBUG_CATEGORY (equalizer_debug);
35 #define GST_CAT_DEFAULT equalizer_debug
36
37 #define BANDS_LOCK(equ) g_mutex_lock(equ->bands_lock)
38 #define BANDS_UNLOCK(equ) g_mutex_unlock(equ->bands_lock)
39
40 static void gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
41     gpointer iface_data);
42
43 static void gst_iir_equalizer_finalize (GObject * object);
44
45 static gboolean gst_iir_equalizer_setup (GstAudioFilter * filter,
46     GstRingBufferSpec * fmt);
47 static GstFlowReturn gst_iir_equalizer_transform_ip (GstBaseTransform * btrans,
48     GstBuffer * buf);
49
50 #define ALLOWED_CAPS \
51     "audio/x-raw-int,"                                                \
52     " depth=(int)16,"                                                 \
53     " width=(int)16,"                                                 \
54     " endianness=(int)BYTE_ORDER,"                                    \
55     " signed=(bool)TRUE,"                                             \
56     " rate=(int)[1000,MAX],"                                          \
57     " channels=(int)[1,MAX]; "                                        \
58     "audio/x-raw-float,"                                              \
59     " width=(int) { 32, 64 } ,"                                       \
60     " endianness=(int)BYTE_ORDER,"                                    \
61     " rate=(int)[1000,MAX],"                                          \
62     " channels=(int)[1,MAX]"
63
64 static void
65 _do_init (GType object_type)
66 {
67   const GInterfaceInfo child_proxy_interface_info = {
68     (GInterfaceInitFunc) gst_iir_equalizer_child_proxy_interface_init,
69     NULL,                       /* interface_finalize */
70     NULL                        /* interface_data */
71   };
72
73   g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
74       &child_proxy_interface_info);
75 }
76
77 GST_BOILERPLATE_FULL (GstIirEqualizer, gst_iir_equalizer,
78     GstAudioFilter, GST_TYPE_AUDIO_FILTER, _do_init);
79
80 /* child object */
81
82 enum
83 {
84   PROP_GAIN = 1,
85   PROP_FREQ,
86   PROP_BANDWIDTH,
87   PROP_TYPE
88 };
89
90 typedef enum
91 {
92   BAND_TYPE_PEAK = 0,
93   BAND_TYPE_LOW_SHELF,
94   BAND_TYPE_HIGH_SHELF
95 } GstIirEqualizerBandType;
96
97 #define GST_TYPE_IIR_EQUALIZER_BAND_TYPE (gst_iir_equalizer_band_type_get_type ())
98 static GType
99 gst_iir_equalizer_band_type_get_type (void)
100 {
101   static GType gtype = 0;
102
103   if (gtype == 0) {
104     static const GEnumValue values[] = {
105       {BAND_TYPE_PEAK, "Peak filter (default for inner bands)", "peak"},
106       {BAND_TYPE_LOW_SHELF, "Low shelf filter (default for first band)",
107           "low-shelf"},
108       {BAND_TYPE_HIGH_SHELF, "High shelf filter (default for last band)",
109           "high-shelf"},
110       {0, NULL, NULL}
111     };
112
113     gtype = g_enum_register_static ("GstIirEqualizerBandType", values);
114   }
115   return gtype;
116 }
117
118
119 typedef struct _GstIirEqualizerBandClass GstIirEqualizerBandClass;
120
121 #define GST_TYPE_IIR_EQUALIZER_BAND \
122   (gst_iir_equalizer_band_get_type())
123 #define GST_IIR_EQUALIZER_BAND(obj) \
124   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IIR_EQUALIZER_BAND,GstIirEqualizerBand))
125 #define GST_IIR_EQUALIZER_BAND_CLASS(klass) \
126   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IIR_EQUALIZER_BAND,GstIirEqualizerBandClass))
127 #define GST_IS_IIR_EQUALIZER_BAND(obj) \
128   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IIR_EQUALIZER_BAND))
129 #define GST_IS_IIR_EQUALIZER_BAND_CLASS(klass) \
130   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IIR_EQUALIZER_BAND))
131
132 struct _GstIirEqualizerBand
133 {
134   GstObject object;
135
136   /*< private > */
137   /* center frequency and gain */
138   gdouble freq;
139   gdouble gain;
140   gdouble width;
141   GstIirEqualizerBandType type;
142
143   /* second order iir filter */
144   gdouble b1, b2;               /* IIR coefficients for outputs */
145   gdouble a0, a1, a2;           /* IIR coefficients for inputs */
146 };
147
148 struct _GstIirEqualizerBandClass
149 {
150   GstObjectClass parent_class;
151 };
152
153 static GType gst_iir_equalizer_band_get_type (void);
154
155 static void
156 gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
157     const GValue * value, GParamSpec * pspec)
158 {
159   GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object);
160   GstIirEqualizer *equ =
161       GST_IIR_EQUALIZER (gst_object_get_parent (GST_OBJECT (band)));
162
163   switch (prop_id) {
164     case PROP_GAIN:{
165       gdouble gain;
166
167       gain = g_value_get_double (value);
168       GST_DEBUG_OBJECT (band, "gain = %lf -> %lf", band->gain, gain);
169       if (gain != band->gain) {
170         BANDS_LOCK (equ);
171         equ->need_new_coefficients = TRUE;
172         band->gain = gain;
173         BANDS_UNLOCK (equ);
174         GST_DEBUG_OBJECT (band, "changed gain = %lf ", band->gain);
175       }
176       break;
177     }
178     case PROP_FREQ:{
179       gdouble freq;
180
181       freq = g_value_get_double (value);
182       GST_DEBUG_OBJECT (band, "freq = %lf -> %lf", band->freq, freq);
183       if (freq != band->freq) {
184         BANDS_LOCK (equ);
185         equ->need_new_coefficients = TRUE;
186         band->freq = freq;
187         BANDS_UNLOCK (equ);
188         GST_DEBUG_OBJECT (band, "changed freq = %lf ", band->freq);
189       }
190       break;
191     }
192     case PROP_BANDWIDTH:{
193       gdouble width;
194
195       width = g_value_get_double (value);
196       GST_DEBUG_OBJECT (band, "width = %lf -> %lf", band->width, width);
197       if (width != band->width) {
198         BANDS_LOCK (equ);
199         equ->need_new_coefficients = TRUE;
200         band->width = width;
201         BANDS_UNLOCK (equ);
202         GST_DEBUG_OBJECT (band, "changed width = %lf ", band->width);
203       }
204       break;
205     }
206     case PROP_TYPE:{
207       GstIirEqualizerBandType type;
208
209       type = g_value_get_enum (value);
210       GST_DEBUG_OBJECT (band, "type = %d -> %d", band->type, type);
211       if (type != band->type) {
212         BANDS_LOCK (equ);
213         equ->need_new_coefficients = TRUE;
214         band->type = type;
215         BANDS_UNLOCK (equ);
216         GST_DEBUG_OBJECT (band, "changed type = %d ", band->type);
217       }
218       break;
219     }
220     default:
221       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
222       break;
223   }
224
225   gst_object_unref (equ);
226 }
227
228 static void
229 gst_iir_equalizer_band_get_property (GObject * object, guint prop_id,
230     GValue * value, GParamSpec * pspec)
231 {
232   GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object);
233
234   switch (prop_id) {
235     case PROP_GAIN:
236       g_value_set_double (value, band->gain);
237       break;
238     case PROP_FREQ:
239       g_value_set_double (value, band->freq);
240       break;
241     case PROP_BANDWIDTH:
242       g_value_set_double (value, band->width);
243       break;
244     case PROP_TYPE:
245       g_value_set_enum (value, band->type);
246       break;
247     default:
248       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
249       break;
250   }
251 }
252
253 static void
254 gst_iir_equalizer_band_class_init (GstIirEqualizerBandClass * klass)
255 {
256   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
257
258   gobject_class->set_property = gst_iir_equalizer_band_set_property;
259   gobject_class->get_property = gst_iir_equalizer_band_get_property;
260
261   g_object_class_install_property (gobject_class, PROP_GAIN,
262       g_param_spec_double ("gain", "gain",
263           "gain for the frequency band ranging from -24.0 dB to +12.0 dB",
264           -24.0, 12.0, 0.0,
265           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
266
267   g_object_class_install_property (gobject_class, PROP_FREQ,
268       g_param_spec_double ("freq", "freq",
269           "center frequency of the band",
270           0.0, 100000.0, 0.0,
271           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
272
273   g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
274       g_param_spec_double ("bandwidth", "bandwidth",
275           "difference between bandedges in Hz",
276           0.0, 100000.0, 1.0,
277           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
278
279   g_object_class_install_property (gobject_class, PROP_TYPE,
280       g_param_spec_enum ("type", "Type",
281           "Filter type", GST_TYPE_IIR_EQUALIZER_BAND_TYPE,
282           BAND_TYPE_PEAK,
283           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
284 }
285
286 static void
287 gst_iir_equalizer_band_init (GstIirEqualizerBand * band,
288     GstIirEqualizerBandClass * klass)
289 {
290   band->freq = 0.0;
291   band->gain = 0.0;
292   band->width = 1.0;
293   band->type = BAND_TYPE_PEAK;
294 }
295
296 static GType
297 gst_iir_equalizer_band_get_type (void)
298 {
299   static GType type = 0;
300
301   if (G_UNLIKELY (!type)) {
302     const GTypeInfo type_info = {
303       sizeof (GstIirEqualizerBandClass),
304       NULL,
305       NULL,
306       (GClassInitFunc) gst_iir_equalizer_band_class_init,
307       NULL,
308       NULL,
309       sizeof (GstIirEqualizerBand),
310       0,
311       (GInstanceInitFunc) gst_iir_equalizer_band_init,
312     };
313     type =
314         g_type_register_static (GST_TYPE_OBJECT, "GstIirEqualizerBand",
315         &type_info, 0);
316   }
317   return (type);
318 }
319
320
321 /* child proxy iface */
322 static GstObject *
323 gst_iir_equalizer_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
324     guint index)
325 {
326   GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy);
327   GstObject *ret;
328
329   BANDS_LOCK (equ);
330   if (G_UNLIKELY (index >= equ->freq_band_count)) {
331     BANDS_UNLOCK (equ);
332     g_return_val_if_fail (index < equ->freq_band_count, NULL);
333   }
334
335   ret = gst_object_ref (equ->bands[index]);
336   BANDS_UNLOCK (equ);
337
338   GST_LOG_OBJECT (equ, "return child[%d] %" GST_PTR_FORMAT, index, ret);
339   return ret;
340 }
341
342 static guint
343 gst_iir_equalizer_child_proxy_get_children_count (GstChildProxy * child_proxy)
344 {
345   GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy);
346
347   GST_LOG ("we have %d children", equ->freq_band_count);
348   return equ->freq_band_count;
349 }
350
351 static void
352 gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
353     gpointer iface_data)
354 {
355   GstChildProxyInterface *iface = g_iface;
356
357   GST_DEBUG ("initializing iface");
358
359   iface->get_child_by_index = gst_iir_equalizer_child_proxy_get_child_by_index;
360   iface->get_children_count = gst_iir_equalizer_child_proxy_get_children_count;
361 }
362
363
364 /* equalizer implementation */
365
366 static void
367 gst_iir_equalizer_base_init (gpointer g_class)
368 {
369   GstAudioFilterClass *audiofilter_class = GST_AUDIO_FILTER_CLASS (g_class);
370   GstCaps *caps;
371
372   caps = gst_caps_from_string (ALLOWED_CAPS);
373   gst_audio_filter_class_add_pad_templates (audiofilter_class, caps);
374   gst_caps_unref (caps);
375 }
376
377 static void
378 gst_iir_equalizer_class_init (GstIirEqualizerClass * klass)
379 {
380   GstAudioFilterClass *audio_filter_class = (GstAudioFilterClass *) klass;
381   GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
382   GObjectClass *gobject_class = (GObjectClass *) klass;
383
384   gobject_class->finalize = gst_iir_equalizer_finalize;
385   audio_filter_class->setup = gst_iir_equalizer_setup;
386   btrans_class->transform_ip = gst_iir_equalizer_transform_ip;
387 }
388
389 static void
390 gst_iir_equalizer_init (GstIirEqualizer * eq, GstIirEqualizerClass * g_class)
391 {
392   eq->bands_lock = g_mutex_new ();
393   eq->need_new_coefficients = TRUE;
394 }
395
396 static void
397 gst_iir_equalizer_finalize (GObject * object)
398 {
399   GstIirEqualizer *equ = GST_IIR_EQUALIZER (object);
400   gint i;
401
402   for (i = 0; i < equ->freq_band_count; i++) {
403     if (equ->bands[i])
404       gst_object_unparent (GST_OBJECT (equ->bands[i]));
405     equ->bands[i] = NULL;
406   }
407   equ->freq_band_count = 0;
408
409   g_free (equ->bands);
410   g_free (equ->history);
411
412   g_mutex_free (equ->bands_lock);
413
414   G_OBJECT_CLASS (parent_class)->finalize (object);
415 }
416
417 /* Filter taken from
418  *
419  * The Equivalence of Various Methods of Computing
420  * Biquad Coefficients for Audio Parametric Equalizers
421  *
422  * by Robert Bristow-Johnson
423  *
424  * http://www.aes.org/e-lib/browse.cfm?elib=6326
425  * http://www.musicdsp.org/files/EQ-Coefficients.pdf
426  * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
427  *
428  * The bandwidth method that we use here is the preferred
429  * one from this article transformed from octaves to frequency
430  * in Hz.
431  */
432 static inline gdouble
433 arg_to_scale (gdouble arg)
434 {
435   return (pow (10.0, arg / 40.0));
436 }
437
438 static gdouble
439 calculate_omega (gdouble freq, gint rate)
440 {
441   gdouble omega;
442
443   if (freq / rate >= 0.5)
444     omega = G_PI;
445   else if (freq <= 0.0)
446     omega = 0.0;
447   else
448     omega = 2.0 * G_PI * (freq / rate);
449
450   return omega;
451 }
452
453 static gdouble
454 calculate_bw (GstIirEqualizerBand * band, gint rate)
455 {
456   gdouble bw = 0.0;
457
458   if (band->width / rate >= 0.5) {
459     /* If bandwidth == 0.5 the calculation below fails as tan(G_PI/2)
460      * is undefined. So set the bandwidth to a slightly smaller value.
461      */
462     bw = G_PI - 0.00000001;
463   } else if (band->width <= 0.0) {
464     /* If bandwidth == 0 this band won't change anything so set
465      * the coefficients accordingly. The coefficient calculation
466      * below would create coefficients that for some reason amplify
467      * the band.
468      */
469     band->a0 = 1.0;
470     band->a1 = 0.0;
471     band->a2 = 0.0;
472     band->b1 = 0.0;
473     band->b2 = 0.0;
474   } else {
475     bw = 2.0 * G_PI * (band->width / rate);
476   }
477   return bw;
478 }
479
480 static void
481 setup_peak_filter (GstIirEqualizer * equ, GstIirEqualizerBand * band)
482 {
483   g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
484
485   {
486     gdouble gain, omega, bw;
487     gdouble alpha, alpha1, alpha2, b0;
488
489     gain = arg_to_scale (band->gain);
490     omega = calculate_omega (band->freq, GST_AUDIO_FILTER (equ)->format.rate);
491     bw = calculate_bw (band, GST_AUDIO_FILTER (equ)->format.rate);
492     if (bw == 0.0)
493       goto out;
494
495     alpha = tan (bw / 2.0);
496
497     alpha1 = alpha * gain;
498     alpha2 = alpha / gain;
499
500     b0 = (1.0 + alpha2);
501
502     band->a0 = (1.0 + alpha1) / b0;
503     band->a1 = (-2.0 * cos (omega)) / b0;
504     band->a2 = (1.0 - alpha1) / b0;
505     band->b1 = (2.0 * cos (omega)) / b0;
506     band->b2 = -(1.0 - alpha2) / b0;
507
508   out:
509     GST_INFO
510         ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
511         band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
512         band->b1, band->b2);
513   }
514 }
515
516 static void
517 setup_low_shelf_filter (GstIirEqualizer * equ, GstIirEqualizerBand * band)
518 {
519   g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
520
521   {
522     gdouble gain, omega, bw;
523     gdouble alpha, delta, b0;
524     gdouble egp, egm;
525
526     gain = arg_to_scale (band->gain);
527     omega = calculate_omega (band->freq, GST_AUDIO_FILTER (equ)->format.rate);
528     bw = calculate_bw (band, GST_AUDIO_FILTER (equ)->format.rate);
529     if (bw == 0.0)
530       goto out;
531
532     egm = gain - 1.0;
533     egp = gain + 1.0;
534     alpha = tan (bw / 2.0);
535
536     delta = 2.0 * sqrt (gain) * alpha;
537     b0 = egp + egm * cos (omega) + delta;
538
539     band->a0 = ((egp - egm * cos (omega) + delta) * gain) / b0;
540     band->a1 = ((egm - egp * cos (omega)) * 2.0 * gain) / b0;
541     band->a2 = ((egp - egm * cos (omega) - delta) * gain) / b0;
542     band->b1 = ((egm + egp * cos (omega)) * 2.0) / b0;
543     band->b2 = -((egp + egm * cos (omega) - delta)) / b0;
544
545
546   out:
547     GST_INFO
548         ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
549         band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
550         band->b1, band->b2);
551   }
552 }
553
554 static void
555 setup_high_shelf_filter (GstIirEqualizer * equ, GstIirEqualizerBand * band)
556 {
557   g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
558
559   {
560     gdouble gain, omega, bw;
561     gdouble alpha, delta, b0;
562     gdouble egp, egm;
563
564     gain = arg_to_scale (band->gain);
565     omega = calculate_omega (band->freq, GST_AUDIO_FILTER (equ)->format.rate);
566     bw = calculate_bw (band, GST_AUDIO_FILTER (equ)->format.rate);
567     if (bw == 0.0)
568       goto out;
569
570     egm = gain - 1.0;
571     egp = gain + 1.0;
572     alpha = tan (bw / 2.0);
573
574     delta = 2.0 * sqrt (gain) * alpha;
575     b0 = egp - egm * cos (omega) + delta;
576
577     band->a0 = ((egp + egm * cos (omega) + delta) * gain) / b0;
578     band->a1 = ((egm + egp * cos (omega)) * -2.0 * gain) / b0;
579     band->a2 = ((egp + egm * cos (omega) - delta) * gain) / b0;
580     band->b1 = ((egm - egp * cos (omega)) * -2.0) / b0;
581     band->b2 = -((egp - egm * cos (omega) - delta)) / b0;
582
583
584   out:
585     GST_INFO
586         ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
587         band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
588         band->b1, band->b2);
589   }
590 }
591
592 /* Must be called with bands_lock and transform lock! */
593 static void
594 set_passthrough (GstIirEqualizer * equ)
595 {
596   gint i;
597   gboolean passthrough = TRUE;
598
599   for (i = 0; i < equ->freq_band_count; i++) {
600     passthrough = passthrough && (equ->bands[i]->gain == 0.0);
601   }
602
603   gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (equ), passthrough);
604   GST_DEBUG ("Passthrough mode: %d\n", passthrough);
605 }
606
607 /* Must be called with bands_lock and transform lock! */
608 static void
609 update_coefficients (GstIirEqualizer * equ)
610 {
611   gint i, n = equ->freq_band_count;
612
613   for (i = 0; i < n; i++) {
614     if (equ->bands[i]->type == BAND_TYPE_PEAK)
615       setup_peak_filter (equ, equ->bands[i]);
616     else if (equ->bands[i]->type == BAND_TYPE_LOW_SHELF)
617       setup_low_shelf_filter (equ, equ->bands[i]);
618     else
619       setup_high_shelf_filter (equ, equ->bands[i]);
620   }
621
622   equ->need_new_coefficients = FALSE;
623 }
624
625 /* Must be called with transform lock! */
626 static void
627 alloc_history (GstIirEqualizer * equ)
628 {
629   /* free + alloc = no memcpy */
630   g_free (equ->history);
631   equ->history =
632       g_malloc0 (equ->history_size * GST_AUDIO_FILTER (equ)->format.channels *
633       equ->freq_band_count);
634 }
635
636 void
637 gst_iir_equalizer_compute_frequencies (GstIirEqualizer * equ, guint new_count)
638 {
639   guint old_count, i;
640   gdouble freq0, freq1, step;
641   gchar name[20];
642
643   if (equ->freq_band_count == new_count)
644     return;
645
646   BANDS_LOCK (equ);
647
648   if (G_UNLIKELY (equ->freq_band_count == new_count)) {
649     BANDS_UNLOCK (equ);
650     return;
651   }
652
653   old_count = equ->freq_band_count;
654   equ->freq_band_count = new_count;
655   GST_DEBUG ("bands %u -> %u", old_count, new_count);
656
657   if (old_count < new_count) {
658     /* add new bands */
659     equ->bands = g_realloc (equ->bands, sizeof (GstObject *) * new_count);
660     for (i = old_count; i < new_count; i++) {
661       equ->bands[i] = g_object_new (GST_TYPE_IIR_EQUALIZER_BAND, NULL);
662       /* otherwise they get names like 'iirequalizerband5' */
663       sprintf (name, "band%u", i);
664       gst_object_set_name (GST_OBJECT (equ->bands[i]), name);
665       GST_DEBUG ("adding band[%d]=%p", i, equ->bands[i]);
666
667       gst_object_set_parent (GST_OBJECT (equ->bands[i]), GST_OBJECT (equ));
668       gst_child_proxy_child_added (GST_OBJECT (equ),
669           GST_OBJECT (equ->bands[i]));
670     }
671   } else {
672     /* free unused bands */
673     for (i = new_count; i < old_count; i++) {
674       GST_DEBUG ("removing band[%d]=%p", i, equ->bands[i]);
675       gst_child_proxy_child_removed (GST_OBJECT (equ),
676           GST_OBJECT (equ->bands[i]));
677       gst_object_unparent (GST_OBJECT (equ->bands[i]));
678       equ->bands[i] = NULL;
679     }
680   }
681
682   alloc_history (equ);
683
684   /* set center frequencies and name band objects
685    * FIXME: arg! we can't change the name of parented objects :(
686    *   application should read band->freq to get the name
687    */
688
689   step = pow (HIGHEST_FREQ / LOWEST_FREQ, 1.0 / new_count);
690   freq0 = LOWEST_FREQ;
691   for (i = 0; i < new_count; i++) {
692     freq1 = freq0 * step;
693
694     if (i == 0)
695       equ->bands[i]->type = BAND_TYPE_LOW_SHELF;
696     else if (i == new_count - 1)
697       equ->bands[i]->type = BAND_TYPE_HIGH_SHELF;
698     else
699       equ->bands[i]->type = BAND_TYPE_PEAK;
700
701     equ->bands[i]->freq = freq0 + ((freq1 - freq0) / 2.0);
702     equ->bands[i]->width = freq1 - freq0;
703     GST_DEBUG ("band[%2d] = '%lf'", i, equ->bands[i]->freq);
704
705     g_object_notify (G_OBJECT (equ->bands[i]), "bandwidth");
706     g_object_notify (G_OBJECT (equ->bands[i]), "freq");
707     g_object_notify (G_OBJECT (equ->bands[i]), "type");
708
709     /*
710        if(equ->bands[i]->freq<10000.0)
711        sprintf (name,"%dHz",(gint)equ->bands[i]->freq);
712        else
713        sprintf (name,"%dkHz",(gint)(equ->bands[i]->freq/1000.0));
714        gst_object_set_name( GST_OBJECT (equ->bands[i]), name);
715        GST_DEBUG ("band[%2d] = '%s'",i,name);
716      */
717     freq0 = freq1;
718   }
719
720   equ->need_new_coefficients = TRUE;
721   BANDS_UNLOCK (equ);
722 }
723
724 /* start of code that is type specific */
725
726 #define CREATE_OPTIMIZED_FUNCTIONS_INT(TYPE,BIG_TYPE,MIN_VAL,MAX_VAL)   \
727 typedef struct {                                                        \
728   BIG_TYPE x1, x2;          /* history of input values for a filter */  \
729   BIG_TYPE y1, y2;          /* history of output values for a filter */ \
730 } SecondOrderHistory ## TYPE;                                           \
731                                                                         \
732 static inline BIG_TYPE                                                  \
733 one_step_ ## TYPE (GstIirEqualizerBand *filter,                         \
734     SecondOrderHistory ## TYPE *history, BIG_TYPE input)                \
735 {                                                                       \
736   /* calculate output */                                                \
737   BIG_TYPE output = filter->a0 * input +                                \
738       filter->a1 * history->x1 + filter->a2 * history->x2 +             \
739       filter->b1 * history->y1 + filter->b2 * history->y2;              \
740   /* update history */                                                  \
741   history->y2 = history->y1;                                            \
742   history->y1 = output;                                                 \
743   history->x2 = history->x1;                                            \
744   history->x1 = input;                                                  \
745                                                                         \
746   return output;                                                        \
747 }                                                                       \
748                                                                         \
749 static const guint                                                      \
750 history_size_ ## TYPE = sizeof (SecondOrderHistory ## TYPE);            \
751                                                                         \
752 static void                                                             \
753 gst_iir_equ_process_ ## TYPE (GstIirEqualizer *equ, guint8 *data,       \
754 guint size, guint channels)                                             \
755 {                                                                       \
756   guint frames = size / channels / sizeof (TYPE);                       \
757   guint i, c, f, nf = equ->freq_band_count;                             \
758   BIG_TYPE cur;                                                         \
759   GstIirEqualizerBand **filters = equ->bands;                           \
760                                                                         \
761   for (i = 0; i < frames; i++) {                                        \
762     SecondOrderHistory ## TYPE *history = equ->history;                 \
763     for (c = 0; c < channels; c++) {                                    \
764       cur = *((TYPE *) data);                                           \
765       for (f = 0; f < nf; f++) {                                        \
766         cur = one_step_ ## TYPE (filters[f], history, cur);             \
767         history++;                                                      \
768       }                                                                 \
769       cur = CLAMP (cur, MIN_VAL, MAX_VAL);                              \
770       *((TYPE *) data) = (TYPE) floor (cur);                            \
771       data += sizeof (TYPE);                                            \
772     }                                                                   \
773   }                                                                     \
774 }
775
776 #define CREATE_OPTIMIZED_FUNCTIONS(TYPE)                                \
777 typedef struct {                                                        \
778   TYPE x1, x2;          /* history of input values for a filter */  \
779   TYPE y1, y2;          /* history of output values for a filter */ \
780 } SecondOrderHistory ## TYPE;                                           \
781                                                                         \
782 static inline TYPE                                                      \
783 one_step_ ## TYPE (GstIirEqualizerBand *filter,                         \
784     SecondOrderHistory ## TYPE *history, TYPE input)                    \
785 {                                                                       \
786   /* calculate output */                                                \
787   TYPE output = filter->a0 * input + filter->a1 * history->x1 +         \
788       filter->a2 * history->x2 + filter->b1 * history->y1 +             \
789       filter->b2 * history->y2;                                         \
790   /* update history */                                                  \
791   history->y2 = history->y1;                                            \
792   history->y1 = output;                                                 \
793   history->x2 = history->x1;                                            \
794   history->x1 = input;                                                  \
795                                                                         \
796   return output;                                                        \
797 }                                                                       \
798                                                                         \
799 static const guint                                                      \
800 history_size_ ## TYPE = sizeof (SecondOrderHistory ## TYPE);            \
801                                                                         \
802 static void                                                             \
803 gst_iir_equ_process_ ## TYPE (GstIirEqualizer *equ, guint8 *data,       \
804 guint size, guint channels)                                             \
805 {                                                                       \
806   guint frames = size / channels / sizeof (TYPE);                       \
807   guint i, c, f, nf = equ->freq_band_count;                             \
808   TYPE cur;                                                             \
809   GstIirEqualizerBand **filters = equ->bands;                           \
810                                                                         \
811   for (i = 0; i < frames; i++) {                                        \
812     SecondOrderHistory ## TYPE *history = equ->history;                 \
813     for (c = 0; c < channels; c++) {                                    \
814       cur = *((TYPE *) data);                                           \
815       for (f = 0; f < nf; f++) {                                        \
816         cur = one_step_ ## TYPE (filters[f], history, cur);             \
817         history++;                                                      \
818       }                                                                 \
819       *((TYPE *) data) = (TYPE) cur;                                    \
820       data += sizeof (TYPE);                                            \
821     }                                                                   \
822   }                                                                     \
823 }
824
825 CREATE_OPTIMIZED_FUNCTIONS_INT (gint16, gfloat, -32768.0, 32767.0);
826 CREATE_OPTIMIZED_FUNCTIONS (gfloat);
827 CREATE_OPTIMIZED_FUNCTIONS (gdouble);
828
829 static GstFlowReturn
830 gst_iir_equalizer_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
831 {
832   GstAudioFilter *filter = GST_AUDIO_FILTER (btrans);
833   GstIirEqualizer *equ = GST_IIR_EQUALIZER (btrans);
834   GstClockTime timestamp;
835
836   if (G_UNLIKELY (filter->format.channels < 1 || equ->process == NULL))
837     return GST_FLOW_NOT_NEGOTIATED;
838
839   BANDS_LOCK (equ);
840   if (equ->need_new_coefficients) {
841     update_coefficients (equ);
842     set_passthrough (equ);
843   }
844   BANDS_UNLOCK (equ);
845
846   if (gst_base_transform_is_passthrough (btrans))
847     return GST_FLOW_OK;
848
849   timestamp = GST_BUFFER_TIMESTAMP (buf);
850   timestamp =
851       gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME, timestamp);
852
853   if (GST_CLOCK_TIME_IS_VALID (timestamp))
854     gst_object_sync_values (G_OBJECT (equ), timestamp);
855
856   equ->process (equ, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
857       filter->format.channels);
858
859   return GST_FLOW_OK;
860 }
861
862 static gboolean
863 gst_iir_equalizer_setup (GstAudioFilter * audio, GstRingBufferSpec * fmt)
864 {
865   GstIirEqualizer *equ = GST_IIR_EQUALIZER (audio);
866
867   switch (fmt->type) {
868     case GST_BUFTYPE_LINEAR:
869       switch (fmt->width) {
870         case 16:
871           equ->history_size = history_size_gint16;
872           equ->process = gst_iir_equ_process_gint16;
873           break;
874         default:
875           return FALSE;
876       }
877       break;
878     case GST_BUFTYPE_FLOAT:
879       switch (fmt->width) {
880         case 32:
881           equ->history_size = history_size_gfloat;
882           equ->process = gst_iir_equ_process_gfloat;
883           break;
884         case 64:
885           equ->history_size = history_size_gdouble;
886           equ->process = gst_iir_equ_process_gdouble;
887           break;
888         default:
889           return FALSE;
890       }
891       break;
892     default:
893       return FALSE;
894   }
895
896   alloc_history (equ);
897   return TRUE;
898 }
899
900
901 static gboolean
902 plugin_init (GstPlugin * plugin)
903 {
904   GST_DEBUG_CATEGORY_INIT (equalizer_debug, "equalizer", 0, "equalizer");
905
906   if (!(gst_element_register (plugin, "equalizer-nbands", GST_RANK_NONE,
907               GST_TYPE_IIR_EQUALIZER_NBANDS)))
908     return FALSE;
909
910   if (!(gst_element_register (plugin, "equalizer-3bands", GST_RANK_NONE,
911               GST_TYPE_IIR_EQUALIZER_3BANDS)))
912     return FALSE;
913
914   if (!(gst_element_register (plugin, "equalizer-10bands", GST_RANK_NONE,
915               GST_TYPE_IIR_EQUALIZER_10BANDS)))
916     return FALSE;
917
918   return TRUE;
919 }
920
921 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
922     GST_VERSION_MINOR,
923     "equalizer",
924     "GStreamer audio equalizers",
925     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)