gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

commit 9c125b764c876de70b09d9cc04d68171e5a35eac
parent faf1e32fcc4567bff6eed09a737f064a4cfe6020
Author: 790 <790@users.noreply.github.com>
Date:   Wed,  5 Jan 2022 20:00:04 +0000

wire up some ui

Diffstat:
Msource/jucePlugin/CMakeLists.txt | 1+
Msource/jucePlugin/VirusController.cpp | 27++++++++++++++++++++++++++-
Msource/jucePlugin/VirusController.h | 6++++++
Msource/jucePlugin/VirusParameterBinding.cpp | 40+++++++++++++++++++++++++++++++++++++++-
Msource/jucePlugin/VirusParameterBinding.h | 8++++++--
Asource/jucePlugin/assets/buttons/part_select_btn_39x72.png | 0
Msource/jucePlugin/ui/VirusEditor.cpp | 52++++++++++++++++++++++++++++++++++++++++++++++++++--
Msource/jucePlugin/ui/VirusEditor.h | 7+++++++
Msource/jucePlugin/ui/Virus_Buttons.cpp | 11+++++++++++
Msource/jucePlugin/ui/Virus_Buttons.h | 8++++++++
Msource/jucePlugin/ui/Virus_LfoEditor.cpp | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msource/jucePlugin/ui/Virus_LfoEditor.h | 4++--
Msource/jucePlugin/ui/Virus_OscEditor.cpp | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msource/jucePlugin/ui/Virus_OscEditor.h | 8++++----
14 files changed, 294 insertions(+), 21 deletions(-)

diff --git a/source/jucePlugin/CMakeLists.txt b/source/jucePlugin/CMakeLists.txt @@ -77,6 +77,7 @@ juce_add_binary_data(jucePlugin_BinaryData "assets/buttons/presets_btn_43_15.png" "assets/buttons/Handle_18x47.png" "assets/buttons/sync2_54x25.png" + "assets/buttons/part_select_btn_39x72.png" "assets/knobs/Gen_70x70_100.png" "assets/knobs/Gen_pol_70x70_100.png" "assets/knobs/GenBlue_70x70_100.png" diff --git a/source/jucePlugin/VirusController.cpp b/source/jucePlugin/VirusController.cpp @@ -181,6 +181,18 @@ namespace Virus return findSynthParam(index); } + Parameter *Controller::getParameter(const ParameterType _param, const uint8_t _part) + { + const auto it = m_paramTypeToParamIndex.find(_param); + if (it == m_paramTypeToParamIndex.end()) + return nullptr; + + const auto &index = it->second; + + ParamIndex paramIndex{index.page, _part, index.paramNum}; + return findSynthParam(paramIndex); + } + void Controller::parseParamChange(const SysEx &msg) { const auto pos = kHeaderWithMsgCodeLen - 1; @@ -510,6 +522,19 @@ namespace Virus } } + juce::String numToFilter2Mode(float idx, Parameter::Description) + { + const auto ridx = juce::roundToInt(idx); + switch (ridx) + { + case 0: return "LowPass"; + case 1: return "HighPass"; + case 2: return "BandPass"; + case 3: return "BandStop"; + default: return juce::String(idx); + } + } + juce::String numToFilterRouting(float idx, Parameter::Description) { const auto ridx = juce::roundToInt(idx); @@ -1343,7 +1368,7 @@ namespace Virus {Parameter::Page::A, Parameter::Class::SOUNDBANK_A, 48, "Filter Balance", {0,127}, paramTo7bitSigned, textTo7bitSigned, true, false, false}, {Parameter::Page::A, Parameter::Class::SOUNDBANK_A, 49, "Saturation Curve", {0,14}, numToSatCurv, {}, true, true, false}, {Parameter::Page::A, Parameter::Class::SOUNDBANK_A, 51, "Filter1 Mode", {0,7}, numToFilterMode, {}, true, true, false}, - {Parameter::Page::A, Parameter::Class::SOUNDBANK_A, 52, "Filter2 Mode", {0,7}, numToFilterMode, {}, true, true, false}, + {Parameter::Page::A, Parameter::Class::SOUNDBANK_A, 52, "Filter2 Mode", {0,3}, numToFilter2Mode, {}, true, true, false}, {Parameter::Page::A, Parameter::Class::SOUNDBANK_A, 53, "Filter Routing", {0,3}, numToFilterRouting, {}, true, true, false}, {Parameter::Page::A, Parameter::Class::SOUNDBANK_A, 54, "Filter Env Attack", {0,127}, {},{}, true, false, false}, {Parameter::Page::A, Parameter::Class::SOUNDBANK_A, 55, "Filter Env Decay", {0,127}, {},{}, true, false, false}, diff --git a/source/jucePlugin/VirusController.h b/source/jucePlugin/VirusController.h @@ -381,6 +381,11 @@ namespace Virus Param_Count }; + enum EnvelopeType + { + Env_Amp, + Env_Filter + }; using SysEx = std::vector<uint8_t>; class Controller : private juce::Timer { @@ -402,6 +407,7 @@ namespace Virus juce::Value *getParamValue(uint8_t ch, uint8_t bank, uint8_t paramIndex); juce::Value *getParamValue(ParameterType _param); Parameter* getParameter(ParameterType _param); + Parameter *getParameter(ParameterType _param, uint8_t _part); // bank - 0-1 (AB) juce::StringArray getSinglePresetNames(virusLib::BankNumber bank) const; diff --git a/source/jucePlugin/VirusParameterBinding.cpp b/source/jucePlugin/VirusParameterBinding.cpp @@ -4,7 +4,7 @@ void VirusParameterBinding::bind(juce::Slider& _slider, Virus::ParameterType _param) const { - const auto v = m_processor.getController().getParameter(_param); + const auto v = m_processor.getController().getParameter(_param, m_part); if (!v) { assert(false && "Failed to find parameter"); @@ -15,3 +15,41 @@ void VirusParameterBinding::bind(juce::Slider& _slider, Virus::ParameterType _pa _slider.setDoubleClickReturnValue(true, v->getDefaultValue()); _slider.getValueObject().referTo(v->getValueObject()); } + +void VirusParameterBinding::bind(juce::ComboBox& _combo, Virus::ParameterType _param) const +{ + const auto v = m_processor.getController().getParameter(_param, m_part); + if (!v) + { + assert(false && "Failed to find parameter"); + return; + } + _combo.setTextWhenNothingSelected("--"); + _combo.addItemList(v->getAllValueStrings(), 1); + _combo.setSelectedItemIndex(v->getValueObject().getValueSource().getValue()); + _combo.onChange = [this, &_combo, v]() { + v->setValue(_combo.getSelectedItemIndex()); + }; +} + +void VirusParameterBinding::bind(juce::DrawableButton &_btn, Virus::ParameterType _param) const +{ + const auto v = m_processor.getController().getParameter(_param, m_part); + if (!v) + { + assert(false && "Failed to find parameter"); + return; + } + _btn.getToggleStateValue().referTo(v->getValueObject()); +} + +void VirusParameterBinding::bind(juce::Component &_btn, Virus::ParameterType _param) const +{ + const auto v = m_processor.getController().getParameter(_param, m_part); + if (!v) + { + assert(false && "Failed to find parameter"); + return; + } + +} diff --git a/source/jucePlugin/VirusParameterBinding.h b/source/jucePlugin/VirusParameterBinding.h @@ -10,11 +10,15 @@ class AudioPluginAudioProcessor; class VirusParameterBinding { public: - VirusParameterBinding(AudioPluginAudioProcessor& _processor) : m_processor(_processor) + VirusParameterBinding(AudioPluginAudioProcessor& _processor, uint8_t _part = 0) : m_processor(_processor) { + m_part = _part; } void bind(juce::Slider& _control, Virus::ParameterType _param) const; - + void bind(juce::ComboBox &_control, Virus::ParameterType _param) const; + void bind(juce::DrawableButton &_control, Virus::ParameterType _param) const; + void bind(juce::Component &_control, Virus::ParameterType _param) const; AudioPluginAudioProcessor& m_processor; + uint8_t m_part; }; diff --git a/source/jucePlugin/assets/buttons/part_select_btn_39x72.png b/source/jucePlugin/assets/buttons/part_select_btn_39x72.png Binary files differ. diff --git a/source/jucePlugin/ui/VirusEditor.cpp b/source/jucePlugin/ui/VirusEditor.cpp @@ -5,6 +5,7 @@ #include "Virus_FxEditor.h" #include "Virus_LfoEditor.h" #include "Virus_OscEditor.h" +#include "../VirusParameterBinding.h" using namespace juce; @@ -35,9 +36,20 @@ VirusEditor::VirusEditor(VirusParameterBinding& _parameterBinding) : m_parameter m_lfoEditor->setVisible(m_mainButtons.m_lfoMatrix.getToggleState()); m_oscEditor->setVisible(m_mainButtons.m_oscFilter.getToggleState()); }; - + m_oscEditor->setVisible(true); + m_mainButtons.m_oscFilter.setToggleState(true, NotificationType::dontSendNotification); addAndMakeVisible(m_presetButtons); - + for (auto i = 0; i < 16; i++) + { + m_partSelect[i].setBounds(34, 161 + i*(36), 39, 36); + m_partSelect[i].setButtonText(juce::String(i)); + m_partSelect[i].setRadioGroupId(kPartGroupId); + m_partSelect[i].setClickingTogglesState(true); + m_partSelect[i].onClick = [this, i]() { + this->changePart(i); + }; + addAndMakeVisible(m_partSelect[i]); + } setSize (kPanelWidth, kPanelHeight); } @@ -60,6 +72,28 @@ void VirusEditor::resized() m_presetButtons.setBounds(statusArea.removeFromRight(188)); applyToSections([this](Component *s) { s->setTopLeftPosition(338, 133); }); } +void VirusEditor::changePart(uint8_t _part) { + + m_parameterBinding.m_part = _part; + removeChildComponent(m_oscEditor.get()); + m_oscEditor = std::make_unique<OscEditor>(m_parameterBinding); + addChildComponent(m_oscEditor.get()); + + removeChildComponent(m_lfoEditor.get()); + m_lfoEditor = std::make_unique<LfoEditor>(m_parameterBinding); + addChildComponent(m_lfoEditor.get()); + + removeChildComponent(m_fxEditor.get()); + m_fxEditor = std::make_unique<FxEditor>(m_parameterBinding); + addChildComponent(m_fxEditor.get()); + + removeChildComponent(m_arpEditor.get()); + m_arpEditor = std::make_unique<ArpEditor>(m_parameterBinding); + addChildComponent(m_arpEditor.get()); + + m_mainButtons.updateSection(); + resized(); +} VirusEditor::MainButtons::MainButtons() : m_oscFilter ("OSC|FILTER", DrawableButton::ImageRaw) @@ -75,6 +109,7 @@ VirusEditor::MainButtons::MainButtons() setSize ((kButtonWidth + kMargin) * numOfMainButtons, kButtonHeight); } + void VirusEditor::MainButtons::valueChanged(juce::Value &) { updateSection(); } void VirusEditor::MainButtons::setupButton (int i, std::unique_ptr<Drawable>&& btnImage, juce::DrawableButton& btn) @@ -99,3 +134,15 @@ VirusEditor::PresetButtons::PresetButtons() m_load.setBounds(36 + w, y, w, Buttons::PresetButton::kHeight); m_presets.setBounds(43 + w * 2, y, w, Buttons::PresetButton::kHeight); } + + + +VirusEditor::PartButtons::PartButtons() +{ + /* for (auto i = 0; i < 16; i++) + { + m_partSelect[i].setButtonText(juce::String(i)); + /m_partSelect[i].onClick = [this, i]() { changePart(i); }; + addAndMakeVisible(m_partSelect[i]); + }*/ +} +\ No newline at end of file diff --git a/source/jucePlugin/ui/VirusEditor.h b/source/jucePlugin/ui/VirusEditor.h @@ -16,8 +16,11 @@ public: VirusEditor(VirusParameterBinding& _parameterBinding); ~VirusEditor() override; void resized() override; + void changePart(uint8_t _part); private: + Buttons::PartSelectButton m_partSelect[16]; + static constexpr auto kPartGroupId = 0x3FBBA; struct MainButtons : juce::Component, juce::Value::Listener { MainButtons(); @@ -38,6 +41,10 @@ private: Buttons::PresetButton m_save, m_load, m_presets; } m_presetButtons; + struct PartButtons : juce::Component { + PartButtons(); + Buttons::PartSelectButton m_partSelect[16]; + }; void applyToSections(std::function<void(juce::Component *)>); VirusParameterBinding& m_parameterBinding; diff --git a/source/jucePlugin/ui/Virus_Buttons.cpp b/source/jucePlugin/ui/Virus_Buttons.cpp @@ -92,4 +92,15 @@ namespace Buttons setColour(DrawableButton::ColourIds::backgroundOnColourId, Colours::transparentBlack); setImages(normal.get(), nullptr, pressed.get(), nullptr, pressed.get(), nullptr, normal.get()); } + + Buttons::PartSelectButton::PartSelectButton() : DrawableButton("PartSelectButton", DrawableButton::ButtonStyle::ImageRaw) + { + auto normal = + Drawable::createFromImageData(BinaryData::part_select_btn_39x72_png, BinaryData::part_select_btn_39x72_pngSize); + auto pressed = normal->createCopy(); + pressed->setOriginWithOriginalSize({0, -36}); + setColour(DrawableButton::ColourIds::backgroundColourId, Colours::transparentBlack); + setColour(DrawableButton::ColourIds::backgroundOnColourId, Colours::transparentBlack); + setImages(normal.get(), nullptr, pressed.get(), nullptr, pressed.get(), nullptr, normal.get()); + } }; // namespace Buttons diff --git a/source/jucePlugin/ui/Virus_Buttons.h b/source/jucePlugin/ui/Virus_Buttons.h @@ -51,4 +51,12 @@ namespace Buttons static constexpr auto kHeight = 15; PresetButton(); }; + + class PartSelectButton : public juce::DrawableButton + { + public: + static constexpr auto kWidth = 39; + static constexpr auto kHeight = 36; + PartSelectButton(); + }; } // namespace Buttons diff --git a/source/jucePlugin/ui/Virus_LfoEditor.cpp b/source/jucePlugin/ui/Virus_LfoEditor.cpp @@ -1,6 +1,7 @@ #include "Virus_LfoEditor.h" #include "BinaryData.h" #include "Ui_Utils.h" +#include "../VirusParameterBinding.h" using namespace juce; constexpr auto comboBoxWidth = 98; @@ -22,7 +23,7 @@ LfoEditor::LfoEditor(VirusParameterBinding& _parameterBinding) : m_lfoOne(_param addAndMakeVisible(m_modMatrix); } -LfoEditor::LfoBase::LfoBase(VirusParameterBinding& _parameterBinding) +LfoEditor::LfoBase::LfoBase(VirusParameterBinding& _parameterBinding, uint8_t _lfoIndex) { for (auto *s : {&m_rate, &m_keytrack, &m_amount}) setupRotary(*this, *s); @@ -34,9 +35,24 @@ LfoEditor::LfoBase::LfoBase(VirusParameterBinding& _parameterBinding) addAndMakeVisible(m_clock); m_clock.setBounds(10, 80, 84, comboBoxHeight); addAndMakeVisible(m_assignDest); + const Virus::ParameterType rate[] = {Virus::Param_Lfo1Rate, Virus::Param_Lfo2Rate, Virus::Param_Lfo3Rate}; + const Virus::ParameterType keytrack[] = {Virus::Param_Lfo1Keyfollow, Virus::Param_Lfo2Keyfollow, + Virus::Param_Lfo3Keyfollow}; + const Virus::ParameterType amount[] = {Virus::Param_Lfo1AssignAmount, Virus::Param_Lfo2AssignAmount, + Virus::Param_OscLfo3Amount}; + const Virus::ParameterType shapes[] = {Virus::Param_Lfo1Shape, Virus::Param_Lfo2Shape, Virus::Param_Lfo3Shape}; + const Virus::ParameterType clock[] = {Virus::Param_Lfo1Clock, Virus::Param_Lfo2Clock, Virus::Param_Lfo3Clock}; + const Virus::ParameterType assignDest[] = {Virus::Param_Lfo1AssignDest, Virus::Param_Lfo2AssignDest, + Virus::Param_Lfo3Destination}; + _parameterBinding.bind(m_rate, rate[_lfoIndex]); + _parameterBinding.bind(m_keytrack, keytrack[_lfoIndex]); + _parameterBinding.bind(m_amount, amount[_lfoIndex]); + _parameterBinding.bind(m_shape, shapes[_lfoIndex]); + _parameterBinding.bind(m_clock, clock[_lfoIndex]); + _parameterBinding.bind(m_assignDest, assignDest[_lfoIndex]); } -LfoEditor::LfoTwoOneShared::LfoTwoOneShared(VirusParameterBinding& _parameterBinding) : LfoBase(_parameterBinding), m_link(false) +LfoEditor::LfoTwoOneShared::LfoTwoOneShared(VirusParameterBinding& _parameterBinding, uint8_t _lfoIndex) : LfoBase(_parameterBinding, _lfoIndex), m_link(false) { for (auto *s : {&m_contour, &m_phase}) setupRotary(*this, *s); @@ -50,9 +66,18 @@ LfoEditor::LfoTwoOneShared::LfoTwoOneShared(VirusParameterBinding& _parameterBin m_link.setBounds(293, 8, 36, 12); m_assignDest.setBounds(393, 122, comboBoxWidth, comboBoxHeight); + + //_parameterBinding.bind(m_rate, Virus::Param_Lfo1Rate); + //_parameterBinding.bind(m_keytrack, Virus::Param_Lfo1Keyfollow); + _parameterBinding.bind(m_contour, _lfoIndex == 0 ? Virus::Param_Lfo1Symmetry : Virus::Param_Lfo2Symmetry); + _parameterBinding.bind(m_phase, _lfoIndex == 0 ? Virus::Param_Lfo1KeyTrigger : Virus::Param_Lfo2Keytrigger); + //parameterBinding.bind(m_amount, Virus::Param_Lfo1AssignAmount); + _parameterBinding.bind(m_envMode, _lfoIndex == 0 ? Virus::Param_Lfo1EnvMode : Virus::Param_Lfo2EnvMode); + _parameterBinding.bind(m_link, _lfoIndex == 0 ? Virus::Param_Lfo1Mode : Virus::Param_Lfo2Mode); + //_parameterBinding.bind(m_assignDest, Virus::Param_Lfo1AssignDest); } -LfoEditor::LfoOne::LfoOne(VirusParameterBinding& _parameterBinding) : LfoTwoOneShared(_parameterBinding) +LfoEditor::LfoOne::LfoOne(VirusParameterBinding& _parameterBinding) : LfoTwoOneShared(_parameterBinding, 0) { for (auto *s : {&m_osc1Pitch, &m_osc2Pitch, &m_filterGain, &m_pw12, &m_reso12}) setupRotary(*this, *s); @@ -62,9 +87,15 @@ LfoEditor::LfoOne::LfoOne(VirusParameterBinding& _parameterBinding) : LfoTwoOneS m_pw12.setBounds(374, 14, knobSize, knobSize); m_reso12.setBounds(m_pw12.getBounds().translated(knobSize - 4, 0)); addAndMakeVisible(m_link); // add last to allow clicking over knobs area... + + _parameterBinding.bind(m_osc1Pitch, Virus::Param_Osc1Lfo1Amount); + _parameterBinding.bind(m_osc2Pitch, Virus::Param_Osc2Lfo1Amount); + _parameterBinding.bind(m_filterGain, Virus::Param_FltGainLfo1Amount); + _parameterBinding.bind(m_pw12, Virus::Param_PWLfo1Amount); + _parameterBinding.bind(m_reso12, Virus::Param_ResoLfo1Amount); } -LfoEditor::LfoTwo::LfoTwo(VirusParameterBinding& _parameterBinding) : LfoTwoOneShared(_parameterBinding) +LfoEditor::LfoTwo::LfoTwo(VirusParameterBinding& _parameterBinding) : LfoTwoOneShared(_parameterBinding, 1) { for (auto *s : {&m_f1cutoff, &m_f2cutoff, &m_panning, &m_shape12, &m_fmAmount}) setupRotary(*this, *s); @@ -74,9 +105,15 @@ LfoEditor::LfoTwo::LfoTwo(VirusParameterBinding& _parameterBinding) : LfoTwoOneS m_shape12.setBounds(374, 14, knobSize, knobSize); m_fmAmount.setBounds(m_shape12.getBounds().translated(knobSize - 4, 0)); addAndMakeVisible(m_link); // add last to allow clicking over knobs area... + + _parameterBinding.bind(m_f1cutoff, Virus::Param_Cutoff1Lfo2Amount); + _parameterBinding.bind(m_f2cutoff, Virus::Param_Cutoff2Lfo2Amount); + _parameterBinding.bind(m_panning, Virus::Param_PanoramaLfo2Amount); + _parameterBinding.bind(m_shape12, Virus::Param_OscShapeLfo2Amount); + _parameterBinding.bind(m_fmAmount, Virus::Param_FmAmountLfo2Amount); } -LfoEditor::LfoThree::LfoThree(VirusParameterBinding& _parameterBinding) : LfoBase(_parameterBinding) +LfoEditor::LfoThree::LfoThree(VirusParameterBinding& _parameterBinding) : LfoBase(_parameterBinding, 2) { setupRotary(*this, m_fadeIn); m_rate.setBounds(107, 22, knobSize, knobSize); @@ -84,6 +121,8 @@ LfoEditor::LfoThree::LfoThree(VirusParameterBinding& _parameterBinding) : LfoBas m_keytrack.setBounds(m_rate.getBounds().translated(0, knobSize + 6)); m_amount.setBounds(307, 22, knobSize, knobSize); m_assignDest.setBounds(393, 45, comboBoxWidth, comboBoxHeight); + + _parameterBinding.bind(m_fadeIn, Virus::Param_Lfo3FadeInTime); } LfoEditor::ModMatrix::ModMatrix(VirusParameterBinding& _parameterBinding) @@ -97,6 +136,33 @@ LfoEditor::ModMatrix::ModMatrix(VirusParameterBinding& _parameterBinding) setupSlot(3, {{255, 214}}, {320, 190}); setupSlot(4, {{255, 338}}, {320, 314}); setupSlot(5, {{255, 462}}, {320, 439}); + + _parameterBinding.bind(m_modMatrix[0]->m_source, Virus::Param_Assign1Source); + _parameterBinding.bind(m_modMatrix[1]->m_source, Virus::Param_Assign2Source); + _parameterBinding.bind(m_modMatrix[2]->m_source, Virus::Param_Assign3Source); + _parameterBinding.bind(m_modMatrix[3]->m_source, Virus::Param_Assign4Source); + _parameterBinding.bind(m_modMatrix[4]->m_source, Virus::Param_Assign5Source); + _parameterBinding.bind(m_modMatrix[5]->m_source, Virus::Param_Assign6Source); + + _parameterBinding.bind(m_modMatrix[0]->m_destinations[0]->m_amount, Virus::Param_Assign1Amount); + _parameterBinding.bind(m_modMatrix[1]->m_destinations[0]->m_amount, Virus::Param_Assign2Amount1); + //_parameterBinding.bind(m_modMatrix[1]->m_destinations[1]->m_amount, Virus::Param_Assign2Amount2); + //_parameterBinding.bind(m_modMatrix[1]->m_destinations[2]->m_amount, Virus::Param_Assign2Amount3); + _parameterBinding.bind(m_modMatrix[2]->m_destinations[0]->m_amount, Virus::Param_Assign3Amount1); + //_parameterBinding.bind(m_modMatrix[2]->m_destinations[1]->m_amount, Virus::Param_Assign3Amount2); + _parameterBinding.bind(m_modMatrix[3]->m_destinations[0]->m_amount, Virus::Param_Assign4Amount); + _parameterBinding.bind(m_modMatrix[4]->m_destinations[0]->m_amount, Virus::Param_Assign5Amount); + _parameterBinding.bind(m_modMatrix[5]->m_destinations[0]->m_amount, Virus::Param_Assign6Amount); + + _parameterBinding.bind(m_modMatrix[0]->m_destinations[0]->m_dest, Virus::Param_Assign1Destination); + _parameterBinding.bind(m_modMatrix[1]->m_destinations[0]->m_dest, Virus::Param_Assign2Destination1); + //_parameterBinding.bind(m_modMatrix[1]->m_destinations[1]->m_dest, Virus::Param_Assign2Destination2); + //_parameterBinding.bind(m_modMatrix[1]->m_destinations[2]->m_dest, Virus::Param_Assign2Destination3); + _parameterBinding.bind(m_modMatrix[2]->m_destinations[0]->m_dest, Virus::Param_Assign3Destination1); + //_parameterBinding.bind(m_modMatrix[2]->m_destinations[1]->m_dest, Virus::Param_Assign3Destination2); + _parameterBinding.bind(m_modMatrix[3]->m_destinations[0]->m_dest, Virus::Param_Assign4Destination); + _parameterBinding.bind(m_modMatrix[4]->m_destinations[0]->m_dest, Virus::Param_Assign5Destination); + _parameterBinding.bind(m_modMatrix[5]->m_destinations[0]->m_dest, Virus::Param_Assign6Destination); } void LfoEditor::ModMatrix::setupSlot(int slotNum, std::initializer_list<juce::Point<int>> destsPos, diff --git a/source/jucePlugin/ui/Virus_LfoEditor.h b/source/jucePlugin/ui/Virus_LfoEditor.h @@ -13,7 +13,7 @@ public: private: struct LfoBase : juce::Component { - LfoBase(VirusParameterBinding& _parameterBinding); + LfoBase(VirusParameterBinding& _parameterBinding, uint8_t _lfoIndex); juce::Slider m_rate; juce::Slider m_keytrack; juce::Slider m_amount; @@ -24,7 +24,7 @@ private: struct LfoTwoOneShared : LfoBase { - LfoTwoOneShared(VirusParameterBinding& _parameterBinding); + LfoTwoOneShared(VirusParameterBinding& _parameterBinding, uint8_t _lfoIndex); juce::Slider m_contour; juce::Slider m_phase; Buttons::LfoButton m_envMode; diff --git a/source/jucePlugin/ui/Virus_OscEditor.cpp b/source/jucePlugin/ui/Virus_OscEditor.cpp @@ -61,7 +61,7 @@ OscEditor::OscOne::OscOne(VirusParameterBinding& _parameterBinding, uint32_t _os _parameterBinding.bind(m_shape, _oscIndex == 0 ? Virus::Param_Osc1Shape : Virus::Param_Osc2Shape); _parameterBinding.bind(m_pulseWidth, _oscIndex == 0 ? Virus::Param_Osc1PW : Virus::Param_Osc2PW); _parameterBinding.bind(m_keyFollow, _oscIndex == 0 ? Virus::Param_Osc1Keyfollow : Virus::Param_Osc2Keyfollow); -// _parameterBinding.bind(m_waveSelect, _oscIndex == 0 ? Virus::Param_Osc1Wave : Virus::Param_Osc2Wave); + _parameterBinding.bind(m_waveSelect, _oscIndex == 0 ? Virus::Param_Osc1Wave : Virus::Param_Osc2Wave); } OscEditor::OscTwo::OscTwo(VirusParameterBinding& _parameterBinding) : OscOne(_parameterBinding, 1) @@ -74,6 +74,12 @@ OscEditor::OscTwo::OscTwo(VirusParameterBinding& _parameterBinding) : OscOne(_pa m_envOsc2.setBounds(m_envFm.getBounds().translated(66, 0)); addAndMakeVisible (m_fmMode); m_fmMode.setBounds (18, 140, comboBoxWidth, comboBoxHeight); + + _parameterBinding.bind(m_fmAmount, Virus::Param_Osc2FMAmount); + _parameterBinding.bind(m_detune, Virus::Param_Osc2Detune); + _parameterBinding.bind(m_envFm, Virus::Param_FMFiltEnvAmt); + _parameterBinding.bind(m_envOsc2, Virus::Param_Osc2FltEnvAmt); + _parameterBinding.bind(m_fmMode, Virus::Param_OscFMMode); } OscEditor::OscThree::OscThree(VirusParameterBinding& _parameterBinding) @@ -86,6 +92,11 @@ OscEditor::OscThree::OscThree(VirusParameterBinding& _parameterBinding) m_level.setBounds(m_detune.getBounds().translated(63, 0)); addAndMakeVisible (m_oscThreeMode); m_oscThreeMode.setBounds (18, 43, comboBoxWidth, comboBoxHeight); + + _parameterBinding.bind(m_semitone, Virus::Param_Osc3Semitone); + _parameterBinding.bind(m_detune, Virus::Param_Osc3Detune); + _parameterBinding.bind(m_level, Virus::Param_Osc3Volume); + _parameterBinding.bind(m_oscThreeMode, Virus::Param_Osc3Mode); } OscEditor::Unison::Unison(VirusParameterBinding& _parameterBinding) @@ -98,6 +109,12 @@ OscEditor::Unison::Unison(VirusParameterBinding& _parameterBinding) m_phaseInit.setBounds(m_lfoPhase.getBounds().translated(66, 0)); addAndMakeVisible (m_unisonVoices); m_unisonVoices.setBounds (18, 42, comboBoxWidth, comboBoxHeight); + + _parameterBinding.bind(m_detune, Virus::Param_UnisonDetune); + _parameterBinding.bind(m_panSpread, Virus::Param_UnisonPanSpread); + _parameterBinding.bind(m_lfoPhase, Virus::Param_UnisonLfoPhase); + _parameterBinding.bind(m_phaseInit, Virus::Param_OscInitPhase); + _parameterBinding.bind(m_unisonVoices, Virus::Param_UnisonMode); } OscEditor::Mixer::Mixer(VirusParameterBinding& _parameterBinding) @@ -107,6 +124,9 @@ OscEditor::Mixer::Mixer(VirusParameterBinding& _parameterBinding) m_oscBalance.setBounds(14, 18, knobSize, knobSize); m_oscLevel.getProperties().set(Virus::LookAndFeel::KnobStyleProp, Virus::LookAndFeel::KnobStyle::GENERIC_RED); m_oscLevel.setBounds(m_oscBalance.getBounds().translated(knobSize, 0)); + + _parameterBinding.bind(m_oscBalance, Virus::Param_OscBalance); + _parameterBinding.bind(m_oscLevel, Virus::Param_OscMainVolume); } OscEditor::RingMod::RingMod(VirusParameterBinding& _parameterBinding) @@ -118,6 +138,10 @@ OscEditor::RingMod::RingMod(VirusParameterBinding& _parameterBinding) m_ringModLevel.getProperties().set(Virus::LookAndFeel::KnobStyleProp, Virus::LookAndFeel::KnobStyle::GENERIC_RED); m_ringModLevel.setBounds(m_noiseLevel.getBounds().translated(knobSize, 0)); m_noiseColor.setBounds(m_noiseLevel.getBounds().translated(0, 95)); + + _parameterBinding.bind(m_noiseLevel, Virus::Param_NoiseVolume); + _parameterBinding.bind(m_ringModLevel, Virus::Param_RingModMVolume); + _parameterBinding.bind(m_noiseColor, Virus::Param_NoiseColor); } OscEditor::Sub::Sub(VirusParameterBinding& _parameterBinding) @@ -127,15 +151,20 @@ OscEditor::Sub::Sub(VirusParameterBinding& _parameterBinding) m_level.setBounds(14 + knobSize, 20, knobSize, knobSize); m_subWaveform.setBounds(30, 34, Buttons::HandleButton::kWidth, Buttons::HandleButton::kHeight); addAndMakeVisible(m_subWaveform); + + _parameterBinding.bind(m_level, Virus::Param_SubOscVolume); + _parameterBinding.bind(m_subWaveform, Virus::Param_SubOscShape); } OscEditor::Portamento::Portamento(VirusParameterBinding& _parameterBinding) { setupRotary(*this, m_portamento); m_portamento.setBounds(12, 18, knobSize, knobSize); + + _parameterBinding.bind(m_portamento, Virus::Param_PortamentoTime); } -OscEditor::Filters::Filters(VirusParameterBinding& _parameterBinding) : m_filter{_parameterBinding,_parameterBinding}, m_link1(true), m_link2(true) +OscEditor::Filters::Filters(VirusParameterBinding &_parameterBinding) : m_filter{Filter(_parameterBinding,0),Filter(_parameterBinding,1)}, m_link1(true), m_link2(true) { addAndMakeVisible(m_filter[0]); addAndMakeVisible(m_filter[1]); @@ -162,9 +191,21 @@ OscEditor::Filters::Filters(VirusParameterBinding& _parameterBinding) : m_filter m_filterRouting.setBounds (m_filterMode[0].getBounds().translated (184, 0)); m_saturationCurve.setBounds (m_filterMode[1].getBounds().translated (184, 0)); m_keyFollowBase.setBounds (m_filterMode[0].getBounds().translated (286, 0)); + + _parameterBinding.bind(m_filterBalance, Virus::Param_FilterBalance); + _parameterBinding.bind(m_filterMode[0], Virus::Param_FilterModeA); + _parameterBinding.bind(m_filterMode[1], Virus::Param_FilterModeB); + _parameterBinding.bind(m_filterRouting, Virus::Param_FilterRouting); + _parameterBinding.bind(m_saturationCurve, Virus::Param_SaturationCurve); + _parameterBinding.bind(m_keyFollowBase, Virus::Param_FilterKeyFollowA); // maybe not right + _parameterBinding.bind(m_link1, Virus::Param_Filter2CutoffLink); + _parameterBinding.bind(m_envPol[0], Virus::Param_Filter1EnvPolarity); + _parameterBinding.bind(m_envPol[1], Virus::Param_Filter2EnvPolarity); + /* _parameterBinding.bind(m_envPol[0], Virus::Param_Filter1EnvPolarity); + _parameterBinding.bind(m_envPol[1], Virus::Param_Filter2EnvPolarity);*/ } -OscEditor::Filters::Filter::Filter(VirusParameterBinding& _parameterBinding) +OscEditor::Filters::Filter::Filter(VirusParameterBinding& _parameterBinding, const uint8_t _fltIndex) { for (auto *s : {&m_cutoff, &m_res, &m_envAmount, &m_keyTrack, &m_resVel, &m_envVel}) setupRotary(*this, *s); @@ -174,9 +215,16 @@ OscEditor::Filters::Filter::Filter(VirusParameterBinding& _parameterBinding) m_keyTrack.setBounds(m_envAmount.getBounds().translated(knobSize - 5, 0)); m_resVel.setBounds(m_keyTrack.getBounds().translated(knobSize - 5, 0)); m_envVel.setBounds(m_resVel.getBounds().translated(knobSize - 5, 0)); + + _parameterBinding.bind(m_cutoff, _fltIndex == 0 ? Virus::Param_FilterCutA : Virus::Param_FilterCutB); + _parameterBinding.bind(m_res, _fltIndex == 0 ? Virus::Param_FilterResA: Virus::Param_FilterResB); + _parameterBinding.bind(m_envAmount, _fltIndex == 0 ? Virus::Param_FilterEnvAmtA : Virus::Param_FilterEnvAmtB); + _parameterBinding.bind(m_keyTrack, _fltIndex == 0 ? Virus::Param_FilterKeyFollowA : Virus::Param_FilterKeyFollowB); + _parameterBinding.bind(m_resVel, _fltIndex == 0 ? Virus::Param_Resonance1Velocity : Virus::Param_Resonance2Velocity); + _parameterBinding.bind(m_envVel, _fltIndex == 0 ? Virus::Param_Filter1EnvAmtVelocity : Virus::Param_Filter2EnvAmtVelocity); } -OscEditor::Envelope::Envelope(VirusParameterBinding& _parameterBinding) +OscEditor::Envelope::Envelope(VirusParameterBinding& _parameterBinding, Virus::EnvelopeType _envIndex) { for (auto *s : {&m_attack, &m_decay, &m_sustain, &m_time, &m_release}) setupRotary(*this, *s); @@ -185,4 +233,15 @@ OscEditor::Envelope::Envelope(VirusParameterBinding& _parameterBinding) m_sustain.setBounds(m_decay.getBounds().translated(knobSize + 9, 0)); m_time.setBounds(m_sustain.getBounds().translated(knobSize + 9, 0)); m_release.setBounds(m_time.getBounds().translated(knobSize + 12, 0)); + + _parameterBinding.bind(m_attack, + _envIndex == Virus::Env_Amp ? Virus::Param_AmpEnvAttack : Virus::Param_FilterEnvAttack); + _parameterBinding.bind(m_decay, + _envIndex == Virus::Env_Amp ? Virus::Param_AmpEnvDecay : Virus::Param_FilterEnvDecay); + _parameterBinding.bind(m_sustain, + _envIndex == Virus::Env_Amp ? Virus::Param_AmpEnvSustain : Virus::Param_FilterEnvSustain); + _parameterBinding.bind(m_release, + _envIndex == Virus::Env_Amp ? Virus::Param_AmpEnvRelease : Virus::Param_FilterEnvRelease); + _parameterBinding.bind(m_time, + _envIndex == Virus::Env_Amp ? Virus::Param_AmpEnvSustainTime : Virus::Param_FilterEnvSustainTime); } diff --git a/source/jucePlugin/ui/Virus_OscEditor.h b/source/jucePlugin/ui/Virus_OscEditor.h @@ -82,7 +82,7 @@ private: Filters(VirusParameterBinding& _parameterBinding); struct Filter : juce::Component { - Filter(VirusParameterBinding& _parameterBinding); + Filter(VirusParameterBinding& _parameterBinding, uint8_t fltIndex); juce::Slider m_cutoff; juce::Slider m_res; juce::Slider m_envAmount; @@ -100,7 +100,7 @@ private: struct Envelope : juce::Component { - Envelope(VirusParameterBinding& _parameterBinding); + Envelope(VirusParameterBinding &_parameterBinding, Virus::EnvelopeType _envIndex); juce::Slider m_attack; juce::Slider m_decay; juce::Slider m_sustain; @@ -110,12 +110,12 @@ private: struct FilterEnv : Envelope { - FilterEnv(VirusParameterBinding& _parameterBinding) : Envelope(_parameterBinding) {} + FilterEnv(VirusParameterBinding& _parameterBinding) : Envelope(_parameterBinding, Virus::EnvelopeType::Env_Filter) {} } m_filterEnv; struct AmpEnv : Envelope { - AmpEnv(VirusParameterBinding& _parameterBinding) : Envelope(_parameterBinding) {} + AmpEnv(VirusParameterBinding &_parameterBinding) : Envelope(_parameterBinding, Virus::EnvelopeType::Env_Amp) {} } m_ampEnv; Buttons::SyncButton m_oscSync;