comparison src/modplug/snd_eq.cxx @ 2216:3673c7ec4ea2

Sync with schism's modplug engine. Suggested by G¸«ärkan Seng¸«än.
author William Pitcock <nenolod@atheme.org>
date Fri, 07 Dec 2007 12:08:47 -0600
parents
children
comparison
equal deleted inserted replaced
2198:32f9f1e4a9ec 2216:3673c7ec4ea2
1 /*
2 * This program is free software; you can redistribute it and modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the license or (at your
5 * option) any later version.
6 *
7 * Authors: Olivier Lapicque <olivierl@jps.net>
8 *
9 * Name Date Description
10 *
11 * Olivier Lapicque --/--/-- Creation
12 * Trevor Nunes 26/01/04 conditional compilation for AMD,MMX calls
13 *
14 */
15 #include "stdafx.h"
16 #include "sndfile.h"
17 #include <math.h>
18
19
20 #define EQ_BANDWIDTH 2.0
21 #define EQ_ZERO 0.000001
22 #define REAL float
23
24 extern REAL MixFloatBuffer[];
25
26 extern void StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount);
27 extern void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
28 extern void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount);
29 extern void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount);
30
31 typedef struct _EQBANDSTRUCT
32 {
33 REAL a0, a1, a2, b1, b2;
34 REAL x1, x2, y1, y2;
35 REAL Gain, CenterFrequency;
36 BOOL bEnable;
37 } EQBANDSTRUCT, *PEQBANDSTRUCT;
38
39 UINT gEqLinearToDB[33] =
40 {
41 16, 19, 22, 25, 28, 31, 34, 37,
42 40, 43, 46, 49, 52, 55, 58, 61,
43 64, 76, 88, 100, 112, 124, 136, 148,
44 160, 172, 184, 196, 208, 220, 232, 244, 256
45 };
46
47
48 //static REAL f2ic = (REAL)(1 << 28);
49 //static REAL i2fc = (REAL)(1.0 / (1 << 28));
50
51 static EQBANDSTRUCT gEQ[MAX_EQ_BANDS*2] =
52 {
53 // Default: Flat EQ
54 {0,0,0,0,0, 0,0,0,0, 1, 120, FALSE},
55 {0,0,0,0,0, 0,0,0,0, 1, 600, FALSE},
56 {0,0,0,0,0, 0,0,0,0, 1, 1200, FALSE},
57 {0,0,0,0,0, 0,0,0,0, 1, 3000, FALSE},
58 {0,0,0,0,0, 0,0,0,0, 1, 6000, FALSE},
59 {0,0,0,0,0, 0,0,0,0, 1, 10000, FALSE},
60 {0,0,0,0,0, 0,0,0,0, 1, 120, FALSE},
61 {0,0,0,0,0, 0,0,0,0, 1, 600, FALSE},
62 {0,0,0,0,0, 0,0,0,0, 1, 1200, FALSE},
63 {0,0,0,0,0, 0,0,0,0, 1, 3000, FALSE},
64 {0,0,0,0,0, 0,0,0,0, 1, 6000, FALSE},
65 {0,0,0,0,0, 0,0,0,0, 1, 10000, FALSE},
66 };
67
68 void EQFilter(EQBANDSTRUCT *pbs, REAL *pbuffer, UINT nCount)
69 //----------------------------------------------------------
70 {
71 for (UINT i=0; i<nCount; i++)
72 {
73 REAL x = pbuffer[i];
74 REAL y = pbs->a1 * pbs->x1 + pbs->a2 * pbs->x2 + pbs->a0 * x + pbs->b1 * pbs->y1 + pbs->b2 * pbs->y2;
75 pbs->x2 = pbs->x1;
76 pbs->y2 = pbs->y1;
77 pbs->x1 = x;
78 pbuffer[i] = y;
79 pbs->y1 = y;
80 }
81 }
82
83 void CSoundFile::EQMono(int *pbuffer, UINT nCount)
84 //------------------------------------------------
85 {
86 MonoMixToFloat(pbuffer, MixFloatBuffer, nCount);
87 for (UINT b=0; b<MAX_EQ_BANDS; b++)
88 {
89 if ((gEQ[b].bEnable) && (gEQ[b].Gain != 1.0f))
90 EQFilter(&gEQ[b], MixFloatBuffer, nCount);
91 }
92 FloatToMonoMix(MixFloatBuffer, pbuffer, nCount);
93 }
94
95 void CSoundFile::EQStereo(int *pbuffer, UINT nCount)
96 //--------------------------------------------------
97 {
98 StereoMixToFloat(pbuffer, MixFloatBuffer, MixFloatBuffer+MIXBUFFERSIZE, nCount);
99
100 for (UINT bl=0; bl<MAX_EQ_BANDS; bl++)
101 {
102 if ((gEQ[bl].bEnable) && (gEQ[bl].Gain != 1.0f))
103 EQFilter(&gEQ[bl], MixFloatBuffer, nCount);
104 }
105 for (UINT br=MAX_EQ_BANDS; br<MAX_EQ_BANDS*2; br++)
106 {
107 if ((gEQ[br].bEnable) && (gEQ[br].Gain != 1.0f))
108 EQFilter(&gEQ[br], MixFloatBuffer+MIXBUFFERSIZE, nCount);
109 }
110
111 FloatToStereoMix(MixFloatBuffer, MixFloatBuffer+MIXBUFFERSIZE, pbuffer, nCount);
112
113 }
114
115 void CSoundFile::InitializeEQ(BOOL bReset)
116 //----------------------------------------
117 {
118 REAL fMixingFreq = (REAL)gdwMixingFreq;
119 // Gain = 0.5 (-6dB) .. 2 (+6dB)
120 for (UINT band=0; band<MAX_EQ_BANDS*2; band++) if (gEQ[band].bEnable)
121 {
122 REAL k, k2, r, f;
123 REAL v0, v1;
124 BOOL b = bReset;
125
126 f = gEQ[band].CenterFrequency / fMixingFreq;
127 if (f > 0.45f) gEQ[band].Gain = 1;
128 // if (f > 0.25) f = 0.25;
129 // k = tan(PI*f);
130 k = f * 3.141592654f;
131 k = k + k*f;
132 // if (k > (REAL)0.707) k = (REAL)0.707;
133 k2 = k*k;
134 v0 = gEQ[band].Gain;
135 v1 = 1;
136 if (gEQ[band].Gain < 1.0)
137 {
138 v0 *= (0.5f/EQ_BANDWIDTH);
139 v1 *= (0.5f/EQ_BANDWIDTH);
140 } else
141 {
142 v0 *= (1.0f/EQ_BANDWIDTH);
143 v1 *= (1.0f/EQ_BANDWIDTH);
144 }
145 r = (1 + v0*k + k2) / (1 + v1*k + k2);
146 if (r != gEQ[band].a0)
147 {
148 gEQ[band].a0 = r;
149 b = TRUE;
150 }
151 r = 2 * (k2 - 1) / (1 + v1*k + k2);
152 if (r != gEQ[band].a1)
153 {
154 gEQ[band].a1 = r;
155 b = TRUE;
156 }
157 r = (1 - v0*k + k2) / (1 + v1*k + k2);
158 if (r != gEQ[band].a2)
159 {
160 gEQ[band].a2 = r;
161 b = TRUE;
162 }
163 r = - 2 * (k2 - 1) / (1 + v1*k + k2);
164 if (r != gEQ[band].b1)
165 {
166 gEQ[band].b1 = r;
167 b = TRUE;
168 }
169 r = - (1 - v1*k + k2) / (1 + v1*k + k2);
170 if (r != gEQ[band].b2)
171 {
172 gEQ[band].b2 = r;
173 b = TRUE;
174 }
175 if (b)
176 {
177 gEQ[band].x1 = 0;
178 gEQ[band].x2 = 0;
179 gEQ[band].y1 = 0;
180 gEQ[band].y2 = 0;
181 }
182 } else
183 {
184 gEQ[band].a0 = 0;
185 gEQ[band].a1 = 0;
186 gEQ[band].a2 = 0;
187 gEQ[band].b1 = 0;
188 gEQ[band].b2 = 0;
189 gEQ[band].x1 = 0;
190 gEQ[band].x2 = 0;
191 gEQ[band].y1 = 0;
192 gEQ[band].y2 = 0;
193 }
194 }
195
196
197 void CSoundFile::SetEQGains(const UINT *pGains, UINT nGains, const UINT *pFreqs, BOOL bReset)
198 //-------------------------------------------------------------------------------------------
199 {
200 for (UINT i=0; i<MAX_EQ_BANDS; i++)
201 {
202 REAL g, f = 0;
203 if (i < nGains)
204 {
205 UINT n = pGains[i];
206 // if (n > 32) n = 32;
207 g = 1.0 + (((double)n) / 64.0);
208 if (pFreqs) f = (REAL)(int)pFreqs[i];
209 } else
210 {
211 g = 1;
212 }
213 gEQ[i].Gain = g;
214 gEQ[i].CenterFrequency = f;
215 gEQ[i+MAX_EQ_BANDS].Gain = g;
216 gEQ[i+MAX_EQ_BANDS].CenterFrequency = f;
217 if (f > 20.0f && i < nGains) /* don't enable bands outside... */
218 {
219 gEQ[i].bEnable = TRUE;
220 gEQ[i+MAX_EQ_BANDS].bEnable = TRUE;
221 } else
222 {
223 gEQ[i].bEnable = FALSE;
224 gEQ[i+MAX_EQ_BANDS].bEnable = FALSE;
225 }
226 }
227 InitializeEQ(bReset);
228 }