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