BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

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 }