commit 7d32dd02ca0ab4ceb1f0403813cd0be3d791ac82
parent 8ed9b308f381bbaeaa5d25c351d76d377aa91e56
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Fri, 2 Aug 2024 17:21:10 +0200
edit single parameter via sysex if needed
Diffstat:
4 files changed, 50 insertions(+), 15 deletions(-)
diff --git a/source/nord/n2x/n2xJucePlugin/n2xController.cpp b/source/nord/n2x/n2xJucePlugin/n2xController.cpp
@@ -175,7 +175,6 @@ namespace n2xJucePlugin
{
auto* param = getParameter(paramIndex, part);
assert(param && "parameter not found for control change");
- // TODO: part
param->setValueFromSynth(_e.c, origin);
}
}
@@ -192,16 +191,24 @@ namespace n2xJucePlugin
return;
}
+ constexpr uint32_t sysexRateLimitMs = 150;
+
+ pluginLib::Parameter& nonConstParam = const_cast<pluginLib::Parameter&>(_parameter);
+
+ const auto singleParam = static_cast<n2x::SingleParam>(_parameter.getDescription().index);
+ const uint8_t part = _parameter.getPart();
+
const auto& controllerMap = getParameterDescriptions().getControllerMap();
- uint32_t paramIndex;
- if(!getParameterDescriptions().getIndexByName(paramIndex, _parameter.getDescription().name))
+ uint32_t descIndex;
+ if(!getParameterDescriptions().getIndexByName(descIndex, _parameter.getDescription().name))
assert(false && "parameter not found");
- const auto& ccs = controllerMap.getControlChanges(synthLib::M_CONTROLCHANGE, paramIndex);
+ const auto& ccs = controllerMap.getControlChanges(synthLib::M_CONTROLCHANGE, descIndex);
if(ccs.empty())
{
- assert(false && "TODO: implement parameter sending for non-CC params");
+ nonConstParam.setRateLimitMilliseconds(sysexRateLimitMs);
+ setSingleParameter(part, singleParam, _value);
return;
}
@@ -210,17 +217,39 @@ namespace n2xJucePlugin
if(cc == n2x::ControlChange::CCSync)
{
// sync and ringmod have the same CC, combine them
- const auto* paramSync = getParameter("Sync", _parameter.getPart());
- const auto* paramRingMod = getParameter("RingMod", _parameter.getPart());
+ const auto* paramSync = getParameter("Sync", part);
+ const auto* paramRingMod = getParameter("RingMod", part);
_value = static_cast<uint8_t>(paramSync->getUnnormalizedValue() | (paramRingMod->getUnnormalizedValue() << 1));
}
- const auto ch = m_state.getPartMidiChannel(_parameter.getPart());
+ const auto ch = m_state.getPartMidiChannel(part);
+
+ const auto parts = m_state.getPartsForMidiChannel(ch);
+
const auto ev = synthLib::SMidiEvent{synthLib::MidiEventSource::Editor, static_cast<uint8_t>(synthLib::M_CONTROLCHANGE + ch), cc, _value};
- m_state.receive(ev);
- sendMidiEvent(ev);
+ if(parts.size() > 1)
+ {
+ // this is problematic. We want to edit one part only but two parts receive on the same channel. We have to send a full dump
+ nonConstParam.setRateLimitMilliseconds(sysexRateLimitMs);
+ setSingleParameter(part, singleParam, _value);
+ }
+ else
+ {
+ nonConstParam.setRateLimitMilliseconds(0);
+ m_state.receive(ev);
+ sendMidiEvent(ev);
+ }
+ }
+
+ void Controller::setSingleParameter(uint8_t _part, n2x::SingleParam _sp, uint8_t _value)
+ {
+ if(!m_state.changeSingleParameter(_part, _sp, _value))
+ return;
+
+ const auto& single = m_state.getSingle(_part);
+ pluginLib::Controller::sendSysEx(pluginLib::SysEx{single.begin(), single.end()});
}
void Controller::setMultiParameter(n2x::MultiParam _mp, uint8_t _value)
@@ -277,7 +306,7 @@ namespace n2xJucePlugin
return dst;
}
- bool Controller::activatePatch(const std::vector<uint8_t>& _sysex, const uint32_t _part)
+ bool Controller::activatePatch(const std::vector<uint8_t>& _sysex, const uint32_t _part) const
{
if(_part >= getPartCount())
return false;
diff --git a/source/nord/n2x/n2xJucePlugin/n2xController.h b/source/nord/n2x/n2xJucePlugin/n2xController.h
@@ -42,6 +42,7 @@ namespace n2xJucePlugin
void sendParameterChange(const pluginLib::Parameter& _parameter, uint8_t _value) override;
+ void setSingleParameter(uint8_t _part, n2x::SingleParam _sp, uint8_t _value);
void setMultiParameter(n2x::MultiParam _mp, uint8_t _value);
uint8_t getMultiParameter(n2x::MultiParam _param) const;
@@ -51,7 +52,7 @@ namespace n2xJucePlugin
void requestDump(uint8_t _bank, uint8_t _patch) const;
std::vector<uint8_t> createSingleDump(uint8_t _bank, uint8_t _program, uint8_t _part) const;
- bool activatePatch(const std::vector<uint8_t>& _sysex, uint32_t _part);
+ bool activatePatch(const std::vector<uint8_t>& _sysex, uint32_t _part) const;
bool isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const override;
diff --git a/source/nord/n2x/n2xLib/n2xstate.cpp b/source/nord/n2x/n2xLib/n2xstate.cpp
@@ -408,13 +408,17 @@ namespace n2x
std::vector<uint8_t> State::getPartsForMidiChannel(const synthLib::SMidiEvent& _ev) const
{
- std::vector<uint8_t> res;
-
const auto ch = _ev.a & 0xf;
+ return getPartsForMidiChannel(ch);
+ }
+
+ std::vector<uint8_t> State::getPartsForMidiChannel(const uint8_t _channel) const
+ {
+ std::vector<uint8_t> res;
for(uint8_t i=0; i<static_cast<uint8_t>(m_singles.size()); ++i)
{
- if(getPartMidiChannel(i) == ch)
+ if(getPartMidiChannel(i) == _channel)
res.push_back(i);
}
return res;
diff --git a/source/nord/n2x/n2xLib/n2xstate.h b/source/nord/n2x/n2xLib/n2xstate.h
@@ -59,6 +59,7 @@ namespace n2x
}
std::vector<uint8_t> getPartsForMidiChannel(const synthLib::SMidiEvent& _ev) const;
+ std::vector<uint8_t> getPartsForMidiChannel(uint8_t _channel) const;
template<typename TDump> static uint8_t getPartMidiChannel(const TDump& _dump, const uint8_t _part)
{