-
Notifications
You must be signed in to change notification settings - Fork 8
/
biquad.c
145 lines (131 loc) · 3.22 KB
/
biquad.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* @file biquad.c
*
* Simple implementation of Biquad filters -- Tom St Denis
*
* Based on the work
*
* Cookbook formulae for audio EQ biquad filter coefficients
* ---------------------------------------------------------
* by Robert Bristow-Johnson, [email protected] a.k.a. [email protected]
*
* Available on the web at
* http://www.musicdsp.org/files/biquad.c
*
* Enjoy.
*
* This work is hereby placed in the public domain for all purposes, whether
* commercial, free [as in speech] or educational, etc. Use the code and please
* give me credit if you wish.
*
* Tom St Denis -- http://tomstdenis.home.dhs.org
*
* See also: http://musicweb.ucsd.edu/~tre/biquad.pdf
*
*/
#include "biquad.h"
/* Computes a BiQuad filter on a sample */
smp_type BiQuad(const smp_type sample, biquad* const b)
{
smp_type result;
/* compute result */
result = b->a0 * sample + b->a1 * b->x1 + b->a2 * b->x2 -
b->a3 * b->y1 - b->a4 * b->y2;
/* shift x1 to x2, sample to x1 */
b->x2 = b->x1;
b->x1 = sample;
/* shift y1 to y2, result to y1 */
b->y2 = b->y1;
b->y1 = result;
return result;
}
/* sets up a BiQuad Filter */
/* Note that dbGain is only used when the type is LSH or HSH */
biquad *BiQuad_new(const int type, const smp_type dbGain, const smp_type freq,
const smp_type srate, const smp_type bandwidth)
{
biquad *b;
smp_type A, omega, sn, cs, alpha, beta;
smp_type a0, a1, a2, b0, b1, b2;
b = malloc(sizeof(biquad));
if (b == NULL)
return NULL;
/* setup variables */
A = pow(10, dbGain /40);
omega = 2 * M_PI * freq /srate;
sn = sin(omega);
cs = cos(omega);
alpha = sn * sinh(M_LN2 /2 * bandwidth * omega /sn);
beta = sqrt(A + A);
switch (type) {
case LPF:
b0 = (1 - cs) /2;
b1 = 1 - cs;
b2 = (1 - cs) /2;
a0 = 1 + alpha;
a1 = -2 * cs;
a2 = 1 - alpha;
break;
case HPF:
b0 = (1 + cs) /2;
b1 = -(1 + cs);
b2 = (1 + cs) /2;
a0 = 1 + alpha;
a1 = -2 * cs;
a2 = 1 - alpha;
break;
case BPF:
b0 = alpha;
b1 = 0;
b2 = -alpha;
a0 = 1 + alpha;
a1 = -2 * cs;
a2 = 1 - alpha;
break;
case NOTCH:
b0 = 1;
b1 = -2 * cs;
b2 = 1;
a0 = 1 + alpha;
a1 = -2 * cs;
a2 = 1 - alpha;
break;
case PEQ:
b0 = 1 + (alpha * A);
b1 = -2 * cs;
b2 = 1 - (alpha * A);
a0 = 1 + (alpha /A);
a1 = -2 * cs;
a2 = 1 - (alpha /A);
break;
case LSH:
b0 = A * ((A + 1) - (A - 1) * cs + beta * sn);
b1 = 2 * A * ((A - 1) - (A + 1) * cs);
b2 = A * ((A + 1) - (A - 1) * cs - beta * sn);
a0 = (A + 1) + (A - 1) * cs + beta * sn;
a1 = -2 * ((A - 1) + (A + 1) * cs);
a2 = (A + 1) + (A - 1) * cs - beta * sn;
break;
case HSH:
b0 = A * ((A + 1) + (A - 1) * cs + beta * sn);
b1 = -2 * A * ((A - 1) + (A + 1) * cs);
b2 = A * ((A + 1) + (A - 1) * cs - beta * sn);
a0 = (A + 1) - (A - 1) * cs + beta * sn;
a1 = 2 * ((A - 1) - (A + 1) * cs);
a2 = (A + 1) - (A - 1) * cs - beta * sn;
break;
default:
free(b);
return NULL;
}
/* precompute the coefficients */
b->a0 = b0 /a0;
b->a1 = b1 /a0;
b->a2 = b2 /a0;
b->a3 = a1 /a0;
b->a4 = a2 /a0;
/* zero initial samples */
b->x1 = b->x2 = 0;
b->y1 = b->y2 = 0;
return b;
}