BogaudioModules

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

commit 9f4967fded1c4a7a721339e38172eafbb7ecbecc
parent 230df78c9241b74592e60ea9bed1d51bd8ceba6b
Author: Matt Demanett <matt@demanett.net>
Date:   Sun, 11 Mar 2018 18:32:55 -0400

Library ADSR.

Diffstat:
Msrc/Test.cpp | 10+++++++++-
Msrc/Test.hpp | 9++++++++-
Asrc/dsp/envelope.cpp | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/dsp/envelope.hpp | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/dsp/oscillator.hpp | 1-
5 files changed, 206 insertions(+), 3 deletions(-)

diff --git a/src/Test.cpp b/src/Test.cpp @@ -87,7 +87,7 @@ void Test::step() { ); float s = 0.0f; for (int i = 0; i < OVERSAMPLEN; ++i) { - // s = _lpf2.next(_lpf.next(_saw2.next())); + // s = _lpf2.next(_lpf.next(_saw2.next())); s = _lpf.next(_saw2.next()); // s = _saw2.next(); } @@ -126,6 +126,14 @@ void Test::step() { _carrier._phase += Phasor::maxPhase; } outputs[OUT_OUTPUT].value = _carrierOutput.nextFromPhasor(_carrier) * 5.0f; + +#elif EG + _envelope.setAttack(params[PARAM1_PARAM].value); + _envelope.setDecay(params[PARAM2_PARAM].value); + _envelope.setSustain(params[PARAM3_PARAM].value); + _envelope.setRelease(params[PARAM2_PARAM].value); + _envelope.setGate(inputs[CV1_INPUT].value > 0.1f); + outputs[OUT_OUTPUT].value = _envelope.next(); #endif } diff --git a/src/Test.hpp b/src/Test.hpp @@ -12,8 +12,9 @@ extern Model* modelTest; // #define TRIANGLE 1 // #define SINEBANK 1 // #define OVERSAMPLING 1 -#define FM 1 +// #define FM 1 // #define PM 1 +#define EG 1 #include "pitch.hpp" #ifdef LPF @@ -40,6 +41,8 @@ extern Model* modelTest; #include "dsp/oscillator.hpp" #elif PM #include "dsp/oscillator.hpp" +#elif EG +#include "dsp/envelope.hpp" #else #error what #endif @@ -103,6 +106,8 @@ struct Test : Module { SineTableOscillator _modulator; Phasor _carrier; SineTableOscillator _carrierOutput; +#elif EG + ADSR _envelope; #endif Test() @@ -134,6 +139,8 @@ struct Test : Module { , _modulator(44100.0, 1000.0, 1.0) , _carrier(44100.0, 1000.0) , _carrierOutput(44100.0, 1000.0) +#elif EG + , _envelope(44100.0) #endif { onReset(); diff --git a/src/dsp/envelope.cpp b/src/dsp/envelope.cpp @@ -0,0 +1,131 @@ +#include <assert.h> +#include <math.h> +#include <stdio.h> + +#include "envelope.hpp" + +using namespace bogaudio::dsp; + +void EnvelopeGenerator::setSampleRate(float sampleRate) { + if (_sampleRate != sampleRate && sampleRate >= 1.0) { + _sampleRate = sampleRate; + _sampleTime = 1.0f / sampleRate; + _sampleRateChanged(); + } +} + + +void ADSR::setGate(bool high) { + _gated = high; +} + +void ADSR::setAttack(float seconds) { + assert(_attack >= 0.0f); + _attack = seconds; +} + +void ADSR::setDecay(float seconds) { + assert(_decay >= 0.0f); + _decay = seconds; +} + +void ADSR::setSustain(float level) { + assert(_sustain >= 0.0f); + assert(_sustain <= 1.0f); + _sustain = level; +} + +void ADSR::setRelease(float seconds) { + assert(_release >= 0.0f); + _release = seconds; +} + +float ADSR::_next() { + if (_gated) { + switch (_stage) { + case STOPPED_STAGE: { + _stage = ATTACK_STAGE; + _stageProgress = 0.0f; + break; + } + case ATTACK_STAGE: { + if (_envelope >= 1.0) { + _stage = DECAY_STAGE; + _stageProgress = 0.0f; + } + break; + } + case DECAY_STAGE: { + if (_stageProgress >= _decay) { + _stage = SUSTAIN_STAGE; + _stageProgress = 0.0f; + } + break; + } + case SUSTAIN_STAGE: { + break; + } + case RELEASE_STAGE: { + _stage = ATTACK_STAGE; + _stageProgress = _attack * powf(_envelope, 2.0f); + break; + } + } + } + else { + switch (_stage) { + case STOPPED_STAGE: { + break; + } + case ATTACK_STAGE: + case DECAY_STAGE: + case SUSTAIN_STAGE: { + _stage = RELEASE_STAGE; + _stageProgress = 0.0f; + _releaseLevel = _envelope; + break; + } + case RELEASE_STAGE: { + if (_stageProgress >= _release) { + _stage = STOPPED_STAGE; + } + break; + } + } + } + + switch (_stage) { + case STOPPED_STAGE: { + _envelope = 0.0f; + break; + } + case ATTACK_STAGE: { + _stageProgress += _sampleTime; + _envelope = _stageProgress / _attack; + _envelope = powf(_envelope, 0.5f); + break; + } + case DECAY_STAGE: { + _stageProgress += _sampleTime; + _envelope = _stageProgress / _decay; + _envelope = powf(_envelope, 0.5f); + _envelope *= 1.0f - _sustain; + _envelope = 1.0f - _envelope; + break; + } + case SUSTAIN_STAGE: { + _envelope = _sustain; + break; + } + case RELEASE_STAGE: { + _stageProgress += _sampleTime; + _envelope = _stageProgress / _release; + _envelope = powf(_envelope, 0.5f); + _envelope *= _releaseLevel; + _envelope = _releaseLevel - _envelope; + break; + } + } + + return 10.0f * _envelope; +} diff --git a/src/dsp/envelope.hpp b/src/dsp/envelope.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include <stdlib.h> + +#include "base.hpp" + +namespace bogaudio { +namespace dsp { + +struct EnvelopeGenerator : Generator { + float _sampleRate; + float _sampleTime; + + EnvelopeGenerator(float sampleRate) + : _sampleRate(sampleRate > 1.0 ? sampleRate : 1.0) + , _sampleTime(1.0f / _sampleRate) + { + } + + void setSampleRate(float sampleRate); + virtual void _sampleRateChanged() {} +}; + +struct ADSR : EnvelopeGenerator { + enum Stage { + STOPPED_STAGE, + ATTACK_STAGE, + DECAY_STAGE, + SUSTAIN_STAGE, + RELEASE_STAGE + }; + + Stage _stage = STOPPED_STAGE; + bool _gated = false; + float _attack = 0.0f; + float _decay = 0.0f; + float _sustain = 1.0f; + float _release = 0.0f; + float _stageProgress = 0.0f; + float _releaseLevel = 0.0f; + float _envelope = 0.0f; + + ADSR(float sampleRate) + : EnvelopeGenerator(sampleRate) + { + } + + void setGate(bool high); + void setAttack(float seconds); + void setDecay(float seconds); + void setSustain(float level); + void setRelease(float seconds); + + virtual float _next() override; +}; + +} // namespace dsp +} // namespace bogaudio diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp @@ -1,7 +1,6 @@ #pragma once #include <stdlib.h> -#include <stdint.h> #include <assert.h> #include <vector>