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 8fff62343d7ba927fb7f71dc524242a7c231c478
parent 69257e42ba951b33b7aaf836e3ce378e63e4b2e9
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Tue,  6 Aug 2024 22:18:33 +0200

implement VM map

Diffstat:
Msource/jucePluginLib/parameterbinding.cpp | 74+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Msource/jucePluginLib/parameterbinding.h | 7++++++-
Msource/nord/n2x/n2xJucePlugin/CMakeLists.txt | 1+
Msource/nord/n2x/n2xJucePlugin/n2xEditor.cpp | 3+++
Msource/nord/n2x/n2xJucePlugin/n2xEditor.h | 3+++
Asource/nord/n2x/n2xJucePlugin/n2xVmMap.cpp | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asource/nord/n2x/n2xJucePlugin/n2xVmMap.h | 35+++++++++++++++++++++++++++++++++++
7 files changed, 176 insertions(+), 22 deletions(-)

diff --git a/source/jucePluginLib/parameterbinding.cpp b/source/jucePluginLib/parameterbinding.cpp @@ -231,6 +231,27 @@ namespace pluginLib addBinding(p); } + bool ParameterBinding::bind(juce::Component& _component, const uint32_t _param, const uint8_t _part) + { + if(auto* slider = dynamic_cast<juce::Slider*>(&_component)) + { + bind(*slider, _param, _part); + return true; + } + if(auto* button = dynamic_cast<juce::DrawableButton*>(&_component)) + { + bind(*button, _param, _part); + return true; + } + if(auto* comboBox = dynamic_cast<juce::ComboBox*>(&_component)) + { + bind(*comboBox, _param, _part); + return true; + } + assert(false && "unknown component type"); + return false; + } + juce::Component* ParameterBinding::getBoundComponent(const Parameter* _parameter) const { const auto it = m_boundParameters.find(_parameter); @@ -247,6 +268,37 @@ namespace pluginLib return it->second; } + bool ParameterBinding::unbind(const Parameter* _param) + { + for (auto it= m_bindings.begin(); it != m_bindings.end(); ++it) + { + if(it->parameter != _param) + continue; + + m_bindings.erase(it); + + return true; + } + return false; + } + + bool ParameterBinding::unbind(const juce::Component* _component) + { + for (auto it= m_bindings.begin(); it != m_bindings.end(); ++it) + { + if(it->component != _component) + continue; + + disableBinding(*it); + + m_disabledBindings.push_back(*it); + m_bindings.erase(it); + + return true; + } + return false; + } + void ParameterBinding::removeMouseListener(juce::Slider& _slider) { const auto it = m_sliderMouseListeners.find(&_slider); @@ -262,27 +314,7 @@ namespace pluginLib void ParameterBinding::bind(const std::vector<BoundParameter>& _bindings, const bool _currentPartOnly) { for (const auto& b : _bindings) - { - auto* slider = dynamic_cast<juce::Slider*>(b.component); - if(slider) - { - bind(*slider, b.type, b.part); - continue; - } - auto* button = dynamic_cast<juce::DrawableButton*>(b.component); - if(button) - { - bind(*button, b.type, b.part); - continue; - } - auto* comboBox = dynamic_cast<juce::ComboBox*>(b.component); - if(comboBox) - { - bind(*comboBox, b.type, b.part); - continue; - } - assert(false && "unknown component type"); - } + bind(*b.component, b.paramIndex, b.part); } void ParameterBinding::addBinding(const BoundParameter& _boundParameter) diff --git a/source/jucePluginLib/parameterbinding.h b/source/jucePluginLib/parameterbinding.h @@ -42,7 +42,7 @@ namespace pluginLib { Parameter* parameter = nullptr; juce::Component* component = nullptr; - uint32_t type = 0xffffffff; + uint32_t paramIndex = 0xffffffff; uint8_t part = CurrentPart; size_t onChangeListenerId = ParameterListener::InvalidListenerId; }; @@ -62,6 +62,8 @@ namespace pluginLib void bind(juce::Button &_control, uint32_t _param); void bind(juce::Button &_control, uint32_t _param, uint8_t _part); + bool bind(juce::Component& _component, uint32_t _param, uint8_t _part); + void clearBindings(); void clear(); void setPart(uint8_t _part); @@ -73,6 +75,9 @@ namespace pluginLib juce::Component* getBoundComponent(const pluginLib::Parameter* _parameter) const; pluginLib::Parameter* getBoundParameter(const juce::Component* _component) const; + bool unbind(const Parameter* _param); + bool unbind(const juce::Component* _component); + private: void removeMouseListener(juce::Slider& _slider); diff --git a/source/nord/n2x/n2xJucePlugin/CMakeLists.txt b/source/nord/n2x/n2xJucePlugin/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES n2xPatchManager.cpp n2xPatchManager.h n2xPluginEditorState.cpp n2xPluginEditorState.h n2xPluginProcessor.cpp n2xPluginProcessor.h + n2xVmMap.cpp n2xVmMap.h parameterDescriptions_n2x.json skins/n2xTrancy/n2xTrancy.json ) diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.cpp b/source/nord/n2x/n2xJucePlugin/n2xEditor.cpp @@ -10,6 +10,7 @@ #include "n2xParts.h" #include "n2xPatchManager.h" #include "n2xPluginProcessor.h" +#include "n2xVmMap.h" #include "jucePluginLib/parameterbinding.h" #include "jucePluginLib/pluginVersion.h" @@ -72,6 +73,7 @@ namespace n2xJucePlugin m_lcd.reset(new Lcd(*this)); m_masterVolume.reset(new MasterVolume(*this)); m_parts.reset(new Parts(*this)); + m_vmMap.reset(new VmMap(*this, m_parameterBinding)); onPartChanged.set(m_controller.onCurrentPartChanged, [this](const uint8_t& _part) { @@ -115,6 +117,7 @@ namespace n2xJucePlugin m_lcd.reset(); m_masterVolume.reset(); m_parts.reset(); + m_vmMap.reset(); } const char* Editor::findEmbeddedResource(const std::string& _filename, uint32_t& _size) diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.h b/source/nord/n2x/n2xJucePlugin/n2xEditor.h @@ -22,6 +22,7 @@ namespace n2xJucePlugin class Arp; class Parts; class MasterVolume; + class VmMap; class Editor final : public jucePluginEditorLib::Editor { @@ -60,6 +61,8 @@ namespace n2xJucePlugin std::unique_ptr<Lcd> m_lcd; std::unique_ptr<MasterVolume> m_masterVolume; std::unique_ptr<Parts> m_parts; + std::unique_ptr<VmMap> m_vmMap; + pluginLib::EventListener<uint8_t> onPartChanged; std::array<std::string, 4> m_activePatchNames; diff --git a/source/nord/n2x/n2xJucePlugin/n2xVmMap.cpp b/source/nord/n2x/n2xJucePlugin/n2xVmMap.cpp @@ -0,0 +1,75 @@ +#include "n2xVmMap.h" + +#include "n2xController.h" +#include "n2xEditor.h" + +namespace n2xJucePlugin +{ + constexpr const char* g_postfix = "Sens"; + constexpr float g_enabledAlpha = 0.5f; + + VmMap::VmMap(Editor& _editor, pluginLib::ParameterBinding& _binding) + : m_editor(_editor) + , m_binding(_binding) + , m_btVmMap(_editor.findComponentT<juce::Button>("VMMAP")) + { + const auto& c = _editor.getN2xController(); + const auto& descs = c.getParameterDescriptions().getDescriptions(); + + for (const auto& desc : descs) + { + uint32_t idx; + + if(c.getParameterDescriptions().getIndexByName(idx, desc.name + g_postfix)) + m_paramNames.insert(desc.name); + } + + m_btVmMap->onClick = [this] + { + toggleVmMap(m_btVmMap->getToggleState()); + }; + } + + void VmMap::toggleVmMap(const bool _enabled) + { + if(m_enabled == _enabled) + return; + + m_enabled = _enabled; + + const auto& controller = m_editor.getN2xController(); + + const auto part = controller.getCurrentPart(); + + for (const auto& paramName : m_paramNames) + { + const auto paramIdxDefault = controller.getParameterIndexByName(paramName); + const auto paramIdxVm = controller.getParameterIndexByName(paramName + g_postfix); + + const auto* paramDefault = controller.getParameter(paramName, part); + const auto* paramVm = controller.getParameter(paramName + g_postfix, part); + + auto* comp = m_binding.getBoundComponent(paramDefault); + + if(comp == nullptr) + comp = m_binding.getBoundComponent(paramVm); + + if(comp != nullptr) + { + m_binding.unbind(comp); + } + else + { + assert(false && "bound component not found"); + return; + } + + m_binding.unbind(paramDefault); + m_binding.unbind(paramVm); + + m_binding.bind(*comp, _enabled ? paramIdxVm : paramIdxDefault, pluginLib::ParameterBinding::CurrentPart); + + comp->setAlpha(_enabled ? g_enabledAlpha : 1.0f); + } + } +} diff --git a/source/nord/n2x/n2xJucePlugin/n2xVmMap.h b/source/nord/n2x/n2xJucePlugin/n2xVmMap.h @@ -0,0 +1,35 @@ +#pragma once + +#include <string> +#include <set> + +namespace pluginLib +{ + class ParameterBinding; +} + +namespace juce +{ + class Button; +} + +namespace n2xJucePlugin +{ + class Editor; + + class VmMap + { + public: + explicit VmMap(Editor& _editor, pluginLib::ParameterBinding& _binding); + + private: + void toggleVmMap(bool _enabled); + + Editor& m_editor; + pluginLib::ParameterBinding& m_binding; + + std::set<std::string> m_paramNames; + juce::Button* m_btVmMap; + bool m_enabled = false; + }; +}