diff --git a/config/profiles/default.yaml b/config/profiles/default.yaml index 7d14c22..471e384 100644 --- a/config/profiles/default.yaml +++ b/config/profiles/default.yaml @@ -11,11 +11,11 @@ Osc1Freq: [100, 20, 600] # wavetable selections OscWaveSelector1: 2 -OscWaveSelector2: 1 +OscWaveSelector2: 3 # Frequency parameters -MasterOctaveOffset: [1, -5, 5] -MasterSemitoneOffset: [1, -12, 12] +MasterOctaveOffset: [0, -5, 5] +MasterSemitoneOffset: [0, -12, 12] MasterPitchOffset: [0, -100, 100] Osc1OctaveOffset: [0, -5, 5] Osc1SemitoneOffset: [0, -12, 12] diff --git a/src/ConfigInterface.cpp b/src/ConfigInterface.cpp index 956803a..dc962b8 100644 --- a/src/ConfigInterface.cpp +++ b/src/ConfigInterface.cpp @@ -47,7 +47,7 @@ int ConfigInterface::getValue(ConfigFile file, std::string key, int defaultVal) } // ugly but if it works it works -void ConfigInterface::loadProfile(std::string filename) { +YAML::Node ConfigInterface::loadProfile(std::string filename) { // load file std::string filepath = "config/profiles/" + filename + ".yaml"; @@ -57,14 +57,14 @@ void ConfigInterface::loadProfile(std::string filename) { config = YAML::LoadFile(filepath); } catch(const std::exception& e) { std::cerr << e.what() << std::endl; - return; + return config; } // check version int version = config["version"].as(); // yaml-cpp parses unquoted hex as integers if(version < CONFIG_VERSION) { std::cout << "Parameter profile version " << version << "is outdated below the compatible version " << CONFIG_VERSION << std::endl; - return; + return config; } else { std::cout << "Parameter profile version " << version << std::endl; } @@ -120,6 +120,8 @@ void ConfigInterface::loadProfile(std::string filename) { // load wavetable settings // load oscillator pitch settings + return config; + } std::array ConfigInterface::loadEnvProfile(YAML::Node* node, std::string profile) { diff --git a/src/ConfigInterface.h b/src/ConfigInterface.h index 084c7ad..bbf3280 100644 --- a/src/ConfigInterface.h +++ b/src/ConfigInterface.h @@ -32,7 +32,7 @@ public: int getValue(ConfigFile file, std::string key, int defaultVal); - void loadProfile(std::string filename); + YAML::Node loadProfile(std::string filename); std::array loadEnvProfile(YAML::Node* node, std::string profile); std::array loadEnvProfile(std::string filename, std::string profile); diff --git a/src/KeyboardController.cpp b/src/KeyboardController.cpp index 4dc24ea..4c9126a 100644 --- a/src/KeyboardController.cpp +++ b/src/KeyboardController.cpp @@ -24,12 +24,10 @@ KeyboardController::KeyboardController(NoteQueue& queue, ConfigInterface* config // for each element in the keymap for (const auto& entry : keymapNode) { - + std::string keyString = entry.first.as(); std::string noteString = entry.second.as(); - std::cout << keyString << ": " << noteString << std::endl; - // match the strings to ints uint8_t noteValue = notesNode[noteString].as(); uint32_t keyValue = keysNode[keyString].as(); diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp index c29389c..b5970f9 100644 --- a/src/ui/MainWindow.cpp +++ b/src/ui/MainWindow.cpp @@ -49,6 +49,67 @@ MainWindow::MainWindow(QWidget *parent) : audio_->parameters()->set(ParamId::Osc1WaveSelector2, index); }); + // rogue sliders, TODO: clean these up in a package + connect(ui_->sliderMasterOctave, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::MasterOctaveOffset, value); + ui_->sliderMasterOctave->setResolution(); + }); + connect(ui_->sliderMasterSemitone, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::MasterSemitoneOffset, value); + ui_->sliderMasterSemitone->setResolution(); + }); + connect(ui_->sliderMasterPitch, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::MasterPitchOffset, value); + }); + + connect(ui_->sliderOsc1Octave, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc1OctaveOffset, value); + ui_->sliderOsc1Octave->setResolution(); + }); + connect(ui_->sliderOsc1Semitone, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc1SemitoneOffset, value); + ui_->sliderOsc1Semitone->setResolution(); + }); + connect(ui_->sliderOsc1Pitch, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc1PitchOffset, value); + }); + + connect(ui_->sliderOsc2Octave, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc2OctaveOffset, value); + ui_->sliderOsc2Octave->setResolution(); + }); + connect(ui_->sliderOsc2Semitone, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc2SemitoneOffset, value); + ui_->sliderOsc2Semitone->setResolution(); + }); + connect(ui_->sliderOsc2Pitch, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc2PitchOffset, value); + }); + + connect(ui_->sliderOsc3Octave, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc3OctaveOffset, value); + ui_->sliderOsc3Octave->setResolution(); + }); + connect(ui_->sliderOsc3Semitone, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc3SemitoneOffset, value); + ui_->sliderOsc3Semitone->setResolution(); + }); + connect(ui_->sliderOsc3Pitch, &SmartSlider::valueChanged, + this, [this](float value) { + audio_->parameters()->set(ParamId::Osc3PitchOffset, value); + }); + // synth business audio_->start(); @@ -75,14 +136,59 @@ void MainWindow::onResetClicked() { // initialize to defaults - config_.loadProfile("default"); + YAML::Node configRoot = config_.loadProfile("default"); // update ui from the paramstore ui_->envelopeOsc1Volume->init(EnvelopeId::Osc1Volume, config_.loadEnvProfile("default", "Osc1Volume")); ui_->envelopeFilterCutoff->init(EnvelopeId::FilterCutoff, config_.loadEnvProfile("default", "FilterCutoff")); ui_->envelopeFilterResonance->init(EnvelopeId::FilterResonance, config_.loadEnvProfile("default", "FilterResonance")); - ui_->comboOsc1WaveSelector1->setCurrentIndex(static_cast(PARAM_DEFS[static_cast(ParamId::Osc1WaveSelector1)].def)); - ui_->comboOsc1WaveSelector2->setCurrentIndex(static_cast(PARAM_DEFS[static_cast(ParamId::Osc1WaveSelector2)].def)); + // TODO: clean these up, maybe put them in a package like the envelope generators (it'll help encapsulate the int-snapping business) + ui_->sliderMasterOctave->setResolution(configRoot["MasterOctaveOffset"][2].as() - configRoot["MasterOctaveOffset"][1].as()); + ui_->sliderMasterOctave->setRange(configRoot["MasterOctaveOffset"][1].as(), configRoot["MasterOctaveOffset"][2].as()); + ui_->sliderMasterOctave->setValue(configRoot["MasterOctaveOffset"][0].as()); + + ui_->sliderMasterSemitone->setResolution(configRoot["MasterSemitoneOffset"][2].as() - configRoot["MasterSemitoneOffset"][1].as()); + ui_->sliderMasterSemitone->setRange(configRoot["MasterSemitoneOffset"][1].as(), configRoot["MasterSemitoneOffset"][2].as()); + ui_->sliderMasterSemitone->setValue(configRoot["MasterSemitoneOffset"][0].as()); + + ui_->sliderMasterPitch->setRange(configRoot["MasterPitchOffset"][1].as(), configRoot["MasterPitchOffset"][2].as()); + ui_->sliderMasterPitch->setValue(configRoot["MasterPitchOffset"][0].as()); + + ui_->sliderOsc1Octave->setResolution(configRoot["Osc1OctaveOffset"][2].as() - configRoot["Osc1OctaveOffset"][1].as()); + ui_->sliderOsc1Octave->setRange(configRoot["Osc1OctaveOffset"][1].as(), configRoot["Osc1OctaveOffset"][2].as()); + ui_->sliderOsc1Octave->setValue(configRoot["Osc1OctaveOffset"][0].as()); + + ui_->sliderOsc1Semitone->setResolution(configRoot["Osc1SemitoneOffset"][2].as() - configRoot["Osc1SemitoneOffset"][1].as()); + ui_->sliderOsc1Semitone->setRange(configRoot["Osc1SemitoneOffset"][1].as(), configRoot["Osc1SemitoneOffset"][2].as()); + ui_->sliderOsc1Semitone->setValue(configRoot["Osc1SemitoneOffset"][0].as()); + + ui_->sliderOsc1Pitch->setRange(configRoot["Osc1PitchOffset"][1].as(), configRoot["Osc1PitchOffset"][2].as()); + ui_->sliderOsc1Pitch->setValue(configRoot["Osc1PitchOffset"][0].as()); + + ui_->sliderOsc2Octave->setResolution(configRoot["Osc2OctaveOffset"][2].as() - configRoot["Osc2OctaveOffset"][1].as()); + ui_->sliderOsc2Octave->setRange(configRoot["Osc2OctaveOffset"][1].as(), configRoot["Osc2OctaveOffset"][2].as()); + ui_->sliderOsc2Octave->setValue(configRoot["Osc2OctaveOffset"][0].as()); + + ui_->sliderOsc2Semitone->setResolution(configRoot["Osc2SemitoneOffset"][2].as() - configRoot["Osc2SemitoneOffset"][1].as()); + ui_->sliderOsc2Semitone->setRange(configRoot["Osc2SemitoneOffset"][1].as(), configRoot["Osc2SemitoneOffset"][2].as()); + ui_->sliderOsc2Semitone->setValue(configRoot["Osc2SemitoneOffset"][0].as()); + + ui_->sliderOsc2Pitch->setRange(configRoot["Osc2PitchOffset"][1].as(), configRoot["Osc2PitchOffset"][2].as()); + ui_->sliderOsc2Pitch->setValue(configRoot["Osc2PitchOffset"][0].as()); + + ui_->sliderOsc3Octave->setResolution(configRoot["Osc3OctaveOffset"][2].as() - configRoot["Osc3OctaveOffset"][1].as()); + ui_->sliderOsc3Octave->setRange(configRoot["Osc3OctaveOffset"][1].as(), configRoot["Osc3OctaveOffset"][2].as()); + ui_->sliderOsc3Octave->setValue(configRoot["Osc3OctaveOffset"][0].as()); + + ui_->sliderOsc3Semitone->setResolution(configRoot["Osc3SemitoneOffset"][2].as() - configRoot["Osc3SemitoneOffset"][1].as()); + ui_->sliderOsc3Semitone->setRange(configRoot["Osc3SemitoneOffset"][1].as(), configRoot["Osc3SemitoneOffset"][2].as()); + ui_->sliderOsc3Semitone->setValue(configRoot["Osc3SemitoneOffset"][0].as()); + + ui_->sliderOsc3Pitch->setRange(configRoot["Osc3PitchOffset"][1].as(), configRoot["Osc3PitchOffset"][2].as()); + ui_->sliderOsc3Pitch->setValue(configRoot["Osc3PitchOffset"][0].as()); + + ui_->comboOsc1WaveSelector1->setCurrentIndex(configRoot["OscWaveSelector1"].as()); + ui_->comboOsc1WaveSelector2->setCurrentIndex(configRoot["OscWaveSelector2"].as()); } diff --git a/src/ui/MainWindow.ui b/src/ui/MainWindow.ui index b6f703b..2e344f4 100644 --- a/src/ui/MainWindow.ui +++ b/src/ui/MainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 1102 - 564 + 1100 + 900 @@ -261,6 +261,602 @@ Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + 340 + 880 + 211 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 410 + 610 + 65 + 280 + + + + true + + + + + + 490 + 580 + 41 + 31 + + + + + 12 + + + + Pitch + + + Qt::AlignmentFlag::AlignCenter + + + + + + 340 + 610 + 65 + 280 + + + + true + + + + + + 410 + 580 + 71 + 31 + + + + + 12 + + + + Semitone + + + Qt::AlignmentFlag::AlignCenter + + + + + + 340 + 600 + 211 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 480 + 610 + 65 + 280 + + + + true + + + + + + 340 + 580 + 71 + 31 + + + + + 12 + + + + Octave + + + Qt::AlignmentFlag::AlignCenter + + + + + + 630 + 580 + 71 + 31 + + + + + 12 + + + + Semitone + + + Qt::AlignmentFlag::AlignCenter + + + + + + 560 + 600 + 211 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 560 + 580 + 71 + 31 + + + + + 12 + + + + Octave + + + Qt::AlignmentFlag::AlignCenter + + + + + + 560 + 880 + 211 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 630 + 610 + 65 + 280 + + + + true + + + + + + 710 + 580 + 41 + 31 + + + + + 12 + + + + Pitch + + + Qt::AlignmentFlag::AlignCenter + + + + + + 560 + 610 + 65 + 280 + + + + true + + + + + + 700 + 610 + 65 + 280 + + + + true + + + + + + 850 + 610 + 65 + 280 + + + + true + + + + + + 920 + 610 + 65 + 280 + + + + true + + + + + + 780 + 580 + 71 + 31 + + + + + 12 + + + + Octave + + + Qt::AlignmentFlag::AlignCenter + + + + + + 780 + 610 + 65 + 280 + + + + true + + + + + + 930 + 580 + 41 + 31 + + + + + 12 + + + + Pitch + + + Qt::AlignmentFlag::AlignCenter + + + + + + 780 + 600 + 211 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 780 + 880 + 211 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 850 + 580 + 71 + 31 + + + + + 12 + + + + Semitone + + + Qt::AlignmentFlag::AlignCenter + + + + + + 390 + 567 + 111 + 20 + + + + + 12 + + + + Oscillator 1 + + + Qt::AlignmentFlag::AlignCenter + + + + + + 611 + 567 + 111 + 20 + + + + + 12 + + + + Oscillator 2 + + + Qt::AlignmentFlag::AlignCenter + + + + + + 830 + 569 + 111 + 20 + + + + + 12 + + + + Oscillator 3 + + + Qt::AlignmentFlag::AlignCenter + + + + + + 120 + 880 + 211 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 170 + 567 + 111 + 20 + + + + + 12 + + + + Master + + + Qt::AlignmentFlag::AlignCenter + + + + + + 270 + 580 + 41 + 31 + + + + + 12 + + + + Pitch + + + Qt::AlignmentFlag::AlignCenter + + + + + + 120 + 610 + 65 + 280 + + + + true + + + + + + 260 + 610 + 65 + 280 + + + + true + + + + + + 120 + 600 + 211 + 20 + + + + Qt::Orientation::Horizontal + + + + + + 190 + 580 + 71 + 31 + + + + + 12 + + + + Semitone + + + Qt::AlignmentFlag::AlignCenter + + + + + + 190 + 610 + 65 + 280 + + + + true + + + + + + 120 + 580 + 71 + 31 + + + + + 12 + + + + Octave + + + Qt::AlignmentFlag::AlignCenter + + @@ -276,6 +872,12 @@
Scope/Scope.h
1 + + SmartSlider + QWidget +
SmartSlider/SmartSlider.h
+ 1 +
diff --git a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp index 09e0f2d..2935cb9 100644 --- a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp +++ b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.cpp @@ -75,24 +75,6 @@ void EnvelopeGenerator::emitEnvelope() { ); } -void EnvelopeGenerator::init(EnvelopeId id) { - - EnvelopeParam params = ENV_PARAMS[static_cast(id)]; - - ui_->sliderDepth->setRange(PARAM_DEFS[static_cast(params.depth)].min, PARAM_DEFS[static_cast(params.depth)].max); - ui_->sliderAttack->setRange(PARAM_DEFS[static_cast(params.a)].min, PARAM_DEFS[static_cast(params.a)].max); - ui_->sliderDecay->setRange(PARAM_DEFS[static_cast(params.d)].min, PARAM_DEFS[static_cast(params.d)].max); - ui_->sliderSustain->setRange(PARAM_DEFS[static_cast(params.s)].min, PARAM_DEFS[static_cast(params.s)].max); - ui_->sliderRelease->setRange(PARAM_DEFS[static_cast(params.r)].min, PARAM_DEFS[static_cast(params.r)].max); - - setDepth(PARAM_DEFS[static_cast(params.depth)].def); - setAttack(PARAM_DEFS[static_cast(params.a)].def); - setDecay(PARAM_DEFS[static_cast(params.d)].def); - setSustain(PARAM_DEFS[static_cast(params.s)].def); - setRelease(PARAM_DEFS[static_cast(params.r)].def); - -} - void EnvelopeGenerator::init(EnvelopeId id, std::array profile) { EnvelopeParam params = ENV_PARAMS[static_cast(id)]; diff --git a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h index 935a76c..1f9af26 100644 --- a/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h +++ b/src/ui/widgets/EnvelopeGenerator/EnvelopeGenerator.h @@ -16,8 +16,7 @@ public: explicit EnvelopeGenerator(QWidget* parent = nullptr); ~EnvelopeGenerator(); - // connects signals, sets parameters to the defaults defined in paramStore - void init(EnvelopeId id); + // connects signals, sets parameters to a provided profile void init(EnvelopeId id, std::array profile); // setters diff --git a/src/ui/widgets/SmartSlider/SmartSlider.cpp b/src/ui/widgets/SmartSlider/SmartSlider.cpp index db20c5b..de9d436 100644 --- a/src/ui/widgets/SmartSlider/SmartSlider.cpp +++ b/src/ui/widgets/SmartSlider/SmartSlider.cpp @@ -42,6 +42,7 @@ void SmartSlider::setRange(float min, float max) { ui_->slider->setValue(sliderValue); ui_->spinValue->setValue(value); + } // sets value of the slider and the spinBox, called by other classes @@ -57,6 +58,10 @@ void SmartSlider::setValue(float value) { emit valueChanged(value); } +void SmartSlider::setResolution(int resolution) { + sliderResolution_ = resolution; +} + float SmartSlider::value() { return ui_->spinValue->value(); } diff --git a/src/ui/widgets/SmartSlider/SmartSlider.h b/src/ui/widgets/SmartSlider/SmartSlider.h index 5ef8f38..fe8877b 100644 --- a/src/ui/widgets/SmartSlider/SmartSlider.h +++ b/src/ui/widgets/SmartSlider/SmartSlider.h @@ -9,6 +9,7 @@ QT_END_NAMESPACE // SmartSlider is the widget including a slider, min/max settings, and a value setting parameter class SmartSlider : public QWidget { + Q_OBJECT public: @@ -18,6 +19,8 @@ public: // setters void setRange(float min, float max); void setValue(float value); + void setResolution(int resolution); + void setResolution() { setResolution(static_cast(max_ - min_)); } // getters float value(); diff --git a/src/ui/widgets/SmartSlider/SmartSlider.ui b/src/ui/widgets/SmartSlider/SmartSlider.ui index 1484e8b..ec6ceef 100644 --- a/src/ui/widgets/SmartSlider/SmartSlider.ui +++ b/src/ui/widgets/SmartSlider/SmartSlider.ui @@ -19,6 +19,9 @@ Form + + false + @@ -62,6 +65,12 @@ QAbstractSpinBox::ButtonSymbols::NoButtons + + -100000.000000000000000 + + + 100000.000000000000000 + @@ -84,8 +93,11 @@ QAbstractSpinBox::ButtonSymbols::NoButtons + + -100000.000000000000000 + - 40000.000000000000000 + 100000.000000000000000 @@ -117,8 +129,11 @@ QAbstractSpinBox::ButtonSymbols::NoButtons + + -100000.000000000000000 + - 80000.000000000000000 + 100000.000000000000000