andrewm@0: // andrewm@0: // ADRS.h andrewm@0: // andrewm@0: // Created by Nigel Redmon on 12/18/12. andrewm@0: // EarLevel Engineering: earlevel.com andrewm@0: // Copyright 2012 Nigel Redmon andrewm@0: // andrewm@0: // For a complete explanation of the ADSR envelope generator and code, andrewm@0: // read the series of articles by the author, starting here: andrewm@0: // http://www.earlevel.com/main/2013/06/01/envelope-generators/ andrewm@0: // andrewm@0: // License: andrewm@0: // andrewm@0: // This source code is provided as is, without warranty. andrewm@0: // You may copy and distribute verbatim copies of this document. andrewm@0: // You may modify and use this source code to create binary code for your own purposes, free or commercial. andrewm@0: // andrewm@0: andrewm@0: #ifndef ADRS_h andrewm@0: #define ADRS_h andrewm@0: andrewm@0: #include andrewm@0: #include andrewm@0: andrewm@0: using namespace std; andrewm@0: andrewm@0: enum envState { andrewm@0: env_idle = 0, andrewm@0: env_attack, andrewm@0: env_decay, andrewm@0: env_sustain, andrewm@0: env_release andrewm@0: }; andrewm@0: andrewm@0: class ADSR { andrewm@0: public: andrewm@0: ADSR(void); andrewm@0: ~ADSR(void); andrewm@0: float process(void); andrewm@0: float process(int sampleCount); andrewm@0: float getOutput(void); andrewm@0: int getState(void); andrewm@0: void gate(int on); andrewm@0: void setAttackRate(float rate); andrewm@0: void setDecayRate(float rate); andrewm@0: void setReleaseRate(float rate); andrewm@0: void setSustainLevel(float level); andrewm@0: void setTargetRatioA(float targetRatio); andrewm@0: void setTargetRatioDR(float targetRatio); andrewm@0: void reset(void); andrewm@0: andrewm@0: protected: andrewm@0: int state; andrewm@0: float output; andrewm@0: float attackRate; andrewm@0: float decayRate; andrewm@0: float releaseRate; andrewm@0: float attackCoef; andrewm@0: float decayCoef; andrewm@0: float releaseCoef; andrewm@0: float sustainLevel; andrewm@0: float targetRatioA; andrewm@0: float targetRatioDR; andrewm@0: float attackBase; andrewm@0: float decayBase; andrewm@0: float releaseBase; andrewm@0: string name; andrewm@0: float calcCoef(float rate, float targetRatio); andrewm@0: }; andrewm@0: andrewm@0: inline float ADSR::process() { andrewm@0: switch (state) { andrewm@0: case env_idle: andrewm@0: break; andrewm@0: case env_attack: andrewm@0: output = attackBase + output * attackCoef; andrewm@0: if (output >= 1.0) { andrewm@0: output = 1.0; andrewm@0: state = env_decay; andrewm@0: } andrewm@0: break; andrewm@0: case env_decay: andrewm@0: output = decayBase + output * decayCoef; andrewm@0: if (output <= sustainLevel) { andrewm@0: output = sustainLevel; andrewm@0: state = env_sustain; andrewm@0: } andrewm@0: break; andrewm@0: case env_sustain: andrewm@0: break; andrewm@0: case env_release: andrewm@0: output = releaseBase + output * releaseCoef; andrewm@0: if (output <= 0.0) { andrewm@0: output = 0.0; andrewm@0: state = env_idle; andrewm@0: } andrewm@0: break; andrewm@0: } andrewm@0: return output; andrewm@0: } andrewm@0: andrewm@0: inline float ADSR::process(int sampleCount) andrewm@0: { andrewm@0: float retVal = 0; andrewm@0: andrewm@0: if(state != env_idle) andrewm@0: { andrewm@0: for(int i=0; i