Files
stk/src/ADSR.cpp

182 lines
4.3 KiB
C++

/***************************************************/
/*! \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--2014.
*/
/***************************************************/
#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