/***************************************************/ /*! \class BandedWG \brief Banded waveguide modeling class. This class uses banded waveguide techniques to model a variety of sounds, including bowed bars, glasses, and bowls. For more information, see Essl, G. and Cook, P. "Banded Waveguides: Towards Physical Modelling of Bar Percussion Instruments", Proceedings of the 1999 International Computer Music Conference. Control Change Numbers: - Bow Pressure = 2 - Bow Motion = 4 - Strike Position = 8 (not implemented) - Vibrato Frequency = 11 - Gain = 1 - Bow Velocity = 128 - Set Striking = 64 - Instrument Presets = 16 - Uniform Bar = 0 - Tuned Bar = 1 - Glass Harmonica = 2 - Tibetan Bowl = 3 by Georg Essl, 1999 - 2004. Modified for Stk 4.0 by Gary Scavone. */ /***************************************************/ #include "BandedWG.h" #include "SKINI.msg" #include using namespace Nyq; BandedWG :: BandedWG() { doPluck_ = true; bowTable_.setSlope( 3.0 ); adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01); frequency_ = 220.0; this->setPreset(0); bowPosition_ = 0; baseGain_ = (StkFloat) 0.999; integrationConstant_ = 0.0; trackVelocity_ = false; bowVelocity_ = 0.0; bowTarget_ = 0.0; strikeAmp_ = 0.0; } BandedWG :: ~BandedWG() { } void BandedWG :: clear() { for (int i=0; i 1568.0) frequency_ = 1568.0; StkFloat radius; StkFloat base = Stk::sampleRate() / frequency_; StkFloat length; for (int i=0; i 2.0) { delay_[i].setDelay( length ); gains_[i]=basegains_[i]; // gains_[i]=(StkFloat) pow(basegains_[i], 1/((StkFloat)delay_[i].getDelay())); // std::cerr << gains_[i]; } else { nModes_ = i; break; } // std::cerr << std::endl; // Set the bandpass filter resonances radius = 1.0 - PI * 32 / Stk::sampleRate(); //frequency_ * modes_[i] / Stk::sampleRate()/32; if ( radius < 0.0 ) radius = 0.0; bandpass_[i].setResonance(frequency_ * modes_[i], radius, true); delay_[i].clear(); bandpass_[i].clear(); } //int olen = (int)(delay_[0].getDelay()); //strikePosition_ = (int)(strikePosition_*(length/modes_[0])/olen); } void BandedWG :: setStrikePosition(StkFloat position) { strikePosition_ = (int)(delay_[0].getDelay() * position / 2.0); } void BandedWG :: startBowing(StkFloat amplitude, StkFloat rate) { adsr_.setRate(rate); adsr_.keyOn(); maxVelocity_ = 0.03 + (0.1 * amplitude); } void BandedWG :: stopBowing(StkFloat rate) { adsr_.setRate(rate); adsr_.keyOff(); } void BandedWG :: pluck(StkFloat amplitude) { int j; StkFloat min_len = delay_[nModes_-1].getDelay(); for (int i=0; isetFrequency(frequency); if ( doPluck_ ) this->pluck(amplitude); else this->startBowing(amplitude, amplitude * 0.001); #if defined(_STK_DEBUG_) errorString_ << "BandedWG::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; handleError( StkError::DEBUG_WARNING ); #endif } void BandedWG :: noteOff(StkFloat amplitude) { if ( !doPluck_ ) this->stopBowing((1.0 - amplitude) * 0.005); #if defined(_STK_DEBUG_) errorString_ << "BandedWG::NoteOff: amplitude = " << amplitude << "."; handleError( StkError::DEBUG_WARNING ); #endif } StkFloat BandedWG :: computeSample() { int k; StkFloat input = 0.0; if ( doPluck_ ) { input = 0.0; // input = strikeAmp_/nModes_; // strikeAmp_ = 0.0; } else { if (integrationConstant_ == 0.0) velocityInput_ = 0.0; else velocityInput_ = integrationConstant_ * velocityInput_; for (k=0; k 1.0 ) { norm = 1.0; errorString_ << "BandedWG::controlChange: control value greater than 128.0 ... setting to 128.0!"; handleError( StkError::WARNING ); } if (number == __SK_BowPressure_) { // 2 if ( norm == 0.0 ) doPluck_ = true; else { doPluck_ = false; bowTable_.setSlope( 10.0 - (9.0 * norm)); } } else if (number == 4) { // 4 if ( !trackVelocity_ ) trackVelocity_ = true; bowTarget_ += 0.005 * (norm - bowPosition_); bowPosition_ = norm; //adsr_.setTarget(bowPosition_); } else if (number == 8) // 8 this->setStrikePosition( norm ); else if (number == __SK_AfterTouch_Cont_) { // 128 //bowTarget_ += 0.02 * (norm - bowPosition_); //bowPosition_ = norm; if ( trackVelocity_ ) trackVelocity_ = false; maxVelocity_ = 0.13 * norm; adsr_.setTarget(norm); } else if (number == __SK_ModWheel_) { // 1 // baseGain_ = 0.9989999999 + (0.001 * norm ); baseGain_ = 0.8999999999999999 + (0.1 * norm); // std::cerr << "Yuck!" << std::endl; for (int i=0; isetPreset((int) value); else { errorString_ << "BandedWG::controlChange: undefined control number (" << number << ")!"; handleError( StkError::WARNING ); } #if defined(_STK_DEBUG_) errorString_ << "BandedWG::controlChange: number = " << number << ", value = " << value << "."; handleError( StkError::DEBUG_WARNING ); #endif }