cleanup envelopeGenerator initialization
This commit is contained in:
@@ -45,6 +45,7 @@ qt_add_executable(metabolus
|
|||||||
src/ui/MainWindow.cpp
|
src/ui/MainWindow.cpp
|
||||||
src/ui/MainWindow.h
|
src/ui/MainWindow.h
|
||||||
src/ui/MainWindow.ui
|
src/ui/MainWindow.ui
|
||||||
|
src/ParameterStore.cpp
|
||||||
src/ParameterStore.h
|
src/ParameterStore.h
|
||||||
src/KeyboardController.cpp
|
src/KeyboardController.cpp
|
||||||
src/KeyboardController.h
|
src/KeyboardController.h
|
||||||
|
|||||||
20
src/ParameterStore.cpp
Normal file
20
src/ParameterStore.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
#include "ParameterStore.h"
|
||||||
|
|
||||||
|
ParameterStore::ParameterStore() {
|
||||||
|
resetToDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParameterStore::set(ParamId id, float value) {
|
||||||
|
values_[static_cast<size_t>(id)].store(value, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ParameterStore::get(ParamId id) const {
|
||||||
|
return values_[static_cast<size_t>(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,17 @@ enum class ParamId : uint16_t {
|
|||||||
Count // for sizing
|
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 def;
|
||||||
float min;
|
float min;
|
||||||
float max;
|
float max;
|
||||||
@@ -33,7 +43,7 @@ struct ParamDef {
|
|||||||
|
|
||||||
// TODO: make these configurable via yml file too
|
// 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
|
// later TODO: and then when I have full on profile saving there will be a default profile to load from
|
||||||
constexpr std::array<ParamDef, static_cast<size_t>(ParamId::Count)> PARAM_DEFS {{
|
constexpr std::array<ParamDefault, static_cast<size_t>(ParamId::Count)> PARAM_DEFS {{
|
||||||
{ 100.0f, 20.0f, 600.0f}, // Osc1Freq
|
{ 100.0f, 20.0f, 600.0f}, // Osc1Freq
|
||||||
{ 0.8f, 0.0f, 1.0f}, // Osc1Gain
|
{ 0.8f, 0.0f, 1.0f}, // Osc1Gain
|
||||||
{ 0.05f, 0.0f, 2.0f}, // Osc1VolumeEnvA,
|
{ 0.05f, 0.0f, 2.0f}, // Osc1VolumeEnvA,
|
||||||
@@ -56,22 +66,12 @@ class ParameterStore {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ParameterStore() { resetToDefaults(); }
|
ParameterStore();
|
||||||
~ParameterStore() = default;
|
~ParameterStore() = default;
|
||||||
|
|
||||||
// TODO: move into implementation file ? idk
|
void set(ParamId id, float value);
|
||||||
void set(ParamId id, float value) {
|
float get(ParamId id) const;
|
||||||
values_[static_cast<size_t>(id)].store(value, std::memory_order_relaxed);
|
void resetToDefaults();
|
||||||
}
|
|
||||||
float get(ParamId id) const {
|
|
||||||
return values_[static_cast<size_t>(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ float Envelope::process() {
|
|||||||
state_ = State::Decay;
|
state_ = State::Decay;
|
||||||
}
|
}
|
||||||
break;
|
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_);
|
value_ -= (1.0f - sustain_) / (decay_ * sampleRate_);
|
||||||
if(value_ <= sustain_) {
|
if(value_ <= sustain_) {
|
||||||
value_ = sustain_;
|
value_ = sustain_;
|
||||||
|
|||||||
@@ -21,28 +21,16 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
// synth business
|
// synth business
|
||||||
audio_->start();
|
audio_->start();
|
||||||
|
|
||||||
|
// connect envelopeGenerator
|
||||||
|
ui_->envelopeOsc1Volume->init(EnvelopeId::Osc1Volume);
|
||||||
connect(ui_->envelopeOsc1Volume, &EnvelopeGenerator::envelopeChanged,
|
connect(ui_->envelopeOsc1Volume, &EnvelopeGenerator::envelopeChanged,
|
||||||
this, [this](float a, float d, float s, float r) {
|
this, [this](float a, float d, float s, float r) {
|
||||||
audio_->parameters()->set(ParamId::Osc1VolumeEnvA, a);
|
audio_->parameters()->set(ParamId::Osc1VolumeEnvA, a);
|
||||||
audio_->parameters()->set(ParamId::Osc1VolumeEnvD, d);
|
audio_->parameters()->set(ParamId::Osc1VolumeEnvD, d);
|
||||||
audio_->parameters()->set(ParamId::Osc1VolumeEnvS, s);
|
audio_->parameters()->set(ParamId::Osc1VolumeEnvS, s);
|
||||||
audio_->parameters()->set(ParamId::Osc1VolumeEnvR, r);
|
audio_->parameters()->set(ParamId::Osc1VolumeEnvR, r);
|
||||||
// TODO: parameters()->setEnv(ENV_ID, a, d, s ,r)
|
|
||||||
});
|
});
|
||||||
|
// this should be easy enough to put into a for each envelopeGenerator loop
|
||||||
// initialize to defaults
|
|
||||||
ui_->envelopeOsc1Volume->setRanges(
|
|
||||||
PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].max,
|
|
||||||
PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].max,
|
|
||||||
PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].max,
|
|
||||||
PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].max
|
|
||||||
);
|
|
||||||
ui_->envelopeOsc1Volume->setAttack(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].def);
|
|
||||||
ui_->envelopeOsc1Volume->setDecay(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].def);
|
|
||||||
ui_->envelopeOsc1Volume->setSustain(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].def);
|
|
||||||
ui_->envelopeOsc1Volume->setRelease(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].def);
|
|
||||||
|
|
||||||
// TODO: assign envelope widget a ParamID so that intialization and parameter bindings can be done from the envelope controller
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
@@ -60,14 +48,5 @@ void MainWindow::keyReleaseEvent(QKeyEvent* event) {
|
|||||||
void MainWindow::onResetClicked() {
|
void MainWindow::onResetClicked() {
|
||||||
|
|
||||||
// initialize to defaults
|
// initialize to defaults
|
||||||
ui_->envelopeOsc1Volume->setRanges(
|
ui_->envelopeOsc1Volume->init(EnvelopeId::Osc1Volume);
|
||||||
PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].max,
|
|
||||||
PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].max,
|
|
||||||
PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].max,
|
|
||||||
PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].max
|
|
||||||
);
|
|
||||||
ui_->envelopeOsc1Volume->setAttack(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].def);
|
|
||||||
ui_->envelopeOsc1Volume->setDecay(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].def);
|
|
||||||
ui_->envelopeOsc1Volume->setSustain(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].def);
|
|
||||||
ui_->envelopeOsc1Volume->setRelease(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].def);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,13 +56,6 @@ void EnvelopeGenerator::setRelease(float v) {
|
|||||||
ui_->sliderRelease->setValue(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() {
|
void EnvelopeGenerator::emitEnvelope() {
|
||||||
emit envelopeChanged(
|
emit envelopeChanged(
|
||||||
attack(),
|
attack(),
|
||||||
@@ -70,4 +63,34 @@ void EnvelopeGenerator::emitEnvelope() {
|
|||||||
sustain(),
|
sustain(),
|
||||||
release()
|
release()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<size_t>(aId)].min, PARAM_DEFS[static_cast<size_t>(aId)].max);
|
||||||
|
ui_->sliderDecay->setRange(PARAM_DEFS[static_cast<size_t>(dId)].min, PARAM_DEFS[static_cast<size_t>(dId)].max);
|
||||||
|
ui_->sliderSustain->setRange(PARAM_DEFS[static_cast<size_t>(sId)].min, PARAM_DEFS[static_cast<size_t>(sId)].max);
|
||||||
|
ui_->sliderRelease->setRange(PARAM_DEFS[static_cast<size_t>(rId)].min, PARAM_DEFS[static_cast<size_t>(rId)].max);
|
||||||
|
|
||||||
|
setAttack(PARAM_DEFS[static_cast<size_t>(aId)].def);
|
||||||
|
setDecay(PARAM_DEFS[static_cast<size_t>(sId)].def);
|
||||||
|
setSustain(PARAM_DEFS[static_cast<size_t>(sId)].def);
|
||||||
|
setRelease(PARAM_DEFS[static_cast<size_t>(rId)].def);
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "../../ParameterStore.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class EnvelopeGenerator; }
|
namespace Ui { class EnvelopeGenerator; }
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -14,13 +16,15 @@ public:
|
|||||||
explicit EnvelopeGenerator(QWidget* parent = nullptr);
|
explicit EnvelopeGenerator(QWidget* parent = nullptr);
|
||||||
~EnvelopeGenerator();
|
~EnvelopeGenerator();
|
||||||
|
|
||||||
|
void init(EnvelopeId id);
|
||||||
|
|
||||||
|
// setters
|
||||||
void setAttack(float v);
|
void setAttack(float v);
|
||||||
void setDecay(float v);
|
void setDecay(float v);
|
||||||
void setSustain(float v);
|
void setSustain(float v);
|
||||||
void setRelease(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 attack() const;
|
||||||
float decay() const;
|
float decay() const;
|
||||||
float sustain() const;
|
float sustain() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user