/***************************************************/ /*! \class Brass \brief STK simple brass instrument class. This class implements a simple brass instrument waveguide model, a la Cook (TBone, HosePlayer). This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Lip Tension = 2 - Slide Length = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Volume = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2005. */ /***************************************************/ #include "Brass.h" #include "SKINI.msg" #include Brass :: Brass(StkFloat lowestFrequency) { length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1); delayLine_.setMaximumDelay( length_ ); delayLine_.setDelay( 0.5 * length_ ); lipFilter_.setGain( 0.03 ); dcBlock_.setBlockZero(); adsr_.setAllTimes( 0.005, 0.001, 1.0, 0.010); vibrato_.setFrequency( 6.137 ); vibratoGain_ = 0.0; this->clear(); maxPressure_ = 0.0; lipTarget_ = 0.0; // This is necessary to initialize variables. this->setFrequency( 220.0 ); } Brass :: ~Brass() { } void Brass :: clear() { delayLine_.clear(); lipFilter_.clear(); dcBlock_.clear(); } void Brass :: setFrequency(StkFloat frequency) { StkFloat freakency = frequency; if ( frequency <= 0.0 ) { errorString_ << "Brass::setFrequency: parameter is less than or equal to zero!"; handleError( StkError::WARNING ); freakency = 220.0; } // Fudge correction for filter delays. slideTarget_ = (Stk::sampleRate() / freakency * 2.0) + 3.0; delayLine_.setDelay( slideTarget_ ); // play a harmonic lipTarget_ = freakency; lipFilter_.setResonance( freakency, 0.997 ); } void Brass :: setLip(StkFloat frequency) { StkFloat freakency = frequency; if ( frequency <= 0.0 ) { errorString_ << "Brass::setLip: parameter is less than or equal to zero!"; handleError( StkError::WARNING ); freakency = 220.0; } lipFilter_.setResonance( freakency, 0.997 ); } void Brass :: startBlowing(StkFloat amplitude, StkFloat rate) { adsr_.setAttackRate( rate ); maxPressure_ = amplitude; adsr_.keyOn(); } void Brass :: stopBlowing(StkFloat rate) { adsr_.setReleaseRate( rate ); adsr_.keyOff(); } void Brass :: noteOn(StkFloat frequency, StkFloat amplitude) { this->setFrequency( frequency ); this->startBlowing( amplitude, amplitude * 0.001 ); #if defined(_STK_DEBUG_) errorString_ << "Brass::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; handleError( StkError::DEBUG_WARNING ); #endif } void Brass :: noteOff(StkFloat amplitude) { this->stopBlowing( amplitude * 0.005 ); #if defined(_STK_DEBUG_) errorString_ << "Brass::NoteOff: amplitude = " << amplitude << "."; handleError( StkError::DEBUG_WARNING ); #endif } StkFloat Brass :: computeSample() { StkFloat breathPressure = maxPressure_ * adsr_.tick(); breathPressure += vibratoGain_ * vibrato_.tick(); StkFloat mouthPressure = 0.3 * breathPressure; StkFloat borePressure = 0.85 * delayLine_.lastOut(); StkFloat deltaPressure = mouthPressure - borePressure; // Differential pressure. deltaPressure = lipFilter_.tick( deltaPressure ); // Force - > position. deltaPressure *= deltaPressure; // Basic position to area mapping. if ( deltaPressure > 1.0 ) deltaPressure = 1.0; // Non-linear saturation. // The following input scattering assumes the mouthPressure = area. lastOutput_ = deltaPressure * mouthPressure + ( 1.0 - deltaPressure) * borePressure; lastOutput_ = delayLine_.tick( dcBlock_.tick( lastOutput_ ) ); return lastOutput_; } void Brass :: controlChange(int number, StkFloat value) { StkFloat norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; errorString_ << "Brass::controlChange: control value less than zero ... setting to zero!"; handleError( StkError::WARNING ); } else if ( norm > 1.0 ) { norm = 1.0; errorString_ << "Brass::controlChange: control value greater than 128.0 ... setting to 128.0!"; handleError( StkError::WARNING ); } if (number == __SK_LipTension_) { // 2 StkFloat temp = lipTarget_ * pow( 4.0, (2.0 * norm) - 1.0 ); this->setLip(temp); } else if (number == __SK_SlideLength_) // 4 delayLine_.setDelay( slideTarget_ * (0.5 + norm) ); 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 { errorString_ << "Brass::controlChange: undefined control number (" << number << ")!"; handleError( StkError::WARNING ); } #if defined(_STK_DEBUG_) errorString_ << "Brass::controlChange: number = " << number << ", value = " << value << "."; handleError( StkError::DEBUG_WARNING ); #endif }