commit 9f4967fded1c4a7a721339e38172eafbb7ecbecc
parent 230df78c9241b74592e60ea9bed1d51bd8ceba6b
Author: Matt Demanett <matt@demanett.net>
Date: Sun, 11 Mar 2018 18:32:55 -0400
Library ADSR.
Diffstat:
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>