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