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