1 /***************************************************/
2 /*! \class Bowed
3 \brief STK bowed string instrument class.
4
5 This class implements a bowed string model, a
6 la Smith (1986), after McIntyre, Schumacher,
7 Woodhouse (1983).
8
9 This is a digital waveguide model, making its
10 use possibly subject to patents held by
11 Stanford University, Yamaha, and others.
12
13 Control Change Numbers:
14 - Bow Pressure = 2
15 - Bow Position = 4
16 - Vibrato Frequency = 11
17 - Vibrato Gain = 1
18 - Volume = 128
19
20 by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
21 */
22 /***************************************************/
23
24 #include "Bowed.h"
25 #include "SKINI.msg"
26
27 using namespace Nyq;
28
Bowed(StkFloat lowestFrequency)29 Bowed :: Bowed(StkFloat lowestFrequency)
30 {
31 unsigned long length;
32 length = (long) ( Stk::sampleRate() / lowestFrequency + 1 );
33 neckDelay_.setMaximumDelay( length );
34 neckDelay_.setDelay( 100.0 );
35
36 length >>= 1;
37 bridgeDelay_.setMaximumDelay( length );
38 bridgeDelay_.setDelay( 29.0 );
39
40 bowTable_.setSlope(3.0 );
41
42 vibrato_.setFrequency( 6.12723 );
43 vibratoGain_ = 0.0;
44
45 stringFilter_.setPole( 0.6 - (0.1 * 22050.0 / Stk::sampleRate()) );
46 stringFilter_.setGain( 0.95 );
47
48 bodyFilter_.setResonance( 500.0, 0.85, true );
49 bodyFilter_.setGain( 0.2 );
50
51 adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01 );
52
53 betaRatio_ = 0.127236;
54
55 // Necessary to initialize internal variables.
56 this->setFrequency( 220.0 );
57 }
58
~Bowed()59 Bowed :: ~Bowed()
60 {
61 }
62
clear()63 void Bowed :: clear()
64 {
65 neckDelay_.clear();
66 bridgeDelay_.clear();
67 }
68
setFrequency(StkFloat frequency)69 void Bowed :: setFrequency(StkFloat frequency)
70 {
71 StkFloat freakency = frequency;
72 if ( frequency <= 0.0 ) {
73 errorString_ << "Bowed::setFrequency: parameter is less than or equal to zero!";
74 handleError( StkError::WARNING );
75 freakency = 220.0;
76 }
77
78 // Delay = length - approximate filter delay.
79 baseDelay_ = Stk::sampleRate() / freakency - 4.0;
80 if ( baseDelay_ <= 0.0 ) baseDelay_ = 0.3;
81 bridgeDelay_.setDelay( baseDelay_ * betaRatio_ ); // bow to bridge length
82 neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) ); // bow to nut (finger) length
83 }
84
startBowing(StkFloat amplitude,StkFloat rate)85 void Bowed :: startBowing(StkFloat amplitude, StkFloat rate)
86 {
87 adsr_.setRate( rate );
88 adsr_.keyOn();
89 maxVelocity_ = 0.03 + ( 0.2 * amplitude );
90 }
91
stopBowing(StkFloat rate)92 void Bowed :: stopBowing(StkFloat rate)
93 {
94 adsr_.setRate( rate );
95 adsr_.keyOff();
96 }
97
noteOn(StkFloat frequency,StkFloat amplitude)98 void Bowed :: noteOn(StkFloat frequency, StkFloat amplitude)
99 {
100 this->startBowing( amplitude, amplitude * 0.001 );
101 this->setFrequency( frequency );
102
103 #if defined(_STK_DEBUG_)
104 errorString_ << "Bowed::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
105 handleError( StkError::DEBUG_WARNING );
106 #endif
107 }
108
noteOff(StkFloat amplitude)109 void Bowed :: noteOff(StkFloat amplitude)
110 {
111 this->stopBowing( (1.0 - amplitude) * 0.005 );
112
113 #if defined(_STK_DEBUG_)
114 errorString_ << "Bowed::NoteOff: amplitude = " << amplitude << ".";
115 handleError( StkError::DEBUG_WARNING );
116 #endif
117 }
118
setVibrato(StkFloat gain)119 void Bowed :: setVibrato(StkFloat gain)
120 {
121 vibratoGain_ = gain;
122 }
123
computeSample()124 StkFloat Bowed :: computeSample()
125 {
126 StkFloat bowVelocity;
127 StkFloat bridgeRefl;
128 StkFloat nutRefl;
129 StkFloat newVel;
130 StkFloat velDiff;
131 StkFloat stringVel;
132
133 bowVelocity = maxVelocity_ * adsr_.tick();
134
135 bridgeRefl = -stringFilter_.tick( bridgeDelay_.lastOut() );
136 nutRefl = -neckDelay_.lastOut();
137 stringVel = bridgeRefl + nutRefl; // Sum is String Velocity
138 velDiff = bowVelocity - stringVel; // Differential Velocity
139 newVel = velDiff * bowTable_.tick( velDiff ); // Non-Linear Bow Function
140 neckDelay_.tick(bridgeRefl + newVel); // Do string propagations
141 bridgeDelay_.tick(nutRefl + newVel);
142
143 if ( vibratoGain_ > 0.0 ) {
144 neckDelay_.setDelay( (baseDelay_ * (1.0 - betaRatio_) ) +
145 (baseDelay_ * vibratoGain_ * vibrato_.tick()) );
146 }
147
148 lastOutput_ = bodyFilter_.tick( bridgeDelay_.lastOut() );
149
150 return lastOutput_;
151 }
152
controlChange(int number,StkFloat value)153 void Bowed :: controlChange(int number, StkFloat value)
154 {
155 StkFloat norm = value * ONE_OVER_128;
156 if ( norm < 0 ) {
157 norm = 0.0;
158 errorString_ << "Bowed::controlChange: control value less than zero ... setting to zero!";
159 handleError( StkError::WARNING );
160 }
161 else if ( norm > 1.0 ) {
162 norm = 1.0;
163 errorString_ << "Bowed::controlChange: control value greater than 128.0 ... setting to 128.0!";
164 handleError( StkError::WARNING );
165 }
166
167 if (number == __SK_BowPressure_) // 2
168 bowTable_.setSlope( 5.0 - (4.0 * norm) );
169 else if (number == __SK_BowPosition_) { // 4
170 betaRatio_ = 0.027236 + (0.2 * norm);
171 bridgeDelay_.setDelay( baseDelay_ * betaRatio_ );
172 neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) );
173 }
174 else if (number == __SK_ModFrequency_) // 11
175 vibrato_.setFrequency( norm * 12.0 );
176 else if (number == __SK_ModWheel_) // 1
177 vibratoGain_ = ( norm * 0.4 );
178 else if (number == __SK_AfterTouch_Cont_) // 128
179 adsr_.setTarget(norm);
180 else {
181 errorString_ << "Bowed::controlChange: undefined control number (" << number << ")!";
182 handleError( StkError::WARNING );
183 }
184
185 #if defined(_STK_DEBUG_)
186 errorString_ << "Bowed::controlChange: number = " << number << ", value = " << value << ".";
187 handleError( StkError::DEBUG_WARNING );
188 #endif
189 }
190