/** @file eq.c * Equalizer effect plugin * * Copyright (C) 2006-2007 XMMS2 Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "xmms/xmms_xformplugin.h" #include "xmms/xmms_config.h" #include "xmms/xmms_log.h" #include #include #include #include #include "iir.h" #define EQ_BANDS_LEGACY 10 static gboolean xmms_eq_plugin_setup (xmms_xform_plugin_t *xform_plugin); static gboolean xmms_eq_init (xmms_xform_t *xform); static void xmms_eq_destroy (xmms_xform_t *xform); static gint xmms_eq_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *error); static gint64 xmms_eq_seek (xmms_xform_t *xform, gint64 offset, xmms_xform_seek_mode_t whence, xmms_error_t *err); static void xmms_eq_gain_changed (xmms_object_t *object, gconstpointer data, gpointer userdata); static void xmms_eq_config_changed (xmms_object_t *object, gconstpointer data, gpointer userdata); static gfloat xmms_eq_gain_scale (gfloat gain, gboolean preamp); typedef struct xmms_equalizer_priv_St { guint use_legacy; guint extra_filtering; guint bands; xmms_config_property_t *gain[EQ_MAX_BANDS]; xmms_config_property_t *legacy[EQ_BANDS_LEGACY]; gboolean enabled; } xmms_equalizer_data_t; XMMS_XFORM_PLUGIN ("equalizer", "Equalizer effect", XMMS_VERSION, "Equalizer effect", xmms_eq_plugin_setup); static gboolean xmms_eq_plugin_setup (xmms_xform_plugin_t *xform_plugin) { xmms_xform_methods_t methods; gchar buf[16]; gint i; XMMS_XFORM_METHODS_INIT (methods); methods.init = xmms_eq_init; methods.destroy = xmms_eq_destroy; methods.read = xmms_eq_read; methods.seek = xmms_eq_seek; xmms_xform_plugin_methods_set (xform_plugin, &methods); xmms_xform_plugin_config_property_register (xform_plugin, "bands", "15", NULL, NULL); xmms_xform_plugin_config_property_register (xform_plugin, "extra_filtering", "0", NULL, NULL); xmms_xform_plugin_config_property_register (xform_plugin, "use_legacy", "1", NULL, NULL); xmms_xform_plugin_config_property_register (xform_plugin, "preamp", "0.0", NULL, NULL); for (i=0; ienabled = !!xmms_config_property_get_int (config); config = xmms_xform_config_lookup (xform, "bands"); g_return_val_if_fail (config, FALSE); xmms_config_property_callback_set (config, xmms_eq_config_changed, priv); priv->bands = xmms_config_property_get_int (config); config = xmms_xform_config_lookup (xform, "extra_filtering"); g_return_val_if_fail (config, FALSE); xmms_config_property_callback_set (config, xmms_eq_config_changed, priv); priv->extra_filtering = xmms_config_property_get_int (config); config = xmms_xform_config_lookup (xform, "use_legacy"); g_return_val_if_fail (config, FALSE); xmms_config_property_callback_set (config, xmms_eq_config_changed, priv); priv->use_legacy = xmms_config_property_get_int (config); config = xmms_xform_config_lookup (xform, "preamp"); g_return_val_if_fail (config, FALSE); xmms_config_property_callback_set (config, xmms_eq_gain_changed, priv); gain = xmms_config_property_get_float (config); for (i=0; ilegacy[i] = config; xmms_config_property_callback_set (config, xmms_eq_gain_changed, priv); gain = xmms_config_property_get_float (config); if (priv->use_legacy) { for (j = 0; j < EQ_CHANNELS; j++) { set_gain (i, j, xmms_eq_gain_scale (gain, FALSE)); } } } for (i=0; igain[i] = config; xmms_config_property_callback_set (config, xmms_eq_gain_changed, priv); gain = xmms_config_property_get_float (config); if (!priv->use_legacy) { for (j = 0; j < EQ_CHANNELS; j++) { set_gain (i, j, xmms_eq_gain_scale (gain, FALSE)); } } } init_iir (); srate = xmms_xform_indata_get_int (xform, XMMS_STREAM_TYPE_FMT_SAMPLERATE); if (priv->use_legacy) { config_iir (srate, EQ_BANDS_LEGACY, 1); } else { config_iir (srate, priv->bands, 0); } xmms_xform_outdata_type_copy (xform); XMMS_DBG ("Equalizer initialized successfully!"); return TRUE; } static void xmms_eq_destroy (xmms_xform_t *xform) { xmms_config_property_t *config; gchar buf[16]; gint i; g_return_if_fail (xform); g_free (xmms_xform_private_data_get (xform)); config = xmms_xform_config_lookup (xform, "enabled"); xmms_config_property_callback_remove (config, xmms_eq_config_changed); config = xmms_xform_config_lookup (xform, "bands"); xmms_config_property_callback_remove (config, xmms_eq_config_changed); config = xmms_xform_config_lookup (xform, "extra_filtering"); xmms_config_property_callback_remove (config, xmms_eq_config_changed); config = xmms_xform_config_lookup (xform, "use_legacy"); xmms_config_property_callback_remove (config, xmms_eq_config_changed); config = xmms_xform_config_lookup (xform, "preamp"); xmms_config_property_callback_remove (config, xmms_eq_gain_changed); for (i=0; i 0 && priv->enabled) { iir (buf, read, chan, priv->extra_filtering); } return read; } static gint64 xmms_eq_seek (xmms_xform_t *xform, gint64 offset, xmms_xform_seek_mode_t whence, xmms_error_t *err) { return xmms_xform_seek (xform, offset, whence, err); } static void xmms_eq_gain_changed (xmms_object_t *object, gconstpointer data, gpointer userdata) { xmms_config_property_t *val; xmms_equalizer_data_t *priv; const gchar *name; gint i; gfloat gain; g_return_if_fail (object); g_return_if_fail (userdata); val = (xmms_config_property_t *) object; priv = userdata; name = xmms_config_property_get_name (val); XMMS_DBG ("gain value changed! %s => %f", name, xmms_config_property_get_float (val)); gain = xmms_config_property_get_float (val); if (gain < -20.0 || gain > 20.0) { gchar buf[20]; gain = CLAMP (gain, -20.0, 20.0); g_snprintf (buf, sizeof (buf), "%g", gain); xmms_config_property_set_data (val, buf); } /* we are passed the full config key, not just the last token, * which makes this code kinda ugly. * fix when bug 97 has been resolved */ name = strrchr (name, '.') + 1; if (!strcmp (name, "preamp")) { /* scale the -20.0 - 20.0 value to correct one */ for (i=0; iuse_legacy) { band = atoi (name + 4); } else if (!strncmp (name, "legacy", 6) && priv->use_legacy) { band = atoi (name + 6); } if (band >= 0) { /* scale the -20.0 - 20.0 value to correct one */ for (i=0; i %d", name, value); /* we are passed the full config key, not just the last token, * which makes this code kinda ugly. * fix when bug 97 has been resolved */ name = strrchr (name, '.') + 1; if (!strcmp (name, "enabled")) { priv->enabled = !!value; } else if (!strcmp (name, "extra_filtering")) { priv->extra_filtering = value; } else if (!strcmp (name, "use_legacy")) { gfloat gain; priv->use_legacy = value; if (priv->use_legacy) { for (i=0; ilegacy[i]); for (j=0; jbands; i++) { gain = xmms_config_property_get_float (priv->gain[i]); for (j=0; jbands); xmms_config_property_set_data (val, buf); } else { priv->bands = value; for (i=0; igain[i], "0.0"); if (!priv->use_legacy) { for (j=0; j