#include "b3ADSR.h" //ADSR mostly copied/reimplemented from Stk, see //http://github.com/thestk/stk //! ADSR envelope states. enum { ADSR_ATTACK, /*!< Attack */ ADSR_DECAY, /*!< Decay */ ADSR_SUSTAIN, /*!< Sustain */ ADSR_RELEASE, /*!< Release */ ADSR_IDLE /*!< Before attack / after release */ }; b3ADSR::b3ADSR() { m_target = 0.0; m_value = 0.0; m_attackRate = 0.001; m_decayRate = 0.00001; m_releaseRate = 0.0005; m_sustainLevel = 0.5; m_state = ADSR_IDLE; m_autoKeyOff = false; } b3ADSR::~b3ADSR() { } double b3ADSR::tick() { switch (m_state) { case ADSR_ATTACK: m_value += m_attackRate; if (m_value >= m_target) { m_value = m_target; m_target = m_sustainLevel; m_state = ADSR_DECAY; } break; case ADSR_DECAY: if (m_value > m_sustainLevel) { m_value -= m_decayRate; if (m_value <= m_sustainLevel) { m_value = m_sustainLevel; m_state = ADSR_SUSTAIN; if (m_autoKeyOff) { keyOff(); } } } else { m_value += m_decayRate; // attack target < sustain level if (m_value >= m_sustainLevel) { m_value = m_sustainLevel; m_state = ADSR_SUSTAIN; if (m_autoKeyOff) { keyOff(); } } } break; case ADSR_RELEASE: m_value -= m_releaseRate; if (m_value <= 0.0) { m_value = 0.0; m_state = ADSR_IDLE; } } return m_value; } bool b3ADSR::isIdle() const { return m_state == ADSR_IDLE; } void b3ADSR::keyOn(bool autoKeyOff) { m_autoKeyOff = autoKeyOff; if (m_target <= 0.0) m_target = 1.0; if (m_attackRate == 1) { m_value = 1.0; } m_state = ADSR_ATTACK; } void b3ADSR::keyOff() { m_autoKeyOff = false; m_target = 0.0; m_state = ADSR_RELEASE; }