From cbd60e2701ed0aa50ac6e4002713f6ae00c9e9f7 Mon Sep 17 00:00:00 2001 From: Blitblank Date: Fri, 26 Dec 2025 15:23:18 -0600 Subject: [PATCH] cleanup envelopeGenerator initialization --- CMakeLists.txt | 1 + src/ParameterStore.cpp | 20 ++++++++++ src/ParameterStore.h | 32 +++++++-------- src/synth/Envelope.cpp | 2 +- src/ui/MainWindow.cpp | 29 ++------------ .../EnvelopeGenerator/EnvelopeGenerator.cpp | 39 +++++++++++++++---- .../EnvelopeGenerator/EnvelopeGenerator.h | 8 +++- 7 files changed, 79 insertions(+), 52 deletions(-) create mode 100644 src/ParameterStore.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a85b6d..12e2a38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ qt_add_executable(metabolus src/ui/MainWindow.cpp src/ui/MainWindow.h src/ui/MainWindow.ui + src/ParameterStore.cpp src/ParameterStore.h src/KeyboardController.cpp src/KeyboardController.h diff --git a/src/ParameterStore.cpp b/src/ParameterStore.cpp new file mode 100644 index 0000000..fde19a0 --- /dev/null +++ b/src/ParameterStore.cpp @@ -0,0 +1,20 @@ + +#include "ParameterStore.h" + +ParameterStore::ParameterStore() { + resetToDefaults(); +} + +void ParameterStore::set(ParamId id, float value) { + values_[static_cast(id)].store(value, std::memory_order_relaxed); +} + +float ParameterStore::get(ParamId id) const { + return values_[static_cast(id)].load(std::memory_order_relaxed); +} + +void ParameterStore::resetToDefaults() { + for(size_t i = 0; i < PARAM_COUNT; i++) { + values_[i].store(PARAM_DEFS[i].def, std::memory_order_relaxed); + } +} diff --git a/src/ParameterStore.h b/src/ParameterStore.h index 292fe8f..4067130 100644 --- a/src/ParameterStore.h +++ b/src/ParameterStore.h @@ -25,7 +25,17 @@ enum class ParamId : uint16_t { Count // for sizing }; -struct ParamDef { +// TODO: might make a map of EnvelopeIds to a struct of 4 ParamIds +enum class EnvelopeId : uint16_t { + Osc1Volume, + Osc2Volume, + Osc3Volume, + FilterCutoff, + FilterResonance, + Count +}; + +struct ParamDefault { float def; float min; float max; @@ -33,7 +43,7 @@ struct ParamDef { // TODO: make these configurable via yml file too // later TODO: and then when I have full on profile saving there will be a default profile to load from -constexpr std::array(ParamId::Count)> PARAM_DEFS {{ +constexpr std::array(ParamId::Count)> PARAM_DEFS {{ { 100.0f, 20.0f, 600.0f}, // Osc1Freq { 0.8f, 0.0f, 1.0f}, // Osc1Gain { 0.05f, 0.0f, 2.0f}, // Osc1VolumeEnvA, @@ -56,22 +66,12 @@ class ParameterStore { public: - ParameterStore() { resetToDefaults(); } + ParameterStore(); ~ParameterStore() = default; - // TODO: move into implementation file ? idk - void set(ParamId id, float value) { - values_[static_cast(id)].store(value, std::memory_order_relaxed); - } - float get(ParamId id) const { - return values_[static_cast(id)].load(std::memory_order_relaxed); - } - - void resetToDefaults() { - for(size_t i = 0; i < PARAM_COUNT; i++) { - values_[i].store(PARAM_DEFS[i].def, std::memory_order_relaxed); - } - } + void set(ParamId id, float value); + float get(ParamId id) const; + void resetToDefaults(); private: diff --git a/src/synth/Envelope.cpp b/src/synth/Envelope.cpp index 2edac52..0d9d2c7 100644 --- a/src/synth/Envelope.cpp +++ b/src/synth/Envelope.cpp @@ -26,7 +26,7 @@ float Envelope::process() { state_ = State::Decay; } break; - case State::Decay: + case State::Decay: // TODO: if noteOff occurs during decay, release doesn't trigger until decay finishes value_ -= (1.0f - sustain_) / (decay_ * sampleRate_); if(value_ <= sustain_) { value_ = sustain_; diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp index 2cea975..72655e0 100644 --- a/src/ui/MainWindow.cpp +++ b/src/ui/MainWindow.cpp @@ -21,28 +21,16 @@ MainWindow::MainWindow(QWidget *parent) : // synth business audio_->start(); + // connect envelopeGenerator + ui_->envelopeOsc1Volume->init(EnvelopeId::Osc1Volume); connect(ui_->envelopeOsc1Volume, &EnvelopeGenerator::envelopeChanged, this, [this](float a, float d, float s, float r) { audio_->parameters()->set(ParamId::Osc1VolumeEnvA, a); audio_->parameters()->set(ParamId::Osc1VolumeEnvD, d); audio_->parameters()->set(ParamId::Osc1VolumeEnvS, s); audio_->parameters()->set(ParamId::Osc1VolumeEnvR, r); - // TODO: parameters()->setEnv(ENV_ID, a, d, s ,r) }); - - // initialize to defaults - ui_->envelopeOsc1Volume->setRanges( - PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].max, - PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].max, - PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].max, - PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].max - ); - ui_->envelopeOsc1Volume->setAttack(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].def); - ui_->envelopeOsc1Volume->setDecay(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].def); - ui_->envelopeOsc1Volume->setSustain(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].def); - ui_->envelopeOsc1Volume->setRelease(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].def); - - // TODO: assign envelope widget a ParamID so that intialization and parameter bindings can be done from the envelope controller + // this should be easy enough to put into a for each envelopeGenerator loop } MainWindow::~MainWindow() { @@ -60,14 +48,5 @@ void MainWindow::keyReleaseEvent(QKeyEvent* event) { void MainWindow::onResetClicked() { // initialize to defaults - ui_->envelopeOsc1Volume->setRanges( - PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].max, - PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].max, - PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].max, - PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].max - ); - ui_->envelopeOsc1Volume->setAttack(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].def); - ui_->envelopeOsc1Volume->setDecay(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].def); - ui_->envelopeOsc1Volume->setSustain(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].def); - ui_->envelopeOsc1Volume->setRelease(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].def); + ui_->envelopeOsc1Volume->init(EnvelopeId::Osc1Volume); } diff --git a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp index 4ace9c1..2cc68d5 100644 --- a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp +++ b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp @@ -56,13 +56,6 @@ void EnvelopeGenerator::setRelease(float v) { ui_->sliderRelease->setValue(v); } -void EnvelopeGenerator::setRanges(float minA, float maxA, float minD, float maxD, float minS, float maxS, float minR, float maxR) { - ui_->sliderAttack->setRange(minA, maxA); - ui_->sliderDecay->setRange(minD, maxD); - ui_->sliderSustain->setRange(minS, maxS); - ui_->sliderRelease->setRange(minR, maxR); -} - void EnvelopeGenerator::emitEnvelope() { emit envelopeChanged( attack(), @@ -70,4 +63,34 @@ void EnvelopeGenerator::emitEnvelope() { sustain(), release() ); -} \ No newline at end of file +} + +void EnvelopeGenerator::init(EnvelopeId id) { + + // could probably make this simpler with a map + ParamId aId, dId, sId, rId; + switch (id) { + case EnvelopeId::Osc1Volume: + aId = ParamId::Osc1VolumeEnvA; dId = ParamId::Osc1VolumeEnvD; sId = ParamId::Osc1VolumeEnvS; rId = ParamId::Osc1VolumeEnvR; + break; + case EnvelopeId::FilterCutoff: + aId = ParamId::FilterCutoffEnvA; dId = ParamId::FilterCutoffEnvD; sId = ParamId::FilterCutoffEnvS; rId = ParamId::FilterCutoffEnvR; + break; + case EnvelopeId::FilterResonance: + aId = ParamId::FilterResonanceEnvA; dId = ParamId::FilterResonanceEnvD; sId = ParamId::FilterResonanceEnvS; rId = ParamId::FilterResonanceEnvR; + break; + default: // not found + break; + } + + ui_->sliderAttack->setRange(PARAM_DEFS[static_cast(aId)].min, PARAM_DEFS[static_cast(aId)].max); + ui_->sliderDecay->setRange(PARAM_DEFS[static_cast(dId)].min, PARAM_DEFS[static_cast(dId)].max); + ui_->sliderSustain->setRange(PARAM_DEFS[static_cast(sId)].min, PARAM_DEFS[static_cast(sId)].max); + ui_->sliderRelease->setRange(PARAM_DEFS[static_cast(rId)].min, PARAM_DEFS[static_cast(rId)].max); + + setAttack(PARAM_DEFS[static_cast(aId)].def); + setDecay(PARAM_DEFS[static_cast(sId)].def); + setSustain(PARAM_DEFS[static_cast(sId)].def); + setRelease(PARAM_DEFS[static_cast(rId)].def); + +} diff --git a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h index 573e13e..3fc14f8 100644 --- a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h +++ b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h @@ -3,6 +3,8 @@ #include +#include "../../ParameterStore.h" + QT_BEGIN_NAMESPACE namespace Ui { class EnvelopeGenerator; } QT_END_NAMESPACE @@ -14,13 +16,15 @@ public: explicit EnvelopeGenerator(QWidget* parent = nullptr); ~EnvelopeGenerator(); + void init(EnvelopeId id); + + // setters void setAttack(float v); void setDecay(float v); void setSustain(float v); void setRelease(float v); - void setRanges(float minA, float maxA, float minD, float maxD, float minS, float maxS, float minR, float maxR); - + // getters float attack() const; float decay() const; float sustain() const;