1 /***************************************************/
2 /*! \class FormSwep
3     \brief STK sweepable formant filter class.
4 
5     This class implements a formant (resonance) which can be "swept"
6     over time from one frequency setting to another.  It provides
7     methods for controlling the sweep rate and target frequency.
8 
9     by Perry R. Cook and Gary P. Scavone, 1995--2021.
10 */
11 /***************************************************/
12 
13 #include "FormSwep.h"
14 #include <cmath>
15 
16 namespace stk {
17 
18 FormSwep :: FormSwep( void )
19 {
20   frequency_ = 0.0;
21   radius_ = 0.0;
22   targetGain_ = 1.0;
23   targetFrequency_ = 0.0;
24   targetRadius_ = 0.0;
25   deltaGain_ = 0.0;
26   deltaFrequency_ = 0.0;
27   deltaRadius_ = 0.0;
28   sweepState_ = 0.0;
29   sweepRate_ = 0.002;
30   dirty_ = false;
31 
32   b_.resize( 3, 0.0 );
33   a_.resize( 3, 0.0 );
34   a_[0] = 1.0;
35   inputs_.resize( 3, 1, 0.0 );
36   outputs_.resize( 3, 1, 0.0 );
37 
38   Stk::addSampleRateAlert( this );
39 }
40 
41 FormSwep :: ~FormSwep()
42 {
43   Stk::removeSampleRateAlert( this );
44 }
45 
46 void FormSwep :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
47 {
48   if ( !ignoreSampleRateChange_ ) {
49     oStream_ << "FormSwep::sampleRateChanged: you may need to recompute filter coefficients!";
50     handleError( StkError::WARNING );
51   }
52 }
53 
54 void FormSwep :: setResonance( StkFloat frequency, StkFloat radius )
55 {
56 #if defined(_STK_DEBUG_)
57   if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
58     oStream_ << "FormSwep::setResonance: frequency argument (" << frequency << ") is out of range!";
59     handleError( StkError::WARNING ); return;
60   }
61   if ( radius < 0.0 || radius >= 1.0 ) {
62     oStream_ << "FormSwep::setResonance: radius argument (" << radius << ") is out of range!";
63     handleError( StkError::WARNING ); return;
64   }
65 #endif
66 
67   radius_ = radius;
68   frequency_ = frequency;
69 
70   a_[2] = radius * radius;
71   a_[1] = -2.0 * radius * cos( TWO_PI * frequency / Stk::sampleRate() );
72 
73   // Use zeros at +- 1 and normalize the filter peak gain.
74   b_[0] = 0.5 - 0.5 * a_[2];
75   b_[1] = 0.0;
76   b_[2] = -b_[0];
77 }
78 
79 void FormSwep :: setStates( StkFloat frequency, StkFloat radius, StkFloat gain )
80 {
81   dirty_ = false;
82 
83   if ( frequency_ != frequency || radius_ != radius )
84     this->setResonance( frequency, radius );
85 
86   gain_ = gain;
87   targetFrequency_ = frequency;
88   targetRadius_ = radius;
89   targetGain_ = gain;
90 }
91 
92 void FormSwep :: setTargets( StkFloat frequency, StkFloat radius, StkFloat gain )
93 {
94   if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
95     oStream_ << "FormSwep::setTargets: frequency argument (" << frequency << ") is out of range!";
96     handleError( StkError::WARNING ); return;
97   }
98   if ( radius < 0.0 || radius >= 1.0 ) {
99     oStream_ << "FormSwep::setTargets: radius argument (" << radius << ") is out of range!";
100     handleError( StkError::WARNING ); return;
101   }
102 
103   dirty_ = true;
104   startFrequency_ = frequency_;
105   startRadius_ = radius_;
106   startGain_ = gain_;
107   targetFrequency_ = frequency;
108   targetRadius_ = radius;
109   targetGain_ = gain;
110   deltaFrequency_ = frequency - frequency_;
111   deltaRadius_ = radius - radius_;
112   deltaGain_ = gain - gain_;
113   sweepState_ = 0.0;
114 }
115 
116 void FormSwep :: setSweepRate( StkFloat rate )
117 {
118   if ( rate < 0.0 || rate > 1.0 ) {
119     oStream_ << "FormSwep::setSweepRate: argument (" << rate << ") is out of range!";
120     handleError( StkError::WARNING ); return;
121   }
122 
123   sweepRate_ = rate;
124 }
125 
126 void FormSwep :: setSweepTime( StkFloat time )
127 {
128   if ( time <= 0.0 ) {
129     oStream_ << "FormSwep::setSweepTime: argument (" << time << ") must be > 0.0!";
130     handleError( StkError::WARNING ); return;
131   }
132 
133   this->setSweepRate( 1.0 / ( time * Stk::sampleRate() ) );
134 }
135 
136 } // stk namespace
137