Mercurial > fife-parpg
comparison ext/openal-soft/Alc/bs2b.c @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children | a18f09b604f2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 /*- | |
2 * Copyright (c) 2005 Boris Mikhaylov | |
3 * | |
4 * Permission is hereby granted, free of charge, to any person obtaining | |
5 * a copy of this software and associated documentation files (the | |
6 * "Software"), to deal in the Software without restriction, including | |
7 * without limitation the rights to use, copy, modify, merge, publish, | |
8 * distribute, sublicense, and/or sell copies of the Software, and to | |
9 * permit persons to whom the Software is furnished to do so, subject to | |
10 * the following conditions: | |
11 * | |
12 * The above copyright notice and this permission notice shall be | |
13 * included in all copies or substantial portions of the Software. | |
14 * | |
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
22 */ | |
23 | |
24 #include "config.h" | |
25 | |
26 #include <math.h> | |
27 | |
28 #include "bs2b.h" | |
29 | |
30 #ifndef M_PI | |
31 #define M_PI 3.14159265358979323846 | |
32 #endif | |
33 | |
34 /* Single pole IIR filter. | |
35 * O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1] | |
36 */ | |
37 | |
38 /* Lowpass filter */ | |
39 #define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1)) | |
40 | |
41 /* Highboost filter */ | |
42 #define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1)) | |
43 | |
44 /* Set up all data. */ | |
45 static void init(struct bs2b *bs2b) | |
46 { | |
47 double Fc_lo, Fc_hi; | |
48 double G_lo, G_hi; | |
49 double x; | |
50 | |
51 if ((bs2b->srate > 192000) || (bs2b->srate < 2000)) | |
52 bs2b->srate = BS2B_DEFAULT_SRATE; | |
53 | |
54 switch(bs2b->level) | |
55 { | |
56 case BS2B_LOW_CLEVEL: /* Low crossfeed level */ | |
57 Fc_lo = 360.0; | |
58 Fc_hi = 501.0; | |
59 G_lo = 0.398107170553497; | |
60 G_hi = 0.205671765275719; | |
61 break; | |
62 | |
63 case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */ | |
64 Fc_lo = 500.0; | |
65 Fc_hi = 711.0; | |
66 G_lo = 0.459726988530872; | |
67 G_hi = 0.228208484414988; | |
68 break; | |
69 | |
70 case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */ | |
71 Fc_lo = 700.0; | |
72 Fc_hi = 1021.0; | |
73 G_lo = 0.530884444230988; | |
74 G_hi = 0.250105790667544; | |
75 break; | |
76 | |
77 case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */ | |
78 Fc_lo = 360.0; | |
79 Fc_hi = 494.0; | |
80 G_lo = 0.316227766016838; | |
81 G_hi = 0.168236228897329; | |
82 break; | |
83 | |
84 case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */ | |
85 Fc_lo = 500.0; | |
86 Fc_hi = 689.0; | |
87 G_lo = 0.354813389233575; | |
88 G_hi = 0.187169483835901; | |
89 break; | |
90 | |
91 default: /* High easy crossfeed level */ | |
92 bs2b->level = BS2B_HIGH_ECLEVEL; | |
93 | |
94 Fc_lo = 700.0; | |
95 Fc_hi = 975.0; | |
96 G_lo = 0.398107170553497; | |
97 G_hi = 0.205671765275719; | |
98 break; | |
99 } /* switch */ | |
100 | |
101 /* $fc = $Fc / $s; | |
102 * $d = 1 / 2 / pi / $fc; | |
103 * $x = exp(-1 / $d); | |
104 */ | |
105 | |
106 x = exp(-2.0 * M_PI * Fc_lo / bs2b->srate); | |
107 bs2b->b1_lo = x; | |
108 bs2b->a0_lo = G_lo * (1.0 - x); | |
109 | |
110 x = exp(-2.0 * M_PI * Fc_hi / bs2b->srate); | |
111 bs2b->b1_hi = x; | |
112 bs2b->a0_hi = 1.0 - G_hi * (1.0 - x); | |
113 bs2b->a1_hi = -x; | |
114 | |
115 bs2b->gain = 1.0 / (1.0 - G_hi + G_lo); | |
116 | |
117 bs2b_clear(bs2b); | |
118 } /* init */ | |
119 | |
120 /* Exported functions. | |
121 * See descriptions in "bs2b.h" | |
122 */ | |
123 | |
124 void bs2b_set_level(struct bs2b *bs2b, int level) | |
125 { | |
126 if(level == bs2b->level) | |
127 return; | |
128 bs2b->level = level; | |
129 init(bs2b); | |
130 } /* bs2b_set_level */ | |
131 | |
132 int bs2b_get_level(struct bs2b *bs2b) | |
133 { | |
134 return bs2b->level; | |
135 } /* bs2b_get_level */ | |
136 | |
137 void bs2b_set_srate(struct bs2b *bs2b, int srate) | |
138 { | |
139 if (srate == bs2b->srate) | |
140 return; | |
141 bs2b->srate = srate; | |
142 init(bs2b); | |
143 } /* bs2b_set_srate */ | |
144 | |
145 int bs2b_get_srate(struct bs2b *bs2b) | |
146 { | |
147 return bs2b->srate; | |
148 } /* bs2b_get_srate */ | |
149 | |
150 void bs2b_clear(struct bs2b *bs2b) | |
151 { | |
152 int loopv = sizeof(bs2b->last_sample); | |
153 | |
154 while (loopv) | |
155 { | |
156 ((char *)&bs2b->last_sample)[--loopv] = 0; | |
157 } | |
158 } /* bs2b_clear */ | |
159 | |
160 int bs2b_is_clear(struct bs2b *bs2b) | |
161 { | |
162 int loopv = sizeof(bs2b->last_sample); | |
163 | |
164 while (loopv) | |
165 { | |
166 if (((char *)&bs2b->last_sample)[--loopv] != 0) | |
167 return 0; | |
168 } | |
169 return 1; | |
170 } /* bs2b_is_clear */ | |
171 | |
172 void bs2b_cross_feed(struct bs2b *bs2b, float *sample) | |
173 { | |
174 /* Lowpass filter */ | |
175 bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]); | |
176 bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]); | |
177 | |
178 /* Highboost filter */ | |
179 bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]); | |
180 bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]); | |
181 bs2b->last_sample.asis[0] = sample[0]; | |
182 bs2b->last_sample.asis[1] = sample[1]; | |
183 | |
184 /* Crossfeed */ | |
185 sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1]; | |
186 sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0]; | |
187 | |
188 /* Bass boost cause allpass attenuation */ | |
189 sample[0] *= bs2b->gain; | |
190 sample[1] *= bs2b->gain; | |
191 | |
192 /* Clipping of overloaded samples */ | |
193 #if 0 | |
194 if (sample[0] > 1.0) | |
195 sample[0] = 1.0; | |
196 if (sample[0] < -1.0) | |
197 sample[0] = -1.0; | |
198 if (sample[1] > 1.0) | |
199 sample[1] = 1.0; | |
200 if (sample[1] < -1.0) | |
201 sample[1] = -1.0; | |
202 #endif | |
203 } /* bs2b_cross_feed */ |