-
Notifications
You must be signed in to change notification settings - Fork 1
/
filter.cpp
95 lines (77 loc) · 2.11 KB
/
filter.cpp
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
// ECS7012P Music and Audio Programming
// School of Electronic Engineering and Computer Science
// Queen Mary University of London
// Spring 2020
// filter.cpp: implement a second-order lowpass filter of variable frequency and Q
#include <cmath>
#include "filter.h"
// Constructor
Filter::Filter() : Filter(44100.0) {}
// Constructor specifying a sample rate
Filter::Filter(float sampleRate)
{
setSampleRate(sampleRate);
reset();
// Set some defaults
frequency_ = 1000.0;
q_ = 0.707;
ready_ = false; // This flag will be set to true when the coefficients are calculated
}
// Set the sample rate, used for all calculations
void Filter::setSampleRate(float rate)
{
sampleRate_ = rate;
if(ready_)
calculateCoefficients(frequency_, q_);
}
// Set the frequency and recalculate coefficients
void Filter::setFrequency(float frequency)
{
frequency_ = frequency;
calculateCoefficients(frequency_, q_);
}
// Set the Q and recalculate the coefficients
void Filter::setQ(float q)
{
q_ = q;
calculateCoefficients(frequency_, q_);
}
// Calculate coefficients
void Filter::calculateCoefficients(float frequency, float q)
{
// Helper variables
float w = frequency * 2.0 * M_PI;
float t = 1.0 / sampleRate_;
// Calculate coefficients
float a0 = 4.0 + ((w/q)*2.0*t) + pow(w, 2.0) * pow(t, 2.0);
coeffB0_ = coeffB2_ = pow(w, 2.0) * pow(t, 2.0) / a0;
coeffB1_ = pow(w, 2.0) * 2.0 * pow(t, 2.0) / a0;
coeffA1_ = ((2.0 * pow(t, 2.0) * pow(w, 2.0)) -8.0) / a0;
coeffA2_ = (4.0 - (w/q*2.0*t) + (pow(w, 2.0) * pow(t, 2.0))) / a0;
ready_ = true;
}
// Reset previous history of filter
void Filter::reset()
{
lastX_[0] = lastX_[1] = 0;
lastY_[0] = lastY_[1] = 0;
}
// Calculate the next sample of output, changing the envelope
// state as needed
float Filter::process(float input)
{
if(!ready_)
return input;
float out = input * coeffB0_ + lastX_[0] * coeffB1_ + lastX_[1] * coeffB2_
- lastY_[0] * coeffA1_ - lastY_[1] * coeffA2_;
lastX_[1] = lastX_[0];
lastX_[0] = input;
lastY_[1] = lastY_[0];
lastY_[0] = out;
return out;
}
// Destructor
Filter::~Filter()
{
// Nothing to do here
}