summaryrefslogtreecommitdiff
path: root/nyqstk/src/ADSR.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'nyqstk/src/ADSR.cpp')
-rw-r--r--nyqstk/src/ADSR.cpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/nyqstk/src/ADSR.cpp b/nyqstk/src/ADSR.cpp
new file mode 100644
index 0000000..2b7dd92
--- /dev/null
+++ b/nyqstk/src/ADSR.cpp
@@ -0,0 +1,191 @@
+/***************************************************/
+/*! \class ADSR
+ \brief STK ADSR envelope class.
+
+ This Envelope subclass 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::DONE after the
+ envelope value reaches 0.0 in the
+ ADSR::RELEASE state.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#include "ADSR.h"
+
+using namespace Nyq;
+
+ADSR :: ADSR() : Envelope()
+{
+ target_ = 0.0;
+ value_ = 0.0;
+ attackRate_ = 0.001;
+ decayRate_ = 0.001;
+ sustainLevel_ = 0.5;
+ releaseRate_ = 0.01;
+ state_ = ATTACK;
+}
+
+ADSR :: ~ADSR()
+{
+}
+
+void ADSR :: keyOn()
+{
+ target_ = 1.0;
+ rate_ = attackRate_;
+ state_ = ATTACK;
+}
+
+void ADSR :: keyOff()
+{
+ target_ = 0.0;
+ rate_ = releaseRate_;
+ state_ = RELEASE;
+}
+
+void ADSR :: setAttackRate(StkFloat rate)
+{
+ if (rate < 0.0) {
+ errorString_ << "ADSR::setAttackRate: negative rates not allowed ... correcting!";
+ handleError( StkError::WARNING );
+ attackRate_ = -rate;
+ }
+ else attackRate_ = rate;
+}
+
+void ADSR :: setDecayRate(StkFloat rate)
+{
+ if (rate < 0.0) {
+ errorString_ << "ADSR::setDecayRate: negative rates not allowed ... correcting!";
+ handleError( StkError::WARNING );
+ decayRate_ = -rate;
+ }
+ else decayRate_ = rate;
+}
+
+void ADSR :: setSustainLevel(StkFloat level)
+{
+ if (level < 0.0 ) {
+ errorString_ << "ADSR::setSustainLevel: level out of range ... correcting!";
+ handleError( StkError::WARNING );
+ sustainLevel_ = 0.0;
+ }
+ else sustainLevel_ = level;
+}
+
+void ADSR :: setReleaseRate(StkFloat rate)
+{
+ if (rate < 0.0) {
+ errorString_ << "ADSR::setReleaseRate: negative rates not allowed ... correcting!";
+ handleError( StkError::WARNING );
+ releaseRate_ = -rate;
+ }
+ else releaseRate_ = rate;
+}
+
+void ADSR :: setAttackTime(StkFloat time)
+{
+ if (time < 0.0) {
+ errorString_ << "ADSR::setAttackTime: negative times not allowed ... correcting!";
+ handleError( StkError::WARNING );
+ attackRate_ = 1.0 / ( -time * Stk::sampleRate() );
+ }
+ else attackRate_ = 1.0 / ( time * Stk::sampleRate() );
+}
+
+void ADSR :: setDecayTime(StkFloat time)
+{
+ if (time < 0.0) {
+ errorString_ << "ADSR::setDecayTime: negative times not allowed ... correcting!";
+ handleError( StkError::WARNING );
+ decayRate_ = 1.0 / ( -time * Stk::sampleRate() );
+ }
+ else decayRate_ = 1.0 / ( time * Stk::sampleRate() );
+}
+
+void ADSR :: setReleaseTime(StkFloat time)
+{
+ if (time < 0.0) {
+ errorString_ << "ADSR::setReleaseTime: negative times not allowed ... correcting!";
+ handleError( StkError::WARNING );
+ releaseRate_ = sustainLevel_ / ( -time * Stk::sampleRate() );
+ }
+ else releaseRate_ = sustainLevel_ / ( time * Stk::sampleRate() );
+}
+
+void ADSR :: setAllTimes(StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime)
+{
+ this->setAttackTime(aTime);
+ this->setDecayTime(dTime);
+ this->setSustainLevel(sLevel);
+ this->setReleaseTime(rTime);
+}
+
+void ADSR :: setTarget(StkFloat target)
+{
+ target_ = target;
+ if (value_ < target_) {
+ state_ = ATTACK;
+ this->setSustainLevel(target_);
+ rate_ = attackRate_;
+ }
+ if (value_ > target_) {
+ this->setSustainLevel(target_);
+ state_ = DECAY;
+ rate_ = decayRate_;
+ }
+}
+
+void ADSR :: setValue(StkFloat value)
+{
+ state_ = SUSTAIN;
+ target_ = value;
+ value_ = value;
+ this->setSustainLevel(value);
+ rate_ = (StkFloat) 0.0;
+}
+
+int ADSR :: getState(void) const
+{
+ return state_;
+}
+
+StkFloat ADSR :: computeSample()
+{
+ switch (state_) {
+
+ case ATTACK:
+ value_ += rate_;
+ if (value_ >= target_) {
+ value_ = target_;
+ rate_ = decayRate_;
+ target_ = sustainLevel_;
+ state_ = DECAY;
+ }
+ break;
+
+ case DECAY:
+ value_ -= decayRate_;
+ if (value_ <= sustainLevel_) {
+ value_ = sustainLevel_;
+ rate_ = (StkFloat) 0.0;
+ state_ = SUSTAIN;
+ }
+ break;
+
+ case RELEASE:
+ value_ -= releaseRate_;
+ if (value_ <= 0.0) {
+ value_ = (StkFloat) 0.0;
+ state_ = DONE;
+ }
+ }
+
+ lastOutput_ = value_;
+ return value_;
+}