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