Initialize Tizen 2.3
[framework/multimedia/gst-plugins-ext0.10.git] / wearable / audioeq / src / gstaudioeq.c
1 /*
2  * audioeq
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Aditi Narula <aditi.n@samsung.com>
7  *
8  * This library is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the
10  * Free Software Foundation; either version 2.1 of the License, or (at your option)
11  * any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; if not, write to the Free Software Foundation, Inc., 51
20  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include "gstaudioeq.h"
30
31 GST_DEBUG_CATEGORY_STATIC (gst_audioeq_debug);
32 #define GST_CAT_DEFAULT gst_audioeq_debug
33
34 #define AUDIOEQ_ENABLE_DUMP
35 #define AUDIOEQ_REDUCE_MEMCPY
36
37 /* Filter signals and args */
38 enum
39 {
40         /* FILL ME */
41         LAST_SIGNAL
42 };
43
44 enum
45 {
46         PROP_0,
47         PROP_FILTER_ACTION,
48         PROP_CUSTOM_EQ,
49         PROP_CUSTOM_EQ_NUM,
50         PROP_CUSTOM_EQ_FREQ,
51         PROP_CUSTOM_EQ_WIDTH,
52 };
53
54 enum FilterActionType
55 {
56         FILTER_NONE,
57         FILTER_PRESET,
58         FILTER_ADVANCED_SETTING
59 };
60
61 enum SampleRate
62 {
63         SAMPLERATE_48000Hz,
64         SAMPLERATE_44100Hz,
65         SAMPLERATE_32000Hz,
66         SAMPLERATE_24000Hz,
67         SAMPLERATE_22050Hz,
68         SAMPLERATE_16000Hz,
69         SAMPLERATE_12000Hz,
70         SAMPLERATE_11025Hz,
71         SAMPLERATE_8000Hz,
72
73         SAMPLERATE_NUM
74 };
75
76 #define DEFAULT_SAMPLE_SIZE                     2
77 #define DEFAULT_VOLUME                                  15
78 #define DEFAULT_GAIN                                    1
79 #define DEFAULT_SAMPLE_RATE                     SAMPLERATE_44100Hz
80 #define DEAFULT_CHANNELS                                2
81 #define DEFAULT_FILTER_ACTION                   FILTER_NONE
82 #define DEFAULT_CUSTOM_EQ_NUM           7
83
84 static GstStaticPadTemplate sinktemplate =
85         GST_STATIC_PAD_TEMPLATE(
86                 "sink",
87                 GST_PAD_SINK,
88                 GST_PAD_ALWAYS,
89                 GST_STATIC_CAPS (
90                         "audio/x-raw-int, "
91                         "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
92                         "signed = (boolean) true, "
93                         "width = (int) 16, "
94                         "depth = (int) 16, "
95                         "channels = (int) [1,2]"
96                         )
97         );
98
99 static GstStaticPadTemplate srctemplate =
100         GST_STATIC_PAD_TEMPLATE(
101                 "src",
102                 GST_PAD_SRC,
103                 GST_PAD_ALWAYS,
104                 GST_STATIC_CAPS (
105                         "audio/x-raw-int, "
106                         "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
107                         "signed = (boolean) true, "
108                         "width = (int) 16, "
109                         "depth = (int) 16, "
110                         "channels = (int) [1,2]"
111                         )
112         );
113
114 static void gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
115     gpointer iface_data);
116
117 static void gst_iir_equalizer_finalize (GObject * object);
118
119 static gboolean gst_iir_equalizer_setup (GstAudioFilter * filter,
120     GstRingBufferSpec * fmt);
121
122 static void
123 _do_init (GType object_type)
124 {
125   const GInterfaceInfo child_proxy_interface_info = {
126     (GInterfaceInitFunc) gst_iir_equalizer_child_proxy_interface_init,
127     NULL,                       /* interface_finalize */
128     NULL                        /* interface_data */
129   };
130
131   g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
132       &child_proxy_interface_info);
133 }
134
135 GST_BOILERPLATE_FULL(Gstaudioeq, gst_audioeq, GstBaseTransform, GST_TYPE_BASE_TRANSFORM,_do_init);
136
137 static void gst_audioeq_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
138 static void gst_audioeq_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
139 #ifdef AUDIOEQ_REDUCE_MEMCPY
140 static GstFlowReturn gst_audioeq_transform_ip (GstBaseTransform * base, GstBuffer * buf);
141 #else
142 static GstFlowReturn gst_audioeq_transform (GstBaseTransform * base, GstBuffer * inbuf, GstBuffer * outbuf);
143 #endif
144 static gboolean gst_audioeq_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps);
145
146 static GstStateChangeReturn
147 gst_audioeq_change_state (GstElement * element, GstStateChange transition)
148 {
149   GST_DEBUG ("gst_audioeq_change_state");
150         GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
151         Gstaudioeq *audioeq = GST_AUDIOEQ (element);
152
153         switch (transition) {
154         case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
155                 audioeq->need_update_filter = TRUE;
156                 break;
157         default:
158                 break;
159         }
160
161         ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
162
163         if (ret == GST_STATE_CHANGE_FAILURE)
164                 return ret;
165
166         switch (transition) {
167         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
168                 break;
169         default:
170                 break;
171         }
172
173         return ret;
174 }
175
176 static void
177 gst_audioeq_base_init (gpointer gclass)
178 {
179
180   GST_DEBUG ("gst_audioeq_base_init");
181         static GstElementDetails element_details = {
182                 "Audio Equalizer",
183                 "Filter/Effect/Audio",
184                 "Set equalisation effect on audio/raw streams",
185                 "Samsung Electronics <www.samsung.com>"
186         };
187
188         GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
189
190         gst_element_class_add_pad_template(element_class,
191                 gst_static_pad_template_get (&srctemplate));
192         gst_element_class_add_pad_template(element_class,
193                 gst_static_pad_template_get (&sinktemplate));
194
195         gst_element_class_set_details(element_class, &element_details);
196 }
197
198 static void
199 gst_audioeq_class_init (GstaudioeqClass * klass)
200 {
201        GST_DEBUG ("gst_audioeq_class_init");
202         GObjectClass *gobject_class;
203         GstElementClass *gstelement_class;
204         GstBaseTransformClass *basetransform_class;
205
206         gobject_class = G_OBJECT_CLASS (klass);
207         gstelement_class = GST_ELEMENT_CLASS (klass);
208         basetransform_class = GST_BASE_TRANSFORM_CLASS(klass);
209
210         gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_audioeq_set_property);
211         gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_audioeq_get_property);
212
213         gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_audioeq_change_state);
214
215         g_object_class_install_property(gobject_class, PROP_FILTER_ACTION,
216                 g_param_spec_uint("filter-action", "filter action", "(0)none (1)preset (2)advanced setting",
217                 0, 2, DEFAULT_FILTER_ACTION, G_PARAM_READWRITE));
218
219         g_object_class_install_property (gobject_class, PROP_CUSTOM_EQ,
220                 g_param_spec_pointer("custom-eq", "custom eq",
221                 "pointer for 9 bands of EQ array", G_PARAM_READWRITE));
222
223         g_object_class_install_property(gobject_class, PROP_CUSTOM_EQ_NUM,
224                 g_param_spec_uint("custom-eq-num", "custom eq num", "number of custom EQ bands",
225                 0, 9, DEFAULT_CUSTOM_EQ_NUM, G_PARAM_READABLE));
226
227         g_object_class_install_property(gobject_class, PROP_CUSTOM_EQ_FREQ,
228                 g_param_spec_pointer("custom-eq-freq", "custom eq freq", "pointer for EQ bands central frequency(Hz) array",
229                 G_PARAM_READABLE));
230
231         g_object_class_install_property(gobject_class, PROP_CUSTOM_EQ_WIDTH,
232                 g_param_spec_pointer("custom-eq-width", "custom eq width", "pointer for EQ bands width(Hz) array",
233                 G_PARAM_READABLE));
234
235         gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_iir_equalizer_finalize);
236
237 /* It is possible to reduce memcpy by setting output same as input of AudioEq_InOutConfig */
238 #ifdef AUDIOEQ_REDUCE_MEMCPY
239         basetransform_class->transform_ip = GST_DEBUG_FUNCPTR(gst_audioeq_transform_ip);
240 #endif
241         basetransform_class->set_caps = GST_DEBUG_FUNCPTR(gst_audioeq_set_caps);
242 }
243
244 static void
245 gst_audioeq_init (Gstaudioeq * audioeq, GstaudioeqClass * gclass)
246 {
247   GST_DEBUG ("gst_audioeq_init");
248         audioeq->samplerate = DEFAULT_SAMPLE_RATE;
249         audioeq->channels = DEAFULT_CHANNELS;
250
251         audioeq->filter_action = DEFAULT_FILTER_ACTION;
252         memset(audioeq->custom_eq, 0x00, sizeof(gint) * CUSTOM_EQ_BAND_MAX);
253         audioeq->need_update_filter = TRUE;
254         audioeq->equ.bands_lock = g_mutex_new ();
255         audioeq->equ.need_new_coefficients = TRUE;
256         gst_iir_equalizer_compute_frequencies (audioeq, DEFAULT_CUSTOM_EQ_NUM);
257 }
258 /* equalizer implementation */
259
260 static void
261 gst_iir_equalizer_finalize (GObject * object)
262 {
263   GST_DEBUG ("gst_iir_equalizer_finalize");
264   Gstaudioeq *audioeq = GST_AUDIOEQ(object);
265   GstIirEqualizer *equ = &audioeq->equ;
266   gint i;
267
268   for (i = 0; i < equ->freq_band_count; i++) {
269     if (equ->bands[i])
270       gst_object_unparent (GST_OBJECT (equ->bands[i]));
271     equ->bands[i] = NULL;
272   }
273   equ->freq_band_count = 0;
274
275   g_free (equ->bands);
276   g_free (equ->history);
277
278   g_mutex_free (equ->bands_lock);
279
280   G_OBJECT_CLASS (parent_class)->finalize (object);
281 }
282
283 #define BANDS_LOCK(equ) g_mutex_lock(equ->bands_lock)
284 #define BANDS_UNLOCK(equ) g_mutex_unlock(equ->bands_lock)
285
286 /* child object */
287
288 enum
289 {
290   PROP_GAIN = 1,
291   PROP_FREQ,
292   PROP_BANDWIDTH,
293   PROP_TYPE
294 };
295
296 typedef enum
297 {
298   BAND_TYPE_PEAK = 0,
299   BAND_TYPE_LOW_SHELF,
300   BAND_TYPE_HIGH_SHELF
301 } GstIirEqualizerBandType;
302
303 #define GST_TYPE_IIR_EQUALIZER_BAND_TYPE (gst_iir_equalizer_band_type_get_type ())
304 static GType
305 gst_iir_equalizer_band_type_get_type (void)
306 {
307   GST_DEBUG ("gst_iir_equalizer_band_type_get_type");
308   static GType gtype = 0;
309
310   if (gtype == 0) {
311     static const GEnumValue values[] = {
312       {BAND_TYPE_PEAK, "Peak filter (default for inner bands)", "peak"},
313       {BAND_TYPE_LOW_SHELF, "Low shelf filter (default for first band)",
314           "low-shelf"},
315       {BAND_TYPE_HIGH_SHELF, "High shelf filter (default for last band)",
316           "high-shelf"},
317       {0, NULL, NULL}
318     };
319
320     gtype = g_enum_register_static ("GstIirEqualizerBandType", values);
321   }
322   return gtype;
323 }
324
325
326 typedef struct _GstIirEqualizerBandClass GstIirEqualizerBandClass;
327
328 #define GST_TYPE_IIR_EQUALIZER_BAND \
329   (gst_iir_equalizer_band_get_type())
330 #define GST_IIR_EQUALIZER_BAND(obj) \
331   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IIR_EQUALIZER_BAND,GstIirEqualizerBand))
332 #define GST_IIR_EQUALIZER_BAND_CLASS(klass) \
333   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IIR_EQUALIZER_BAND,GstIirEqualizerBandClass))
334 #define GST_IS_IIR_EQUALIZER_BAND(obj) \
335   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IIR_EQUALIZER_BAND))
336 #define GST_IS_IIR_EQUALIZER_BAND_CLASS(klass) \
337   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IIR_EQUALIZER_BAND))
338
339 struct _GstIirEqualizerBand
340 {
341   GstObject object;
342
343   /*< private > */
344   /* center frequency and gain */
345   gdouble freq;
346   gdouble gain;
347   gdouble width;
348   GstIirEqualizerBandType type;
349
350   /* second order iir filter */
351   gdouble b1, b2;               /* IIR coefficients for outputs */
352   gdouble a0, a1, a2;           /* IIR coefficients for inputs */
353 };
354
355 struct _GstIirEqualizerBandClass
356 {
357   GstObjectClass parent_class;
358 };
359
360 static GType gst_iir_equalizer_band_get_type (void);
361
362 static void
363 gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
364     const GValue * value, GParamSpec * pspec)
365 {
366   GST_DEBUG ("gst_iir_equalizer_band_set_property");
367   GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object);
368   Gstaudioeq *audioeq = GST_AUDIOEQ (gst_object_get_parent (GST_OBJECT (band)));
369   GstIirEqualizer *equ = &audioeq->equ;
370
371   switch (prop_id) {
372     case PROP_GAIN:{
373       gdouble gain;
374
375       gain = g_value_get_double (value);
376       GST_DEBUG_OBJECT (band, "gain = %lf -> %lf", band->gain, gain);
377       if (gain != band->gain) {
378         BANDS_LOCK (equ);
379         equ->need_new_coefficients = TRUE;
380         band->gain = gain;
381         BANDS_UNLOCK (equ);
382         GST_DEBUG_OBJECT (band, "changed gain = %lf ", band->gain);
383       }
384       break;
385     }
386     case PROP_FREQ:{
387       gdouble freq;
388
389       freq = g_value_get_double (value);
390       GST_DEBUG_OBJECT (band, "freq = %lf -> %lf", band->freq, freq);
391       if (freq != band->freq) {
392         BANDS_LOCK (equ);
393         equ->need_new_coefficients = TRUE;
394         band->freq = freq;
395         BANDS_UNLOCK (equ);
396         GST_DEBUG_OBJECT (band, "changed freq = %lf ", band->freq);
397       }
398       break;
399     }
400     case PROP_BANDWIDTH:{
401       gdouble width;
402
403       width = g_value_get_double (value);
404       GST_DEBUG_OBJECT (band, "width = %lf -> %lf", band->width, width);
405       if (width != band->width) {
406         BANDS_LOCK (equ);
407         equ->need_new_coefficients = TRUE;
408         band->width = width;
409         BANDS_UNLOCK (equ);
410         GST_DEBUG_OBJECT (band, "changed width = %lf ", band->width);
411       }
412       break;
413     }
414     case PROP_TYPE:{
415       GstIirEqualizerBandType type;
416
417       type = g_value_get_enum (value);
418       GST_DEBUG_OBJECT (band, "type = %d -> %d", band->type, type);
419       if (type != band->type) {
420         BANDS_LOCK (equ);
421         equ->need_new_coefficients = TRUE;
422         band->type = type;
423         BANDS_UNLOCK (equ);
424         GST_DEBUG_OBJECT (band, "changed type = %d ", band->type);
425       }
426       break;
427     }
428     default:
429       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
430       break;
431   }
432
433   gst_object_unref (audioeq);
434 }
435
436 static void
437 gst_iir_equalizer_band_get_property (GObject * object, guint prop_id,
438     GValue * value, GParamSpec * pspec)
439 {
440   GST_DEBUG ("gst_iir_equalizer_band_get_property");
441   GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object);
442
443   switch (prop_id) {
444     case PROP_GAIN:
445       g_value_set_double (value, band->gain);
446       break;
447     case PROP_FREQ:
448       g_value_set_double (value, band->freq);
449       break;
450     case PROP_BANDWIDTH:
451       g_value_set_double (value, band->width);
452       break;
453     case PROP_TYPE:
454       g_value_set_enum (value, band->type);
455       break;
456     default:
457       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
458       break;
459   }
460 }
461
462 static void
463 gst_iir_equalizer_band_class_init (GstIirEqualizerBandClass * klass)
464 {
465   GST_DEBUG ("gst_iir_equalizer_band_class_init");
466   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
467
468   gobject_class->set_property = gst_iir_equalizer_band_set_property;
469   gobject_class->get_property = gst_iir_equalizer_band_get_property;
470
471   g_object_class_install_property (gobject_class, PROP_GAIN,
472       g_param_spec_double ("gain", "gain",
473           "gain for the frequency band ranging from -12.0 dB to +12.0 dB",
474           -12.0, 12.0, 0.0,
475           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
476
477   g_object_class_install_property (gobject_class, PROP_FREQ,
478       g_param_spec_double ("freq", "freq",
479           "center frequency of the band",
480           0.0, 100000.0, 0.0,
481           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
482
483   g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
484       g_param_spec_double ("bandwidth", "bandwidth",
485           "difference between bandedges in Hz",
486           0.0, 100000.0, 1.0,
487           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
488
489   g_object_class_install_property (gobject_class, PROP_TYPE,
490       g_param_spec_enum ("type", "Type",
491           "Filter type", GST_TYPE_IIR_EQUALIZER_BAND_TYPE,
492           BAND_TYPE_PEAK,
493           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
494 }
495
496 static void
497 gst_iir_equalizer_band_init (GstIirEqualizerBand * band,
498     GstIirEqualizerBandClass * klass)
499 {
500   GST_DEBUG ("gst_iir_equalizer_band_init");
501   band->freq = 0.0;
502   band->gain = 0.0;
503   band->width = 1.0;
504   band->type = BAND_TYPE_PEAK;
505 }
506
507 static GType
508 gst_iir_equalizer_band_get_type (void)
509 {
510   GST_DEBUG ("gst_iir_equalizer_band_get_type");
511   static GType type = 0;
512
513   if (G_UNLIKELY (!type)) {
514     const GTypeInfo type_info = {
515       sizeof (GstIirEqualizerBandClass),
516       NULL,
517       NULL,
518       (GClassInitFunc) gst_iir_equalizer_band_class_init,
519       NULL,
520       NULL,
521       sizeof (GstIirEqualizerBand),
522       0,
523       (GInstanceInitFunc) gst_iir_equalizer_band_init,
524     };
525     type =
526         g_type_register_static (GST_TYPE_OBJECT, "GstIirEqualizerBand",
527         &type_info, 0);
528   }
529   return (type);
530 }
531
532
533 /* child proxy iface */
534 static GstObject *
535 gst_iir_equalizer_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
536     guint index)
537 {
538   GST_DEBUG ("gst_iir_equalizer_child_proxy_get_child_by_index");
539   Gstaudioeq *audioeq = GST_AUDIOEQ(child_proxy);
540   GstIirEqualizer *equ = &audioeq->equ;
541   GstObject *ret;
542
543   BANDS_LOCK (equ);
544   if (G_UNLIKELY (index >= equ->freq_band_count)) {
545     BANDS_UNLOCK (equ);
546     g_return_val_if_fail (index < equ->freq_band_count, NULL);
547   }
548
549   ret = gst_object_ref (equ->bands[index]);
550   BANDS_UNLOCK (equ);
551
552   GST_LOG_OBJECT (equ, "return child[%d] %" GST_PTR_FORMAT, index, ret);
553   return ret;
554 }
555
556 static guint
557 gst_iir_equalizer_child_proxy_get_children_count (GstChildProxy * child_proxy)
558 {
559   GST_DEBUG ("gst_iir_equalizer_child_proxy_get_children_count");
560   Gstaudioeq *audioeq = GST_AUDIOEQ(child_proxy);
561   GstIirEqualizer *equ = &audioeq->equ;
562
563   GST_LOG ("we have %d children", equ->freq_band_count);
564   return equ->freq_band_count;
565 }
566
567 static void
568 gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
569     gpointer iface_data)
570 {
571   GstChildProxyInterface *iface = g_iface;
572
573   GST_DEBUG ("initializing iface");
574
575   iface->get_child_by_index = gst_iir_equalizer_child_proxy_get_child_by_index;
576   iface->get_children_count = gst_iir_equalizer_child_proxy_get_children_count;
577 }
578 static void
579 gst_iir_equalizer_class_init (GstIirEqualizerClass * klass)
580 {
581   GST_DEBUG ("gst_iir_equalizer_class_init");
582 }
583
584 static void
585 gst_iir_equalizer_init (GstIirEqualizer * eq, GstIirEqualizerClass * g_class)
586 {
587   GST_DEBUG ("gst_iir_equalizer_init");
588   eq->bands_lock = g_mutex_new ();
589   eq->need_new_coefficients = TRUE;
590 }
591
592 GType
593 gst_iir_equalizer_get_type (void)
594 {
595   GST_DEBUG ("gst_iir_equalizer_get_type");
596   static GType type = 0;
597
598   if (G_UNLIKELY (!type)) {
599     const GTypeInfo type_info = {
600       sizeof (GstIirEqualizerClass),
601       NULL,
602       NULL,
603       (GClassInitFunc) gst_iir_equalizer_class_init,
604       NULL,
605       NULL,
606       sizeof (GstIirEqualizer),
607       0,
608       (GInstanceInitFunc) gst_iir_equalizer_init,
609     };
610     type =
611         g_type_register_static (GST_TYPE_OBJECT, "GstIirEqualizer",
612         &type_info, 0);
613   }
614   return (type);
615 }
616 /* Filter taken from
617  *
618  * The Equivalence of Various Methods of Computing
619  * Biquad Coefficients for Audio Parametric Equalizers
620  *
621  * by Robert Bristow-Johnson
622  *
623  * http://www.aes.org/e-lib/browse.cfm?elib=6326
624  * http://www.musicdsp.org/files/EQ-Coefficients.pdf
625  * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
626  *
627  * The bandwidth method that we use here is the preferred
628  * one from this article transformed from octaves to frequency
629  * in Hz.
630  */
631 static inline gdouble
632 arg_to_scale (gdouble arg)
633 {
634   GST_DEBUG ("arg_to_scale");
635   return (pow (10.0, arg / 40.0));
636 }
637
638 static gdouble
639 calculate_omega (gdouble freq, gint rate)
640 {
641   GST_DEBUG ("calculate_omega");
642   gdouble omega;
643
644   if (freq / rate >= 0.5)
645     omega = G_PI;
646   else if (freq <= 0.0)
647     omega = 0.0;
648   else
649     omega = 2.0 * G_PI * (freq / rate);
650
651   return omega;
652 }
653
654 static gdouble
655 calculate_bw (GstIirEqualizerBand * band, gint rate)
656 {
657   GST_DEBUG ("calculate_bw");
658   gdouble bw = 0.0;
659
660   if (band->width / rate >= 0.5) {
661     /* If bandwidth == 0.5 the calculation below fails as tan(G_PI/2)
662      * is undefined. So set the bandwidth to a slightly smaller value.
663      */
664     bw = G_PI - 0.00000001;
665   } else if (band->width <= 0.0) {
666     /* If bandwidth == 0 this band won't change anything so set
667      * the coefficients accordingly. The coefficient calculation
668      * below would create coefficients that for some reason amplify
669      * the band.
670      */
671     band->a0 = 1.0;
672     band->a1 = 0.0;
673     band->a2 = 0.0;
674     band->b1 = 0.0;
675     band->b2 = 0.0;
676   } else {
677     bw = 2.0 * G_PI * (band->width / rate);
678   }
679   return bw;
680 }
681
682 static void
683 setup_peak_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
684 {
685   GST_DEBUG ("setup_peak_filter");
686   //g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
687
688   {
689     gdouble gain, omega, bw;
690     gdouble alpha, alpha1, alpha2, b0;
691
692     gain = arg_to_scale (band->gain);
693     omega = calculate_omega (band->freq, audioeq->samplerate);
694     bw = calculate_bw (band, audioeq->samplerate);
695     if (bw == 0.0)
696       goto out;
697
698     alpha = tan (bw / 2.0);
699
700     alpha1 = alpha * gain;
701     alpha2 = alpha / gain;
702
703     b0 = (1.0 + alpha2);
704
705     band->a0 = (1.0 + alpha1) / b0;
706     band->a1 = (-2.0 * cos (omega)) / b0;
707     band->a2 = (1.0 - alpha1) / b0;
708     band->b1 = (2.0 * cos (omega)) / b0;
709     band->b2 = -(1.0 - alpha2) / b0;
710
711   out:
712     GST_INFO
713         ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
714         band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
715         band->b1, band->b2);
716   }
717 }
718
719 static void
720 setup_low_shelf_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
721 {
722   GST_DEBUG ("setup_low_shelf_filter");
723   //g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
724
725   {
726     gdouble gain, omega, bw;
727     gdouble alpha, delta, b0;
728     gdouble egp, egm;
729
730     gain = arg_to_scale (band->gain);
731     omega = calculate_omega (band->freq, audioeq->samplerate);
732     bw = calculate_bw (band, audioeq->samplerate);
733     if (bw == 0.0)
734       goto out;
735
736     egm = gain - 1.0;
737     egp = gain + 1.0;
738     alpha = tan (bw / 2.0);
739
740     delta = 2.0 * sqrt (gain) * alpha;
741     b0 = egp + egm * cos (omega) + delta;
742
743     band->a0 = ((egp - egm * cos (omega) + delta) * gain) / b0;
744     band->a1 = ((egm - egp * cos (omega)) * 2.0 * gain) / b0;
745     band->a2 = ((egp - egm * cos (omega) - delta) * gain) / b0;
746     band->b1 = ((egm + egp * cos (omega)) * 2.0) / b0;
747     band->b2 = -((egp + egm * cos (omega) - delta)) / b0;
748
749
750   out:
751     GST_INFO
752         ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
753         band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
754         band->b1, band->b2);
755   }
756 }
757
758 static void
759 setup_high_shelf_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
760 {
761   GST_DEBUG ("setup_high_shelf_filter");
762   {
763     gdouble gain, omega, bw;
764     gdouble alpha, delta, b0;
765     gdouble egp, egm;
766
767     gain = arg_to_scale (band->gain);
768     omega = calculate_omega (band->freq, audioeq->samplerate);
769     bw = calculate_bw (band, audioeq->samplerate);
770     if (bw == 0.0)
771       goto out;
772
773     egm = gain - 1.0;
774     egp = gain + 1.0;
775     alpha = tan (bw / 2.0);
776
777     delta = 2.0 * sqrt (gain) * alpha;
778     b0 = egp - egm * cos (omega) + delta;
779
780     band->a0 = ((egp + egm * cos (omega) + delta) * gain) / b0;
781     band->a1 = ((egm + egp * cos (omega)) * -2.0 * gain) / b0;
782     band->a2 = ((egp + egm * cos (omega) - delta) * gain) / b0;
783     band->b1 = ((egm - egp * cos (omega)) * -2.0) / b0;
784     band->b2 = -((egp - egm * cos (omega) - delta)) / b0;
785
786
787   out:
788     GST_INFO
789         ("gain = %5.1f, width= %7.2f, freq = %7.2f, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
790         band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
791         band->b1, band->b2);
792   }
793 }
794
795 /* Must be called with bands_lock and transform lock! */
796 static void
797 set_passthrough (Gstaudioeq* audioeq)
798 {
799   GST_DEBUG ("set_passthrough");
800   GstIirEqualizer* equ=&audioeq->equ;
801   gint i;
802   gboolean passthrough = TRUE;
803
804   for (i = 0; i < equ->freq_band_count; i++) {
805     passthrough = passthrough && (equ->bands[i]->gain == 0.0);
806   }
807
808   gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (audioeq), passthrough);
809   GST_DEBUG ("Passthrough mode: %d\n", passthrough);
810 }
811
812 /* Must be called with bands_lock and transform lock! */
813 static void
814 update_coefficients (Gstaudioeq* audioeq)
815 {
816   GST_DEBUG ("update_coefficients");
817   GstIirEqualizer* equ=&audioeq->equ;
818   gint i, n = equ->freq_band_count;
819
820   for (i = 0; i < n; i++) {
821     if (equ->bands[i]->type == BAND_TYPE_PEAK)
822       setup_peak_filter (audioeq, equ->bands[i]);
823     else if (equ->bands[i]->type == BAND_TYPE_LOW_SHELF)
824       setup_low_shelf_filter (audioeq, equ->bands[i]);
825     else
826       setup_high_shelf_filter (audioeq, equ->bands[i]);
827   }
828
829   equ->need_new_coefficients = FALSE;
830 }
831
832 /* Must be called with transform lock! */
833 static void
834 alloc_history (GstIirEqualizer * equ)
835 {
836   GST_DEBUG ("alloc_history");
837   /* free + alloc = no memcpy */
838   g_free (equ->history);
839   equ->history =
840       g_malloc0 (equ->history_size *  equ->audiofilter.format.channels *
841       equ->freq_band_count);
842 }
843 void
844 gst_audioeq_band_set_property(Gstaudioeq * audioeq)
845 {
846   GST_DEBUG ("gst_audioeq_band_set_property");
847   GstIirEqualizer *equ = &audioeq->equ;
848   gshort i ;
849   for ( i = 0; i < DEFAULT_CUSTOM_EQ_NUM; i++){
850      GST_DEBUG ("gain = %lf -> %d", equ->bands[i]->gain, audioeq->custom_eq[i] );
851      if (audioeq->custom_eq[i] != equ->bands[i]->gain) {
852         equ->bands[i]->gain = audioeq->custom_eq[i];
853         GST_DEBUG("changed gain = %lf ", equ->bands[i]->gain);
854         g_object_notify (G_OBJECT (equ->bands[i]), "gain");
855      }
856   }
857 }
858
859 void
860 gst_iir_equalizer_compute_frequencies (Gstaudioeq * audioeq, guint new_count)
861 {
862   GST_DEBUG ("gst_iir_equalizer_compute_frequencies");
863
864   GstIirEqualizer *equ = &audioeq->equ;
865   guint old_count, i;
866   gdouble freq0, freq1, step;
867   gchar name[20];
868   GST_DEBUG ("gst_iir_equalizer_compute_frequencies before calling equalizer object");
869   if (equ->freq_band_count == new_count)
870     return;
871
872   GST_DEBUG ("gst_iir_equalizer_compute_frequencies equalizer object");
873
874   BANDS_LOCK (equ);
875   GST_DEBUG ("gst_iir_equalizer_compute_frequencies 1");
876   if (G_UNLIKELY (equ->freq_band_count == new_count)) {
877     BANDS_UNLOCK (equ);
878     return;
879   }
880   GST_DEBUG ("gst_iir_equalizer_compute_frequencies 2");
881   old_count = equ->freq_band_count;
882   equ->freq_band_count = new_count;
883   GST_DEBUG ("bands %u -> %u", old_count, new_count);
884
885   if (old_count < new_count) {
886     /* add new bands */
887     equ->bands = g_realloc (equ->bands, sizeof (GstObject *) * new_count);
888     for (i = old_count; i < new_count; i++) {
889       equ->bands[i] = g_object_new (GST_TYPE_IIR_EQUALIZER_BAND, NULL);
890       /* otherwise they get names like 'iirequalizerband5' */
891       sprintf (name, "band%u", i);
892       gst_object_set_name (GST_OBJECT (equ->bands[i]), name);
893       GST_DEBUG ("adding band[%d]=%p", i, equ->bands[i]);
894
895       gst_object_set_parent (GST_OBJECT (equ->bands[i]), GST_OBJECT (audioeq));
896       gst_child_proxy_child_added (GST_OBJECT (audioeq),
897           GST_OBJECT (equ->bands[i]));
898     }
899   } else {
900     /* free unused bands */
901     for (i = new_count; i < old_count; i++) {
902       GST_DEBUG ("removing band[%d]=%p", i, equ->bands[i]);
903       gst_child_proxy_child_removed (GST_OBJECT (audioeq),
904           GST_OBJECT (equ->bands[i]));
905       gst_object_unparent (GST_OBJECT (equ->bands[i]));
906       equ->bands[i] = NULL;
907     }
908   }
909
910   alloc_history (equ);
911
912   /* set center frequencies and name band objects
913    * FIXME: arg! we can't change the name of parented objects :(
914    *   application should read band->freq to get the name
915    */
916
917   step = pow (HIGHEST_FREQ / LOWEST_FREQ, 1.0 / new_count);
918   freq0 = LOWEST_FREQ;
919   for (i = 0; i < new_count; i++) {
920     freq1 = freq0 * step;
921
922     if (i == 0)
923       equ->bands[i]->type = BAND_TYPE_LOW_SHELF;
924     else if (i == new_count - 1)
925       equ->bands[i]->type = BAND_TYPE_HIGH_SHELF;
926     else
927       equ->bands[i]->type = BAND_TYPE_PEAK;
928
929     equ->bands[i]->freq = freq0 + ((freq1 - freq0) / 2.0);
930     equ->bands[i]->width = freq1 - freq0;
931     GST_DEBUG ("band[%2d] = '%lf'", i, equ->bands[i]->freq);
932
933     g_object_notify (G_OBJECT (equ->bands[i]), "bandwidth");
934     g_object_notify (G_OBJECT (equ->bands[i]), "freq");
935     g_object_notify (G_OBJECT (equ->bands[i]), "type");
936
937     freq0 = freq1;
938   }
939
940   equ->need_new_coefficients = TRUE;
941
942   BANDS_UNLOCK (equ);
943 }
944 /* start of code that is type specific */
945
946 #define CREATE_OPTIMIZED_FUNCTIONS_INT(TYPE,BIG_TYPE,MIN_VAL,MAX_VAL)   \
947 typedef struct {                                                        \
948   BIG_TYPE x1, x2;          /* history of input values for a filter */  \
949   BIG_TYPE y1, y2;          /* history of output values for a filter */ \
950 } SecondOrderHistory ## TYPE;                                           \
951                                                                         \
952 static inline BIG_TYPE                                                  \
953 one_step_ ## TYPE (GstIirEqualizerBand *filter,                         \
954     SecondOrderHistory ## TYPE *history, BIG_TYPE input)                \
955 {                                                                       \
956   /* calculate output */                                                \
957   BIG_TYPE output = filter->a0 * input +                                \
958       filter->a1 * history->x1 + filter->a2 * history->x2 +             \
959       filter->b1 * history->y1 + filter->b2 * history->y2;              \
960   /* update history */                                                  \
961   history->y2 = history->y1;                                            \
962   history->y1 = output;                                                 \
963   history->x2 = history->x1;                                            \
964   history->x1 = input;                                                  \
965                                                                         \
966   return output;                                                        \
967 }                                                                       \
968                                                                         \
969 static const guint                                                      \
970 history_size_ ## TYPE = sizeof (SecondOrderHistory ## TYPE);            \
971                                                                         \
972 static void                                                             \
973 gst_iir_equ_process_ ## TYPE (GstIirEqualizer *equ, guint8 *data,       \
974 guint size, guint channels)                                             \
975 {                                                                       \
976   guint frames = size / channels / sizeof (TYPE);                       \
977   guint i, c, f, nf = equ->freq_band_count;                             \
978   BIG_TYPE cur;                                                         \
979   GstIirEqualizerBand **filters = equ->bands;                           \
980                                                                         \
981   for (i = 0; i < frames; i++) {                                        \
982     SecondOrderHistory ## TYPE *history = equ->history;                 \
983     for (c = 0; c < channels; c++) {                                    \
984       cur = *((TYPE *) data);                                           \
985       for (f = 0; f < nf; f++) {                                        \
986         cur = one_step_ ## TYPE (filters[f], history, cur);             \
987         history++;                                                      \
988       }                                                                 \
989       cur = CLAMP (cur, MIN_VAL, MAX_VAL);                              \
990       *((TYPE *) data) = (TYPE) floor (cur);                            \
991       data += sizeof (TYPE);                                            \
992     }                                                                   \
993   }                                                                     \
994 }
995
996 #define CREATE_OPTIMIZED_FUNCTIONS(TYPE)                                \
997 typedef struct {                                                        \
998   TYPE x1, x2;          /* history of input values for a filter */  \
999   TYPE y1, y2;          /* history of output values for a filter */ \
1000 } SecondOrderHistory ## TYPE;                                           \
1001                                                                         \
1002 static inline TYPE                                                      \
1003 one_step_ ## TYPE (GstIirEqualizerBand *filter,                         \
1004     SecondOrderHistory ## TYPE *history, TYPE input)                    \
1005 {                                                                       \
1006   /* calculate output */                                                \
1007   TYPE output = filter->a0 * input + filter->a1 * history->x1 +         \
1008       filter->a2 * history->x2 + filter->b1 * history->y1 +             \
1009       filter->b2 * history->y2;                                         \
1010   /* update history */                                                  \
1011   history->y2 = history->y1;                                            \
1012   history->y1 = output;                                                 \
1013   history->x2 = history->x1;                                            \
1014   history->x1 = input;                                                  \
1015                                                                         \
1016   return output;                                                        \
1017 }                                                                       \
1018                                                                         \
1019 static const guint                                                      \
1020 history_size_ ## TYPE = sizeof (SecondOrderHistory ## TYPE);            \
1021                                                                         \
1022 static void                                                             \
1023 gst_iir_equ_process_ ## TYPE (GstIirEqualizer *equ, guint8 *data,       \
1024 guint size, guint channels)                                             \
1025 {                                                                       \
1026   guint frames = size / channels / sizeof (TYPE);                       \
1027   guint i, c, f, nf = equ->freq_band_count;                             \
1028   TYPE cur;                                                             \
1029   GstIirEqualizerBand **filters = equ->bands;                           \
1030                                                                         \
1031   for (i = 0; i < frames; i++) {                                        \
1032     SecondOrderHistory ## TYPE *history = equ->history;                 \
1033     for (c = 0; c < channels; c++) {                                    \
1034       cur = *((TYPE *) data);                                           \
1035       for (f = 0; f < nf; f++) {                                        \
1036         cur = one_step_ ## TYPE (filters[f], history, cur);             \
1037         history++;                                                      \
1038       }                                                                 \
1039       *((TYPE *) data) = (TYPE) cur;                                    \
1040       data += sizeof (TYPE);                                            \
1041     }                                                                   \
1042   }                                                                     \
1043 }
1044
1045 CREATE_OPTIMIZED_FUNCTIONS_INT (gint16, gfloat, -32768.0, 32767.0);
1046 CREATE_OPTIMIZED_FUNCTIONS (gfloat);
1047 CREATE_OPTIMIZED_FUNCTIONS (gdouble);
1048
1049 #ifdef AUDIOEQ_REDUCE_MEMCPY
1050 static GstFlowReturn
1051 gst_audioeq_transform_ip (GstBaseTransform * base, GstBuffer * buf)
1052 {
1053   GST_DEBUG ("gst_audioeq_transform_ip");
1054   Gstaudioeq *audioeq = GST_AUDIOEQ(base);
1055   GstIirEqualizer *equ = &audioeq->equ;
1056
1057   equ->history_size = history_size_gint16;
1058   equ->process = gst_iir_equ_process_gint16;
1059    g_free (equ->history);
1060   equ->history = g_malloc0 (equ->history_size *  audioeq->channels * equ->freq_band_count);
1061   GstClockTime timestamp;
1062
1063   if (G_UNLIKELY (audioeq->channels < 1 || equ->process == NULL)) {
1064     GST_DEBUG ("gst_audioeq_transform_ip return GST_FLOW_NOT_NEGOTIATED;");
1065     if (G_UNLIKELY (equ->process == NULL))
1066     GST_DEBUG ("gst_audioeq_transform_ip equ->process ");
1067     if (G_UNLIKELY (audioeq->channels < 1))
1068     GST_DEBUG ("gst_audioeq_transform_ip audioeq->channels");
1069     return GST_FLOW_NOT_NEGOTIATED;
1070   }
1071       GST_DEBUG ("gst_audioeq_transform_ip  BANDS_LOCK (equ);");
1072   BANDS_LOCK (equ);
1073   if (equ->need_new_coefficients) {
1074     GST_DEBUG ("gst_audioeq_transform_ip  update_coefficients");
1075     update_coefficients (audioeq);
1076     set_passthrough (audioeq);
1077   }
1078   BANDS_UNLOCK (equ);
1079
1080   if (gst_base_transform_is_passthrough (base)) {
1081     GST_DEBUG ("gst_audioeq_transform_ip gst_base_transform_is_passthrough return GST_FLOW_OK;");
1082     return GST_FLOW_OK;
1083   }
1084   timestamp = GST_BUFFER_TIMESTAMP (buf);
1085   timestamp =
1086       gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
1087
1088   if (GST_CLOCK_TIME_IS_VALID (timestamp))
1089     gst_object_sync_values (G_OBJECT (audioeq), timestamp);
1090   GST_DEBUG ("  equ->process ++");
1091   equ->process (equ, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
1092       audioeq->channels);
1093   GST_DEBUG ("  equ->process --");
1094   GST_DEBUG ("gst_audioeq_transform_ip return GST_FLOW_OK;");
1095   return GST_FLOW_OK;
1096 }
1097 #endif
1098
1099 static gboolean
1100 gst_audioeq_set_caps (GstBaseTransform * base, GstCaps * incaps,
1101         GstCaps * outcaps)
1102 {
1103   GST_DEBUG ("gst_audioeq_set_caps");
1104         Gstaudioeq *audioeq = GST_AUDIOEQ(base);
1105         GstStructure *ins;
1106         GstPad *pad;
1107         gint samplerate;
1108         gint channels;
1109         gshort old_samplerate;
1110         gshort old_channels;
1111
1112         pad = gst_element_get_static_pad(GST_ELEMENT(audioeq), "src");
1113
1114         /* forward-negotiate */
1115         if(!gst_pad_set_caps(pad, incaps)) {
1116                 gst_object_unref(pad);
1117                 return FALSE;
1118         }
1119
1120         /* negotiation succeeded, so now configure ourselves */
1121         ins = gst_caps_get_structure(incaps, 0);
1122
1123         /* get samplerate from caps & convert */
1124         old_samplerate = audioeq->samplerate;
1125         old_channels = audioeq->channels;
1126         gst_structure_get_int(ins, "rate", &samplerate);
1127         switch (samplerate) {
1128         case 48000:
1129                 audioeq->samplerate = SAMPLERATE_48000Hz;
1130                 break;
1131         case 44100:
1132                 audioeq->samplerate = SAMPLERATE_44100Hz;
1133                 break;
1134         case 32000:
1135                 audioeq->samplerate = SAMPLERATE_32000Hz;
1136                 break;
1137         case 24000:
1138                 audioeq->samplerate = SAMPLERATE_24000Hz;
1139                 break;
1140         case 22050:
1141                 audioeq->samplerate = SAMPLERATE_22050Hz;
1142                 break;
1143         case 16000:
1144                 audioeq->samplerate = SAMPLERATE_16000Hz;
1145                 break;
1146         case 12000:
1147                 audioeq->samplerate = SAMPLERATE_12000Hz;
1148                 break;
1149         case 11025:
1150                 audioeq->samplerate = SAMPLERATE_11025Hz;
1151                 break;
1152         case 8000:
1153                 audioeq->samplerate = SAMPLERATE_8000Hz;
1154                 break;
1155         default:
1156                 if (samplerate < 8000) {
1157                         audioeq->samplerate = SAMPLERATE_8000Hz;
1158                 } else if (samplerate > 48000) {
1159                         audioeq->samplerate = SAMPLERATE_48000Hz;
1160                 }
1161                 break;
1162         }
1163         /* get number of channels from caps */
1164         gst_structure_get_int(ins, "channels", &channels);
1165         audioeq->channels = (gshort)channels;
1166
1167         if ((old_samplerate != audioeq->samplerate)
1168                 || (old_channels != audioeq->channels)) {
1169                 audioeq->need_update_filter = TRUE;
1170         }
1171
1172         gst_object_unref (pad);
1173
1174         return TRUE;
1175 }
1176
1177 static void
1178 gst_audioeq_set_property (GObject * object, guint prop_id,
1179         const GValue * value, GParamSpec * pspec)
1180 {
1181         GST_DEBUG ("gst_audioeq_set_property");
1182         Gstaudioeq *audioeq = GST_AUDIOEQ (object);
1183         GstIirEqualizer *equ = &audioeq->equ;
1184         gshort *pointer;
1185
1186         switch (prop_id) {
1187
1188         case PROP_FILTER_ACTION:
1189                 audioeq->filter_action = g_value_get_uint(value);
1190                 BANDS_LOCK(equ);
1191                 equ->need_new_coefficients = TRUE;
1192                 BANDS_UNLOCK(equ);
1193                 break;
1194
1195         case PROP_CUSTOM_EQ:
1196                 pointer = g_value_get_pointer(value);
1197                 if (pointer) {
1198                         memcpy(audioeq->custom_eq, pointer, sizeof(gint) * CUSTOM_EQ_BAND_MAX);
1199                         if (audioeq->filter_action == FILTER_ADVANCED_SETTING) {
1200                                 BANDS_LOCK(equ);
1201                                 equ->need_new_coefficients = TRUE;
1202                                 gst_audioeq_band_set_property(audioeq);
1203                                 BANDS_UNLOCK(equ);
1204                         }
1205                 }
1206                 break;
1207
1208         default:
1209                 break;
1210         }
1211         GST_DEBUG ("gst_audioeq_set_property need_update_filter %d", audioeq->need_update_filter);
1212 }
1213
1214 static void
1215 gst_audioeq_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
1216 {
1217 GST_DEBUG ("gst_audioeq_get_property");
1218
1219         Gstaudioeq *audioeq = GST_AUDIOEQ (object);
1220         GstIirEqualizer *equ = &audioeq->equ;
1221         gshort i;
1222         gdouble widtharr[DEFAULT_CUSTOM_EQ_NUM],freqarr[DEFAULT_CUSTOM_EQ_NUM];
1223
1224         switch (prop_id) {
1225         case PROP_FILTER_ACTION:
1226                 g_value_set_uint(value, audioeq->filter_action);
1227                 break;
1228
1229         case PROP_CUSTOM_EQ:
1230                 g_value_set_pointer(value, audioeq->custom_eq);
1231                 break;
1232
1233         case PROP_CUSTOM_EQ_NUM:
1234                 g_value_set_uint(value, DEFAULT_CUSTOM_EQ_NUM);
1235                 break;
1236
1237         case PROP_CUSTOM_EQ_FREQ:
1238                 for(i=0;i<DEFAULT_CUSTOM_EQ_NUM;i++) {
1239                          freqarr[i] =   equ->bands[i]->freq;
1240                 }
1241                 g_value_set_pointer(value, &freqarr);
1242                 break;
1243
1244         case PROP_CUSTOM_EQ_WIDTH:
1245                 for(i=0;i<DEFAULT_CUSTOM_EQ_NUM;i++) {
1246                          widtharr[i] =  equ->bands[i]->width;
1247                 }
1248                 g_value_set_pointer(value, &widtharr);
1249                 break;
1250
1251         default:
1252                 break;
1253         }
1254 }
1255
1256 static gboolean
1257 gst_iir_equalizer_setup (GstAudioFilter * audio, GstRingBufferSpec * fmt)
1258 {
1259 GST_DEBUG ("gst_iir_equalizer_setup");
1260   GstIirEqualizer *equ = GST_IIR_EQUALIZER (audio);
1261
1262   switch (fmt->type) {
1263     case GST_BUFTYPE_LINEAR:
1264       switch (fmt->width) {
1265         case 16:
1266           equ->history_size = history_size_gint16;
1267           equ->process = gst_iir_equ_process_gint16;
1268           break;
1269         default:
1270           return FALSE;
1271       }
1272       break;
1273     case GST_BUFTYPE_FLOAT:
1274       switch (fmt->width) {
1275         case 32:
1276           equ->history_size = history_size_gfloat;
1277           equ->process = gst_iir_equ_process_gfloat;
1278           break;
1279         case 64:
1280           equ->history_size = history_size_gdouble;
1281           equ->process = gst_iir_equ_process_gdouble;
1282           break;
1283         default:
1284           return FALSE;
1285       }
1286       break;
1287     default:
1288       return FALSE;
1289   }
1290
1291   alloc_history (equ);
1292   return TRUE;
1293 }
1294
1295
1296 static gboolean
1297 plugin_init (GstPlugin * plugin)
1298 {
1299        GST_DEBUG ("audioeq plugin_init ");
1300         GST_DEBUG_CATEGORY_INIT(gst_audioeq_debug, "audioeq", 0, "Audio Equalizer Plugin");
1301         return gst_element_register(plugin, "audioeq", GST_RANK_NONE, GST_TYPE_AUDIOEQ);
1302 }
1303
1304
1305 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1306         GST_VERSION_MINOR,
1307         "audioeq",
1308         "Audio Equalizer Plugin",
1309         plugin_init,
1310         VERSION,
1311         "LGPL",
1312         "gst-plugins-ext",
1313         "https://www.tizen.org/")