commit 248abc25366c8d7703ea4c815396c488b0cd1ca7
parent 70ef5508291afbfbe36b9055b8d982128ebb6ea5
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Sat, 10 Aug 2024 17:12:33 +0200
implement LFO sync
Diffstat:
7 files changed, 126 insertions(+), 3 deletions(-)
diff --git a/source/nord/n2x/n2xJucePlugin/CMakeLists.txt b/source/nord/n2x/n2xJucePlugin/CMakeLists.txt
@@ -11,6 +11,7 @@ set(SOURCES
n2xOctLed.cpp n2xOctLed.h
n2xParameterDrivenLed.cpp n2xParameterDrivenLed.h
n2xLcd.cpp n2xLcd.h
+ n2xLfo.cpp n2xLfo.h
n2xPart.cpp n2xPart.h
n2xPartLed.cpp n2xPartLed.h
n2xParts.cpp n2xParts.h
diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.cpp b/source/nord/n2x/n2xJucePlugin/n2xEditor.cpp
@@ -6,6 +6,7 @@
#include "n2xController.h"
#include "n2xFocusedParameter.h"
#include "n2xLcd.h"
+#include "n2xLfo.h"
#include "n2xMasterVolume.h"
#include "n2xOctLed.h"
#include "n2xPart.h"
@@ -74,6 +75,8 @@ namespace n2xJucePlugin
m_arp.reset(new Arp(*this));
m_focusedParameter.reset(new FocusedParameter(*this));
m_lcd.reset(new Lcd(*this));
+ for(uint8_t i=0; i<m_lfos.size(); ++i)
+ m_lfos[i].reset(new Lfo(*this, i));
m_masterVolume.reset(new MasterVolume(*this));
m_octLed.reset(new OctLed(*this));
m_parts.reset(new Parts(*this));
@@ -120,6 +123,8 @@ namespace n2xJucePlugin
m_arp.reset();
m_focusedParameter.reset();
m_lcd.reset();
+ for (auto& lfo : m_lfos)
+ lfo.reset();
m_masterVolume.reset();
m_octLed.reset();
m_parts.reset();
diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.h b/source/nord/n2x/n2xJucePlugin/n2xEditor.h
@@ -16,6 +16,7 @@ namespace pluginLib
namespace n2xJucePlugin
{
+ class Lfo;
class FocusedParameter;
class PatchManager;
class Controller;
@@ -72,6 +73,7 @@ namespace n2xJucePlugin
std::unique_ptr<Arp> m_arp;
std::unique_ptr<FocusedParameter> m_focusedParameter;
std::unique_ptr<Lcd> m_lcd;
+ std::array<std::unique_ptr<Lfo>, 2> m_lfos;
std::unique_ptr<MasterVolume> m_masterVolume;
std::unique_ptr<OctLed> m_octLed;
std::unique_ptr<Parts> m_parts;
diff --git a/source/nord/n2x/n2xJucePlugin/n2xLfo.cpp b/source/nord/n2x/n2xJucePlugin/n2xLfo.cpp
@@ -0,0 +1,44 @@
+#include "n2xLfo.h"
+
+#include "n2xController.h"
+#include "n2xEditor.h"
+
+namespace n2xJucePlugin
+{
+ Lfo::Lfo(Editor& _editor, const uint8_t _index)
+ : m_editor(_editor)
+ , m_index(_index)
+ , m_button(_editor.findComponentT<juce::Button>(_index ? "PerfLfo2SyncA" : "PerfLfo1SyncA"))
+ {
+ m_onCurrentPartChanged.set(_editor.getN2xController().onCurrentPartChanged, [this](const uint8_t&)
+ {
+ bind();
+ });
+
+ bind();
+ }
+
+ std::string Lfo::getSyncMultiParamName(const uint8_t _part, const uint8_t _lfoIndex)
+ {
+ return std::string("PerfLfo") + std::to_string(_lfoIndex+1) + "Sync" + static_cast<char>('A' + _part);
+ }
+
+ void Lfo::bind()
+ {
+ const auto& controller = m_editor.getN2xController();
+
+ auto* syncMultiParam = controller.getParameter(getSyncMultiParamName(controller.getCurrentPart(), m_index), 0);
+
+ m_onSyncMultiParamChanged.set(syncMultiParam, [this](pluginLib::Parameter* const& _parameter)
+ {
+ updateState(_parameter);
+ });
+
+ updateState(syncMultiParam);
+ }
+
+ void Lfo::updateState(const pluginLib::Parameter* _param) const
+ {
+ m_button->setToggleState(_param->getUnnormalizedValue() > 0, juce::dontSendNotification);
+ }
+}
diff --git a/source/nord/n2x/n2xJucePlugin/n2xLfo.h b/source/nord/n2x/n2xJucePlugin/n2xLfo.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "n2xParameterDrivenLed.h"
+
+namespace juce
+{
+ class Slider;
+}
+
+namespace n2xJucePlugin
+{
+ class Lfo
+ {
+ public:
+ Lfo(Editor& _editor, uint8_t _index);
+
+ static std::string getSyncMultiParamName(const uint8_t _part, const uint8_t _lfoIndex);
+
+ private:
+ void bind();
+ void updateState(const pluginLib::Parameter* _param) const;
+
+ Editor& m_editor;
+ const uint8_t m_index;
+ juce::Button* m_button;
+
+ pluginLib::ParameterListener m_onSyncMultiParamChanged;
+ pluginLib::ParameterListener m_onSyncRateParamChanged;
+ pluginLib::EventListener<uint8_t> m_onCurrentPartChanged;
+ };
+}
diff --git a/source/nord/n2x/n2xJucePlugin/n2xPart.cpp b/source/nord/n2x/n2xJucePlugin/n2xPart.cpp
@@ -2,6 +2,7 @@
#include "n2xController.h"
#include "n2xEditor.h"
+#include "n2xLfo.h"
namespace n2xJucePlugin
{
@@ -26,6 +27,7 @@ namespace n2xJucePlugin
auto& controller = m_editor.getN2xController();
+ // Midi Channel
{
juce::PopupMenu menuChannel;
@@ -50,6 +52,8 @@ namespace n2xJucePlugin
menu.addSubMenu("Midi Channel", menuChannel);
}
+
+ // Output Mode
{
juce::PopupMenu menuOut;
@@ -97,6 +101,42 @@ namespace n2xJucePlugin
menu.addSubMenu("Output Mode", menuOut);
}
+ // LFO Sync
+ {
+ juce::PopupMenu lfoA;
+ juce::PopupMenu lfoB;
+
+ auto createSyncMenu = [this](juce::PopupMenu& _menu, uint8_t _lfoIndex)
+ {
+ const auto paramName = Lfo::getSyncMultiParamName(getPart(), _lfoIndex);
+ auto* param = m_editor.getN2xController().getParameter(paramName, 0);
+ const auto v = param->getUnnormalizedValue();
+
+ auto createEntry = [&_menu, param, v](const char* _name, const uint8_t _v)
+ {
+ _menu.addItem(_name, true, _v == v, [param, _v]
+ {
+ param->setUnnormalizedValueNotifyingHost(_v, pluginLib::Parameter::Origin::Ui);
+ });
+ };
+
+ createEntry("Off", 0);
+ createEntry("2/1", 1);
+ createEntry("1/1", 2);
+ createEntry("1/2", 3);
+ createEntry("1/4", 4);
+ createEntry("1/8", 5);
+ createEntry("1/8.", 6);
+ createEntry("1/16", 7);
+ };
+
+ createSyncMenu(lfoA, 0);
+ createSyncMenu(lfoB, 1);
+
+ menu.addSubMenu("LFO 1 Sync", lfoA);
+ menu.addSubMenu("LFO 2 Sync", lfoB);
+ }
+
menu.showMenuAsync({});
}
}
diff --git a/source/nord/n2x/n2xJucePlugin/skins/n2xTrancy/n2xTrancy.json b/source/nord/n2x/n2xJucePlugin/skins/n2xTrancy/n2xTrancy.json
@@ -114,7 +114,7 @@
{ "name" : "Distortion", "parameterAttachment" : { "parameter" : "Distortion"}, "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "1954", "y" : "705", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70" , "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":150} },
- { "name" : "PerfLfo1SyncA", "parameterAttachment" : { "parameter" : "PerfLfo1SyncA"}, "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "485", "y" : "-13", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70", "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":130 } },
+ { "name" : "PerfLfo1SyncA", "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "485", "y" : "-13", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70", "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":130 } },
{ "name" : "Lfo1Rate", "parameterAttachment" : { "parameter" : "Lfo1Rate" }, "rotary" : { }, "spritesheet" : { "x" : "36", "y" : "88", "width" : "113", "height" : "113", "texture" : "knob_big", "tileSizeX" : "113", "tileSizeY" : "113" } },
{ "name" : "Lfo1Level", "parameterAttachment" : { "parameter" : "Lfo1Level" }, "rotary" : { }, "spritesheet" : { "x" : "508", "y" : "88", "width" : "113", "height" : "113", "texture" : "knob_big", "tileSizeX" : "113", "tileSizeY" : "113" } },
@@ -138,7 +138,6 @@
{ "name" : "Lfo2Dest_LFO2_OSC1+2", "parameterAttachment" : { "parameter" : "Lfo2Dest", "value":4}, "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "162", "y" : "45", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70", "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":100 } },
{ "name" : "Lfo2Dest_LFO2_AMP", "parameterAttachment" : { "parameter" : "Lfo2Dest", "value":3}, "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "162", "y" : "82", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70", "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":100 } },
{ "name" : "Lfo2Dest_LFO2_FILTER", "parameterAttachment" : { "parameter" : "Lfo2Dest", "value":7}, "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "162", "y" : "119", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70", "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":100 } },
- { "name" : "PerfLfo2SyncA", "parameterAttachment" : { "parameter" : "PerfLfo2SyncA"}, "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "350", "y" : "-13", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70", "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":130 } },
]
},
@@ -160,7 +159,8 @@
]
},
- { "name" : "ArpEnabled", "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "485", "y" : "254", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70" , "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":90} },
+ { "name" : "PerfLfo2SyncA", "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "350", "y" : "254", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70", "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":130 } },
+ { "name" : "ArpEnabled", "button" : { "isToggle" : "1", "normalImage" : "0", "overImage" : "0", "downImage" : "0", "normalImageOn" : "1", "overImageOn" : "1", "downImageOn" : "1", "x" : "485", "y" : "254", "width" : "70", "height" : "70", "texture" : "button_round", "tileSizeX" : "70", "tileSizeY" : "70" , "hitOffsetT":20, "hitOffsetB":-20, "hitOffsetR":90} },
{ "name" : "Lfo2Rate", "parameterAttachment" : { "parameter" : "Lfo2Rate" }, "rotary" : { }, "spritesheet" : { "x" : "36", "y" : "350", "width" : "113", "height" : "113", "texture" : "knob_big", "tileSizeX" : "113", "tileSizeY" : "113" } },