CUGL 1.2
Cornell University Game Library
CUBiquadIIR.h
1 //
2 // CUBiquadIIR.h
3 // Cornell University Game Library (CUGL)
4 //
5 // This class is represents a biquad filter that supports a wide variety of
6 // of 2nd order filters (lowpass, highpass, bandpass, etc...) It is adapted
7 // from the code by Nigel Redmon at
8 //
9 // http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
10 //
11 // This class supports vector optimizations for SSE and Neon 64. In timed
12 // simulations, these optimizations provide at least a 3-4x performance
13 // increase (and in isolated cases, much higher). These optimizations make
14 // use of the matrix precomputation outlined in "Implementation of Recursive
15 // Digital Filters into Vector SIMD DSP Architectures"
16 //
17 // https://pdfs.semanticscholar.org/d150/a3f75dc033916f14029cd9101a8ea1d050bb.pdf
18 //
19 // The algorithm in this paper performs extremely well in our tests, and even
20 // out-performs Apple's Acceleration library. However, our implementation is
21 // limited to 128-bit words as 256-bit (e.g. AVX) and higher show no significant
22 // increase in performance.
23 //
24 // For performance reasons, this class does not have a (virtualized) subclass
25 // relationship with other IIR or FIR filters. However, the signature of the
26 // the calculation and coefficient methods has been standardized so that it
27 // can support templated polymorphism.
28 //
29 // This class is NOT THREAD SAFE. This is by design, for performance reasons.
30 // External locking may be required when the filter is shared between multiple
31 // threads (such as between an audio thread and the main thread).
32 //
33 // CUGL MIT License:
34 // This software is provided 'as-is', without any express or implied
35 // warranty. In no event will the authors be held liable for any damages
36 // arising from the use of this software.
37 //
38 // Permission is granted to anyone to use this software for any purpose,
39 // including commercial applications, and to alter it and redistribute it
40 // freely, subject to the following restrictions:
41 //
42 // 1. The origin of this software must not be misrepresented; you must not
43 // claim that you wrote the original software. If you use this software
44 // in a product, an acknowledgment in the product documentation would be
45 // appreciated but is not required.
46 //
47 // 2. Altered source versions must be plainly marked as such, and must not
48 // be misrepresented as being the original software.
49 //
50 // 3. This notice may not be removed or altered from any source distribution.
51 //
52 // Author: Walker White
53 // Version: 6/11/18
54 //
55 #ifndef __CU_BIQUAD_IIR_H__
56 #define __CU_BIQUAD_IIR_H__
57 
58 #include <cugl/math/dsp/CUIIRFilter.h>
59 #include <cugl/math/CUMathBase.h>
60 #include <cugl/util/CUAligned.h>
61 #include <cstring>
62 #include <vector>
63 
65 #define INV_SQRT2 0.7071067812
66 
67 namespace cugl {
68  namespace dsp {
69 
107 class BiquadIIR {
108 public:
116  enum class Type : int {
118  UNDEFINED = 0,
120  LOWPASS = 1,
122  HIGHPASS = 2,
124  BANDPASS = 3,
126  ALLPASS = 4,
128  NOTCH = 5,
130  PEAK = 6,
132  LOWSHELF = 7,
134  HIGHSHELF = 8,
136  RESONANCE = 9,
137  };
138 
140  static bool VECTORIZE;
141 
142 private:
144  unsigned _channels;
146  float _b0, _b1, _b2;
148  float _a1, _a2;
149 
151  cugl::Aligned<float> _inns;
153  cugl::Aligned<float> _outs;
154 
155  // Optimization data structures (single channel)
156  float __attribute__((__aligned__(16))) _c1[8];
157  float __attribute__((__aligned__(16))) _d1[16];
158 
159  // Optimization data structures (dual channel)
160  float __attribute__((__aligned__(16))) _c2[16];
161  float __attribute__((__aligned__(16))) _d2[16];
162 
168  void reset();
169 
170 
171 #pragma mark SPECIALIZED FILTERS
172 
201  void stride(float gain, float* input, float* output, size_t size, unsigned channel);
202 
225  void single(float gain, float* input, float* output, size_t size);
226 
250  void dual(float gain, float* input, float* output, size_t size);
251 
278  void trio(float gain, float* input, float* output, size_t size);
279 
303  void quad(float gain, float* input, float* output, size_t size);
304 
328  void quart(float gain, float* input, float* output, size_t size);
329 
330 public:
331 #pragma mark Constructors
332 
335  BiquadIIR();
336 
342  BiquadIIR(unsigned channels);
343 
374  BiquadIIR(unsigned channels, Type type, float frequency, float gainDB, float qVal=INV_SQRT2);
375 
381  BiquadIIR(const BiquadIIR& copy);
382 
388  BiquadIIR(BiquadIIR&& filter);
389 
393  ~BiquadIIR();
394 
395 
396 #pragma mark IIR Signature
397 
405  unsigned getChannels() const { return _channels; }
406 
415  void setChannels(unsigned channels);
416 
434  void setCoeff(const std::vector<float> &bvals, const std::vector<float> &avals);
435 
447  const std::vector<float> getBCoeff() const;
448 
460  const std::vector<float> getACoeff() const;
461 
462 #pragma mark Specialized Attributes
463 
472  void setBCoeff(float b0, float b1, float b2);
473 
482  void setACoeff(float a1, float a2);
483 
514  void setType(Type type, float frequency, float gainDB, float qVal=INV_SQRT2);
515 
527  static float db2gain(float gainDB);
528 
539  static float gain2db(float gain);
540 
552  static float bandwidth2q(float width);
553 
565  static float q2Bandwidth(float qVal);
566 
567 #pragma mark Filter Methods
568 
589  void step(float gain, float* input, float* output);
590 
614  void calculate(float gain, float* input, float* output, size_t size);
615 
619  void clear();
620 
629  size_t flush(float* output);
630 };
631 
632  }
633 }
634 
635 #endif /* __CU_BIQUAD_IIR_H__ */
void setChannels(unsigned channels)
void calculate(float gain, float *input, float *output, size_t size)
void step(float gain, float *input, float *output)
void setCoeff(const std::vector< float > &bvals, const std::vector< float > &avals)
size_t flush(float *output)
static float bandwidth2q(float width)
static float db2gain(float gainDB)
Definition: CUBiquadIIR.h:107
const std::vector< float > getACoeff() const
const std::vector< float > getBCoeff() const
static float gain2db(float gain)
static float q2Bandwidth(float qVal)
void setBCoeff(float b0, float b1, float b2)
static bool VECTORIZE
Definition: CUBiquadIIR.h:140
void setType(Type type, float frequency, float gainDB, float qVal=INV_SQRT2)
Definition: CUAction.h:51
Type
Definition: CUBiquadIIR.h:116
void setACoeff(float a1, float a2)
unsigned getChannels() const
Definition: CUBiquadIIR.h:405