Mercurial > audio-send
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Alc/bs2b.c Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,201 @@ 1.4 +/*- 1.5 + * Copyright (c) 2005 Boris Mikhaylov 1.6 + * 1.7 + * Permission is hereby granted, free of charge, to any person obtaining 1.8 + * a copy of this software and associated documentation files (the 1.9 + * "Software"), to deal in the Software without restriction, including 1.10 + * without limitation the rights to use, copy, modify, merge, publish, 1.11 + * distribute, sublicense, and/or sell copies of the Software, and to 1.12 + * permit persons to whom the Software is furnished to do so, subject to 1.13 + * the following conditions: 1.14 + * 1.15 + * The above copyright notice and this permission notice shall be 1.16 + * included in all copies or substantial portions of the Software. 1.17 + * 1.18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 1.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 1.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 1.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 1.24 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1.25 + */ 1.26 + 1.27 +#include "config.h" 1.28 + 1.29 +#include <math.h> 1.30 + 1.31 +#include "bs2b.h" 1.32 + 1.33 +#ifndef M_PI 1.34 +#define M_PI 3.14159265358979323846 1.35 +#endif 1.36 + 1.37 +/* Single pole IIR filter. 1.38 + * O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1] 1.39 + */ 1.40 + 1.41 +/* Lowpass filter */ 1.42 +#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1)) 1.43 + 1.44 +/* Highboost filter */ 1.45 +#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1)) 1.46 + 1.47 +/* Set up all data. */ 1.48 +static void init(struct bs2b *bs2b) 1.49 +{ 1.50 + double Fc_lo, Fc_hi; 1.51 + double G_lo, G_hi; 1.52 + double x; 1.53 + 1.54 + if ((bs2b->srate > 192000) || (bs2b->srate < 2000)) 1.55 + bs2b->srate = BS2B_DEFAULT_SRATE; 1.56 + 1.57 + switch(bs2b->level) 1.58 + { 1.59 + case BS2B_LOW_CLEVEL: /* Low crossfeed level */ 1.60 + Fc_lo = 360.0; 1.61 + Fc_hi = 501.0; 1.62 + G_lo = 0.398107170553497; 1.63 + G_hi = 0.205671765275719; 1.64 + break; 1.65 + 1.66 + case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */ 1.67 + Fc_lo = 500.0; 1.68 + Fc_hi = 711.0; 1.69 + G_lo = 0.459726988530872; 1.70 + G_hi = 0.228208484414988; 1.71 + break; 1.72 + 1.73 + case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */ 1.74 + Fc_lo = 700.0; 1.75 + Fc_hi = 1021.0; 1.76 + G_lo = 0.530884444230988; 1.77 + G_hi = 0.250105790667544; 1.78 + break; 1.79 + 1.80 + case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */ 1.81 + Fc_lo = 360.0; 1.82 + Fc_hi = 494.0; 1.83 + G_lo = 0.316227766016838; 1.84 + G_hi = 0.168236228897329; 1.85 + break; 1.86 + 1.87 + case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */ 1.88 + Fc_lo = 500.0; 1.89 + Fc_hi = 689.0; 1.90 + G_lo = 0.354813389233575; 1.91 + G_hi = 0.187169483835901; 1.92 + break; 1.93 + 1.94 + default: /* High easy crossfeed level */ 1.95 + bs2b->level = BS2B_HIGH_ECLEVEL; 1.96 + 1.97 + Fc_lo = 700.0; 1.98 + Fc_hi = 975.0; 1.99 + G_lo = 0.398107170553497; 1.100 + G_hi = 0.205671765275719; 1.101 + break; 1.102 + } /* switch */ 1.103 + 1.104 + /* $fc = $Fc / $s; 1.105 + * $d = 1 / 2 / pi / $fc; 1.106 + * $x = exp(-1 / $d); 1.107 + */ 1.108 + 1.109 + x = exp(-2.0 * M_PI * Fc_lo / bs2b->srate); 1.110 + bs2b->b1_lo = x; 1.111 + bs2b->a0_lo = G_lo * (1.0 - x); 1.112 + 1.113 + x = exp(-2.0 * M_PI * Fc_hi / bs2b->srate); 1.114 + bs2b->b1_hi = x; 1.115 + bs2b->a0_hi = 1.0 - G_hi * (1.0 - x); 1.116 + bs2b->a1_hi = -x; 1.117 + 1.118 + bs2b->gain = 1.0 / (1.0 - G_hi + G_lo); 1.119 +} /* init */ 1.120 + 1.121 +/* Exported functions. 1.122 + * See descriptions in "bs2b.h" 1.123 + */ 1.124 + 1.125 +void bs2b_set_level(struct bs2b *bs2b, int level) 1.126 +{ 1.127 + if(level == bs2b->level) 1.128 + return; 1.129 + bs2b->level = level; 1.130 + init(bs2b); 1.131 +} /* bs2b_set_level */ 1.132 + 1.133 +int bs2b_get_level(struct bs2b *bs2b) 1.134 +{ 1.135 + return bs2b->level; 1.136 +} /* bs2b_get_level */ 1.137 + 1.138 +void bs2b_set_srate(struct bs2b *bs2b, int srate) 1.139 +{ 1.140 + if (srate == bs2b->srate) 1.141 + return; 1.142 + bs2b->srate = srate; 1.143 + init(bs2b); 1.144 +} /* bs2b_set_srate */ 1.145 + 1.146 +int bs2b_get_srate(struct bs2b *bs2b) 1.147 +{ 1.148 + return bs2b->srate; 1.149 +} /* bs2b_get_srate */ 1.150 + 1.151 +void bs2b_clear(struct bs2b *bs2b) 1.152 +{ 1.153 + int loopv = sizeof(bs2b->last_sample); 1.154 + 1.155 + while (loopv) 1.156 + { 1.157 + ((char *)&bs2b->last_sample)[--loopv] = 0; 1.158 + } 1.159 +} /* bs2b_clear */ 1.160 + 1.161 +int bs2b_is_clear(struct bs2b *bs2b) 1.162 +{ 1.163 + int loopv = sizeof(bs2b->last_sample); 1.164 + 1.165 + while (loopv) 1.166 + { 1.167 + if (((char *)&bs2b->last_sample)[--loopv] != 0) 1.168 + return 0; 1.169 + } 1.170 + return 1; 1.171 +} /* bs2b_is_clear */ 1.172 + 1.173 +void bs2b_cross_feed(struct bs2b *bs2b, float *sample) 1.174 +{ 1.175 + /* Lowpass filter */ 1.176 + bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]); 1.177 + bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]); 1.178 + 1.179 + /* Highboost filter */ 1.180 + bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]); 1.181 + bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]); 1.182 + bs2b->last_sample.asis[0] = sample[0]; 1.183 + bs2b->last_sample.asis[1] = sample[1]; 1.184 + 1.185 + /* Crossfeed */ 1.186 + sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1]; 1.187 + sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0]; 1.188 + 1.189 + /* Bass boost cause allpass attenuation */ 1.190 + sample[0] *= bs2b->gain; 1.191 + sample[1] *= bs2b->gain; 1.192 + 1.193 + /* Clipping of overloaded samples */ 1.194 +#if 0 1.195 + if (sample[0] > 1.0) 1.196 + sample[0] = 1.0; 1.197 + if (sample[0] < -1.0) 1.198 + sample[0] = -1.0; 1.199 + if (sample[1] > 1.0) 1.200 + sample[1] = 1.0; 1.201 + if (sample[1] < -1.0) 1.202 + sample[1] = -1.0; 1.203 +#endif 1.204 +} /* bs2b_cross_feed */