envelope.cpp (3400B)
1 #include <assert.h> 2 #include <math.h> 3 #include <stdio.h> 4 #include <algorithm> 5 6 #include "envelope.hpp" 7 8 using namespace bogaudio::dsp; 9 10 void EnvelopeGenerator::setSampleRate(float sampleRate) { 11 assert(sampleRate >= 1.0f); 12 if (_sampleRate != sampleRate) { 13 _sampleRate = sampleRate; 14 _sampleTime = 1.0f / sampleRate; 15 _sampleRateChanged(); 16 } 17 } 18 19 20 void ADSR::reset() { 21 _stage = STOPPED_STAGE; 22 _gated = false; 23 _envelope = 0.0f; 24 } 25 26 void ADSR::setGate(bool high) { 27 _gated = high; 28 } 29 30 void ADSR::setAttack(float seconds) { 31 assert(_attack >= 0.0f); 32 _attack = std::max(seconds, 0.001f); 33 } 34 35 void ADSR::setDecay(float seconds) { 36 assert(_decay >= 0.0f); 37 _decay = std::max(seconds, 0.001f); 38 } 39 40 void ADSR::setSustain(float level) { 41 assert(_sustain >= 0.0f); 42 assert(_sustain <= 1.0f); 43 _sustain = level; 44 } 45 46 void ADSR::setRelease(float seconds) { 47 assert(_release >= 0.0f); 48 _release = std::max(seconds, 0.001f); 49 } 50 51 void ADSR::setLinearShape(bool linear) { 52 if (linear) { 53 setShapes(1.0f, 1.0f, 1.0f); 54 } 55 else { 56 setShapes(0.5f, 2.0f, 2.0f); 57 } 58 } 59 60 void ADSR::setShapes(float attackShape, float decayShape, float releaseShape) { 61 assert(attackShape >= 0.1f && attackShape <= 10.0f); 62 assert(decayShape >= 0.0f && decayShape <= 10.0f); 63 assert(releaseShape >= 0.0f && releaseShape <= 10.0f); 64 _attackShape = attackShape; 65 _decayShape = decayShape; 66 _releaseShape = releaseShape; 67 } 68 69 void ADSR::retrigger() { 70 switch (_stage) { 71 case STOPPED_STAGE: { 72 _stage = ATTACK_STAGE; 73 _stageProgress = 0.0f; 74 break; 75 } 76 default: { 77 _stage = ATTACK_STAGE; 78 float e = powf(_envelope, 1.0f / _attackShape); 79 _stageProgress = e * _attack; 80 } 81 } 82 } 83 84 float ADSR::_next() { 85 if (_gated) { 86 switch (_stage) { 87 case STOPPED_STAGE: { 88 _stage = ATTACK_STAGE; 89 _stageProgress = 0.0f; 90 break; 91 } 92 case ATTACK_STAGE: { 93 if (_envelope >= 1.0) { 94 _stage = DECAY_STAGE; 95 _stageProgress = 0.0f; 96 } 97 break; 98 } 99 case DECAY_STAGE: { 100 if (_stageProgress >= _decay) { 101 _stage = SUSTAIN_STAGE; 102 _stageProgress = 0.0f; 103 } 104 break; 105 } 106 case SUSTAIN_STAGE: { 107 break; 108 } 109 case RELEASE_STAGE: { 110 _stage = ATTACK_STAGE; 111 _stageProgress = _attack * powf(_envelope, _releaseShape); 112 break; 113 } 114 } 115 } 116 else { 117 switch (_stage) { 118 case STOPPED_STAGE: { 119 break; 120 } 121 case ATTACK_STAGE: 122 case DECAY_STAGE: 123 case SUSTAIN_STAGE: { 124 _stage = RELEASE_STAGE; 125 _stageProgress = 0.0f; 126 _releaseLevel = _envelope; 127 break; 128 } 129 case RELEASE_STAGE: { 130 if (_stageProgress >= _release) { 131 _stage = STOPPED_STAGE; 132 } 133 break; 134 } 135 } 136 } 137 138 switch (_stage) { 139 case STOPPED_STAGE: { 140 _envelope = 0.0f; 141 break; 142 } 143 case ATTACK_STAGE: { 144 _stageProgress += _sampleTime; 145 _envelope = std::min(1.0f, _stageProgress / _attack); 146 _envelope = powf(_envelope, _attackShape); 147 break; 148 } 149 case DECAY_STAGE: { 150 _stageProgress += _sampleTime; 151 _envelope = std::min(1.0f, _stageProgress / _decay); 152 _envelope = powf(1.0f - _envelope, _decayShape); 153 _envelope *= 1.0f - _sustain; 154 _envelope += _sustain; 155 break; 156 } 157 case SUSTAIN_STAGE: { 158 _envelope = _sustain; 159 break; 160 } 161 case RELEASE_STAGE: { 162 _stageProgress += _sampleTime; 163 _envelope = std::min(1.0f, _stageProgress / _release); 164 _envelope = powf(1.0f - _envelope, _releaseShape); 165 _envelope *= _releaseLevel; 166 break; 167 } 168 } 169 170 return _envelope; 171 }