Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
equalizer.c
Go to the documentation of this file.
1 /*
2  * equalizer.c
3  * Copyright 2001 Anders Johansson
4  * Copyright 2010-2011 John Lindgren
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions, and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions, and the following disclaimer in the documentation
14  * provided with the distribution.
15  *
16  * This software is provided "as is" and without any warranty, express or
17  * implied. In no event shall the authors be liable for any damages arising from
18  * the use of this software.
19  */
20 
21 /*
22  * Anders Johansson prefers float *ptr; formatting. Please keep it that way.
23  * - tallica
24  */
25 
26 #include <glib.h>
27 #include <math.h>
28 #include <pthread.h>
29 #include <string.h>
30 
31 #include <libaudcore/audstrings.h>
32 #include <libaudcore/hook.h>
33 
34 #include "equalizer.h"
35 #include "misc.h"
36 #include "types.h"
37 
38 #define EQ_BANDS AUD_EQUALIZER_NBANDS
39 #define MAX_CHANNELS 10
40 
41 /* Q value for band-pass filters 1.2247 = (3/2)^(1/2)
42  * Gives 4 dB suppression at Fc*2 and Fc/2 */
43 #define Q 1.2247449
44 
45 /* Center frequencies for band-pass filters (Hz) */
46 /* These are not the historical WinAmp frequencies, because the IIR filters used
47  * here are designed for each frequency to be twice the previous. Using WinAmp
48  * frequencies leads to too much gain in some bands and too little in others. */
49 static const float CF[EQ_BANDS] = {31.25, 62.5, 125, 250, 500, 1000, 2000,
50  4000, 8000, 16000};
51 
52 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
53 static bool_t active;
54 static int channels, rate;
55 static float a[EQ_BANDS][2]; /* A weights */
56 static float b[EQ_BANDS][2]; /* B weights */
57 static float wqv[MAX_CHANNELS][EQ_BANDS][2]; /* Circular buffer for W data */
58 static float gv[MAX_CHANNELS][EQ_BANDS]; /* Gain factor for each channel and band */
59 static int K; /* Number of used eq bands */
60 
61 /* 2nd order band-pass filter design */
62 static void bp2 (float *a, float *b, float fc, float q)
63 {
64  float th = 2 * M_PI * fc;
65  float C = (1 - tanf (th * q / 2)) / (1 + tanf (th * q / 2));
66 
67  a[0] = (1 + C) * cosf (th);
68  a[1] = -C;
69  b[0] = (1 - C) / 2;
70  b[1] = -1.005;
71 }
72 
73 void eq_set_format (int new_channels, int new_rate)
74 {
75  int k;
76 
77  pthread_mutex_lock (& mutex);
78 
79  channels = new_channels;
80  rate = new_rate;
81 
82  /* Calculate number of active filters */
83  K = EQ_BANDS;
84 
85  while (CF[K - 1] > (float) rate / 2.2)
86  K --;
87 
88  /* Generate filter taps */
89  for (k = 0; k < K; k ++)
90  bp2 (a[k], b[k], CF[k] / (float) rate, Q);
91 
92  /* Reset state */
93  memset (wqv[0][0], 0, sizeof wqv);
94 
95  pthread_mutex_unlock (& mutex);
96 }
97 
98 static void eq_set_bands_real (double preamp, double *values)
99 {
100  float adj[EQ_BANDS];
101  for (int i = 0; i < EQ_BANDS; i ++)
102  adj[i] = preamp + values[i];
103 
104  for (int c = 0; c < MAX_CHANNELS; c ++)
105  for (int i = 0; i < EQ_BANDS; i ++)
106  gv[c][i] = pow (10, adj[i] / 20) - 1;
107 }
108 
109 void eq_filter (float *data, int samples)
110 {
111  int channel;
112 
113  pthread_mutex_lock (& mutex);
114 
115  if (! active)
116  {
117  pthread_mutex_unlock (& mutex);
118  return;
119  }
120 
121  for (channel = 0; channel < channels; channel ++)
122  {
123  float *g = gv[channel]; /* Gain factor */
124  float *end = data + samples;
125  float *f;
126 
127  for (f = data + channel; f < end; f += channels)
128  {
129  int k; /* Frequency band index */
130  float yt = *f; /* Current input sample */
131 
132  for (k = 0; k < K; k ++)
133  {
134  /* Pointer to circular buffer wq */
135  float *wq = wqv[channel][k];
136  /* Calculate output from AR part of current filter */
137  float w = yt * b[k][0] + wq[0] * a[k][0] + wq[1] * a[k][1];
138 
139  /* Calculate output from MA part of current filter */
140  yt += (w + wq[1] * b[k][1]) * g[k];
141 
142  /* Update circular buffer */
143  wq[1] = wq[0];
144  wq[0] = w;
145  }
146 
147  /* Calculate output */
148  *f = yt;
149  }
150  }
151 
152  pthread_mutex_unlock (& mutex);
153 }
154 
155 static void eq_update (void *data, void *user)
156 {
157  pthread_mutex_lock (& mutex);
158 
159  active = get_bool (NULL, "equalizer_active");
160 
161  double values[EQ_BANDS];
162  eq_get_bands (values);
163  eq_set_bands_real (get_double (NULL, "equalizer_preamp"), values);
164 
165  pthread_mutex_unlock (& mutex);
166 }
167 
168 void eq_init (void)
169 {
170  eq_update (NULL, NULL);
171  hook_associate ("set equalizer_active", eq_update, NULL);
172  hook_associate ("set equalizer_preamp", eq_update, NULL);
173  hook_associate ("set equalizer_bands", eq_update, NULL);
174 }
175 
176 void eq_cleanup (void)
177 {
178  hook_dissociate ("set equalizer_active", eq_update);
179  hook_dissociate ("set equalizer_preamp", eq_update);
180  hook_dissociate ("set equalizer_bands", eq_update);
181 }
182 
183 void eq_set_bands (const double *values)
184 {
185  char *string = double_array_to_string (values, EQ_BANDS);
186  g_return_if_fail (string);
187  set_string (NULL, "equalizer_bands", string);
188  g_free (string);
189 }
190 
191 void eq_get_bands (double *values)
192 {
193  memset (values, 0, sizeof (double) * EQ_BANDS);
194  char *string = get_string (NULL, "equalizer_bands");
195  string_to_double_array (string, values, EQ_BANDS);
196  g_free (string);
197 }
198 
199 void eq_set_band (int band, double value)
200 {
201  g_return_if_fail (band >= 0 && band < EQ_BANDS);
202  double values[EQ_BANDS];
203  eq_get_bands (values);
204  values[band] = value;
205  eq_set_bands (values);
206 }
207 
208 double eq_get_band (int band)
209 {
210  g_return_val_if_fail (band >= 0 && band < EQ_BANDS, 0);
211  double values[EQ_BANDS];
212  eq_get_bands (values);
213  return values[band];
214 }