-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathFilter.h
183 lines (145 loc) · 3.7 KB
/
Filter.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
#pragma once
/*
MINI VIRTUAL ANALOG SYNTHESIZER
Copyright 2014 Kenneth D. Miller III
Filter
*/
#include "Envelope.h"
// filter type
#define FILTER_IMPROVED_MOOG 0
#define FILTER_LINEAR_MOOG 1
#define FILTER_NONLINEAR_MOOG 2
#define FILTER_TPT_MOOG 3
#define FILTER 3
// resonant lowpass filter
class FilterConfig
{
public:
bool enable;
enum Mode
{
PEAK,
LOWPASS_1,
LOWPASS_2,
LOWPASS_3,
LOWPASS_4,
HIGHPASS_1,
HIGHPASS_2,
HIGHPASS_3,
HIGHPASS_4,
BANDPASS_1,
BANDPASS_1_LOWPASS_1,
BANDPASS_1_LOWPASS_2,
BANDPASS_1_HIGHPASS_1,
BANDPASS_1_HIGHPASS_2,
BANDPASS_2,
NOTCH_1,
NOTCH_1_LOWPASS_1,
NOTCH_1_LOWPASS_2,
NOTCH_1_HIGHPASS_1,
NOTCH_1_HIGHPASS_2,
NOTCH_2,
PHASESHIFT_1,
PHASESHIFT_2,
PHASESHIFT_3,
PHASESHIFT_4,
COUNT
};
Mode mode;
float mix[5];
// drive parameter
float drive;
// gain compensation
float compensation;
// resonance parameter
float resonance;
// cutoff frequency (logarithmic)
float cutoff_base;
float cutoff_lfo;
float cutoff_env;
float cutoff_env_vel;
// key follow
float key_follow;
FilterConfig(bool const enable, Mode const mode, float const drive, float const compensation, float const resonance, float const cutoff_base, float const cutoff_lfo, float const cutoff_env, float const cutoff_env_vel, float const key_follow)
: enable(enable)
, drive(drive)
, compensation(compensation)
, resonance(resonance)
, cutoff_base(cutoff_base)
, cutoff_lfo(cutoff_lfo)
, cutoff_env(cutoff_env)
, cutoff_env_vel(cutoff_env_vel)
, key_follow(key_follow)
{
SetMode(mode);
}
// set filter mode
void SetMode(Mode newmode);
// get the modulated cutoff value
float GetCutoff(float const lfo, float const env, float const vel)
{
return powf(2, cutoff_base + lfo * cutoff_lfo + env * (cutoff_env + vel * cutoff_env_vel));
}
};
// filter state
class FilterState
{
public:
// feedback coefficient
float feedback;
#if FILTER == FILTER_NONLINEAR_MOOG
#define FILTER_OVERSAMPLE 2
// output delayed by half a sample for phase compensation
float previous;
float delayed;
// tuning coefficient
float tune;
// nonlinear output values from each stage
float z[5];
#elif FILTER == FILTER_LINEAR_MOOG
#define FILTER_OVERSAMPLE 2
// output delayed by half a sample for phase compensation
float previous;
float delayed;
// tuning coefficient
float tune;
#elif FILTER == FILTER_IMPROVED_MOOG
#define FILTER_OVERSAMPLE 2
// filter stage IIR coefficients
// H(z) = (b0 * z + b1) / (z + a1)
// H(z) = (b0 + b1 * z^-1) / (1 + a1 * z-1)
// H(z) = Y(z) / X(z)
// Y(z) = b0 + b1 * z^-1
// X(z) = 1 + a1 * z^-1
// (1 + a1 * z^-1) * Y(z) = (b0 + b1 * z^-1) * X(z)
// y[n] + a1 * y[n - 1] = b0 * x[n] + b1 * x[n - 1]
// y[n] = b0 * x[n] + b1 * x[n-1] - a1 * y[n-1]
float b0, b1, a1;
#elif FILTER == FILTER_TPT_MOOG
#define FILTER_OVERSAMPLE 1
// parameters derived from cutoff and resonance
float inv1g, G, alpha0;
// delay element values
float z[4];
#endif
// linear output values from each stage
// (y[0] is input to the first stage)
float y[5];
FilterState()
{
Reset();
}
void Reset(void);
void Setup(float const cutoff, float const resonance, float const step);
float Update(FilterConfig const &config, float const input);
};
// filter mode names
extern char const * const filter_name[FilterConfig::COUNT];
// filter configuration
extern FilterConfig flt_config;
// filter envelope configuration
extern EnvelopeConfig flt_env_config;
// filter state
extern FilterState flt_state[];
// filter envelope state
extern EnvelopeState flt_env_state[];