/***************************************************/ /*! \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 "SKINImsg.h" #include namespace stk { BandedWG :: BandedWG( void ) { 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_ = 0.999; integrationConstant_ = 0.0; trackVelocity_ = false; bowVelocity_ = 0.0; bowTarget_ = 0.0; strikeAmp_ = 0.0; } BandedWG :: ~BandedWG( void ) { } void BandedWG :: clear( void ) { 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_.setAttackRate(rate); adsr_.keyOn(); maxVelocity_ = 0.03 + (0.1 * amplitude); } void BandedWG :: stopBowing( StkFloat rate ) { adsr_.setReleaseRate(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 ); } void BandedWG :: noteOff( StkFloat amplitude ) { if ( !doPluck_ ) this->stopBowing( (1.0 - amplitude) * 0.005 ); } StkFloat BandedWG :: tick( unsigned int ) { 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 128.0 ) ) { oStream_ << "BandedWG::controlChange: value (" << value << ") is out of range!"; handleError( StkError::WARNING ); return; } #endif StkFloat normalizedValue = value * ONE_OVER_128; if (number == __SK_BowPressure_) { // 2 if ( normalizedValue == 0.0 ) doPluck_ = true; else { doPluck_ = false; bowTable_.setSlope( 10.0 - (9.0 * normalizedValue)); } } else if (number == 4) { // 4 if ( !trackVelocity_ ) trackVelocity_ = true; bowTarget_ += 0.005 * (normalizedValue - bowPosition_); bowPosition_ = normalizedValue; //adsr_.setTarget(bowPosition_); } else if (number == 8) // 8 this->setStrikePosition( normalizedValue ); else if (number == __SK_AfterTouch_Cont_) { // 128 //bowTarget_ += 0.02 * (normalizedValue - bowPosition_); //bowPosition_ = normalizedValue; if ( trackVelocity_ ) trackVelocity_ = false; maxVelocity_ = 0.13 * normalizedValue; adsr_.setTarget(normalizedValue); } else if (number == __SK_ModWheel_) { // 1 // baseGain_ = 0.9989999999 + (0.001 * normalizedValue ); baseGain_ = 0.8999999999999999 + (0.1 * normalizedValue); // std::cerr << "Yuck!" << std::endl; for (int i=0; isetPreset((int) value); #if defined(_STK_DEBUG_) else { oStream_ << "BandedWG::controlChange: undefined control number (" << number << ")!"; handleError( StkError::WARNING ); } #endif } } // stk namespace