/***************************************************/ /*! \class ADSR \brief STK ADSR envelope class. This class implements a traditional ADSR (Attack, Decay, Sustain, Release) envelope. It responds to simple keyOn and keyOff messages, keeping track of its state. The \e state = ADSR::IDLE before being triggered and after the envelope value reaches 0.0 in the ADSR::RELEASE state. All rate, target and level settings must be non-negative. All time settings must be positive. by Perry R. Cook and Gary P. Scavone, 1995--2017. */ /***************************************************/ #include "ADSR.h" namespace stk { ADSR :: ADSR( void ) { target_ = 0.0; value_ = 0.0; attackRate_ = 0.001; decayRate_ = 0.001; releaseRate_ = 0.005; releaseTime_ = -1.0; sustainLevel_ = 0.5; state_ = IDLE; Stk::addSampleRateAlert( this ); } ADSR :: ~ADSR( void ) { Stk::removeSampleRateAlert( this ); } void ADSR :: sampleRateChanged( StkFloat newRate, StkFloat oldRate ) { if ( !ignoreSampleRateChange_ ) { attackRate_ = oldRate * attackRate_ / newRate; decayRate_ = oldRate * decayRate_ / newRate; releaseRate_ = oldRate * releaseRate_ / newRate; } } void ADSR :: keyOn() { if ( target_ <= 0.0 ) target_ = 1.0; state_ = ATTACK; } void ADSR :: keyOff() { target_ = 0.0; state_ = RELEASE; // FIXED October 2010 - Nick Donaldson // Need to make release rate relative to current value!! // Only update if we have set a TIME rather than a RATE, // in which case releaseTime_ will be -1 if ( releaseTime_ > 0.0 ) releaseRate_ = value_ / ( releaseTime_ * Stk::sampleRate() ); } void ADSR :: setAttackRate( StkFloat rate ) { if ( rate < 0.0 ) { oStream_ << "ADSR::setAttackRate: argument must be >= 0.0!"; handleError( StkError::WARNING ); return; } attackRate_ = rate; } void ADSR :: setAttackTarget( StkFloat target ) { if ( target < 0.0 ) { oStream_ << "ADSR::setAttackTarget: negative target not allowed!"; handleError( StkError::WARNING ); return; } target_ = target; } void ADSR :: setDecayRate( StkFloat rate ) { if ( rate < 0.0 ) { oStream_ << "ADSR::setDecayRate: negative rates not allowed!"; handleError( StkError::WARNING ); return; } decayRate_ = rate; } void ADSR :: setSustainLevel( StkFloat level ) { if ( level < 0.0 ) { oStream_ << "ADSR::setSustainLevel: negative level not allowed!"; handleError( StkError::WARNING ); return; } sustainLevel_ = level; } void ADSR :: setReleaseRate( StkFloat rate ) { if ( rate < 0.0 ) { oStream_ << "ADSR::setReleaseRate: negative rates not allowed!"; handleError( StkError::WARNING ); return; } releaseRate_ = rate; // Set to negative value so we don't update the release rate on keyOff() releaseTime_ = -1.0; } void ADSR :: setAttackTime( StkFloat time ) { if ( time <= 0.0 ) { oStream_ << "ADSR::setAttackTime: negative or zero times not allowed!"; handleError( StkError::WARNING ); return; } attackRate_ = 1.0 / ( time * Stk::sampleRate() ); } void ADSR :: setDecayTime( StkFloat time ) { if ( time <= 0.0 ) { oStream_ << "ADSR::setDecayTime: negative or zero times not allowed!"; handleError( StkError::WARNING ); return; } decayRate_ = (1.0 - sustainLevel_) / ( time * Stk::sampleRate() ); } void ADSR :: setReleaseTime( StkFloat time ) { if ( time <= 0.0 ) { oStream_ << "ADSR::setReleaseTime: negative or zero times not allowed!"; handleError( StkError::WARNING ); return; } releaseRate_ = sustainLevel_ / ( time * Stk::sampleRate() ); releaseTime_ = time; } void ADSR :: setAllTimes( StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime ) { this->setAttackTime( aTime ); this->setSustainLevel( sLevel ); this->setDecayTime( dTime ); this->setReleaseTime( rTime ); } void ADSR :: setTarget( StkFloat target ) { if ( target < 0.0 ) { oStream_ << "ADSR::setTarget: negative target not allowed!"; handleError( StkError::WARNING ); return; } target_ = target; this->setSustainLevel( target_ ); if ( value_ < target_ ) state_ = ATTACK; if ( value_ > target_ ) state_ = DECAY; } void ADSR :: setValue( StkFloat value ) { state_ = SUSTAIN; target_ = value; value_ = value; this->setSustainLevel( value ); lastFrame_[0] = value; } } // stk namespace