Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
equalizer.c
Go to the documentation of this file.
00001 /*
00002  *  Equalizer filter, implementation of a 10 band time domain graphic equalizer
00003  *  using IIR filters.  The IIR filters are implemented using a Direct Form II
00004  *  approach, modified (b1 == 0 always) to save computation.
00005  *
00006  *  This software has been released under the terms of the GNU General Public
00007  *  license.  See http://www.gnu.org/copyleft/gpl.html for details.
00008  *
00009  *  Copyright 2001 Anders Johansson <ajh@atri.curtin.edu.au>
00010  *
00011  *  Adapted for Audacious by John Lindgren, 2010
00012  */
00013 
00014 #include <glib.h>
00015 #include <math.h>
00016 #include <string.h>
00017 
00018 #include <libaudcore/hook.h>
00019 
00020 #include "audconfig.h"
00021 #include "equalizer.h"
00022 
00023 #define EQ_BANDS AUD_EQUALIZER_NBANDS
00024 #define MAX_CHANNELS 10
00025 
00026 /* Q value for band-pass filters 1.2247 = (3/2)^(1/2)
00027  * Gives 4 dB suppression at Fc*2 and Fc/2 */
00028 #define Q 1.2247449
00029 
00030 /* Center frequencies for band-pass filters (Hz) */
00031 /* These are not the historical WinAmp frequencies, because the IIR filters used
00032  * here are designed for each frequency to be twice the previous.  Using WinAmp
00033  * frequencies leads to too much gain in some bands and too little in others. */
00034 static const gfloat CF[EQ_BANDS] = {31.25, 62.5, 125, 250, 500, 1000, 2000,
00035  4000, 8000, 16000};
00036 
00037 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
00038 static gboolean active;
00039 static gint channels, rate;
00040 static gfloat a[EQ_BANDS][2]; /* A weights */
00041 static gfloat b[EQ_BANDS][2]; /* B weights */
00042 static gfloat wqv[MAX_CHANNELS][EQ_BANDS][2]; /* Circular buffer for W data */
00043 static gfloat gv[MAX_CHANNELS][EQ_BANDS]; /* Gain factor for each channel and band */
00044 static gint K; /* Number of used eq bands */
00045 
00046 /* 2nd order band-pass filter design */
00047 static void bp2 (gfloat * a, gfloat * b, gfloat fc, gfloat q)
00048 {
00049     gfloat th = 2 * M_PI * fc;
00050     gfloat C = (1 - tanf (th * q / 2)) / (1 + tanf (th * q / 2));
00051 
00052     a[0] = (1 + C) * cosf (th);
00053     a[1] = -C;
00054     b[0] = (1 - C) / 2;
00055     b[1] = -1.005;
00056 }
00057 
00058 void eq_set_format (gint new_channels, gint new_rate)
00059 {
00060     gint k;
00061 
00062     g_static_mutex_lock (& mutex);
00063 
00064     channels = new_channels;
00065     rate = new_rate;
00066 
00067     /* Calculate number of active filters */
00068     K = EQ_BANDS;
00069 
00070     while (CF[K - 1] > (gfloat) rate / 2.2)
00071         K --;
00072 
00073     /* Generate filter taps */
00074     for (k = 0; k < K; k ++)
00075         bp2 (a[k], b[k], CF[k] / (gfloat) rate, Q);
00076 
00077     /* Reset state */
00078     memset (wqv[0][0], 0, sizeof wqv);
00079 
00080     g_static_mutex_unlock (& mutex);
00081 }
00082 
00083 static void eq_set_channel_bands (gint channel, gfloat * bands)
00084 {
00085     gint k;
00086 
00087     for (k = 0; k < EQ_BANDS; k ++)
00088         gv[channel][k] = pow (10, bands[k] / 20) - 1;
00089 }
00090 
00091 static void eq_set_bands (gfloat preamp, gfloat * bands)
00092 {
00093     gfloat adjusted[EQ_BANDS];
00094     gint i;
00095 
00096     for (i = 0; i < EQ_BANDS; i ++)
00097         adjusted[i] = preamp + bands[i];
00098 
00099     for (i = 0; i < MAX_CHANNELS; i ++)
00100         eq_set_channel_bands (i, adjusted);
00101 }
00102 
00103 void eq_filter (gfloat * data, gint samples)
00104 {
00105     gint channel;
00106 
00107     g_static_mutex_lock (& mutex);
00108 
00109     if (! active)
00110     {
00111         g_static_mutex_unlock (& mutex);
00112         return;
00113     }
00114 
00115     for (channel = 0; channel < channels; channel ++)
00116     {
00117         gfloat * g = gv[channel]; /* Gain factor */
00118         gfloat * end = data + samples;
00119         gfloat * f;
00120 
00121         for (f = data + channel; f < end; f += channels)
00122         {
00123             gint k; /* Frequency band index */
00124             gfloat yt = * f; /* Current input sample */
00125 
00126             for (k = 0; k < K; k ++)
00127             {
00128                 /* Pointer to circular buffer wq */
00129                 gfloat * wq = wqv[channel][k];
00130                 /* Calculate output from AR part of current filter */
00131                 gfloat w = yt * b[k][0] + wq[0] * a[k][0] + wq[1] * a[k][1];
00132 
00133                 /* Calculate output from MA part of current filter */
00134                 yt += (w + wq[1] * b[k][1]) * g[k];
00135 
00136                 /* Update circular buffer */
00137                 wq[1] = wq[0];
00138                 wq[0] = w;
00139             }
00140 
00141             /* Calculate output */
00142             * f = yt;
00143         }
00144     }
00145 
00146     g_static_mutex_unlock (& mutex);
00147 }
00148 
00149 static void eq_update (void * data, void * user_data)
00150 {
00151     g_static_mutex_lock (& mutex);
00152 
00153     active = cfg.equalizer_active;
00154     eq_set_bands (cfg.equalizer_preamp, cfg.equalizer_bands);
00155 
00156     g_static_mutex_unlock (& mutex);
00157 }
00158 
00159 void eq_init (void)
00160 {
00161     eq_update (NULL, NULL);
00162     hook_associate ("equalizer changed", eq_update, NULL);
00163 }