-
Notifications
You must be signed in to change notification settings - Fork 185
/
Flute.cpp
163 lines (134 loc) · 4.41 KB
/
Flute.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/***************************************************/
/*! \Class Flute
\brief STK flute physical model class.
This class implements a simple flute
physical model, as discussed by Karjalainen,
Smith, Waryznyk, etc. The jet model uses
a polynomial, a la Cook.
This is a digital waveguide model, making its
use possibly subject to patents held by Stanford
University, Yamaha, and others.
Control Change Numbers:
- Jet Delay = 2
- Noise Gain = 4
- Vibrato Frequency = 11
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995--2023.
*/
/***************************************************/
#include "Flute.h"
#include "SKINImsg.h"
namespace stk {
Flute :: Flute( StkFloat lowestFrequency )
{
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Flute::Flute: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / lowestFrequency );
boreDelay_.setMaximumDelay( nDelays + 1 );
jetDelay_.setMaximumDelay( nDelays + 1 );
jetDelay_.setDelay( 49.0 );
vibrato_.setFrequency( 5.925 );
filter_.setPole( 0.7 - ( 0.1 * 22050.0 / Stk::sampleRate() ) );
dcBlock_.setBlockZero();
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010 );
endReflection_ = 0.5;
jetReflection_ = 0.5;
noiseGain_ = 0.15; // Breath pressure random component
vibratoGain_ = 0.05; // Breath periodic vibrato component
jetRatio_ = 0.32;
maxPressure_ = 0.0;
this->clear();
this->setFrequency( 220.0 );
}
Flute :: ~Flute( void )
{
}
void Flute :: clear( void )
{
jetDelay_.clear();
boreDelay_.clear();
filter_.clear();
dcBlock_.clear();
}
void Flute :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "Flute::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
// We're overblowing here.
lastFrequency_ = frequency * 0.66666;
// Account for filter delay and one sample "lastOut" delay
// (previously approximated as 2.0 samples). The tuning is still
// not perfect but I'm not sure why. Also, we are not accounting
// for the dc blocking filter delay.
StkFloat delay = Stk::sampleRate() / lastFrequency_ - filter_.phaseDelay( lastFrequency_ ) - 1.0;
boreDelay_.setDelay( delay );
jetDelay_.setDelay( delay * jetRatio_ );
}
void Flute :: setJetDelay( StkFloat aRatio )
{
jetRatio_ = aRatio;
jetDelay_.setDelay( boreDelay_.getDelay() * aRatio ); // Scaled by ratio.
}
void Flute :: startBlowing( StkFloat amplitude, StkFloat rate )
{
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "Flute::startBlowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setAttackRate( rate );
maxPressure_ = amplitude / (StkFloat) 0.8;
adsr_.keyOn();
}
void Flute :: stopBlowing( StkFloat rate )
{
if ( rate < 0.0 ) {
oStream_ << "Flute::stopBlowing: argument is less than zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
void Flute :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02 );
outputGain_ = amplitude + 0.001;
}
void Flute :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.02 );
}
void Flute :: controlChange( int number, StkFloat value )
{
#if defined(_STK_DEBUG_)
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Flute::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_JetDelay_) // 2
this->setJetDelay( (StkFloat) (0.08 + (0.48 * normalizedValue)) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( normalizedValue * 0.4);
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( normalizedValue * 12.0);
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( normalizedValue * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
oStream_ << "Flute::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}
} // stk namespace