package adsr sliders into an envelopeGenerator widget
This commit is contained in:
@@ -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<size_t>(ParamId::Osc1VolumeEnvA)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].max);
|
||||
ui_->sliderGainA->setValue(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].def);
|
||||
ui_->sliderGainD->setRange(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].max);
|
||||
ui_->sliderGainD->setValue(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].def);
|
||||
ui_->sliderGainS->setRange(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].max);
|
||||
ui_->sliderGainS->setValue(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].def);
|
||||
ui_->sliderGainR->setRange(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].max);
|
||||
ui_->sliderGainR->setValue(PARAM_DEFS[static_cast<size_t>(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<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() {
|
||||
@@ -63,12 +60,14 @@ void MainWindow::keyReleaseEvent(QKeyEvent* event) {
|
||||
void MainWindow::onResetClicked() {
|
||||
|
||||
// initialize to defaults
|
||||
ui_->sliderGainA->setRange(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].max);
|
||||
ui_->sliderGainA->setValue(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvA)].def);
|
||||
ui_->sliderGainD->setRange(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].max);
|
||||
ui_->sliderGainD->setValue(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvD)].def);
|
||||
ui_->sliderGainS->setRange(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].max);
|
||||
ui_->sliderGainS->setValue(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvS)].def);
|
||||
ui_->sliderGainR->setRange(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].min, PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].max);
|
||||
ui_->sliderGainR->setValue(PARAM_DEFS[static_cast<size_t>(ParamId::Osc1VolumeEnvR)].def);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>739</width>
|
||||
<height>605</height>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -35,53 +35,17 @@
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="SmartSlider" name="sliderGainR" native="true">
|
||||
<widget class="EnvelopeGenerator" name="envelopeOsc1Volume" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>480</x>
|
||||
<y>180</y>
|
||||
<width>120</width>
|
||||
<height>300</height>
|
||||
<x>150</x>
|
||||
<y>130</y>
|
||||
<width>500</width>
|
||||
<height>360</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="SmartSlider" name="sliderGainA" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>120</x>
|
||||
<y>180</y>
|
||||
<width>120</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="SmartSlider" name="sliderGainD" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>240</x>
|
||||
<y>180</y>
|
||||
<width>120</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="SmartSlider" name="sliderGainS" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>360</x>
|
||||
<y>180</y>
|
||||
<width>120</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
@@ -91,9 +55,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SmartSlider</class>
|
||||
<class>EnvelopeGenerator</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>SmartSlider.h</header>
|
||||
<header>EnvelopeGenerator/EnvelopeGenerator.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
|
||||
73
src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp
Normal file
73
src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
#include "EnvelopeGenerator.h"
|
||||
#include "ui_EnvelopeGenerator.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
37
src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h
Normal file
37
src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
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();
|
||||
};
|
||||
195
src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.ui
Normal file
195
src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.ui
Normal file
@@ -0,0 +1,195 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EnvelopeGenerator</class>
|
||||
<widget class="QWidget" name="EnvelopeGenerator">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>360</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="SmartSlider" name="sliderDecay" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>130</x>
|
||||
<y>50</y>
|
||||
<width>120</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="SmartSlider" name="sliderRelease" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>370</x>
|
||||
<y>50</y>
|
||||
<width>120</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="SmartSlider" name="sliderSustain" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>250</x>
|
||||
<y>50</y>
|
||||
<width>120</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="SmartSlider" name="sliderAttack" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>120</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="line">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>340</y>
|
||||
<width>491</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>30</y>
|
||||
<width>491</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>50</x>
|
||||
<y>0</y>
|
||||
<width>21</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>A</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>170</x>
|
||||
<y>0</y>
|
||||
<width>30</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>D</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>300</x>
|
||||
<y>0</y>
|
||||
<width>20</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>S</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>420</x>
|
||||
<y>0</y>
|
||||
<width>20</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>R</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SmartSlider</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>SmartSlider/SmartSlider.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -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();
|
||||
@@ -19,6 +19,9 @@ public:
|
||||
void setRange(float min, float max);
|
||||
void setValue(float value);
|
||||
|
||||
// getters
|
||||
float value();
|
||||
|
||||
signals:
|
||||
void valueChanged(float value);
|
||||
|
||||
Reference in New Issue
Block a user