1 /*
2 * Schism Tracker - a cross-platform Impulse Tracker clone
3 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5 * copyright (c) 2009 Storlek & Mrs. Brisby
6 * copyright (c) 2010-2012 Storlek
7 * URL: http://schismtracker.org/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "sndfile.h"
25 #include "cmixer.h"
26 #include <math.h>
27
28
29 #define EQ_BANDWIDTH 2.0
30 #define EQ_ZERO 0.000001
31
32
33
34 typedef struct {
35 float a0, a1, a2, b1, b2;
36 float x1, x2, y1, y2;
37 float gain, center_frequency;
38 int enabled;
39 } eq_band;
40
41
42
43 //static REAL f2ic = (REAL)(1 << 28);
44 //static REAL i2fc = (REAL)(1.0 / (1 << 28));
45
46 static eq_band eq[MAX_EQ_BANDS * 2] =
47 {
48 // Default: Flat EQ
49 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 120, 0},
50 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 600, 0},
51 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1200, 0},
52 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3000, 0},
53 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6000, 0},
54 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10000, 0},
55 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 120, 0},
56 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 600, 0},
57 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1200, 0},
58 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3000, 0},
59 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6000, 0},
60 {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10000, 0},
61 };
62
63
eq_filter(eq_band * pbs,float * pbuffer,unsigned int count)64 static void eq_filter(eq_band *pbs, float *pbuffer, unsigned int count)
65 {
66 for (unsigned int i = 0; i < count; i++) {
67 float x = pbuffer[i];
68 float y = pbs->a1 * pbs->x1 +
69 pbs->a2 * pbs->x2 +
70 pbs->a0 * x +
71 pbs->b1 * pbs->y1 +
72 pbs->b2 * pbs->y2;
73
74 pbs->x2 = pbs->x1;
75 pbs->y2 = pbs->y1;
76 pbs->x1 = x;
77 pbuffer[i] = y;
78 pbs->y1 = y;
79 }
80 }
81
82
eq_mono(song_t * csf,int * buffer,unsigned int count)83 void eq_mono(song_t *csf, int *buffer, unsigned int count)
84 {
85 mono_mix_to_float(buffer, csf->mix_buffer_float, count);
86
87 for (unsigned int b = 0; b < MAX_EQ_BANDS; b++)
88 {
89 if (eq[b].enabled && eq[b].gain != 1.0f)
90 eq_filter(&eq[b], csf->mix_buffer_float, count);
91 }
92
93 float_to_mono_mix(csf->mix_buffer_float, buffer, count);
94 }
95
96
97 // XXX: I rolled the two loops into one. Make sure this works.
eq_stereo(song_t * csf,int * buffer,unsigned int count)98 void eq_stereo(song_t *csf, int *buffer, unsigned int count)
99 {
100 stereo_mix_to_float(buffer, csf->mix_buffer_float, csf->mix_buffer_float + MIXBUFFERSIZE, count);
101
102 for (unsigned int b = 0; b < MAX_EQ_BANDS; b++) {
103 int br = b + MAX_EQ_BANDS;
104
105 // Left band
106 if (eq[b].enabled && eq[b].gain != 1.0f)
107 eq_filter(&eq[b], csf->mix_buffer_float, count);
108
109 // Right band
110 if (eq[br].enabled && eq[br].gain != 1.0f)
111 eq_filter(&eq[br], csf->mix_buffer_float + MIXBUFFERSIZE, count);
112 }
113
114 float_to_stereo_mix(csf->mix_buffer_float, csf->mix_buffer_float + MIXBUFFERSIZE, buffer, count);
115 }
116
117
initialize_eq(int reset,float freq)118 void initialize_eq(int reset, float freq)
119 {
120 //float fMixingFreq = (REAL)mix_frequency;
121
122 // Gain = 0.5 (-6dB) .. 2 (+6dB)
123 for (unsigned int band = 0; band < MAX_EQ_BANDS * 2; band++) {
124 float k, k2, r, f;
125 float v0, v1;
126 int b = reset;
127
128 if (!eq[band].enabled) {
129 eq[band].a0 = 0;
130 eq[band].a1 = 0;
131 eq[band].a2 = 0;
132 eq[band].b1 = 0;
133 eq[band].b2 = 0;
134 eq[band].x1 = 0;
135 eq[band].x2 = 0;
136 eq[band].y1 = 0;
137 eq[band].y2 = 0;
138 continue;
139 }
140
141 f = eq[band].center_frequency / freq;
142
143 if (f > 0.45f)
144 eq[band].gain = 1;
145
146 //if (f > 0.25)
147 // f = 0.25;
148
149 //k = tan(PI * f);
150
151 k = f * 3.141592654f;
152 k = k + k * f;
153
154 //if (k > (float) 0.707)
155 // k = (float) 0.707;
156
157 k2 = k*k;
158 v0 = eq[band].gain;
159 v1 = 1;
160
161 if (eq[band].gain < 1.0) {
162 v0 *= 0.5f / EQ_BANDWIDTH;
163 v1 *= 0.5f / EQ_BANDWIDTH;
164 }
165 else {
166 v0 *= 1.0f / EQ_BANDWIDTH;
167 v1 *= 1.0f / EQ_BANDWIDTH;
168 }
169
170 r = (1 + v0 * k + k2) / (1 + v1 * k + k2);
171
172 if (r != eq[band].a0) {
173 eq[band].a0 = r;
174 b = 1;
175 }
176
177 r = 2 * (k2 - 1) / (1 + v1 * k + k2);
178
179 if (r != eq[band].a1) {
180 eq[band].a1 = r;
181 b = 1;
182 }
183
184 r = (1 - v0 * k + k2) / (1 + v1 * k + k2);
185
186 if (r != eq[band].a2) {
187 eq[band].a2 = r;
188 b = 1;
189 }
190
191 r = -2 * (k2 - 1) / (1 + v1 * k + k2);
192
193 if (r != eq[band].b1) {
194 eq[band].b1 = r;
195 b = 1;
196 }
197
198 r = -(1 - v1 * k + k2) / (1 + v1 * k + k2);
199
200 if (r != eq[band].b2) {
201 eq[band].b2 = r;
202 b = 1;
203 }
204
205 if (b) {
206 eq[band].x1 = 0;
207 eq[band].x2 = 0;
208 eq[band].y1 = 0;
209 eq[band].y2 = 0;
210 }
211 }
212 }
213
214
set_eq_gains(const unsigned int * gainbuff,unsigned int gains,const unsigned int * freqs,int reset,int mix_freq)215 void set_eq_gains(const unsigned int *gainbuff, unsigned int gains, const unsigned int *freqs,
216 int reset, int mix_freq)
217 {
218 for (unsigned int i = 0; i < MAX_EQ_BANDS; i++) {
219 float g, f = 0;
220
221 if (i < gains) {
222 unsigned int n = gainbuff[i];
223
224 //if (n > 32)
225 // n = 32;
226
227 g = 1.0 + (((double) n) / 64.0);
228
229 if (freqs)
230 f = (float)(int) freqs[i];
231 }
232 else {
233 g = 1;
234 }
235
236 eq[i].gain =
237 eq[i + MAX_EQ_BANDS].gain = g;
238 eq[i].center_frequency =
239 eq[i + MAX_EQ_BANDS].center_frequency = f;
240
241 /* don't enable bands outside... */
242 if (f > 20.0f &&
243 i < gains) {
244 eq[i].enabled =
245 eq[i + MAX_EQ_BANDS].enabled = 1;
246 }
247 else {
248 eq[i].enabled =
249 eq[i + MAX_EQ_BANDS].enabled = 0;
250 }
251 }
252
253 initialize_eq(reset, mix_freq);
254 }
255
256