| andrewm@0 | 1 // | 
| andrewm@0 | 2 //  ADRS.h | 
| andrewm@0 | 3 // | 
| andrewm@0 | 4 //  Created by Nigel Redmon on 12/18/12. | 
| andrewm@0 | 5 //  EarLevel Engineering: earlevel.com | 
| andrewm@0 | 6 //  Copyright 2012 Nigel Redmon | 
| andrewm@0 | 7 // | 
| andrewm@0 | 8 //  For a complete explanation of the ADSR envelope generator and code, | 
| andrewm@0 | 9 //  read the series of articles by the author, starting here: | 
| andrewm@0 | 10 //  http://www.earlevel.com/main/2013/06/01/envelope-generators/ | 
| andrewm@0 | 11 // | 
| andrewm@0 | 12 //  License: | 
| andrewm@0 | 13 // | 
| andrewm@0 | 14 //  This source code is provided as is, without warranty. | 
| andrewm@0 | 15 //  You may copy and distribute verbatim copies of this document. | 
| andrewm@0 | 16 //  You may modify and use this source code to create binary code for your own purposes, free or commercial. | 
| andrewm@0 | 17 // | 
| andrewm@0 | 18 | 
| andrewm@0 | 19 #ifndef ADRS_h | 
| andrewm@0 | 20 #define ADRS_h | 
| andrewm@0 | 21 | 
| andrewm@0 | 22 #include <stdio.h> | 
| andrewm@0 | 23 #include <string> | 
| andrewm@0 | 24 | 
| andrewm@0 | 25 using namespace std; | 
| andrewm@0 | 26 | 
| andrewm@0 | 27 enum envState { | 
| andrewm@0 | 28 	env_idle = 0, | 
| andrewm@0 | 29 	env_attack, | 
| andrewm@0 | 30 	env_decay, | 
| andrewm@0 | 31 	env_sustain, | 
| andrewm@0 | 32 	env_release | 
| andrewm@0 | 33 }; | 
| andrewm@0 | 34 | 
| andrewm@0 | 35 class ADSR { | 
| andrewm@0 | 36 public: | 
| andrewm@0 | 37 	ADSR(void); | 
| andrewm@0 | 38 	~ADSR(void); | 
| andrewm@0 | 39 	float process(void); | 
| andrewm@0 | 40 	float process(int sampleCount); | 
| andrewm@0 | 41     float getOutput(void); | 
| andrewm@0 | 42     int getState(void); | 
| andrewm@0 | 43 	void gate(int on); | 
| andrewm@0 | 44     void setAttackRate(float rate); | 
| andrewm@0 | 45     void setDecayRate(float rate); | 
| andrewm@0 | 46     void setReleaseRate(float rate); | 
| andrewm@0 | 47 	void setSustainLevel(float level); | 
| andrewm@0 | 48     void setTargetRatioA(float targetRatio); | 
| andrewm@0 | 49     void setTargetRatioDR(float targetRatio); | 
| andrewm@0 | 50     void reset(void); | 
| andrewm@0 | 51 | 
| andrewm@0 | 52 protected: | 
| andrewm@0 | 53 	int state; | 
| andrewm@0 | 54 	float output; | 
| andrewm@0 | 55 	float attackRate; | 
| andrewm@0 | 56 	float decayRate; | 
| andrewm@0 | 57 	float releaseRate; | 
| andrewm@0 | 58 	float attackCoef; | 
| andrewm@0 | 59 	float decayCoef; | 
| andrewm@0 | 60 	float releaseCoef; | 
| andrewm@0 | 61 	float sustainLevel; | 
| andrewm@0 | 62     float targetRatioA; | 
| andrewm@0 | 63     float targetRatioDR; | 
| andrewm@0 | 64     float attackBase; | 
| andrewm@0 | 65     float decayBase; | 
| andrewm@0 | 66     float releaseBase; | 
| andrewm@0 | 67 	string name; | 
| andrewm@0 | 68     float calcCoef(float rate, float targetRatio); | 
| andrewm@0 | 69 }; | 
| andrewm@0 | 70 | 
| andrewm@0 | 71 inline float ADSR::process() { | 
| andrewm@0 | 72 	switch (state) { | 
| andrewm@0 | 73         case env_idle: | 
| andrewm@0 | 74             break; | 
| andrewm@0 | 75         case env_attack: | 
| andrewm@0 | 76             output = attackBase + output * attackCoef; | 
| andrewm@0 | 77             if (output >= 1.0) { | 
| andrewm@0 | 78                 output = 1.0; | 
| andrewm@0 | 79                 state = env_decay; | 
| andrewm@0 | 80             } | 
| andrewm@0 | 81             break; | 
| andrewm@0 | 82         case env_decay: | 
| andrewm@0 | 83             output = decayBase + output * decayCoef; | 
| andrewm@0 | 84             if (output <= sustainLevel) { | 
| andrewm@0 | 85                 output = sustainLevel; | 
| andrewm@0 | 86                 state = env_sustain; | 
| andrewm@0 | 87             } | 
| andrewm@0 | 88             break; | 
| andrewm@0 | 89         case env_sustain: | 
| andrewm@0 | 90             break; | 
| andrewm@0 | 91         case env_release: | 
| andrewm@0 | 92             output = releaseBase + output * releaseCoef; | 
| andrewm@0 | 93             if (output <= 0.0) { | 
| andrewm@0 | 94                 output = 0.0; | 
| andrewm@0 | 95                 state = env_idle; | 
| andrewm@0 | 96             } | 
| andrewm@0 | 97             break; | 
| andrewm@0 | 98 	} | 
| andrewm@0 | 99 	return output; | 
| andrewm@0 | 100 } | 
| andrewm@0 | 101 | 
| andrewm@0 | 102 inline float ADSR::process(int sampleCount) | 
| andrewm@0 | 103 { | 
| andrewm@0 | 104 	float retVal = 0; | 
| andrewm@0 | 105 | 
| andrewm@0 | 106 	if(state != env_idle) | 
| andrewm@0 | 107 	{ | 
| andrewm@0 | 108 		for(int i=0; i<sampleCount; i++) | 
| andrewm@0 | 109 			retVal = process(); | 
| andrewm@0 | 110 	} | 
| andrewm@0 | 111 | 
| andrewm@0 | 112 	return retVal; | 
| andrewm@0 | 113 } | 
| andrewm@0 | 114 | 
| andrewm@0 | 115 inline void ADSR::gate(int gate) { | 
| andrewm@0 | 116 | 
| andrewm@0 | 117 	if (gate) | 
| andrewm@0 | 118 		state = env_attack; | 
| andrewm@0 | 119 	else if (state != env_idle) | 
| andrewm@0 | 120         state = env_release; | 
| andrewm@0 | 121 } | 
| andrewm@0 | 122 | 
| andrewm@0 | 123 inline int ADSR::getState() { | 
| andrewm@0 | 124     return state; | 
| andrewm@0 | 125 } | 
| andrewm@0 | 126 | 
| andrewm@0 | 127 inline void ADSR::reset() { | 
| andrewm@0 | 128     state = env_idle; | 
| andrewm@0 | 129     output = 0.0; | 
| andrewm@0 | 130 } | 
| andrewm@0 | 131 | 
| andrewm@0 | 132 inline float ADSR::getOutput() { | 
| andrewm@0 | 133 	return output; | 
| andrewm@0 | 134 } | 
| andrewm@0 | 135 | 
| andrewm@0 | 136 | 
| andrewm@0 | 137 #endif |