1 /***************************************************/
2 /*! \class TwoPole
3     \brief STK two-pole filter class.
4 
5     This class implements a two-pole digital filter.  A method is
6     provided for creating a resonance in the frequency response while
7     maintaining a nearly constant filter gain.
8 
9     by Perry R. Cook and Gary P. Scavone, 1995--2021.
10 */
11 /***************************************************/
12 
13 #include "TwoPole.h"
14 #include <cmath>
15 
16 namespace stk {
17 
TwoPole(void)18 TwoPole :: TwoPole( void )
19 {
20   b_.resize( 1 );
21   a_.resize( 3 );
22   inputs_.resize( 1, 1, 0.0 );
23   outputs_.resize( 3, 1, 0.0 );
24   b_[0] = 1.0;
25   a_[0] = 1.0;
26 
27   Stk::addSampleRateAlert( this );
28 }
29 
~TwoPole()30 TwoPole :: ~TwoPole()
31 {
32   Stk::removeSampleRateAlert( this );
33 }
34 
sampleRateChanged(StkFloat newRate,StkFloat oldRate)35 void TwoPole :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
36 {
37   if ( !ignoreSampleRateChange_ ) {
38     oStream_ << "TwoPole::sampleRateChanged: you may need to recompute filter coefficients!";
39     handleError( StkError::WARNING );
40   }
41 }
42 
setResonance(StkFloat frequency,StkFloat radius,bool normalize)43 void TwoPole :: setResonance( StkFloat frequency, StkFloat radius, bool normalize )
44 {
45 #if defined(_STK_DEBUG_)
46   if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
47     oStream_ << "TwoPole::setResonance: frequency argument (" << frequency << ") is out of range!";
48     handleError( StkError::WARNING ); return;
49   }
50   if ( radius < 0.0 || radius >= 1.0 ) {
51     oStream_ << "TwoPole::setResonance: radius argument (" << radius << ") is out of range!";
52     handleError( StkError::WARNING ); return;
53   }
54 #endif
55 
56   a_[2] = radius * radius;
57   a_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());
58 
59   if ( normalize ) {
60     // Normalize the filter gain ... not terribly efficient.
61     StkFloat real = 1 - radius + (a_[2] - radius) * cos(TWO_PI * 2 * frequency / Stk::sampleRate());
62     StkFloat imag = (a_[2] - radius) * sin(TWO_PI * 2 * frequency / Stk::sampleRate());
63     b_[0] = sqrt( pow(real, 2) + pow(imag, 2) );
64   }
65 }
66 
setCoefficients(StkFloat b0,StkFloat a1,StkFloat a2,bool clearState)67 void TwoPole :: setCoefficients( StkFloat b0, StkFloat a1, StkFloat a2, bool clearState )
68 {
69   b_[0] = b0;
70   a_[1] = a1;
71   a_[2] = a2;
72 
73   if ( clearState ) this->clear();
74 }
75 
76 } // stk namespace
77