2
* Copyright (C) 1999 topher lafata <topher@topher.com>,
3
* Jake Donham <jake@bitmechanic.com>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* General Public License for more details.
15
* You should have received a copy of the GNU General Public
16
* License along with this program (see COPYING); if not, write to the
17
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, USA.
26
#define FILTER_SECTIONS 2 /* 2 filter sections for 24 db/oct filter */
30
#define SAMPLE_RATE 44100
33
void filter_next_buffer(filter *this);
36
double a0, a1, a2; /* numerator coefficients */
37
double b0, b1, b2; /* denominator coefficients */
40
BIQUAD ProtoCoef[FILTER_SECTIONS] = {
41
{ 1.0, 0, 0, 1.0, 0.765367, 1.0 },
42
{ 1.0, 0, 0, 1.0, 1.847759, 1.0 }
46
static float **coef_lookup_table;
47
static int looked_up = 0;
51
/*coeficient calculation function */
53
double *a0, double *a1, double *a2, /* numerator coefficients */
54
double *b0, double *b1, double *b2, /* denominator coefficients */
55
double fc, /* Filter cutoff frequency */
56
double fs, /* sampling rate */
57
double *k, /* overall gain factor */
58
float *coef); /* pointer to 4 iir coefficients */
60
float *filter_get_coef(int sections,double cutoff,double q, double gain)
66
float *Coef = (float *)calloc(4 * sections + 1, sizeof(float));
67
float *coef = Coef + 1;
70
double fs = SAMPLE_RATE;
72
double a0, a1, a2, b0, b1, b2;
75
/* printf("cutoff is %f\n",fc); */
76
/* printf("Q is %f\n",Q); */
78
for(nInd = 0; nInd < sections; nInd++)
80
a0 = ProtoCoef[nInd].a0;
81
a1 = ProtoCoef[nInd].a1;
82
a2 = ProtoCoef[nInd].a2;
84
b0 = ProtoCoef[nInd].b0;
85
b1 = ProtoCoef[nInd].b1 / Q; /* Divide by resonance or Q */
86
b2 = ProtoCoef[nInd].b2;
87
szxform(&a0, &a1, &a2, &b0, &b1, &b2, fc, fs, &k, coef);
88
coef += 4; /* Point to next filter section */
97
void filter_init_lookup_table()
101
int freq_range, q_range, table_length;
105
q_scale = MAX_Q/MAX_FC;
106
gain_scale = - (MAX_GAIN - MIN_GAIN) / MAX_FC;
107
freq_range = MAX_FC - MIN_FC;
108
q_range = (MAX_Q - MIN_Q) / (double)Q_INCREMENT;
110
table_length = freq_range * q_range;
112
printf("Calculating coefficient table.");
115
for(fc = MIN_FC; fc < MAX_FC;fc++)
116
for(q = MIN_Q;q < MAX_Q; q += (double)Q_INCREMENT){
117
/*PATCH BY: Harold Gutch <logix@foobar.franken.de>
118
FreeBSD can't handle devide by zero and it was possible
119
for scaled_q to go to zero*/
120
double scaled_q = (((q_scale * (fc)) / MAX_Q)* q) + MIN_Q;
121
coef_lookup_table[index] = filter_get_coef(FILTER_SECTIONS,
124
gain_scale * fc + MAX_GAIN);
127
if(index % 1000 == 0){
136
void filter_set_coeffs(filter *this, int fc, float q)
139
index = ((fc - MIN_FC) * (MAX_Q - MIN_Q) / Q_INCREMENT)
142
this->coef = coef_lookup_table[index];
149
sample filter_process_sample(filter *this, sample input)
153
float *hist1_ptr,*hist2_ptr,*coef_ptr;
154
float output,new_hist,history1,history2;
157
/* allocate history array if different size than last call */
159
this->history = (float *) calloc(2*this->length,sizeof(float));
161
coef_ptr = this->coef; /* coefficient pointer */
163
hist1_ptr = this->history; /* first history */
164
hist2_ptr = hist1_ptr + 1; /* next history */
167
output = (float)input * (*coef_ptr++);
169
for (i = 0 ; i < this->length; i++)
171
history1 = *hist1_ptr; /* history values */
172
history2 = *hist2_ptr;
174
output = output - history1 * (*coef_ptr++);
175
new_hist = output - history2 * (*coef_ptr++); /* poles */
177
output = new_hist + history1 * (*coef_ptr++);
178
output = output + history2 * (*coef_ptr++); /* zeros */
180
*hist2_ptr++ = *hist1_ptr;
181
*hist1_ptr++ = new_hist;
186
return (sample)output;
189
void filter_next_buffer(filter *this) {
193
sample *filter_get_buffer(filter *this)
196
sample *filt_e_buffer;
201
buffer = this->sp->get_buffer(this->sp);
202
filt_e_buffer = this->filt_e->get_buffer(this->filt_e);
203
for(i = 0; i < TBASS_BUFF_SIZE; i++)
208
we're scaling the 0-SAMPLE_MAX range of the envelope into
209
a LIMIT-SAMPLE_MAX range 'cause the filter doesn't like the
212
int fe = filt_e_buffer[i] * (SAMPLE_MAX - LIMIT) / SAMPLE_MAX + LIMIT;
213
int fc = this->fc * fe / SAMPLE_MAX;
214
filter_set_coeffs(this,
217
s = filter_process_sample(this,buffer[i]);
220
PATCH: Benno Senoner <benno@gardena.net>
221
clip on underflow as well as overflow
225
else if (s < SAMPLE_MIN)
236
void filter_set_cutoff(filter *this,double cutoff)
239
filter_set_coeffs(this,this->fc,this->Q);
243
void filter_set_gain(filter *this,double gain)
249
void filter_set_q(filter *this,double q)
252
filter_set_coeffs(this,this->fc,this->Q);
256
void filter_delete(filter *this)
267
* ----------------------------------------------------------
270
* Perform bilinear transformation on s-domain coefficients
271
* of 2nd order biquad section.
272
* First design an analog filter and use s-domain coefficients
273
* as input to szxform() to convert them to z-domain.
275
* Here's the butterworth polinomials for 2nd, 4th and 6th order sections.
276
* When we construct a 24 db/oct filter, we take to 2nd order
277
* sections and compute the coefficients separately for each section.
280
* --------------------------------------------------------------------
282
* 4 (s^2 + 0.765367s + 1) (s^2 + 1.847759s + 1)
283
* 6 (s^2 + 0.5176387s + 1) (s^2 + 1.414214 + 1) (s^2 + 1.931852s + 1)
285
* Where n is a filter order.
286
* For n=4, or two second order sections, we have following equasions for each
289
* (1 / (s^2 + (1/Q) * 0.765367s + 1)) * (1 / (s^2 + (1/Q) * 1.847759s + 1))
291
* Where Q is filter quality factor in the range of
292
* 1 to 1000. The overall filter Q is a product of all
293
* 2nd order stages. For example, the 6th order filter
294
* (3 stages, or biquads) with individual Q of 2 will
295
* have filter Q = 2 * 2 * 2 = 8.
297
* The nominator part is just 1.
298
* The denominator coefficients for stage 1 of filter are:
299
* b2 = 1; b1 = 0.765367; b0 = 1;
301
* a2 = 0; a1 = 0; a0 = 1;
303
* The denominator coefficients for stage 1 of filter are:
304
* b2 = 1; b1 = 1.847759; b0 = 1;
306
* a2 = 0; a1 = 0; a0 = 1;
308
* These coefficients are used directly by the szxform()
309
* and bilinear() functions. For all stages the numerator
310
* is the same and the only thing that is different between
311
* different stages is 1st order coefficient. The rest of
312
* coefficients are the same for any stage and equal to 1.
314
* Any filter could be constructed using this approach.
317
* Van Valkenburg, "Analog Filter Design"
318
* Oxford University Press 1982
321
* C Language Algorithms for Digital Signal Processing
322
* Paul Embree, Bruce Kimble
323
* Prentice Hall, 1991
326
* Digital Filter Designer's Handbook
327
* With C++ Algorithms
331
* ----------------------------------------------------------
335
void prewarp(double *a0, double *a1, double *a2, double fc, double fs);
337
double a0, double a1, double a2, /* numerator coefficients */
338
double b0, double b1, double b2, /* denominator coefficients */
339
double *k, /* overall gain factor */
340
double fs, /* sampling rate */
341
float *coef); /* pointer to 4 iir coefficients */
345
* ----------------------------------------------------------
346
* Pre-warp the coefficients of a numerator or denominator.
347
* Note that a0 is assumed to be 1, so there is no wrapping
349
* ----------------------------------------------------------
352
double *a0, double *a1, double *a2,
353
double fc, double fs)
357
pi = 4.0 * atan(1.0);
358
wp = 2.0 * fs * tan(pi * fc / fs);
360
if(wp == 0) /*PATCH BY: free bsd from Hans Huebner<hans@huebner.org> */
362
*a2 = (*a2) / (wp * wp);
372
* ----------------------------------------------------------
375
* Transform the numerator and denominator coefficients
376
* of s-domain biquad section into corresponding
377
* z-domain coefficients.
379
* Store the 4 IIR coefficients in array pointed by coef
380
* in following order:
381
* beta1, beta2 (denominator)
382
* alpha1, alpha2 (numerator)
385
* a0-a2 - s-domain numerator coefficients
386
* b0-b2 - s-domain denominator coefficients
387
* k - filter gain factor. initially set to 1
388
* and modified by each biquad section in such
389
* a way, as to make it the coefficient by
390
* which to multiply the overall filter gain
391
* in order to achieve a desired overall filter gain,
392
* specified in initial value of k.
393
* fs - sampling rate (Hz)
394
* coef - array of z-domain coefficients to be filled in.
397
* On return, set coef z-domain coefficients
398
* ----------------------------------------------------------
401
double a0, double a1, double a2, /* numerator coefficients */
402
double b0, double b1, double b2, /* denominator coefficients */
403
double *k, /* overall gain factor */
404
double fs, /* sampling rate */
405
float *coef /* pointer to 4 iir coefficients */
410
/* alpha (Numerator in s-domain) */
411
ad = 4. * a2 * fs * fs + 2. * a1 * fs + a0;
412
/* beta (Denominator in s-domain) */
413
bd = 4. * b2 * fs * fs + 2. * b1* fs + b0;
415
/* update gain constant for this section */
419
*coef++ = (2. * b0 - 8. * b2 * fs * fs)
421
*coef++ = (4. * b2 * fs * fs - 2. * b1 * fs + b0)
425
*coef++ = (2. * a0 - 8. * a2 * fs * fs)
427
*coef = (4. * a2 * fs * fs - 2. * a1 * fs + a0)
433
* ----------------------------------------------------------
434
* Transform from s to z domain using bilinear transform
438
* For argument description look at bilinear()
440
* coef - pointer to array of floating point coefficients,
441
* corresponding to output of bilinear transofrm
444
* Note: frequencies are in Hz.
445
* ----------------------------------------------------------
448
double *a0, double *a1, double *a2, /* numerator coefficients */
449
double *b0, double *b1, double *b2, /* denominator coefficients */
450
double fc, /* Filter cutoff frequency */
451
double fs, /* sampling rate */
452
double *k, /* overall gain factor */
453
float *coef) /* pointer to 4 iir coefficients */
455
/* Calculate a1 and a2 and overwrite the original values */
456
prewarp(a0, a1, a2, fc, fs);
457
prewarp(b0, b1, b2, fc, fs);
458
bilinear(*a0, *a1, *a2, *b0, *b1, *b2, k, fs, coef);
463
static sample_producer **get_children(filter *this)
468
static char **get_header(filter *this)
470
static char *header[] = {
471
"int $n_fc = ((filter *)$t)->fc;",
472
"float $n_Q = ((filter *)$t)->Q;",
479
static char **get_code(filter *this)
481
static char *code[] = {
482
"filter_set_coeffs((filter *)$t, $n_fc *",
483
" ($i1 * (SAMPLE_MAX - LIMIT) / SAMPLE_MAX + LIMIT) /",
484
" SAMPLE_MAX, $n_Q);",
485
"$n_s = filter_process_sample((filter *)$t, $i0);",
486
"if ($n_s > SAMPLE_MAX) $n_s = SAMPLE_MAX;",
487
"else if ($n_s < SAMPLE_MIN) $n_s = SAMPLE_MIN;",
494
static char **get_footer(filter *this)
496
static char *footer[] = { NULL };
500
filter *filter_new(double cutoff, double q, sample_producer *filt_e,
504
filter *out = malloc(sizeof(filter));
505
out->get_buffer = filter_get_buffer;
506
out->next_buffer = filter_next_buffer;
507
out->get_children = get_children;
508
out->get_header = get_header;
509
out->get_code = get_code;
510
out->get_footer = get_footer;
512
out->schedule = sp_schedule_event;
513
out->trigger = NULL; /*what does it mean to trigger the filter? */
515
/*we aren't responding to events yet in the filter */
516
out->events = (event **)malloc(sizeof(event *)
519
for(i = 0; i < TBASS_BUFF_SIZE; i++)
520
out->events[i] = NULL;
523
out->length = FILTER_SECTIONS;
524
out->gain = MAX_GAIN;
525
out->coef = (float *) calloc(4 * out->length + 1, sizeof(float));
529
out->filt_e = filt_e;
531
out->buffer = (sample *)malloc(sizeof(sample) * TBASS_BUFF_SIZE);
533
/* we're doing this here because we don't call filter_init_lookup_table
534
in fusebirth, and we need to create the filter but not have it
535
blow up in filter_set_coeffs because the table doesn't exist. */
536
coef_lookup_table = (float **)
537
malloc(sizeof(float*) *
538
(MAX_FC - MIN_FC) * (MAX_Q - MIN_Q) / (double)Q_INCREMENT);
540
filter_set_coeffs(out,out->fc,out->Q);