1 /***************************************************/
2 /*! \class BiQuad
3     \brief STK biquad (two-pole, two-zero) filter class.
4 
5     This protected Filter subclass implements a
6     two-pole, two-zero digital filter.  A method
7     is provided for creating a resonance in the
8     frequency response while maintaining a constant
9     filter gain.
10 
11     by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
12 */
13 /***************************************************/
14 
15 #include "BiQuad.h"
16 #include <cmath>
17 
18 using namespace Nyq;
19 
BiQuad()20 BiQuad :: BiQuad() : Filter()
21 {
22   std::vector<StkFloat> b(3, 0.0);
23   std::vector<StkFloat> a(3, 0.0);
24   b[0] = 1.0;
25   a[0] = 1.0;
26   Filter::setCoefficients( b, a );
27 }
28 
~BiQuad()29 BiQuad :: ~BiQuad()
30 {
31 }
32 
clear(void)33 void BiQuad :: clear(void)
34 {
35   Filter::clear();
36 }
37 
setB0(StkFloat b0)38 void BiQuad :: setB0(StkFloat b0)
39 {
40   b_[0] = b0;
41 }
42 
setB1(StkFloat b1)43 void BiQuad :: setB1(StkFloat b1)
44 {
45   b_[1] = b1;
46 }
47 
setB2(StkFloat b2)48 void BiQuad :: setB2(StkFloat b2)
49 {
50   b_[2] = b2;
51 }
52 
setA1(StkFloat a1)53 void BiQuad :: setA1(StkFloat a1)
54 {
55   a_[1] = a1;
56 }
57 
setA2(StkFloat a2)58 void BiQuad :: setA2(StkFloat a2)
59 {
60   a_[2] = a2;
61 }
62 
setResonance(StkFloat frequency,StkFloat radius,bool normalize)63 void BiQuad :: setResonance(StkFloat frequency, StkFloat radius, bool normalize)
64 {
65   a_[2] = radius * radius;
66   a_[1] = -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());
67 
68   if ( normalize ) {
69     // Use zeros at +- 1 and normalize the filter peak gain.
70     b_[0] = 0.5 - 0.5 * a_[2];
71     b_[1] = 0.0;
72     b_[2] = -b_[0];
73   }
74 }
75 
setNotch(StkFloat frequency,StkFloat radius)76 void BiQuad :: setNotch(StkFloat frequency, StkFloat radius)
77 {
78   // This method does not attempt to normalize the filter gain.
79   b_[2] = radius * radius;
80   b_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate());
81 }
82 
setEqualGainZeroes()83 void BiQuad :: setEqualGainZeroes()
84 {
85   b_[0] = 1.0;
86   b_[1] = 0.0;
87   b_[2] = -1.0;
88 }
89 
setGain(StkFloat gain)90 void BiQuad :: setGain(StkFloat gain)
91 {
92   Filter::setGain(gain);
93 }
94 
getGain(void) const95 StkFloat BiQuad :: getGain(void) const
96 {
97   return Filter::getGain();
98 }
99 
lastOut(void) const100 StkFloat BiQuad :: lastOut(void) const
101 {
102   return Filter::lastOut();
103 }
104 
computeSample(StkFloat input)105 StkFloat BiQuad :: computeSample( StkFloat input )
106 {
107   inputs_[0] = gain_ * input;
108   outputs_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
109   outputs_[0] -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
110   inputs_[2] = inputs_[1];
111   inputs_[1] = inputs_[0];
112   outputs_[2] = outputs_[1];
113   outputs_[1] = outputs_[0];
114 
115   return outputs_[0];
116 }
117 
tick(StkFloat input)118 StkFloat BiQuad :: tick( StkFloat input )
119 {
120   return this->computeSample( input );
121 }
122 
tick(StkFrames & frames,unsigned int channel)123 StkFrames& BiQuad :: tick( StkFrames& frames, unsigned int channel )
124 {
125   return Filter::tick( frames, channel );
126 }
127