-
Notifications
You must be signed in to change notification settings - Fork 5
/
biquad.c
93 lines (77 loc) · 3.18 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
////////////////////////////////////////////////////////////////////////////
// **** BIQUAD **** //
// Simple Biquad Filter Library //
// Copyright (c) 2021 - 2022 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// biquad.c
#include "biquad.h"
// Second-order Lowpass
void biquad_lowpass (BiquadCoefficients *filter, double frequency)
{
double Q = sqrt (0.5), K = tan (M_PI * frequency);
double norm = 1.0 / (1.0 + K / Q + K * K);
filter->a0 = K * K * norm;
filter->a1 = 2 * filter->a0;
filter->a2 = filter->a0;
filter->b1 = 2.0 * (K * K - 1.0) * norm;
filter->b2 = (1.0 - K / Q + K * K) * norm;
}
// Second-order Highpass
void biquad_highpass (BiquadCoefficients *filter, double frequency)
{
double Q = sqrt (0.5), K = tan (M_PI * frequency);
double norm = 1.0 / (1.0 + K / Q + K * K);
filter->a0 = norm;
filter->a1 = -2.0 * norm;
filter->a2 = filter->a0;
filter->b1 = 2.0 * (K * K - 1.0) * norm;
filter->b2 = (1.0 - K / Q + K * K) * norm;
}
// Initialize the specified biquad filter with the given parameters. Note that the "gain" parameter is supplied here
// to save a multiply every time the filter in applied.
void biquad_init (Biquad *f, const BiquadCoefficients *coeffs, float gain)
{
f->coeffs = *coeffs;
f->coeffs.a0 *= gain;
f->coeffs.a1 *= gain;
f->coeffs.a2 *= gain;
f->in_d1 = f->in_d2 = 0.0F;
f->out_d1 = f->out_d2 = 0.0F;
f->first_order = (coeffs->a2 == 0.0F && coeffs->b2 == 0.0F);
}
// Apply the supplied sample to the specified biquad filter, which must have been initialized with biquad_init().
float biquad_apply_sample (Biquad *f, float input)
{
float sum;
if (f->first_order)
sum = (input * f->coeffs.a0) + (f->in_d1 * f->coeffs.a1) - (f->coeffs.b1 * f->out_d1);
else
sum = (input * f->coeffs.a0) + (f->in_d1 * f->coeffs.a1) + (f->in_d2 * f->coeffs.a2) - (f->coeffs.b1 * f->out_d1) - (f->coeffs.b2 * f->out_d2);
f->out_d2 = f->out_d1;
f->out_d1 = sum;
f->in_d2 = f->in_d1;
f->in_d1 = input;
return sum;
}
// Apply the supplied buffer to the specified biquad filter, which must have been initialized with biquad_init().
void biquad_apply_buffer (Biquad *f, float *buffer, int num_samples, int stride)
{
if (f->first_order) while (num_samples--) {
float sum = (*buffer * f->coeffs.a0) + (f->in_d1 * f->coeffs.a1) - (f->coeffs.b1 * f->out_d1);
f->out_d2 = f->out_d1;
f->in_d2 = f->in_d1;
f->in_d1 = *buffer;
*buffer = f->out_d1 = sum;
buffer += stride;
}
else while (num_samples--) {
float sum = (*buffer * f->coeffs.a0) + (f->in_d1 * f->coeffs.a1) + (f->in_d2 * f->coeffs.a2) - (f->coeffs.b1 * f->out_d1) - (f->coeffs.b2 * f->out_d2);
f->out_d2 = f->out_d1;
f->in_d2 = f->in_d1;
f->in_d1 = *buffer;
*buffer = f->out_d1 = sum;
buffer += stride;
}
}