Mercurial > audio-send
comparison Alc/bs2b.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f9476ff7637e |
---|---|
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 } /* init */ | |
117 | |
118 /* Exported functions. | |
119 * See descriptions in "bs2b.h" | |
120 */ | |
121 | |
122 void bs2b_set_level(struct bs2b *bs2b, int level) | |
123 { | |
124 if(level == bs2b->level) | |
125 return; | |
126 bs2b->level = level; | |
127 init(bs2b); | |
128 } /* bs2b_set_level */ | |
129 | |
130 int bs2b_get_level(struct bs2b *bs2b) | |
131 { | |
132 return bs2b->level; | |
133 } /* bs2b_get_level */ | |
134 | |
135 void bs2b_set_srate(struct bs2b *bs2b, int srate) | |
136 { | |
137 if (srate == bs2b->srate) | |
138 return; | |
139 bs2b->srate = srate; | |
140 init(bs2b); | |
141 } /* bs2b_set_srate */ | |
142 | |
143 int bs2b_get_srate(struct bs2b *bs2b) | |
144 { | |
145 return bs2b->srate; | |
146 } /* bs2b_get_srate */ | |
147 | |
148 void bs2b_clear(struct bs2b *bs2b) | |
149 { | |
150 int loopv = sizeof(bs2b->last_sample); | |
151 | |
152 while (loopv) | |
153 { | |
154 ((char *)&bs2b->last_sample)[--loopv] = 0; | |
155 } | |
156 } /* bs2b_clear */ | |
157 | |
158 int bs2b_is_clear(struct bs2b *bs2b) | |
159 { | |
160 int loopv = sizeof(bs2b->last_sample); | |
161 | |
162 while (loopv) | |
163 { | |
164 if (((char *)&bs2b->last_sample)[--loopv] != 0) | |
165 return 0; | |
166 } | |
167 return 1; | |
168 } /* bs2b_is_clear */ | |
169 | |
170 void bs2b_cross_feed(struct bs2b *bs2b, float *sample) | |
171 { | |
172 /* Lowpass filter */ | |
173 bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]); | |
174 bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]); | |
175 | |
176 /* Highboost filter */ | |
177 bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]); | |
178 bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]); | |
179 bs2b->last_sample.asis[0] = sample[0]; | |
180 bs2b->last_sample.asis[1] = sample[1]; | |
181 | |
182 /* Crossfeed */ | |
183 sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1]; | |
184 sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0]; | |
185 | |
186 /* Bass boost cause allpass attenuation */ | |
187 sample[0] *= bs2b->gain; | |
188 sample[1] *= bs2b->gain; | |
189 | |
190 /* Clipping of overloaded samples */ | |
191 #if 0 | |
192 if (sample[0] > 1.0) | |
193 sample[0] = 1.0; | |
194 if (sample[0] < -1.0) | |
195 sample[0] = -1.0; | |
196 if (sample[1] > 1.0) | |
197 sample[1] = 1.0; | |
198 if (sample[1] < -1.0) | |
199 sample[1] = -1.0; | |
200 #endif | |
201 } /* bs2b_cross_feed */ |