diff --git a/CMakeLists.txt b/CMakeLists.txt index 88ecb47..5a85b6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,9 +57,12 @@ qt_add_executable(metabolus src/synth/Synth.cpp src/synth/Synth.h resources/resources.qrc - src/ui/widgets/SmartSlider.cpp - src/ui/widgets/SmartSlider.h - src/ui/widgets/SmartSlider.ui + src/ui/widgets/SmartSlider/SmartSlider.cpp + src/ui/widgets/SmartSlider/SmartSlider.h + src/ui/widgets/SmartSlider/SmartSlider.ui + src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp + src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h + src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.ui ) set_target_properties(metabolus PROPERTIES AUTOUIC ON) diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp index b5e3328..2cea975 100644 --- a/src/ui/MainWindow.cpp +++ b/src/ui/MainWindow.cpp @@ -2,7 +2,7 @@ #include "MainWindow.h" #include "ui_MainWindow.h" -#include "SmartSlider.h" +#include "SmartSlider/SmartSlider.h" #include "../ParameterStore.h" MainWindow::MainWindow(QWidget *parent) : @@ -11,41 +11,38 @@ MainWindow::MainWindow(QWidget *parent) : audio_(new AudioEngine()), keyboard_(audio_->noteQueue()) { + // Initialize UI ui_->setupUi(this); setFocusPolicy(Qt::StrongFocus); - // Initialize UI - // Connect buttons to slots connect(ui_->buttonReset, &QPushButton::clicked, this, &MainWindow::onResetClicked); // synth business audio_->start(); - // slider business - connect(ui_->sliderGainA, &SmartSlider::valueChanged, this, [this](float v) { - audio_->parameters()->set(ParamId::Osc1VolumeEnvA, v); // bind valueChanged signal to the ParameterStore - }); - connect(ui_->sliderGainD, &SmartSlider::valueChanged, this, [this](float v) { - audio_->parameters()->set(ParamId::Osc1VolumeEnvD, v); // bind valueChanged signal to the ParameterStore - }); - connect(ui_->sliderGainS, &SmartSlider::valueChanged, this, [this](float v) { - audio_->parameters()->set(ParamId::Osc1VolumeEnvS, v); // bind valueChanged signal to the ParameterStore - }); - connect(ui_->sliderGainR, &SmartSlider::valueChanged, this, [this](float v) { - audio_->parameters()->set(ParamId::Osc1VolumeEnvR, v); // bind valueChanged signal to the ParameterStore - }); + 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_->sliderGainA->setRange(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].max); - ui_->sliderGainA->setValue(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].def); - ui_->sliderGainD->setRange(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].max); - ui_->sliderGainD->setValue(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].def); - ui_->sliderGainS->setRange(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].max); - ui_->sliderGainS->setValue(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].def); - ui_->sliderGainR->setRange(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].max); - ui_->sliderGainR->setValue(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].def); - // TODO: package a smartSlider into an envelope controller widget - // then intialization and parameter bindings can be done from the envelope controller + 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 } MainWindow::~MainWindow() { @@ -63,12 +60,14 @@ void MainWindow::keyReleaseEvent(QKeyEvent* event) { void MainWindow::onResetClicked() { // initialize to defaults - ui_->sliderGainA->setRange(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].max); - ui_->sliderGainA->setValue(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvA)].def); - ui_->sliderGainD->setRange(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].max); - ui_->sliderGainD->setValue(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvD)].def); - ui_->sliderGainS->setRange(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].max); - ui_->sliderGainS->setValue(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvS)].def); - ui_->sliderGainR->setRange(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].min, PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].max); - ui_->sliderGainR->setValue(PARAM_DEFS[static_cast(ParamId::Osc1VolumeEnvR)].def); + 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); } diff --git a/src/ui/MainWindow.ui b/src/ui/MainWindow.ui index 75e7a27..4faadb0 100644 --- a/src/ui/MainWindow.ui +++ b/src/ui/MainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 739 - 605 + 800 + 600 @@ -35,53 +35,17 @@ Reset - + - 480 - 180 - 120 - 300 + 150 + 130 + 500 + 360 - - true - - - - - - 120 - 180 - 120 - 300 - - - - true - - - - - - 240 - 180 - 120 - 300 - - - - true - - - - - - 360 - 180 - 120 - 300 - + + false true @@ -91,9 +55,9 @@ - SmartSlider + EnvelopeGenerator QWidget -
SmartSlider.h
+
EnvelopeGenerator/EnvelopeGenerator.h
1
diff --git a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp new file mode 100644 index 0000000..4ace9c1 --- /dev/null +++ b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp @@ -0,0 +1,73 @@ + +#include "EnvelopeGenerator.h" +#include "ui_EnvelopeGenerator.h" + +#include + +EnvelopeGenerator::EnvelopeGenerator(QWidget* parent) : QWidget(parent), ui_(new Ui::EnvelopeGenerator) { + + ui_->setupUi(this); + + auto connectSlider = [this](SmartSlider* s) { + connect(s, &SmartSlider::valueChanged, + this, &EnvelopeGenerator::emitEnvelope); + }; + + connectSlider(ui_->sliderAttack); + connectSlider(ui_->sliderDecay); + connectSlider(ui_->sliderSustain); + connectSlider(ui_->sliderRelease); +} + +EnvelopeGenerator::~EnvelopeGenerator() { + delete ui_; +} + +// getters are here to separate ui from header +float EnvelopeGenerator::attack() const { + return ui_->sliderAttack->value(); +} + +float EnvelopeGenerator::decay() const { + return ui_->sliderDecay->value(); +} + +float EnvelopeGenerator::sustain() const { + return ui_->sliderSustain->value(); +} + +float EnvelopeGenerator::release() const { + return ui_->sliderRelease->value(); +} + +void EnvelopeGenerator::setAttack(float v) { + ui_->sliderAttack->setValue(v); +} + +void EnvelopeGenerator::setDecay(float v) { + ui_->sliderDecay->setValue(v); +} + +void EnvelopeGenerator::setSustain(float v) { + ui_->sliderSustain->setValue(v); +} + +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(), + decay(), + sustain(), + release() + ); +} \ No newline at end of file diff --git a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h new file mode 100644 index 0000000..573e13e --- /dev/null +++ b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h @@ -0,0 +1,37 @@ + +#pragma once + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class EnvelopeGenerator; } +QT_END_NAMESPACE + +// this is for the widget, not the synth object named Envelope +class EnvelopeGenerator : public QWidget { + Q_OBJECT +public: + explicit EnvelopeGenerator(QWidget* parent = nullptr); + ~EnvelopeGenerator(); + + 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); + + float attack() const; + float decay() const; + float sustain() const; + float release() const; + +signals: + void envelopeChanged(double a, double d, double s, double r); + +private: + + Ui::EnvelopeGenerator* ui_; + + void emitEnvelope(); +}; diff --git a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.ui b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.ui new file mode 100644 index 0000000..6511e09 --- /dev/null +++ b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.ui @@ -0,0 +1,195 @@ + + + EnvelopeGenerator + + + + 0 + 0 + 500 + 360 + + + + + 0 + 0 + + + + Form + + + + + 130 + 50 + 120 + 300 + + + + true + + + + + + 370 + 50 + 120 + 300 + + + + true + + + + + + 250 + 50 + 120 + 300 + + + + true + + + + + + 10 + 50 + 120 + 300 + + + + true + + + + + + 0 + 340 + 491 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 0 + 30 + 491 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 50 + 0 + 21 + 31 + + + + + 20 + + + + A + + + Qt::AlignmentFlag::AlignCenter + + + + + + 170 + 0 + 30 + 31 + + + + + 20 + + + + D + + + Qt::AlignmentFlag::AlignCenter + + + + + + 300 + 0 + 20 + 31 + + + + + 20 + + + + S + + + Qt::AlignmentFlag::AlignCenter + + + + + + 420 + 0 + 20 + 31 + + + + + 20 + + + + R + + + Qt::AlignmentFlag::AlignCenter + + + + + + SmartSlider + QWidget +
SmartSlider/SmartSlider.h
+ 1 +
+
+ + +
diff --git a/src/ui/widgets/SmartSlider.cpp b/src/ui/widgets/SmartSlider/SmartSlider.cpp similarity index 97% rename from src/ui/widgets/SmartSlider.cpp rename to src/ui/widgets/SmartSlider/SmartSlider.cpp index 7fd0e33..db20c5b 100644 --- a/src/ui/widgets/SmartSlider.cpp +++ b/src/ui/widgets/SmartSlider/SmartSlider.cpp @@ -57,6 +57,10 @@ void SmartSlider::setValue(float value) { emit valueChanged(value); } +float SmartSlider::value() { + return ui_->spinValue->value(); +} + void SmartSlider::onSliderChanged(int32_t v) { float min = ui_->spinMin->value(); float max = ui_->spinMax->value(); diff --git a/src/ui/widgets/SmartSlider.h b/src/ui/widgets/SmartSlider/SmartSlider.h similarity index 96% rename from src/ui/widgets/SmartSlider.h rename to src/ui/widgets/SmartSlider/SmartSlider.h index cf49f87..5ef8f38 100644 --- a/src/ui/widgets/SmartSlider.h +++ b/src/ui/widgets/SmartSlider/SmartSlider.h @@ -19,6 +19,9 @@ public: void setRange(float min, float max); void setValue(float value); + // getters + float value(); + signals: void valueChanged(float value); diff --git a/src/ui/widgets/SmartSlider.ui b/src/ui/widgets/SmartSlider/SmartSlider.ui similarity index 100% rename from src/ui/widgets/SmartSlider.ui rename to src/ui/widgets/SmartSlider/SmartSlider.ui