diff --git a/CMakeLists.txt b/CMakeLists.txt index 004e535..4cb23b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,9 +42,8 @@ qt_standard_project_setup() qt_add_executable(metabolus src/main.cpp - src/MainWindow.cpp - src/MainWindow.h - src/MainWindow.ui + src/ui/MainWindow.cpp + src/ui/MainWindow.h src/ParameterStore.h src/KeyboardController.cpp src/KeyboardController.h @@ -57,6 +56,8 @@ qt_add_executable(metabolus src/synth/Synth.cpp src/synth/Synth.h resources/resources.qrc + src/ui/MainWindow.ui + src/ui/SmartSlider.ui ) if (WIN32) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp deleted file mode 100644 index 21e0914..0000000 --- a/src/MainWindow.cpp +++ /dev/null @@ -1,118 +0,0 @@ - -#include "MainWindow.h" - -#include -#include "ui_MainWindow.h" - -#include "ParameterStore.h" - -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow), - audio_(new AudioEngine()), - keyboard_(audio_->noteQueue()) { - - ui->setupUi(this); - setFocusPolicy(Qt::StrongFocus); - - // Initialize UI - updateCounterLabel(); - - // Connect buttons to slots - connect(ui->buttonIncrement, &QPushButton::clicked, this, &MainWindow::onIncrementClicked); - connect(ui->buttonReset, &QPushButton::clicked, this, &MainWindow::onResetClicked); - - // slider business - // TODO: smart slider widget - connect(ui->slider, &QSlider::valueChanged, this, &MainWindow::onSliderValueChanged); - connect(ui->inputMin, &QLineEdit::editingFinished, this, &MainWindow::onMinChanged); - connect(ui->inputMax, &QLineEdit::editingFinished, this, &MainWindow::onMaxChanged); - connect(ui->inputStep, &QLineEdit::editingFinished, this, &MainWindow::onStepChanged); - connect(ui->inputValue, &QLineEdit::editingFinished, this, &MainWindow::onValueChanged); - - // synth business - audio_->start(); - - // init defaults - // TODO:: there's gotta be a better way - ui->slider->setValue(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].def); - ui->slider->setMinimum(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].min); - ui->slider->setMaximum(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].max); - ui->inputValue->setText(QString::number(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].def)); - ui->inputMin->setText(QString::number(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].min)); - ui->inputMax->setText(QString::number(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].max)); -} - -MainWindow::~MainWindow() { - delete ui; -} - -void MainWindow::keyPressEvent(QKeyEvent* event) { - keyboard_.handleKeyPress(event); -} - -void MainWindow::keyReleaseEvent(QKeyEvent* event) { - keyboard_.handleKeyRelease(event); -} - -void MainWindow::onIncrementClicked() { - counter_++; - updateCounterLabel(); -} - -void MainWindow::onResetClicked() { - counter_ = 0; - updateCounterLabel(); -} - -void MainWindow::updateCounterLabel() { - ui->labelCounter->setText(QString::number(counter_)); -} - -// allows only numbers to be set -void MainWindow::onSliderValueChanged(int value) { - QSignalBlocker blocker(ui->inputValue); - ui->inputValue->setText(QString::number(value)); - - // forward value so synthesizer can read - audio_->parameters()->set(ParamId::Osc1Frequency, static_cast(value)); -} - -// allows only values within the min, max to be set by the text field -void MainWindow::onValueChanged() { - bool ok = false; - int value = ui->inputValue->text().toInt(&ok); - if(!ok) return; - - value = qBound(ui->slider->minimum(), value, ui->slider->maximum()); - ui->slider->setValue(value); -} - -void MainWindow::applySliderRange() { - bool minOk, maxOk; - int min = ui->inputMin->text().toInt(&minOk); - int max = ui->inputMax->text().toInt(&maxOk); - if(!minOk || !maxOk || min > max) return; - - ui->slider->setRange(min, max); - - syncValueToUi(ui->slider->value()); -} - -void MainWindow::applySliderStep() { - bool ok; - int step = ui->inputStep->text().toInt(&ok); - if(!ok || step <= 0) return; - - ui->slider->setSingleStep(step); - ui->slider->setPageStep(step); -} - -void MainWindow::syncValueToUi(int value) { - QSignalBlocker block1(ui->slider); - QSignalBlocker block2(ui->inputValue); - - value = qBound(ui->slider->minimum(), value, ui->slider->maximum()); - ui->slider->setValue(value); - ui->inputValue->setText(QString::number(value)); -} diff --git a/src/main.cpp b/src/main.cpp index a93a0a3..dea8c3a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include -#include "MainWindow.h" +#include "ui/MainWindow.h" #include diff --git a/src/synth/Synth.cpp b/src/synth/Synth.cpp index 105ca5c..347e626 100644 --- a/src/synth/Synth.cpp +++ b/src/synth/Synth.cpp @@ -88,7 +88,7 @@ void Synth::process(float* out, uint32_t nFrames, uint32_t sampleRate) { float sineSample = std::sin(phase_); float squareSample = -0.707f; if(phase_ >= M_PI) squareSample = 0.707f; - sampleOut = sineSample * gain; + sampleOut = squareSample * gain; // write to buffer out[2*i] = sampleOut; // left diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp new file mode 100644 index 0000000..b5afbc9 --- /dev/null +++ b/src/ui/MainWindow.cpp @@ -0,0 +1,118 @@ + +#include "MainWindow.h" + +#include +#include "ui_MainWindow.h" + +#include "../ParameterStore.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui_(new Ui::MainWindow), + audio_(new AudioEngine()), + keyboard_(audio_->noteQueue()) { + + ui_->setupUi(this); + setFocusPolicy(Qt::StrongFocus); + + // Initialize UI + updateCounterLabel(); + + // Connect buttons to slots + connect(ui_->buttonIncrement, &QPushButton::clicked, this, &MainWindow::onIncrementClicked); + connect(ui_->buttonReset, &QPushButton::clicked, this, &MainWindow::onResetClicked); + + // slider business + // TODO: smart slider widget + connect(ui_->slider, &QSlider::valueChanged, this, &MainWindow::onSliderValueChanged); + connect(ui_->inputMin, &QLineEdit::editingFinished, this, &MainWindow::onMinChanged); + connect(ui_->inputMax, &QLineEdit::editingFinished, this, &MainWindow::onMaxChanged); + connect(ui_->inputStep, &QLineEdit::editingFinished, this, &MainWindow::onStepChanged); + connect(ui_->inputValue, &QLineEdit::editingFinished, this, &MainWindow::onValueChanged); + + // synth business + audio_->start(); + + // init defaults + // TODO:: there's gotta be a better way + ui_->slider->setValue(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].def); + ui_->slider->setMinimum(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].min); + ui_->slider->setMaximum(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].max); + ui_->inputValue->setText(QString::number(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].def)); + ui_->inputMin->setText(QString::number(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].min)); + ui_->inputMax->setText(QString::number(PARAM_DEFS[static_cast(ParamId::Osc1Frequency)].max)); +} + +MainWindow::~MainWindow() { + delete ui_; +} + +void MainWindow::keyPressEvent(QKeyEvent* event) { + keyboard_.handleKeyPress(event); +} + +void MainWindow::keyReleaseEvent(QKeyEvent* event) { + keyboard_.handleKeyRelease(event); +} + +void MainWindow::onIncrementClicked() { + counter_++; + updateCounterLabel(); +} + +void MainWindow::onResetClicked() { + counter_ = 0; + updateCounterLabel(); +} + +void MainWindow::updateCounterLabel() { + ui_->labelCounter->setText(QString::number(counter_)); +} + +// allows only numbers to be set +void MainWindow::onSliderValueChanged(int value) { + QSignalBlocker blocker(ui_->inputValue); + ui_->inputValue->setText(QString::number(value)); + + // forward value so synthesizer can read + audio_->parameters()->set(ParamId::Osc1Frequency, static_cast(value)); +} + +// allows only values within the min, max to be set by the text field +void MainWindow::onValueChanged() { + bool ok = false; + int value = ui_->inputValue->text().toInt(&ok); + if(!ok) return; + + value = qBound(ui_->slider->minimum(), value, ui_->slider->maximum()); + ui_->slider->setValue(value); +} + +void MainWindow::applySliderRange() { + bool minOk, maxOk; + int min = ui_->inputMin->text().toInt(&minOk); + int max = ui_->inputMax->text().toInt(&maxOk); + if(!minOk || !maxOk || min > max) return; + + ui_->slider->setRange(min, max); + + syncValueToUi(ui_->slider->value()); +} + +void MainWindow::applySliderStep() { + bool ok; + int step = ui_->inputStep->text().toInt(&ok); + if(!ok || step <= 0) return; + + ui_->slider->setSingleStep(step); + ui_->slider->setPageStep(step); +} + +void MainWindow::syncValueToUi(int value) { + QSignalBlocker block1(ui_->slider); + QSignalBlocker block2(ui_->inputValue); + + value = qBound(ui_->slider->minimum(), value, ui_->slider->maximum()); + ui_->slider->setValue(value); + ui_->inputValue->setText(QString::number(value)); +} diff --git a/src/MainWindow.h b/src/ui/MainWindow.h similarity index 93% rename from src/MainWindow.h rename to src/ui/MainWindow.h index e1450b3..78ee455 100644 --- a/src/MainWindow.h +++ b/src/ui/MainWindow.h @@ -4,7 +4,7 @@ #include #include -#include "synth/AudioEngine.h" +#include "../synth/AudioEngine.h" QT_BEGIN_NAMESPACE namespace Ui { @@ -35,7 +35,7 @@ private slots: void onValueChanged(); private: - Ui::MainWindow *ui; + Ui::MainWindow *ui_; int counter_ = 0; int value = 0; diff --git a/src/MainWindow.ui b/src/ui/MainWindow.ui similarity index 100% rename from src/MainWindow.ui rename to src/ui/MainWindow.ui diff --git a/src/ui/SmartSlider.ui b/src/ui/SmartSlider.ui new file mode 100644 index 0000000..e69de29 diff --git a/src/widgets/SmartSlider.cpp b/src/widgets/SmartSlider.cpp new file mode 100644 index 0000000..1af64eb --- /dev/null +++ b/src/widgets/SmartSlider.cpp @@ -0,0 +1,35 @@ + +#include "SmartSlider.h" + +SmartSlider(QWidget* parent = nullptr) { + +} + +void SmartSlider::setRange(float min, float max) { + +} + +void SmartSlider::setStep(float step) { + +} + +void SmartSlider::setValue(float value) { + +} + +void SmartSlider::value() const; +void SmartSlider::valueChanged(float value) { + +} + +void SmartSlider::onSliderChanged(int v) { + +} + +void SmartSlider::onSpinValueChanged(float v) { + +} + +void SmartSlider::onRangeChanged() { + +} diff --git a/src/widgets/SmartSlider.h b/src/widgets/SmartSlider.h new file mode 100644 index 0000000..cb025a8 --- /dev/null +++ b/src/widgets/SmartSlider.h @@ -0,0 +1,37 @@ + +#pragma once + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class SmartSlider; } +QT_END_NAMESPACE + +class SmartSlider : public QWidget { + Q_OBJECT + +public: + explicit SmartSlider(QWidget* parent = nullptr); + ~SmartSlider() = default; + + void setRange(float min, float max); + void setStep(float step); + void setValue(float value); + + void value() const; + +signals: + void valueChanged(float value); + +private slots: + void onSliderChanged(int v); + void onSpinValueChanged(float v); + void onRangeChanged(); + +private: + + Ui::SmartSlider* ui_; + + int sliderResolution_ = 10000; + +}; \ No newline at end of file