annotate Alc/bs2b.c @ 14:63312ec4a2bf

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