CSL  5.2
Filters.h
Go to the documentation of this file.
1 ///
2 /// Filters.h -- CSL filter classes.
3 ///
4 /// The base Filter class can perform the generic filter equation based upon a set of feedback
5 /// and feedforward coefficients. Subclasses of Filter implement the setupCoeffs method to build
6 /// these coefficients according to different algorithms.
7 /// The subclasses here mostly inherit from the FrequencyAmount controllable, which specifies a
8 /// center frequency and an 'amount' which may variously be resonance, radius, bandwidth etc
9 /// according to the algorithm.
10 ///
11 /// OK so for example Butter class has a CenterFrequency port and a Bandwidth port,
12 /// but pull_controls must be calling Controllables to do the pullInput()
13 ///
14 /// Or, a generic filter that can take a multichannel UGen for each of aCoeffs and bCoeffs (i.e.
15 /// multichannel ports), and other filter classes that wrap this and have Frequency and Bandwidth ports etc.
16 /// This reduces the calls to setupCoeffs, because they'd actually be part of the nextBuffer instead
17 ///
18 /// The reason is that the Scalable type approach & macros can't be extended to filter otherwise.
19 /// ALSO, there are no similar macros for Effect; how should this work?
20 ///
21 /// OK, the way he had it working here is filtering in place, i.e. no internal buffer,
22 /// but if I inherit from Effect, I do have an internal buffer; this means the first thing to do is
23 /// memcopy the input to the output, then pounce on that; or do the in-place stuff in the Effect port
24 /// and finally copy to output, say with scale & offset performed there.
25 ///
26 /// See the copyright notice and acknowledgment of authors in the file COPYRIGHT
27 ///
28 
29 #ifndef CSL_Filters_H
30 #define CSL_Filters_H
31 
32 #define FILTER_MAX_COEFFICIENTS (16) // seems reasonable?
33 
34 #include "CSL_Core.h"
35 
36 namespace csl {
37 
38 #ifdef CSL_ENUMS
39 
40 typedef enum {
41  BW_LOW_PASS = 0,
46 #else
47  #define BW_LOW_PASS 0
48  #define BW_HIGH_PASS 1
49  #define BW_BAND_PASS 2
50  #define BW_BAND_STOP 3
51  typedef int ButterworthType;
52 #endif
53 
54 /// Declare the pointer to freq/bw buffers (if used) and current scale/offset values
55 
56 #define DECLARE_FILTER_CONTROLS \
57  Port * freqPort = mInputs[CSL_FILTER_FREQUENCY]; \
58  Port * bwPort = mInputs[CSL_FILTER_AMOUNT]
59 
60 /// Load the freq/bw-related values at the start
61 
62 #define LOAD_FILTER_CONTROLS \
63  if (freqPort) Controllable::pullInput(freqPort, numFrames); \
64  if (bwPort) Controllable::pullInput(bwPort, numFrames)
65 
66 /// FrequencyAmount -- mix-in class with frequency and amount (BW) control inputs (may be constants or
67 /// generators). amount (probably 0..1) is a generalised placeholder for bandwidth, resonance or radius,
68 /// according to filter type or could equally be used as a kind of x,y location in the frequency domain
69 
70 class FrequencyAmount : public virtual Controllable {
71 public:
72  FrequencyAmount(); ///< Constructors
73 /* FrequencyAmount(float frequency, float amount = 1.f); ///< also specify bandwidth/radius/resonance etc.
74  FrequencyAmount(UnitGenerator & frequency, float amount = 1.f);
75  FrequencyAmount(UnitGenerator & frequency, UnitGenerator & amount);
76 */ ~FrequencyAmount(); ///< Destructor
77 
78  // accessors
79  void setFrequency(UnitGenerator & frequency); ///< set the receiver's frequency to a UGen or a float
80  void setFrequency(float frequency);
81  float getFrequency();
82 
83  void setAmount(UnitGenerator & amount); ///< set the receiver's amount to a UGen or a float
84  void setAmount(float amount);
85 };
86 
87 ///
88 /// Filter: the canonical-form n-pole/m-zero filter class
89 ///
90 
91 class Filter : public Effect, public Scalable, public FrequencyAmount {
92 
93 public:
94  Filter();
95  Filter(unsigned num_b, unsigned num_a = 1);
96  Filter(UnitGenerator & in, unsigned num_b = 1, unsigned num_a = 1);
97  Filter(UnitGenerator & in, SampleBuffer bCoeffs, SampleBuffer aCoeffs, unsigned num_b, unsigned num_a);
98  ~Filter();
99 
100  void clear(void); ///< clears the input/output buffers
101  virtual void setupCoeffs() { }; ///< to be overloaded by subclasses
102  /// supply the coefficients directly
103  void setupCoeffs(SampleBuffer bCoeffs, SampleBuffer aCoeffs, unsigned num_b, unsigned num_a );
104 
105  virtual void nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException);
106 
107  void dump(); ///< log information about myself
108 
109 protected:
110  void init(unsigned a, unsigned b); ///< shared initialization function
111 
112  float mBCoeff[FILTER_MAX_COEFFICIENTS]; ///< array of numerator coeffs
113  float mACoeff[FILTER_MAX_COEFFICIENTS]; ///< array of denominator coeffs
114  unsigned mBNum; ///< number of coeffs in b
115  unsigned mANum; ///< number of coeffs in a
116  Buffer * mPrevInputs; ///< arrays of past input and output samples
118  float mFrame; ///< to keep hold of sample rate for calculating coeffs
119 };
120 
121 /// Butterworth IIR (2nd order recursive) filter.
122 /// This operates upon a buffer of frames of amplitude samples by applying the following equation
123 /// y(n) = a0*x(n) + a1*x(n-1) + a2*x(n-2) - b1*y(n-1) - b2*y(n-2) where x is an amplitude sample.
124 /// It has constructors that can calculate the coefficients from a given cutoff frequency.
125 
126 class Butter : public Filter {
127 
128 public:
129  // constructors / destructor
130  Butter ();
131  Butter (ButterworthType type, float cutoff);
132  Butter (ButterworthType type, float center, float bandwidth);
133  Butter (UnitGenerator & in, ButterworthType type, float cutoff);
134  Butter (UnitGenerator & in, ButterworthType type, UnitGenerator & cutoff);
135  Butter (UnitGenerator & in, ButterworthType type, float center, float bandwidth);
136  Butter (UnitGenerator & in, ButterworthType type, UnitGenerator & center, UnitGenerator & bandwidth);
137  // Filtering
138  void setupCoeffs ();
139 
140 protected:
141  int mFilterType; // flag as to what kind of filter I am
142 
143 };
144 
145 /// Formant Filter with zeros at +-z and complex conjugate poles at +-omega.
146 /// setupCoeffs() looks at the member var called normalize;
147 /// if normalize is true, the filter zeros are placed at z = 1, z = -1, and the coefficients
148 /// are then normalized to produce a constant unity peak gain. The resulting filter
149 /// frequency response has a resonance at the given frequency. The closer the poles
150 /// are to the unit-circle (radius close to one), the narrower the resulting resonance width.
151 
152 class Formant : public Filter {
153 
154 public:
155  /// constructors & destructor
156  Formant (UnitGenerator & in, float center_freq, float radius);
157  Formant (UnitGenerator & in, UnitGenerator & center_freq, float radius);
158  ~Formant(void) { };
159 
160  /// Filtering methods
161  void setupCoeffs();
162  void setNormalize(bool normalize);
163 
164 protected:
166 };
167 
168 /// Notch Filter with poles at +-z and complex conjugate zeros at +-omega.
169 
170 class Notch : public Filter {
171 
172 public:
173  /// constructors & destructor
174  Notch (UnitGenerator & in, float center_freq, float radius);
175  Notch (UnitGenerator & in, UnitGenerator & center_freq, float radius);
176  ~Notch(void) { };
177  // Filtering
178  void setupCoeffs ();
179 
180 };
181 
182 /// Allpass Filter with a pole and a zero at equal frequency and straddling the unit circle.
183 /// Allows all freqs to pass through but messes with phases.
184 /// Note that the Amount parameter of FrequencyAmount is ignored.
185 
186 class Allpass : public Filter {
187 
188 public:
189  // constructors / destructor
190  Allpass (UnitGenerator & in, float coeff);
191  Allpass (UnitGenerator & in, UnitGenerator & coeff);
192  ~Allpass(void) { };
193  // Filtering
194  void setupCoeffs();
195 
196 protected:
198  float mCoeff;
200 };
201 
202 /// Moog VCF class
203 
204 class Moog : public Filter {
205 
206 public:
207  // constructors / destructor
208  Moog (UnitGenerator & in);
209  Moog (UnitGenerator & in, UnitGenerator & cutoff);
210  Moog (UnitGenerator & in, UnitGenerator & cutoff, UnitGenerator & resonance);
211  Moog (UnitGenerator & in, float cutoff);
212  Moog (UnitGenerator & in, float cutoff, float resonance);
213  ~Moog (void) { };
214  // Filtering
215  void setupCoeffs ();
216 
217  void nextBuffer(Buffer & outputBuffer, unsigned outBufNum) throw (CException);
218 
219 protected:
220  float k, p, r; // coefficients
221  float x, oldx;
222  float y1, y2, y3, y4, oldy1, oldy2, oldy3;
223  bool debugging;
224 };
225 
226 }
227 
228 #endif