-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSVF2.h
205 lines (183 loc) · 5.94 KB
/
SVF2.h
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
* SVF2.h
*
* A State Variable Filter implementation
* Higher quality but less efficient than SVF.h
*
* by Andrew R. Brown 2024
*
* Based on the Resonant Filter by Paul Kellett with SVF mods by Peter Schofhauzer from:
* https://www.musicdsp.org/en/latest/Filters/29-resonant-filter.html
*
* This file is part of the M16 audio library.
*
* M16 is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
*/
#ifndef SVF2_H_
#define SVF2_H_
class SVF2 {
public:
/** Constructor */
SVF2() {
setRes(0.2);
}
/** Set how resonant the filter will be.
* 0.01 > res < 1.0
*/
inline
void setRes(float resonance) {
q = min(0.96, pow(max(0.0f, min(1.0f, resonance)), 0.6));
fb = q + q * (1.0 - f);
}
/** Return the resonance or q of the filter.*/
inline
float getRes() {
return q;
}
/** Set the cutoff or centre frequency of the filter.
* @param freq_val 0 - 10k Hz (~SAMPLE_RATE/4).
*/
inline
void setFreq(int32_t freq_val) {
freq = max(0, min(maxFreq, freq_val));
f = min(0.96f, 2.0f * sin(3.1459f * freq * SAMPLE_RATE_INV));
}
/** Return the cutoff or centre frequency of the filter.*/
inline
int32_t getFreq() {
return freq;
}
/** Return the f value.*/
inline
float getF() {
return f;
}
/** Set the cutoff or corner frequency of the filter.
* @param cutoff_val 0.0 - 1.0 which equates to 0 - 10k Hz (SAMPLE_RATE/2).
* Sweeping the cutoff value linearly is mapped to a non-linear frequency sweep
*/
inline
void setCutoff(float cutoff_val) {
f = min(0.96, pow(max(0.0f, min(1.0f, cutoff_val)), 2.2));
freq = maxFreq * f;
fb = q + q * (1.0 + f);
}
/** Calculate the next Lowpass filter sample, given an input signal.
* Input is an output from an oscillator or other audio element.
*/
inline
int16_t nextLPF(int32_t input) {
input = clip16(input);
calcFilter(input);
return clip16(low);
}
/** Calculate the next Lowpass filter sample, given an input signal.
* Input is an output from an oscillator or other audio element.
*/
inline
int16_t next(int32_t input) {
return nextLPF(input);
}
/** Retrieve the current Lowpass filter sample.
* Allows simultaneous use of LPF, HPF & BPF.
* Use nextXXX() for one of them at each sample to compute the next filter values.
*/
inline
int16_t currentLPF() {
return clip16(low);
}
/** Calculate the next Highpass filter sample, given an input signal.
* Input is an output from an oscillator or other audio element.
*/
inline
int16_t nextHPF(int32_t input) {
input = clip16(input);
calcFilter(input);
return clip16(high);
}
/** Retrieve the current Highpass filter sample.
* Allows simultaneous use of LPF, HPF & BPF.
* Use nextXXX() for one of them at each sample to compute the next filter values.
*/
inline
int16_t currentHPF() {
return clip16(high);
}
/** Calculate the next Bandpass filter sample, given an input signal.
* Input is an output from an oscillator or other audio element.
*/
inline
int16_t nextBPF(int32_t input) {
input = clip16(input);
calcFilter(input);
return clip16(band);
}
/** Retrieve the current Bandpass filter sample.
* Allows simultaneous use of LPF, HPF & BPF.
* Use nextXXX() for one of them at each sample to compute the next filter values.
*/
inline
int16_t nextBPF() {
return clip16(band);
}
/** Calculate the next filter sample, for a mix between low, band and high pass filters.
* @input is an output from an oscillator or other audio element.
* @mix is the balance between low, band and high pass outputs, 0.0 - 1.0
* Mix 0 is LPF, Mix 0.5 is BPF and Mix 1.0 is HPF, inbetween are combinations
*/
inline
int16_t nextFiltMix(int32_t input, float mix) {
input = clip16(input);
calcFilter(input);
int32_t lpfAmnt = 0;
if (mix < 0.5) lpfAmnt = low * pow((1 - mix * 2), 0.5);
int32_t bpfAmnt = 0;
if (mix > 0.25 || mix < 0.75) {
bpfAmnt = band * pow(1 - (abs(mix - 0.5) * 2), 0.5);
}
int32_t hpfAmnt = 0;
if (mix > 0.5) hpfAmnt = clip16(high * pow((mix - 0.5) * 2, 0.5));
return max(-MAX_16, min(MAX_16, lpfAmnt + bpfAmnt + hpfAmnt));
}
/** Calculate the next Allpass filter sample, given an input signal.
* Input is an output from an oscillator or other audio element.
* Perhaps not technically a state variable filter, but...
*/
inline
int16_t nextAllpass(int32_t input) {
// y = x + x(t-1) - y(t-1)
input = clip16(input);
int32_t output = input + allpassPrevIn - allpassPrevOut;
allpassPrevIn = input;
allpassPrevOut = output;
return max(-MAX_16, (int)min((int32_t)MAX_16, output));
}
/** Calculate the next Notch filter sample, given an input signal.
* Input is an output from an oscillator or other audio element.
*/
inline
int16_t nextNotch(int32_t input) {
input = clip16(input);
calcFilter(input);
return max(-MAX_16, (int)min((int32_t)MAX_16, notch));
}
private:
int32_t low, band, high, notch, allpassPrevIn, allpassPrevOut, simplePrev;
int32_t maxFreq = SAMPLE_RATE * 0.195;
int32_t freq = 0;
float f = 1.0;
float q = 0.0;
float fb = 0.0;
float buf0 = 0.0;
float buf1 = 0.0;
void calcFilter(int32_t input) {
float in = max(-1.0f, min(1.0f, (float)(input * MAX_16_INV)));
buf0 = buf0 + f * (in - buf0 + fb * (buf0 - buf1));
buf1 = buf1 + f * (buf0 - buf1);
low = buf1 * MAX_16; // LowPass
high = (in - buf0) * MAX_16; // HighPass
band = (buf0 - buf1) * MAX_16; // BandPass
notch = (in - buf0 + buf1) * MAX_16; // Notch
}
};
#endif /* SVF2_H_ */