OpenWareLaboratory
StateVariableFilter.h
Go to the documentation of this file.
1 #ifndef __StateVariableFilter_h__
2 #define __StateVariableFilter_h__
3 
4 #include "FloatArray.h"
5 #include "SignalProcessor.h"
6 
7 #define SVF_COMPUTE_BOUNDED
8 
19 protected:
20  float kvalue(float fc, float q){
21 #ifdef SVF_COMPUTE_BOUNDED
22  const float g = tanf(pioversr*fc);
23 #else
24  g = tanf(pioversr*fc);
25 #endif
26  const float k = 1.0f / q;
27  a1 = 1.0f/(1.0f + g * (g + k));
28  a2 = g * a1;
29  a3 = g * a2;
30  return k;
31  }
32 public:
34 
35  void setCutoff(float fc, float q){
36  const float k = kvalue(fc, q);
37  m0 = k;
38  }
39 
40  void setLowPass(float fc, float q){
41  kvalue(fc, q);
42  m0 = 0;
43  m1 = 0;
44  m2 = 1.0f;
45  }
46 
47  void setHighPass(float fc, float q){
48  m0 = 1.0f;
49  m1 = -kvalue(fc, q);
50  m2 = -1.0f;
51  }
52 
53  void setBandPass(float fc, float q){
54  kvalue(fc, q);
55  m0 = 0.0f;
56  m1 = 1.0f;
57  m2 = 0.0f;
58  }
59 
60  void setNotch(float fc, float q){
61  const float k = kvalue(fc, q);
62  m0 = 1.0f;
63  m1 = -k;
64  m2 = 0.0f;
65  }
66 
67  void setPeak(float fc, float q){
68  const float k = kvalue(fc, q);
69  m0 = 1.0f;
70  m1 = -k;
71  m2 = -2.0f;
72  }
73 
74  void setBell(float fc, float q, float gain){
75  const float k = kvalue(fc, q);
76  const float A = exp10f(gain/40.);
77  m0 = 1.0f;
78  m1 = k * (A * A - 1.);
79  m2 = 0.0f;
80  }
81 
82  void setLowShelf(float fc, float q, float gain){
83  const float k = kvalue(fc, q);
84  const float A = exp10f(gain/40.);
85  m0 = 1.0f;
86  m1 = k * (A - 1.0f);
87  m2 = (A * A - 1.0f);
88  }
89 
90  void setHighShelf(float fc, float q, float gain){
91  const float k = kvalue(fc, q);
92  const float A = exp10f(gain/40.);
93  m0 = A * A;
94  m1 = k * (1.0f - A) * A;
95  m2 = (1.0f - A * A);
96  }
97 
98  void setAllPass(float fc, float q){
99  const float k = kvalue(fc, q);
100  m0 = 1.0f;
101  m1 = 2.0f * k;
102  m2 = 0.0f;
103  }
104 protected:
105  const float pioversr;
106  // coefficients
107 #ifndef SVF_COMPUTE_BOUNDED
108  float g = 0.0f;
109 #endif
110  float a1 = 0.0f;
111  float a2 = 0.0f;
112  float a3 = 0.0f;
113  float m0 = 0.0f;
114  float m1 = 0.0f;
115  float m2 = 0.0f;
116 };
117 
119 public:
121 
122  float process(float v0){
123 #ifdef SVF_COMPUTE_BOUNDED
124  float v3 = v0 - ic2eq;
125  float v1 = a1 * ic1eq + a2*v3;
126  float v2 = ic2eq + a2 * ic1eq + a3 * v3;
127 #else
128  float v1 = a1 * ic1eq + a2 * (v0 - ic2eq);
129  float v2 = ic2eq + g * v1;
130 #endif
131  ic1eq = 2. * v1 - ic1eq;
132  ic2eq = 2. * v2 - ic2eq;
133  return m0 * v0 + m1 * v1 + m2 * v2;
134  }
135 
136  void process(FloatArray input, FloatArray output){
137  size_t nFrames = input.getSize();
138  float v0, v1, v2, v3;
139  for(size_t s = 0; s < nFrames; s++){
140  v0 = input[s];
141 #ifdef SVF_COMPUTE_BOUNDED
142  v3 = v0 - ic2eq;
143  v1 = a1 * ic1eq + a2*v3;
144  v2 = ic2eq + a2 * ic1eq + a3 * v3;
145 #else
146  v1 = a1 * ic1eq + a2 * (v0 - ic2eq);
147  v2 = ic2eq + g * v1;
148 #endif
149  ic1eq = 2. * v1 - ic1eq;
150  ic2eq = 2. * v2 - ic2eq;
151  output[s] = m0 * v0 + m1 * v1 + m2 * v2;
152  }
153  }
154 
155  void processLowPass(FloatArray in, FloatArray fc, float q, FloatArray out){
156  for(size_t i = 0; i < in.getSize(); i++){
157  setLowPass(fc[i], q);
158  out[i] = process(in[i]);
159  }
160  }
161 
162  void processHighPass(FloatArray in, FloatArray fc, float q, FloatArray out){
163  for(size_t i = 0; i < in.getSize(); i++){
164  setHighPass(fc[i], q);
165  out[i] = process(in[i]);
166  }
167  }
168 
169  void processBandPass(FloatArray in, FloatArray fc, float q, FloatArray out){
170  for(size_t i = 0; i < in.getSize(); i++){
171  setBandPass(fc[i], q);
172  out[i] = process(in[i]);
173  }
174  }
175 
179  void processLowBandHighPass(FloatArray in, float fc, float q, FloatArray low, FloatArray band, FloatArray high){
180  size_t nFrames = in.getSize();
181  float v0, v1, v2, v3;
182  setCutoff(fc, q);
183  for(size_t s = 0; s < nFrames; s++){
184  v0 = in[s];
185 #ifdef SVF_COMPUTE_BOUNDED
186  v3 = v0 - ic2eq;
187  v1 = a1 * ic1eq + a2*v3;
188  v2 = ic2eq + a2 * ic1eq + a3 * v3;
189 #else
190  v1 = a1 * ic1eq + a2 * (v0 - ic2eq);
191  v2 = ic2eq + g * v1;
192 #endif
193  ic1eq = 2. * v1 - ic1eq;
194  ic2eq = 2. * v2 - ic2eq;
195  low[s] = v2;
196  band[s] = v1;
197  high[s] = v0 - m0*v1 - v2;
198  // notch = low + high = v0 - k*v1;
199  // peak = low - high = v0 - k*v1 - 2*v2;
200  // all = low + high - k*band = v0 - 2*k*v1;
201  }
202  }
203 
205  FloatArray low, FloatArray band, FloatArray high){
206  size_t nFrames = in.getSize();
207  float v0, v1, v2, v3;
208  for(size_t s = 0; s < nFrames; s++){
209  setCutoff(fc[s], q);
210  v0 = in[s];
211 #ifdef SVF_COMPUTE_BOUNDED
212  v3 = v0 - ic2eq;
213  v1 = a1 * ic1eq + a2*v3;
214  v2 = ic2eq + a2 * ic1eq + a3 * v3;
215 #else
216  v1 = a1 * ic1eq + a2 * (v0 - ic2eq);
217  v2 = ic2eq + g * v1;
218 #endif
219  ic1eq = 2. * v1 - ic1eq;
220  ic2eq = 2. * v2 - ic2eq;
221  low[s] = v2;
222  band[s] = v1;
223  high[s] = v0 - m0*v1 - v2;
224  // notch = low + high = v0 - k*v1;
225  // peak = low - high = v0 - k*v1 - 2*v2;
226  // all = low + high - k*band = v0 - 2*k*v1;
227  }
228  }
229 
230  void reset() {
231  ic1eq = 0.0f;
232  ic2eq = 0.0f;
233  }
234 
235  static StateVariableFilter* create(float sr){
236  return new StateVariableFilter(sr);
237  }
238 
239  static void destroy(StateVariableFilter* svf){
240  delete svf;
241  }
242 
243 private:
244  // state
245  float ic1eq = 0.0f;
246  float ic2eq = 0.0f;
247 };
248 
249 
251 protected:
252  size_t mChannels;
253  float* mState;
254  static constexpr size_t STATE_VARIABLES_PER_CHANNEL = 2;
255 public:
258  mChannels(0), mState(NULL) {}
259 
260  MultiStateVariableFilter(float sr, size_t channels, float* state) :
261  AbstractStateVariableFilter(sr), mChannels(channels), mState(state) {}
262 
263  void process(AudioBuffer &input, AudioBuffer &output){
264  size_t len = min((int)mChannels, min(input.getChannels(), output.getChannels()));
265  float* state = mState;
266  for(size_t ch=0; ch<len; ++ch){
267  FloatArray in = input.getSamples(ch);
268  FloatArray out = output.getSamples(ch);
269  size_t nFrames = in.getSize();
270  float v0, v1, v2, v3;
271  float ic1eq = state[0];
272  float ic2eq = state[1];
273  for(size_t s = 0; s < nFrames; s++){
274  v0 = in[s];
275 #ifdef SVF_COMPUTE_BOUNDED
276  v3 = v0 - ic2eq;
277  v1 = a1 * ic1eq + a2*v3;
278  v2 = ic2eq + a2 * ic1eq + a3 * v3;
279 #else
280  v1 = a1 * ic1eq + a2 * (v0 - ic2eq);
281  v2 = ic2eq + g * v1;
282 #endif
283  ic1eq = 2. * v1 - ic1eq;
284  ic2eq = 2. * v2 - ic2eq;
285  out[s] = m0 * v0 + m1 * v1 + m2 * v2;
286  }
287  state[0] = ic1eq;
288  state[1] = ic2eq;
290  }
291  }
292 
293  void reset() {
294  memset(mState, 0, mChannels*STATE_VARIABLES_PER_CHANNEL*sizeof(float));
295  }
296 
297  static MultiStateVariableFilter* create(float sr, size_t channels){
298  return new MultiStateVariableFilter(sr, channels, new float[STATE_VARIABLES_PER_CHANNEL]);
299  }
300 
302  delete[] svf->mState;
303  delete svf;
304  }
305 };
306 
307 
309 public:
310  StereoStateVariableFilter(float sr, float* state) :
311  MultiStateVariableFilter(sr, 2, state) {}
313  return new StereoStateVariableFilter(sr, new float[STATE_VARIABLES_PER_CHANNEL]);
314  }
315 
318  }
319 
320 };
321 
322 #endif // __StateVariableFilter_h__
#define min(a, b)
Definition: basicmaths.h:38
#define M_PI
Definition: basicmaths.h:52
State Variable Filter based on Andy Simper's code and analysis: http://www.cytomic....
void setCutoff(float fc, float q)
void setPeak(float fc, float q)
void setBell(float fc, float q, float gain)
void setHighPass(float fc, float q)
void setLowShelf(float fc, float q, float gain)
void setBandPass(float fc, float q)
float kvalue(float fc, float q)
void setLowPass(float fc, float q)
void setNotch(float fc, float q)
void setAllPass(float fc, float q)
void setHighShelf(float fc, float q, float gain)
virtual int getChannels()=0
virtual FloatArray getSamples(int channel)=0
This class contains useful methods for manipulating arrays of floats.
Definition: FloatArray.h:12
static void destroy(MultiStateVariableFilter *svf)
MultiStateVariableFilter(float sr, size_t channels, float *state)
static MultiStateVariableFilter * create(float sr, size_t channels)
static constexpr size_t STATE_VARIABLES_PER_CHANNEL
void process(AudioBuffer &input, AudioBuffer &output)
Base class for signal processors such as Filters.
size_t getSize() const
Definition: SimpleArray.h:31
void processLowBandHighPass(FloatArray in, FloatArray fc, float q, FloatArray low, FloatArray band, FloatArray high)
void processBandPass(FloatArray in, FloatArray fc, float q, FloatArray out)
static StateVariableFilter * create(float sr)
void processHighPass(FloatArray in, FloatArray fc, float q, FloatArray out)
void processLowPass(FloatArray in, FloatArray fc, float q, FloatArray out)
static void destroy(StateVariableFilter *svf)
void processLowBandHighPass(FloatArray in, float fc, float q, FloatArray low, FloatArray band, FloatArray high)
Simultaneously process lowpass, bandpass and highpass filtered output.
void process(FloatArray input, FloatArray output)
static StereoStateVariableFilter * create(float sr)
StereoStateVariableFilter(float sr, float *state)
static void destroy(StereoStateVariableFilter *svf)