Files
stk/src/Bowed.cpp
Gary Scavone 586b0add5f Version 4.1.2
2013-09-29 23:05:20 +02:00

190 lines
5.2 KiB
C++

/***************************************************/
/*! \class Bowed
\brief STK bowed string instrument class.
This class implements a bowed string model, a
la Smith (1986), after McIntyre, Schumacher,
Woodhouse (1983).
This is a digital waveguide model, making its
use possibly subject to patents held by
Stanford University, Yamaha, and others.
Control Change Numbers:
- Bow Pressure = 2
- Bow Position = 4
- Vibrato Frequency = 11
- Vibrato Gain = 1
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
*/
/***************************************************/
#include "Bowed.h"
#include "SKINI.msg"
Bowed :: Bowed(MY_FLOAT lowestFrequency)
{
long length;
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
neckDelay = new DelayL(100.0, length);
length >>= 1;
bridgeDelay = new DelayL(29.0, length);
bowTable = new BowTabl;
bowTable->setSlope((MY_FLOAT) 3.0);
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency((MY_FLOAT) 6.12723);
vibratoGain = (MY_FLOAT) 0.0;
stringFilter = new OnePole;
stringFilter->setPole((MY_FLOAT) (0.6 - (0.1 * 22050.0 / Stk::sampleRate() ) ) );
stringFilter->setGain((MY_FLOAT) 0.95);
bodyFilter = new BiQuad;
bodyFilter->setResonance( 500.0, 0.85, TRUE );
bodyFilter->setGain((MY_FLOAT) 0.2);
adsr = new ADSR;
adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01);
betaRatio = (MY_FLOAT) 0.127236;
// Necessary to initialize internal variables.
setFrequency( 220.0 );
}
Bowed :: ~Bowed()
{
delete neckDelay;
delete bridgeDelay;
delete bowTable;
delete stringFilter;
delete bodyFilter;
delete vibrato;
delete adsr;
}
void Bowed :: clear()
{
neckDelay->clear();
bridgeDelay->clear();
}
void Bowed :: setFrequency(MY_FLOAT frequency)
{
MY_FLOAT freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Bowed: setFrequency parameter is less than or equal to zero!" << std::endl;
freakency = 220.0;
}
// Delay = length - approximate filter delay.
baseDelay = Stk::sampleRate() / freakency - (MY_FLOAT) 4.0;
if ( baseDelay <= 0.0 ) baseDelay = 0.3;
bridgeDelay->setDelay(baseDelay * betaRatio); // bow to bridge length
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio)); // bow to nut (finger) length
}
void Bowed :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate)
{
adsr->setRate(rate);
adsr->keyOn();
maxVelocity = (MY_FLOAT) 0.03 + ((MY_FLOAT) 0.2 * amplitude);
}
void Bowed :: stopBowing(MY_FLOAT rate)
{
adsr->setRate(rate);
adsr->keyOff();
}
void Bowed :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
{
this->startBowing(amplitude, amplitude * 0.001);
this->setFrequency(frequency);
#if defined(_STK_DEBUG_)
std::cerr << "Bowed: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
#endif
}
void Bowed :: noteOff(MY_FLOAT amplitude)
{
this->stopBowing(((MY_FLOAT) 1.0 - amplitude) * (MY_FLOAT) 0.005);
#if defined(_STK_DEBUG_)
std::cerr << "Bowed: NoteOff amplitude = " << amplitude << std::endl;
#endif
}
void Bowed :: setVibrato(MY_FLOAT gain)
{
vibratoGain = gain;
}
MY_FLOAT Bowed :: tick()
{
MY_FLOAT bowVelocity;
MY_FLOAT bridgeRefl;
MY_FLOAT nutRefl;
MY_FLOAT newVel;
MY_FLOAT velDiff;
MY_FLOAT stringVel;
bowVelocity = maxVelocity * adsr->tick();
bridgeRefl = -stringFilter->tick( bridgeDelay->lastOut() );
nutRefl = -neckDelay->lastOut();
stringVel = bridgeRefl + nutRefl; // Sum is String Velocity
velDiff = bowVelocity - stringVel; // Differential Velocity
newVel = velDiff * bowTable->tick( velDiff ); // Non-Linear Bow Function
neckDelay->tick(bridgeRefl + newVel); // Do string propagations
bridgeDelay->tick(nutRefl + newVel);
if (vibratoGain > 0.0) {
neckDelay->setDelay((baseDelay * ((MY_FLOAT) 1.0 - betaRatio)) +
(baseDelay * vibratoGain * vibrato->tick()));
}
lastOutput = bodyFilter->tick(bridgeDelay->lastOut());
return lastOutput;
}
void Bowed :: controlChange(int number, MY_FLOAT value)
{
MY_FLOAT norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Bowed: Control value less than zero!" << std::endl;
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Bowed: Control value greater than 128.0!" << std::endl;
}
if (number == __SK_BowPressure_) // 2
bowTable->setSlope( 5.0 - (4.0 * norm) );
else if (number == __SK_BowPosition_) { // 4
betaRatio = 0.027236 + (0.2 * norm);
bridgeDelay->setDelay(baseDelay * betaRatio);
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio));
}
else if (number == __SK_ModFrequency_) // 11
vibrato->setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain = ( norm * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr->setTarget(norm);
else
std::cerr << "Bowed: Undefined Control Number (" << number << ")!!" << std::endl;
#if defined(_STK_DEBUG_)
std::cerr << "Bowed: controlChange number = " << number << ", value = " << value << std::endl;
#endif
}