CUGL 1.3
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 
106 class BiquadIIR {
107 public:
115  enum class Type : int {
117  UNDEFINED = 0,
119  LOWPASS = 1,
121  HIGHPASS = 2,
123  BANDPASS = 3,
125  ALLPASS = 4,
127  NOTCH = 5,
129  PEAK = 6,
131  LOWSHELF = 7,
133  HIGHSHELF = 8,
135  RESONANCE = 9,
136  };
137 
139  static bool VECTORIZE;
140 
141 private:
143  unsigned _channels;
145  float _b0, _b1, _b2;
147  float _a1, _a2;
148 
150  cugl::Aligned<float> _inns;
152  cugl::Aligned<float> _outs;
153 
154  // Optimization data structures (single channel)
155  float __attribute__((__aligned__(16))) _c1[8];
156  float __attribute__((__aligned__(16))) _d1[16];
157 
158  // Optimization data structures (dual channel)
159  float __attribute__((__aligned__(16))) _c2[16];
160  float __attribute__((__aligned__(16))) _d2[16];
161 
167  void reset();
168 
169 
170 #pragma mark SPECIALIZED FILTERS
171 
200  void stride(float gain, float* input, float* output, size_t size, unsigned channel);
201 
224  void single(float gain, float* input, float* output, size_t size);
225 
249  void dual(float gain, float* input, float* output, size_t size);
250 
277  void trio(float gain, float* input, float* output, size_t size);
278 
302  void quad(float gain, float* input, float* output, size_t size);
303 
327  void quart(float gain, float* input, float* output, size_t size);
328 
329 public:
330 #pragma mark Constructors
331 
334  BiquadIIR();
335 
341  BiquadIIR(unsigned channels);
342 
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 
584  void step(float gain, float* input, float* output);
585 
605  void calculate(float gain, float* input, float* output, size_t size);
606 
610  void clear();
611 
620  size_t flush(float* output);
621 };
622 
623  }
624 }
625 
626 #endif /* __CU_BIQUAD_IIR_H__ */
cugl::dsp::BiquadIIR::Type::UNDEFINED
cugl::dsp::BiquadIIR::Type::LOWPASS
cugl::dsp::BiquadIIR::gain2db
static float gain2db(float gain)
cugl::dsp::BiquadIIR::q2Bandwidth
static float q2Bandwidth(float qVal)
cugl::dsp::BiquadIIR::Type::BANDPASS
cugl::dsp::BiquadIIR::setBCoeff
void setBCoeff(float b0, float b1, float b2)
cugl::dsp::BiquadIIR::setType
void setType(Type type, float frequency, float gainDB, float qVal=INV_SQRT2)
cugl::dsp::BiquadIIR
Definition: CUBiquadIIR.h:106
cugl::dsp::BiquadIIR::~BiquadIIR
~BiquadIIR()
cugl::dsp::BiquadIIR::VECTORIZE
static bool VECTORIZE
Definition: CUBiquadIIR.h:139
cugl::dsp::BiquadIIR::Type::NOTCH
cugl::dsp::BiquadIIR::Type
Type
Definition: CUBiquadIIR.h:115
cugl::dsp::BiquadIIR::setACoeff
void setACoeff(float a1, float a2)
cugl::dsp::BiquadIIR::Type::HIGHPASS
cugl::Aligned< float >
cugl::dsp::BiquadIIR::getBCoeff
const std::vector< float > getBCoeff() const
cugl::dsp::BiquadIIR::calculate
void calculate(float gain, float *input, float *output, size_t size)
cugl::dsp::BiquadIIR::getChannels
unsigned getChannels() const
Definition: CUBiquadIIR.h:405
cugl::dsp::BiquadIIR::setChannels
void setChannels(unsigned channels)
cugl::dsp::BiquadIIR::Type::HIGHSHELF
cugl::dsp::BiquadIIR::flush
size_t flush(float *output)
cugl::dsp::BiquadIIR::clear
void clear()
cugl::dsp::BiquadIIR::setCoeff
void setCoeff(const std::vector< float > &bvals, const std::vector< float > &avals)
cugl::dsp::BiquadIIR::BiquadIIR
BiquadIIR()
cugl::dsp::BiquadIIR::Type::PEAK
cugl::dsp::BiquadIIR::db2gain
static float db2gain(float gainDB)
cugl::dsp::BiquadIIR::step
void step(float gain, float *input, float *output)
cugl::dsp::BiquadIIR::bandwidth2q
static float bandwidth2q(float width)
cugl::dsp::BiquadIIR::Type::ALLPASS
cugl::dsp::BiquadIIR::getACoeff
const std::vector< float > getACoeff() const
cugl::dsp::BiquadIIR::Type::LOWSHELF
cugl::dsp::BiquadIIR::Type::RESONANCE