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 2c76bef819e904dcae061b68d407bdf0de876c4f
parent 37b267ef77bc7253e0c800def35eb60673c02014
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Fri,  2 Aug 2024 01:45:41 +0200

support part select and editing of other parts

Diffstat:
Msource/nord/n2x/n2xJucePlugin/n2xController.cpp | 30+++++++++++++++++++++++-------
Msource/nord/n2x/n2xJucePlugin/n2xController.h | 2++
Msource/nord/n2x/n2xJucePlugin/n2xEditor.cpp | 6++++++
Msource/nord/n2x/n2xJucePlugin/n2xEditor.h | 2++
Msource/nord/n2x/n2xJucePlugin/n2xPart.cpp | 7+++++++
Msource/nord/n2x/n2xJucePlugin/n2xPart.h | 2++
Msource/nord/n2x/n2xJucePlugin/n2xParts.cpp | 32++++++++++++++++++++++++++++++++
Msource/nord/n2x/n2xJucePlugin/n2xParts.h | 10++++++++++
8 files changed, 84 insertions(+), 7 deletions(-)

diff --git a/source/nord/n2x/n2xJucePlugin/n2xController.cpp b/source/nord/n2x/n2xJucePlugin/n2xController.cpp @@ -41,6 +41,11 @@ namespace n2xJucePlugin requestDump(n2x::SysexByte::SingleRequestBankEditBuffer, 3); requestDump(n2x::SysexByte::MultiRequestBankEditBuffer, 0); // performance edit buffer + + m_currentPartChanged.set(onCurrentPartChanged, [this](const uint8_t& _part) + { + setMultiParameter(n2x::SelectedChannel, _part); + }); } Controller::~Controller() = default; @@ -128,6 +133,9 @@ namespace n2xJucePlugin applyPatchParameters(params, 0); + const auto part = m_state.getMultiParam(n2x::SelectedChannel, 0); + setCurrentPart(part); + return true; } @@ -182,7 +190,7 @@ namespace n2xJucePlugin const auto& controllerMap = getParameterDescriptions().getControllerMap(); - const auto& ccs = controllerMap.getControlChanges(synthLib::M_CONTROLCHANGE, _parameter.getParameterIndex()); + const auto& ccs = controllerMap.getControlChanges(synthLib::M_CONTROLCHANGE, _parameter.getDescription().index); if(ccs.empty()) { assert(false && "TODO: implement parameter sending for non-CC params"); @@ -200,8 +208,19 @@ namespace n2xJucePlugin _value = static_cast<uint8_t>(paramSync->getUnnormalizedValue() | (paramRingMod->getUnnormalizedValue() << 1)); } - m_state.receive(synthLib::SMidiEvent{synthLib::MidiEventSource::Editor, synthLib::M_CONTROLCHANGE, cc, _value}); - sendMidiEvent(synthLib::M_CONTROLCHANGE, cc, _value); + const auto ch = m_state.getPartMidiChannel(_parameter.getPart()); + const auto ev = synthLib::SMidiEvent{synthLib::MidiEventSource::Editor, static_cast<uint8_t>(synthLib::M_CONTROLCHANGE + ch), cc, _value}; + + m_state.receive(ev); + sendMidiEvent(ev); + } + + void Controller::setMultiParameter(n2x::MultiParam _mp, uint8_t _value) + { + if(!m_state.changeMultiParameter(_mp, _value)) + return; + const auto& multi = m_state.updateAndGetMulti(); + pluginLib::Controller::sendSysEx(pluginLib::SysEx{multi.begin(), multi.end()}); } void Controller::sendMultiParameter(const pluginLib::Parameter& _parameter, const uint8_t _value) @@ -210,10 +229,7 @@ namespace n2xJucePlugin const auto mp = static_cast<n2x::MultiParam>(desc.index + (desc.page - g_multiPage) * 128); - if(!m_state.changeMultiParameter(mp, _value)) - return; - const auto& multi = m_state.updateAndGetMulti(); - pluginLib::Controller::sendSysEx(pluginLib::SysEx{multi.begin(), multi.end()}); + setMultiParameter(mp, _value); } bool Controller::sendSysEx(MidiPacketType _packet, const std::map<pluginLib::MidiDataType, uint8_t>& _params) const diff --git a/source/nord/n2x/n2xJucePlugin/n2xController.h b/source/nord/n2x/n2xJucePlugin/n2xController.h @@ -39,6 +39,7 @@ namespace n2xJucePlugin bool parseControllerMessage(const synthLib::SMidiEvent&) override; void sendParameterChange(const pluginLib::Parameter& _parameter, uint8_t _value) override; + void setMultiParameter(n2x::MultiParam _mp, uint8_t _value); void sendMultiParameter(const pluginLib::Parameter& _parameter, uint8_t _value); bool sendSysEx(MidiPacketType _packet, const std::map<pluginLib::MidiDataType, uint8_t>& _params) const; @@ -51,5 +52,6 @@ namespace n2xJucePlugin private: n2x::State m_state; + pluginLib::EventListener<uint8_t> m_currentPartChanged; }; } diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.cpp b/source/nord/n2x/n2xJucePlugin/n2xEditor.cpp @@ -70,6 +70,12 @@ namespace n2xJucePlugin m_arp.reset(new Arp(*this)); m_lcd.reset(new Lcd(*this)); m_parts.reset(new Parts(*this)); + + onPartChanged.set(m_controller.onCurrentPartChanged, [this](const uint8_t& _part) + { + setCurrentPart(_part); + m_parameterBinding.setPart(_part); + }); } Editor::~Editor() diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.h b/source/nord/n2x/n2xJucePlugin/n2xEditor.h @@ -39,6 +39,7 @@ namespace n2xJucePlugin Controller& getN2xController() const { return m_controller; } genericUI::Button<juce::DrawableButton>* createJuceComponent(genericUI::Button<juce::DrawableButton>*, genericUI::UiObject& _object, const std::string& _name, juce::DrawableButton::ButtonStyle) override; + private: Controller& m_controller; pluginLib::ParameterBinding& m_parameterBinding; @@ -46,5 +47,6 @@ namespace n2xJucePlugin std::unique_ptr<Arp> m_arp; std::unique_ptr<Lcd> m_lcd; std::unique_ptr<Parts> m_parts; + pluginLib::EventListener<uint8_t> onPartChanged; }; } diff --git a/source/nord/n2x/n2xJucePlugin/n2xPart.cpp b/source/nord/n2x/n2xJucePlugin/n2xPart.cpp @@ -1,4 +1,6 @@ #include "n2xPart.h" + +#include "n2xController.h" #include "n2xEditor.h" namespace n2xJucePlugin @@ -6,4 +8,9 @@ namespace n2xJucePlugin Part::Part(Editor& _editor, const std::string& _name, const ButtonStyle _buttonStyle) : PartButton(_editor, _name, _buttonStyle), m_editor(_editor) { } + + void Part::onClick() + { + m_editor.getN2xController().setCurrentPart(getPart()); + } } diff --git a/source/nord/n2x/n2xJucePlugin/n2xPart.h b/source/nord/n2x/n2xJucePlugin/n2xPart.h @@ -11,6 +11,8 @@ namespace n2xJucePlugin public: Part(Editor& _editor, const std::string& _name, ButtonStyle _buttonStyle); + void onClick() override; + private: Editor& m_editor; }; diff --git a/source/nord/n2x/n2xJucePlugin/n2xParts.cpp b/source/nord/n2x/n2xJucePlugin/n2xParts.cpp @@ -1,8 +1,40 @@ #include "n2xParts.h" +#include "n2xController.h" +#include "n2xEditor.h" + namespace n2xJucePlugin { Parts::Parts(Editor& _editor): m_editor(_editor) { + m_parts[0] = _editor.findComponentT<Part>("PerfMidiChannelA"); + m_parts[1] = _editor.findComponentT<Part>("PerfMidiChannelB"); + m_parts[2] = _editor.findComponentT<Part>("PerfMidiChannelC"); + m_parts[3] = _editor.findComponentT<Part>("PerfMidiChannelD"); + + for(uint8_t p=0; p<static_cast<uint8_t>(m_parts.size()); ++p) + { + auto* part = m_parts[p]; + part->initalize(p); + } + + onCurrentPartChanged.set(_editor.getN2xController().onCurrentPartChanged, [this](const uint8_t& _part) + { + setCurrentPart(_part); + }); + + setCurrentPart(0); + } + + void Parts::setCurrentPart(const uint8_t _part) const + { + juce::MessageManager::callAsync([this, _part] + { + for(uint8_t p=0; p<static_cast<uint8_t>(m_parts.size()); ++p) + { + auto* part = m_parts[p]; + part->setToggleState(_part == p, juce::dontSendNotification); + } + }); } } diff --git a/source/nord/n2x/n2xJucePlugin/n2xParts.h b/source/nord/n2x/n2xJucePlugin/n2xParts.h @@ -1,5 +1,9 @@ #pragma once +#include "n2xPart.h" + +#include "jucePluginLib/event.h" + namespace n2xJucePlugin { class Editor; @@ -10,6 +14,12 @@ namespace n2xJucePlugin explicit Parts(Editor& _editor); private: + void setCurrentPart(uint8_t _part) const; + Editor& m_editor; + + std::array<Part*,4> m_parts; + pluginLib::EventListener<uint8_t> onCurrentPartChanged; + }; }