4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Aditi Narula <aditi.n@samsung.com>
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)
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.
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
29 #include "gstaudioeq.h"
31 GST_DEBUG_CATEGORY_STATIC (gst_audioeq_debug);
32 #define GST_CAT_DEFAULT gst_audioeq_debug
34 #define AUDIOEQ_ENABLE_DUMP
35 #define AUDIOEQ_REDUCE_MEMCPY
37 /* Filter signals and args */
58 FILTER_ADVANCED_SETTING
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
84 static GstStaticPadTemplate sinktemplate =
85 GST_STATIC_PAD_TEMPLATE(
91 "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
92 "signed = (boolean) true, "
95 "channels = (int) [1,2]"
99 static GstStaticPadTemplate srctemplate =
100 GST_STATIC_PAD_TEMPLATE(
106 "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
107 "signed = (boolean) true, "
110 "channels = (int) [1,2]"
114 static void gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
115 gpointer iface_data);
117 static void gst_iir_equalizer_finalize (GObject * object);
119 static gboolean gst_iir_equalizer_setup (GstAudioFilter * filter,
120 GstRingBufferSpec * fmt);
123 _do_init (GType object_type)
125 const GInterfaceInfo child_proxy_interface_info = {
126 (GInterfaceInitFunc) gst_iir_equalizer_child_proxy_interface_init,
127 NULL, /* interface_finalize */
128 NULL /* interface_data */
131 g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
132 &child_proxy_interface_info);
135 GST_BOILERPLATE_FULL(Gstaudioeq, gst_audioeq, GstBaseTransform, GST_TYPE_BASE_TRANSFORM,_do_init);
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);
142 static GstFlowReturn gst_audioeq_transform (GstBaseTransform * base, GstBuffer * inbuf, GstBuffer * outbuf);
144 static gboolean gst_audioeq_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps);
146 static GstStateChangeReturn
147 gst_audioeq_change_state (GstElement * element, GstStateChange transition)
149 GST_DEBUG ("gst_audioeq_change_state");
150 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
151 Gstaudioeq *audioeq = GST_AUDIOEQ (element);
153 switch (transition) {
154 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
155 audioeq->need_update_filter = TRUE;
161 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
163 if (ret == GST_STATE_CHANGE_FAILURE)
166 switch (transition) {
167 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
177 gst_audioeq_base_init (gpointer gclass)
180 GST_DEBUG ("gst_audioeq_base_init");
181 static GstElementDetails element_details = {
183 "Filter/Effect/Audio",
184 "Set equalisation effect on audio/raw streams",
185 "Samsung Electronics <www.samsung.com>"
188 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
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));
195 gst_element_class_set_details(element_class, &element_details);
199 gst_audioeq_class_init (GstaudioeqClass * klass)
201 GST_DEBUG ("gst_audioeq_class_init");
202 GObjectClass *gobject_class;
203 GstElementClass *gstelement_class;
204 GstBaseTransformClass *basetransform_class;
206 gobject_class = G_OBJECT_CLASS (klass);
207 gstelement_class = GST_ELEMENT_CLASS (klass);
208 basetransform_class = GST_BASE_TRANSFORM_CLASS(klass);
210 gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_audioeq_set_property);
211 gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_audioeq_get_property);
213 gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_audioeq_change_state);
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));
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));
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));
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",
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",
235 gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_iir_equalizer_finalize);
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);
241 basetransform_class->set_caps = GST_DEBUG_FUNCPTR(gst_audioeq_set_caps);
245 gst_audioeq_init (Gstaudioeq * audioeq, GstaudioeqClass * gclass)
247 GST_DEBUG ("gst_audioeq_init");
248 audioeq->samplerate = DEFAULT_SAMPLE_RATE;
249 audioeq->channels = DEAFULT_CHANNELS;
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);
258 /* equalizer implementation */
261 gst_iir_equalizer_finalize (GObject * object)
263 GST_DEBUG ("gst_iir_equalizer_finalize");
264 Gstaudioeq *audioeq = GST_AUDIOEQ(object);
265 GstIirEqualizer *equ = &audioeq->equ;
268 for (i = 0; i < equ->freq_band_count; i++) {
270 gst_object_unparent (GST_OBJECT (equ->bands[i]));
271 equ->bands[i] = NULL;
273 equ->freq_band_count = 0;
276 g_free (equ->history);
278 g_mutex_free (equ->bands_lock);
280 G_OBJECT_CLASS (parent_class)->finalize (object);
283 #define BANDS_LOCK(equ) g_mutex_lock(equ->bands_lock)
284 #define BANDS_UNLOCK(equ) g_mutex_unlock(equ->bands_lock)
301 } GstIirEqualizerBandType;
303 #define GST_TYPE_IIR_EQUALIZER_BAND_TYPE (gst_iir_equalizer_band_type_get_type ())
305 gst_iir_equalizer_band_type_get_type (void)
307 GST_DEBUG ("gst_iir_equalizer_band_type_get_type");
308 static GType 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)",
315 {BAND_TYPE_HIGH_SHELF, "High shelf filter (default for last band)",
320 gtype = g_enum_register_static ("GstIirEqualizerBandType", values);
326 typedef struct _GstIirEqualizerBandClass GstIirEqualizerBandClass;
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))
339 struct _GstIirEqualizerBand
344 /* center frequency and gain */
348 GstIirEqualizerBandType type;
350 /* second order iir filter */
351 gdouble b1, b2; /* IIR coefficients for outputs */
352 gdouble a0, a1, a2; /* IIR coefficients for inputs */
355 struct _GstIirEqualizerBandClass
357 GstObjectClass parent_class;
360 static GType gst_iir_equalizer_band_get_type (void);
363 gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
364 const GValue * value, GParamSpec * pspec)
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;
375 gain = g_value_get_double (value);
376 GST_DEBUG_OBJECT (band, "gain = %lf -> %lf", band->gain, gain);
377 if (gain != band->gain) {
379 equ->need_new_coefficients = TRUE;
382 GST_DEBUG_OBJECT (band, "changed gain = %lf ", band->gain);
389 freq = g_value_get_double (value);
390 GST_DEBUG_OBJECT (band, "freq = %lf -> %lf", band->freq, freq);
391 if (freq != band->freq) {
393 equ->need_new_coefficients = TRUE;
396 GST_DEBUG_OBJECT (band, "changed freq = %lf ", band->freq);
400 case PROP_BANDWIDTH:{
403 width = g_value_get_double (value);
404 GST_DEBUG_OBJECT (band, "width = %lf -> %lf", band->width, width);
405 if (width != band->width) {
407 equ->need_new_coefficients = TRUE;
410 GST_DEBUG_OBJECT (band, "changed width = %lf ", band->width);
415 GstIirEqualizerBandType type;
417 type = g_value_get_enum (value);
418 GST_DEBUG_OBJECT (band, "type = %d -> %d", band->type, type);
419 if (type != band->type) {
421 equ->need_new_coefficients = TRUE;
424 GST_DEBUG_OBJECT (band, "changed type = %d ", band->type);
429 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
433 gst_object_unref (audioeq);
437 gst_iir_equalizer_band_get_property (GObject * object, guint prop_id,
438 GValue * value, GParamSpec * pspec)
440 GST_DEBUG ("gst_iir_equalizer_band_get_property");
441 GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object);
445 g_value_set_double (value, band->gain);
448 g_value_set_double (value, band->freq);
451 g_value_set_double (value, band->width);
454 g_value_set_enum (value, band->type);
457 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
463 gst_iir_equalizer_band_class_init (GstIirEqualizerBandClass * klass)
465 GST_DEBUG ("gst_iir_equalizer_band_class_init");
466 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
468 gobject_class->set_property = gst_iir_equalizer_band_set_property;
469 gobject_class->get_property = gst_iir_equalizer_band_get_property;
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",
475 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
477 g_object_class_install_property (gobject_class, PROP_FREQ,
478 g_param_spec_double ("freq", "freq",
479 "center frequency of the band",
481 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
483 g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
484 g_param_spec_double ("bandwidth", "bandwidth",
485 "difference between bandedges in Hz",
487 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
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,
493 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
497 gst_iir_equalizer_band_init (GstIirEqualizerBand * band,
498 GstIirEqualizerBandClass * klass)
500 GST_DEBUG ("gst_iir_equalizer_band_init");
504 band->type = BAND_TYPE_PEAK;
508 gst_iir_equalizer_band_get_type (void)
510 GST_DEBUG ("gst_iir_equalizer_band_get_type");
511 static GType type = 0;
513 if (G_UNLIKELY (!type)) {
514 const GTypeInfo type_info = {
515 sizeof (GstIirEqualizerBandClass),
518 (GClassInitFunc) gst_iir_equalizer_band_class_init,
521 sizeof (GstIirEqualizerBand),
523 (GInstanceInitFunc) gst_iir_equalizer_band_init,
526 g_type_register_static (GST_TYPE_OBJECT, "GstIirEqualizerBand",
533 /* child proxy iface */
535 gst_iir_equalizer_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
538 GST_DEBUG ("gst_iir_equalizer_child_proxy_get_child_by_index");
539 Gstaudioeq *audioeq = GST_AUDIOEQ(child_proxy);
540 GstIirEqualizer *equ = &audioeq->equ;
544 if (G_UNLIKELY (index >= equ->freq_band_count)) {
546 g_return_val_if_fail (index < equ->freq_band_count, NULL);
549 ret = gst_object_ref (equ->bands[index]);
552 GST_LOG_OBJECT (equ, "return child[%d] %" GST_PTR_FORMAT, index, ret);
557 gst_iir_equalizer_child_proxy_get_children_count (GstChildProxy * child_proxy)
559 GST_DEBUG ("gst_iir_equalizer_child_proxy_get_children_count");
560 Gstaudioeq *audioeq = GST_AUDIOEQ(child_proxy);
561 GstIirEqualizer *equ = &audioeq->equ;
563 GST_LOG ("we have %d children", equ->freq_band_count);
564 return equ->freq_band_count;
568 gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
571 GstChildProxyInterface *iface = g_iface;
573 GST_DEBUG ("initializing iface");
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;
579 gst_iir_equalizer_class_init (GstIirEqualizerClass * klass)
581 GST_DEBUG ("gst_iir_equalizer_class_init");
585 gst_iir_equalizer_init (GstIirEqualizer * eq, GstIirEqualizerClass * g_class)
587 GST_DEBUG ("gst_iir_equalizer_init");
588 eq->bands_lock = g_mutex_new ();
589 eq->need_new_coefficients = TRUE;
593 gst_iir_equalizer_get_type (void)
595 GST_DEBUG ("gst_iir_equalizer_get_type");
596 static GType type = 0;
598 if (G_UNLIKELY (!type)) {
599 const GTypeInfo type_info = {
600 sizeof (GstIirEqualizerClass),
603 (GClassInitFunc) gst_iir_equalizer_class_init,
606 sizeof (GstIirEqualizer),
608 (GInstanceInitFunc) gst_iir_equalizer_init,
611 g_type_register_static (GST_TYPE_OBJECT, "GstIirEqualizer",
618 * The Equivalence of Various Methods of Computing
619 * Biquad Coefficients for Audio Parametric Equalizers
621 * by Robert Bristow-Johnson
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
627 * The bandwidth method that we use here is the preferred
628 * one from this article transformed from octaves to frequency
631 static inline gdouble
632 arg_to_scale (gdouble arg)
634 GST_DEBUG ("arg_to_scale");
635 return (pow (10.0, arg / 40.0));
639 calculate_omega (gdouble freq, gint rate)
641 GST_DEBUG ("calculate_omega");
644 if (freq / rate >= 0.5)
646 else if (freq <= 0.0)
649 omega = 2.0 * G_PI * (freq / rate);
655 calculate_bw (GstIirEqualizerBand * band, gint rate)
657 GST_DEBUG ("calculate_bw");
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.
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
677 bw = 2.0 * G_PI * (band->width / rate);
683 setup_peak_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
685 GST_DEBUG ("setup_peak_filter");
686 //g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
689 gdouble gain, omega, bw;
690 gdouble alpha, alpha1, alpha2, b0;
692 gain = arg_to_scale (band->gain);
693 omega = calculate_omega (band->freq, audioeq->samplerate);
694 bw = calculate_bw (band, audioeq->samplerate);
698 alpha = tan (bw / 2.0);
700 alpha1 = alpha * gain;
701 alpha2 = alpha / gain;
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;
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,
720 setup_low_shelf_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
722 GST_DEBUG ("setup_low_shelf_filter");
723 //g_return_if_fail (GST_AUDIO_FILTER (equ)->format.rate);
726 gdouble gain, omega, bw;
727 gdouble alpha, delta, b0;
730 gain = arg_to_scale (band->gain);
731 omega = calculate_omega (band->freq, audioeq->samplerate);
732 bw = calculate_bw (band, audioeq->samplerate);
738 alpha = tan (bw / 2.0);
740 delta = 2.0 * sqrt (gain) * alpha;
741 b0 = egp + egm * cos (omega) + delta;
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;
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,
759 setup_high_shelf_filter (Gstaudioeq* audioeq, GstIirEqualizerBand * band)
761 GST_DEBUG ("setup_high_shelf_filter");
763 gdouble gain, omega, bw;
764 gdouble alpha, delta, b0;
767 gain = arg_to_scale (band->gain);
768 omega = calculate_omega (band->freq, audioeq->samplerate);
769 bw = calculate_bw (band, audioeq->samplerate);
775 alpha = tan (bw / 2.0);
777 delta = 2.0 * sqrt (gain) * alpha;
778 b0 = egp - egm * cos (omega) + delta;
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;
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,
795 /* Must be called with bands_lock and transform lock! */
797 set_passthrough (Gstaudioeq* audioeq)
799 GST_DEBUG ("set_passthrough");
800 GstIirEqualizer* equ=&audioeq->equ;
802 gboolean passthrough = TRUE;
804 for (i = 0; i < equ->freq_band_count; i++) {
805 passthrough = passthrough && (equ->bands[i]->gain == 0.0);
808 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (audioeq), passthrough);
809 GST_DEBUG ("Passthrough mode: %d\n", passthrough);
812 /* Must be called with bands_lock and transform lock! */
814 update_coefficients (Gstaudioeq* audioeq)
816 GST_DEBUG ("update_coefficients");
817 GstIirEqualizer* equ=&audioeq->equ;
818 gint i, n = equ->freq_band_count;
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]);
826 setup_high_shelf_filter (audioeq, equ->bands[i]);
829 equ->need_new_coefficients = FALSE;
832 /* Must be called with transform lock! */
834 alloc_history (GstIirEqualizer * equ)
836 GST_DEBUG ("alloc_history");
837 /* free + alloc = no memcpy */
838 g_free (equ->history);
840 g_malloc0 (equ->history_size * equ->audiofilter.format.channels *
841 equ->freq_band_count);
844 gst_audioeq_band_set_property(Gstaudioeq * audioeq)
846 GST_DEBUG ("gst_audioeq_band_set_property");
847 GstIirEqualizer *equ = &audioeq->equ;
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");
860 gst_iir_equalizer_compute_frequencies (Gstaudioeq * audioeq, guint new_count)
862 GST_DEBUG ("gst_iir_equalizer_compute_frequencies");
864 GstIirEqualizer *equ = &audioeq->equ;
866 gdouble freq0, freq1, step;
868 GST_DEBUG ("gst_iir_equalizer_compute_frequencies before calling equalizer object");
869 if (equ->freq_band_count == new_count)
872 GST_DEBUG ("gst_iir_equalizer_compute_frequencies equalizer object");
875 GST_DEBUG ("gst_iir_equalizer_compute_frequencies 1");
876 if (G_UNLIKELY (equ->freq_band_count == new_count)) {
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);
885 if (old_count < new_count) {
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]);
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]));
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;
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
917 step = pow (HIGHEST_FREQ / LOWEST_FREQ, 1.0 / new_count);
919 for (i = 0; i < new_count; i++) {
920 freq1 = freq0 * step;
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;
927 equ->bands[i]->type = BAND_TYPE_PEAK;
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);
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");
940 equ->need_new_coefficients = TRUE;
944 /* start of code that is type specific */
946 #define CREATE_OPTIMIZED_FUNCTIONS_INT(TYPE,BIG_TYPE,MIN_VAL,MAX_VAL) \
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; \
952 static inline BIG_TYPE \
953 one_step_ ## TYPE (GstIirEqualizerBand *filter, \
954 SecondOrderHistory ## TYPE *history, BIG_TYPE input) \
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; \
970 history_size_ ## TYPE = sizeof (SecondOrderHistory ## TYPE); \
973 gst_iir_equ_process_ ## TYPE (GstIirEqualizer *equ, guint8 *data, \
974 guint size, guint channels) \
976 guint frames = size / channels / sizeof (TYPE); \
977 guint i, c, f, nf = equ->freq_band_count; \
979 GstIirEqualizerBand **filters = equ->bands; \
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); \
989 cur = CLAMP (cur, MIN_VAL, MAX_VAL); \
990 *((TYPE *) data) = (TYPE) floor (cur); \
991 data += sizeof (TYPE); \
996 #define CREATE_OPTIMIZED_FUNCTIONS(TYPE) \
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; \
1002 static inline TYPE \
1003 one_step_ ## TYPE (GstIirEqualizerBand *filter, \
1004 SecondOrderHistory ## TYPE *history, TYPE input) \
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; \
1019 static const guint \
1020 history_size_ ## TYPE = sizeof (SecondOrderHistory ## TYPE); \
1023 gst_iir_equ_process_ ## TYPE (GstIirEqualizer *equ, guint8 *data, \
1024 guint size, guint channels) \
1026 guint frames = size / channels / sizeof (TYPE); \
1027 guint i, c, f, nf = equ->freq_band_count; \
1029 GstIirEqualizerBand **filters = equ->bands; \
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); \
1039 *((TYPE *) data) = (TYPE) cur; \
1040 data += sizeof (TYPE); \
1045 CREATE_OPTIMIZED_FUNCTIONS_INT (gint16, gfloat, -32768.0, 32767.0);
1046 CREATE_OPTIMIZED_FUNCTIONS (gfloat);
1047 CREATE_OPTIMIZED_FUNCTIONS (gdouble);
1049 #ifdef AUDIOEQ_REDUCE_MEMCPY
1050 static GstFlowReturn
1051 gst_audioeq_transform_ip (GstBaseTransform * base, GstBuffer * buf)
1053 GST_DEBUG ("gst_audioeq_transform_ip");
1054 Gstaudioeq *audioeq = GST_AUDIOEQ(base);
1055 GstIirEqualizer *equ = &audioeq->equ;
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;
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;
1071 GST_DEBUG ("gst_audioeq_transform_ip 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);
1080 if (gst_base_transform_is_passthrough (base)) {
1081 GST_DEBUG ("gst_audioeq_transform_ip gst_base_transform_is_passthrough return GST_FLOW_OK;");
1084 timestamp = GST_BUFFER_TIMESTAMP (buf);
1086 gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
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),
1093 GST_DEBUG (" equ->process --");
1094 GST_DEBUG ("gst_audioeq_transform_ip return GST_FLOW_OK;");
1100 gst_audioeq_set_caps (GstBaseTransform * base, GstCaps * incaps,
1103 GST_DEBUG ("gst_audioeq_set_caps");
1104 Gstaudioeq *audioeq = GST_AUDIOEQ(base);
1109 gshort old_samplerate;
1110 gshort old_channels;
1112 pad = gst_element_get_static_pad(GST_ELEMENT(audioeq), "src");
1114 /* forward-negotiate */
1115 if(!gst_pad_set_caps(pad, incaps)) {
1116 gst_object_unref(pad);
1120 /* negotiation succeeded, so now configure ourselves */
1121 ins = gst_caps_get_structure(incaps, 0);
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) {
1129 audioeq->samplerate = SAMPLERATE_48000Hz;
1132 audioeq->samplerate = SAMPLERATE_44100Hz;
1135 audioeq->samplerate = SAMPLERATE_32000Hz;
1138 audioeq->samplerate = SAMPLERATE_24000Hz;
1141 audioeq->samplerate = SAMPLERATE_22050Hz;
1144 audioeq->samplerate = SAMPLERATE_16000Hz;
1147 audioeq->samplerate = SAMPLERATE_12000Hz;
1150 audioeq->samplerate = SAMPLERATE_11025Hz;
1153 audioeq->samplerate = SAMPLERATE_8000Hz;
1156 if (samplerate < 8000) {
1157 audioeq->samplerate = SAMPLERATE_8000Hz;
1158 } else if (samplerate > 48000) {
1159 audioeq->samplerate = SAMPLERATE_48000Hz;
1163 /* get number of channels from caps */
1164 gst_structure_get_int(ins, "channels", &channels);
1165 audioeq->channels = (gshort)channels;
1167 if ((old_samplerate != audioeq->samplerate)
1168 || (old_channels != audioeq->channels)) {
1169 audioeq->need_update_filter = TRUE;
1172 gst_object_unref (pad);
1178 gst_audioeq_set_property (GObject * object, guint prop_id,
1179 const GValue * value, GParamSpec * pspec)
1181 GST_DEBUG ("gst_audioeq_set_property");
1182 Gstaudioeq *audioeq = GST_AUDIOEQ (object);
1183 GstIirEqualizer *equ = &audioeq->equ;
1188 case PROP_FILTER_ACTION:
1189 audioeq->filter_action = g_value_get_uint(value);
1191 equ->need_new_coefficients = TRUE;
1195 case PROP_CUSTOM_EQ:
1196 pointer = g_value_get_pointer(value);
1198 memcpy(audioeq->custom_eq, pointer, sizeof(gint) * CUSTOM_EQ_BAND_MAX);
1199 if (audioeq->filter_action == FILTER_ADVANCED_SETTING) {
1201 equ->need_new_coefficients = TRUE;
1202 gst_audioeq_band_set_property(audioeq);
1211 GST_DEBUG ("gst_audioeq_set_property need_update_filter %d", audioeq->need_update_filter);
1215 gst_audioeq_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
1217 GST_DEBUG ("gst_audioeq_get_property");
1219 Gstaudioeq *audioeq = GST_AUDIOEQ (object);
1220 GstIirEqualizer *equ = &audioeq->equ;
1222 gdouble widtharr[DEFAULT_CUSTOM_EQ_NUM],freqarr[DEFAULT_CUSTOM_EQ_NUM];
1225 case PROP_FILTER_ACTION:
1226 g_value_set_uint(value, audioeq->filter_action);
1229 case PROP_CUSTOM_EQ:
1230 g_value_set_pointer(value, audioeq->custom_eq);
1233 case PROP_CUSTOM_EQ_NUM:
1234 g_value_set_uint(value, DEFAULT_CUSTOM_EQ_NUM);
1237 case PROP_CUSTOM_EQ_FREQ:
1238 for(i=0;i<DEFAULT_CUSTOM_EQ_NUM;i++) {
1239 freqarr[i] = equ->bands[i]->freq;
1241 g_value_set_pointer(value, &freqarr);
1244 case PROP_CUSTOM_EQ_WIDTH:
1245 for(i=0;i<DEFAULT_CUSTOM_EQ_NUM;i++) {
1246 widtharr[i] = equ->bands[i]->width;
1248 g_value_set_pointer(value, &widtharr);
1257 gst_iir_equalizer_setup (GstAudioFilter * audio, GstRingBufferSpec * fmt)
1259 GST_DEBUG ("gst_iir_equalizer_setup");
1260 GstIirEqualizer *equ = GST_IIR_EQUALIZER (audio);
1262 switch (fmt->type) {
1263 case GST_BUFTYPE_LINEAR:
1264 switch (fmt->width) {
1266 equ->history_size = history_size_gint16;
1267 equ->process = gst_iir_equ_process_gint16;
1273 case GST_BUFTYPE_FLOAT:
1274 switch (fmt->width) {
1276 equ->history_size = history_size_gfloat;
1277 equ->process = gst_iir_equ_process_gfloat;
1280 equ->history_size = history_size_gdouble;
1281 equ->process = gst_iir_equ_process_gdouble;
1291 alloc_history (equ);
1297 plugin_init (GstPlugin * plugin)
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);
1305 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1308 "Audio Equalizer Plugin",
1313 "https://www.tizen.org/")