Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
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 }