/***************************************************/ /*! \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 - 2002. Modified for Stk 4.0 by Gary Scavone. */ /***************************************************/ #include "BandedWG.h" #include "SKINI.msg" #include "Noise.h" #include BandedWG :: BandedWG() { doPluck = true; delay = new DelayL[MAX_BANDED_MODES]; bandpass = new BiQuad[MAX_BANDED_MODES]; bowTabl = new BowTabl; bowTabl->setSlope( 3.0 ); adsr = new ADSR; adsr->setAllTimes( 0.02, 0.005, 0.9, 0.01); freakency = 220.0; setPreset(0); bowPosition = 0; baseGain = (MY_FLOAT) 0.999; integrationConstant = 0.0; trackVelocity = false; bowVelocity = 0.0; bowTarget = 0.0; strikeAmp = 0.0; } BandedWG :: ~BandedWG() { delete bowTabl; delete adsr; delete [] bandpass; delete [] delay; } void BandedWG :: clear() { for (int i=0; i 1568.0) freakency = 1568.0; MY_FLOAT radius; MY_FLOAT base = Stk::sampleRate() / freakency; MY_FLOAT length; for (int i=0; i 2.0) { delay[i].setDelay( length ); gains[i]=basegains[i]; // gains[i]=(MY_FLOAT) pow(basegains[i], 1/((MY_FLOAT)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(); //freakency * modes[i] / Stk::sampleRate()/32; if ( radius < 0.0 ) radius = 0.0; bandpass[i].setResonance(freakency * 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(MY_FLOAT position) { strikePosition = (int)(delay[0].getDelay() * position / 2.0); } void BandedWG :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate) { adsr->setRate(rate); adsr->keyOn(); maxVelocity = 0.03 + (0.1 * amplitude); } void BandedWG :: stopBowing(MY_FLOAT rate) { adsr->setRate(rate); adsr->keyOff(); } void BandedWG :: pluck(MY_FLOAT amplitude) { int j; MY_FLOAT 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_) std::cerr << "BandedWG: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void BandedWG :: noteOff(MY_FLOAT amplitude) { if ( !doPluck ) this->stopBowing((1.0 - amplitude) * 0.005); #if defined(_STK_DEBUG_) std::cerr << "BandedWG: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT BandedWG :: tick() { int k; MY_FLOAT 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; ktick() * maxVelocity; input = bowVelocity - velocityInput; input = input * bowTabl->tick(input); input = input/(MY_FLOAT)nModes; } MY_FLOAT data = 0.0; for (k=0; k 1.0 ) { norm = 1.0; std::cerr << "BandedWG: Control value greater than 128.0!" << std::endl; } if (number == __SK_BowPressure_) { // 2 if ( norm == 0.0 ) doPluck = true; else { doPluck = false; bowTabl->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 std::cerr << "BandedWG: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "BandedWG: controlChange number = " << number << ", value = " << value << std::endl; #endif }