commit eeeedff1475020d4c3000ec08b5348cd98f63f37
parent fe7527b3990009152ad2830e5bcdace01c732f36
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Wed, 9 Mar 2022 20:02:25 +0100
add ability to have multiple Juce parameters for one synth params
Diffstat:
2 files changed, 107 insertions(+), 59 deletions(-)
diff --git a/source/jucePlugin/VirusController.cpp b/source/jucePlugin/VirusController.cpp
@@ -26,16 +26,20 @@ namespace Virus
registerParams();
// add lambda to enforce updating patches when virus switch from/to multi/single.
- (findSynthParam(0, 0x72, 0x7a))->onValueChanged = [this] {
- const uint8_t prg = isMultiMode() ? 0x0 : virusLib::SINGLE;
- sendSysEx(constructMessage({MessageType::REQUEST_SINGLE, 0x0, prg}));
- sendSysEx(constructMessage({MessageType::REQUEST_MULTI, 0x0, prg}));
+ const auto& params = findSynthParam(0, 0x72, 0x7a);
+ for (const auto& parameter : params)
+ {
+ parameter->onValueChanged = [this] {
+ const uint8_t prg = isMultiMode() ? 0x0 : virusLib::SINGLE;
+ sendSysEx(constructMessage({ MessageType::REQUEST_SINGLE, 0x0, prg }));
+ sendSysEx(constructMessage({ MessageType::REQUEST_MULTI, 0x0, prg }));
- if (onMsgDone)
- {
- onMsgDone();
- }
- };
+ if (onMsgDone)
+ {
+ onMsgDone();
+ }
+ };
+ }
sendSysEx(constructMessage({MessageType::REQUEST_TOTAL}));
sendSysEx(constructMessage({MessageType::REQUEST_ARRANGEMENT}));
@@ -84,18 +88,45 @@ namespace Virus
}
if (p->getDescription().isPublic)
{
- // lifecycle managed by host
- m_synthParams.insert_or_assign(idx, p.get());
+ // lifecycle managed by Juce
+
+ auto itExisting = m_synthParams.find(idx);
+ if (itExisting != m_synthParams.end())
+ {
+ itExisting->second.push_back(p.get());
+ }
+ else
+ {
+ ParameterList params;
+ params.emplace_back(p.get());
+ m_synthParams.insert(std::make_pair(idx, std::move(params)));
+ }
+
if (isNonPartExclusive)
{
- jassert(pt == 0);
+ jassert(part == 0);
globalParams->addChild(std::move(p));
}
else
group->addChild(std::move(p));
}
else
- m_synthInternalParams.insert_or_assign(idx, std::move(p));
+ {
+ // lifecycle handled by us
+
+ auto itExisting = m_synthInternalParams.find(idx);
+ if (itExisting != m_synthInternalParams.end())
+ {
+ itExisting->second.push_back(p.get());
+ }
+ else
+ {
+ ParameterList params;
+ params.emplace_back(p.get());
+ m_synthInternalParams.insert(std::make_pair(idx, std::move(params)));
+ }
+ m_synthInternalParamList.emplace_back(std::move(p));
+ }
}
m_processor.addParameterGroup(std::move(group));
}
@@ -152,39 +183,41 @@ namespace Virus
}
}
- Parameter *Controller::findSynthParam(const uint8_t _part, const uint8_t _page, const uint8_t _paramIndex)
+ const Controller::ParameterList& Controller::findSynthParam(const uint8_t _part, const uint8_t _page, const uint8_t _paramIndex)
{
const ParamIndex paramIndex{ _page, _part, _paramIndex };
return findSynthParam(paramIndex);
}
- Parameter* Controller::findSynthParam(const ParamIndex& _paramIndex)
+ const Controller::ParameterList& Controller::findSynthParam(const ParamIndex& _paramIndex)
{
const auto it = m_synthParams.find(_paramIndex);
- if (it == m_synthParams.end())
- {
- const auto iti = m_synthInternalParams.find(_paramIndex);
+ if (it != m_synthParams.end())
+ return it->second;
- if (iti == m_synthInternalParams.end())
- return nullptr;
+ const auto iti = m_synthInternalParams.find(_paramIndex);
- return iti->second.get();
+ if (iti == m_synthInternalParams.end())
+ {
+ static ParameterList empty;
+ return empty;
}
- return it->second;
- }
- juce::Value *Controller::getParamValue(uint8_t ch, uint8_t bank, uint8_t paramIndex)
+ return iti->second;
+ }
+
+ juce::Value* Controller::getParamValue(uint8_t ch, uint8_t bank, uint8_t paramIndex)
{
- auto *param = findSynthParam(ch, static_cast<uint8_t>(virusLib::PAGE_A + bank), paramIndex);
- if (param == nullptr)
+ const auto& params = findSynthParam(ch, static_cast<uint8_t>(virusLib::PAGE_A + bank), paramIndex);
+ if (params.empty())
{
// unregistered param?
jassertfalse;
return nullptr;
}
- return ¶m->getValueObject();
+ return ¶ms.front()->getValueObject();
}
juce::Value* Controller::getParamValue(const ParameterType _param)
@@ -193,12 +226,12 @@ namespace Virus
return res ? &res->getValueObject() : nullptr;
}
- Parameter* Controller::getParameter(const ParameterType _param)
+ Parameter* Controller::getParameter(const ParameterType _param) const
{
return getParameter(_param, 0);
}
- Parameter *Controller::getParameter(const ParameterType _param, const uint8_t _part)
+ Parameter* Controller::getParameter(const ParameterType _param, const uint8_t _part) const
{
if (_part >= m_paramsByParamType.size())
return nullptr;
@@ -216,24 +249,32 @@ namespace Virus
const auto ch = msg[pos + 1];
const auto index = msg[pos + 2];
const auto value = msg[pos + 3];
- auto param = findSynthParam(ch, page, index);
- if (param == nullptr && ch != 0)
+
+ const auto& partParams = findSynthParam(ch, page, index);
+
+ if (partParams.empty() && ch != 0)
{
// ensure it's not global
- param = findSynthParam(0, page, index);
- if (param == nullptr)
+ const auto& globalParams = findSynthParam(0, page, index);
+ if (globalParams.empty())
{
jassertfalse;
return;
}
- auto flags = param->getDescription().classFlags;
- if (!(flags & Parameter::Class::GLOBAL) && !(flags & Parameter::Class::NON_PART_SENSITIVE))
+ for (const auto& param : globalParams)
{
- jassertfalse;
- return;
+ auto flags = param->getDescription().classFlags;
+ if (!(flags & Parameter::Class::GLOBAL) && !(flags & Parameter::Class::NON_PART_SENSITIVE))
+ {
+ jassertfalse;
+ return;
+ }
}
- }
- param->setValueFromSynth(value, true);
+ for (const auto& param : globalParams)
+ param->setValueFromSynth(value, true);
+ }
+ for (const auto& param : partParams)
+ param->setValueFromSynth(value, true);
// TODO:
/**
If a
@@ -357,11 +398,15 @@ namespace Virus
for (size_t i = 0; i < std::size(patch.data); i++)
{
const uint8_t page = virusLib::PAGE_A + static_cast<uint8_t>(i / pageSize);
- if (auto *p = findSynthParam(ch, page, i % pageSize))
+ const auto& params = findSynthParam(ch, page, i % pageSize);
+ if (!params.empty())
{
- if((p->getDescription().classFlags & Parameter::MULTI_OR_SINGLE) && isMultiMode())
- continue;
- p->setValueFromSynth(patch.data[i], true);
+ for (const auto& param : params)
+ {
+ if ((param->getDescription().classFlags & Parameter::MULTI_OR_SINGLE) && isMultiMode())
+ continue;
+ param->setValueFromSynth(patch.data[i], true);
+ }
}
}
if (onProgramChange)
@@ -396,13 +441,13 @@ namespace Virus
if (patch.bankNumber == 0) {
for (uint8_t pt = 0; pt < 16; pt++) {
for(int i = 0; i < 8; i++) {
- if (auto* p = findSynthParam(pt, virusLib::PAGE_C, virusLib::PART_MIDI_CHANNEL+i)) {
- p->setValueFromSynth(patch.data[virusLib::MD_PART_MIDI_CHANNEL + (i*16) + pt], true);
- }
+ const auto& params = findSynthParam(pt, virusLib::PAGE_C, virusLib::PART_MIDI_CHANNEL + i);
+ for (const auto& p : params)
+ p->setValueFromSynth(patch.data[virusLib::MD_PART_MIDI_CHANNEL + (i * 16) + pt], true);
}
- if (auto* p = findSynthParam(pt, virusLib::PAGE_B, virusLib::CLOCK_TEMPO)) {
+ const auto& params = findSynthParam(pt, virusLib::PAGE_B, virusLib::CLOCK_TEMPO);
+ for (const auto& p : params)
p->setValueFromSynth(patch.data[virusLib::MD_CLOCK_TEMPO], true);
- }
/* if (auto* p = findSynthParam(pt, virusLib::PAGE_A, virusLib::EFFECT_SEND)) {
p->setValueFromSynth(patch.data[virusLib::MD_PART_EFFECT_SEND], true);
}*/
@@ -439,8 +484,8 @@ namespace Virus
return;
DBG(juce::String::formatted("Set part: %d bank: %s param: %d value: %d", part, page == 0 ? "A" : "B", m.b, m.c));
- auto* p = findSynthParam(part, page, m.b);
- if(p)
+ const auto& params = findSynthParam(part, page, m.b);
+ for (const auto & p : params)
p->setValueFromSynth(m.c, true);
}
diff --git a/source/jucePlugin/VirusController.h b/source/jucePlugin/VirusController.h
@@ -39,10 +39,10 @@ namespace Virus
// ch - [0-15]
// bank - [0-2] (ABC)
// paramIndex - [0-127]
- 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);
+ juce::Value* getParamValue(uint8_t ch, uint8_t bank, uint8_t paramIndex);
+ juce::Value* getParamValue(ParameterType _param);
+ Parameter* getParameter(ParameterType _param) const;
+ Parameter *getParameter(ParameterType _param, uint8_t _part) const;
uint8_t getVirusModel() const;
// bank - 0-1 (AB)
juce::StringArray getSinglePresetNames(virusLib::BankNumber bank) const;
@@ -104,15 +104,18 @@ namespace Virus
}
};
- std::map<ParamIndex, std::unique_ptr<Parameter>> m_synthInternalParams;
- std::map<ParamIndex, Parameter *> m_synthParams; // exposed and managed by audio processor
- std::array<std::vector<Parameter*>, 16> m_paramsByParamType;
+ using ParameterList = std::vector<Parameter*>;
+
+ std::map<ParamIndex, ParameterList> m_synthInternalParams;
+ std::map<ParamIndex, ParameterList> m_synthParams; // exposed and managed by audio processor
+ std::array<ParameterList, 16> m_paramsByParamType;
+ std::vector<std::unique_ptr<Parameter>> m_synthInternalParamList;
void registerParams();
// tries to find synth param in both internal and host.
// @return found parameter or nullptr if none found.
- Parameter *findSynthParam(uint8_t _part, uint8_t _page, uint8_t _paramIndex);
- Parameter* findSynthParam(const ParamIndex& _paramIndex);
+ const ParameterList& findSynthParam(uint8_t _part, uint8_t _page, uint8_t _paramIndex);
+ const ParameterList& findSynthParam(const ParamIndex& _paramIndex);
// unchecked copy for patch data bytes
static inline uint8_t copyData(const SysEx &src, int startPos, std::array<uint8_t, kDataSizeInBytes>& dst);