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 01bac3c2da514dafba3b45ef323033313c820fe2
parent 7c35bf93294df2a80669c6eebf7009ae214d8140
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Tue, 30 Apr 2024 00:14:24 +0200

add controller map parser

Diffstat:
Msource/jucePluginLib/parameterdescriptions.cpp | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msource/jucePluginLib/parameterdescriptions.h | 4++++
Msource/mqJucePlugin/parameterDescriptions_mq.json | 216++++++++++++++++++++++++++++++++++++++++----------------------------------------
3 files changed, 182 insertions(+), 108 deletions(-)

diff --git a/source/jucePluginLib/parameterdescriptions.cpp b/source/jucePluginLib/parameterdescriptions.cpp @@ -394,6 +394,9 @@ namespace pluginLib const auto regions = json["regions"].getArray(); parseParameterRegions(errors, regions); + const auto controllers = json["controllerMap"].getArray(); + parseControllerMap(errors, controllers); + auto res = errors.str(); if(!res.empty()) @@ -789,4 +792,71 @@ namespace pluginLib m_regions.insert({id, ParameterRegion(id, name, std::move(paramMap))}); } + + void ParameterDescriptions::parseControllerMap(std::stringstream& _errors, const juce::Array<juce::var>* _controllers) + { + if(!_controllers) + return; + + for (const auto& controller : *_controllers) + parseController(_errors, controller); + } + + void ParameterDescriptions::parseController(std::stringstream& _errors, const juce::var& _value) + { + const auto ccStr = _value["cc"].toString().toStdString(); + const auto ppStr = _value["pp"].toString().toStdString(); + const auto paramName = _value["param"].toString().toStdString(); + + if(ccStr.empty() && ppStr.empty()) + { + _errors << "Controller needs to define control change (cc) or poly pressure (pp) parameter\n"; + return; + } + + static constexpr uint8_t Invalid = 0xff; + + uint8_t cc = Invalid; + uint8_t pp = Invalid; + + if(!ccStr.empty()) + { + cc = static_cast<uint8_t>(::strtol(ccStr.c_str(), nullptr, 10)); + if(cc < 0 || cc > 127) + { + _errors << "Controller needs to be in range 0-127, param " << paramName << '\n'; + return; + } + } + + if(!ppStr.empty()) + { + pp = static_cast<uint8_t>(::strtol(ppStr.c_str(), nullptr, 10)); + if(pp < 0 || pp > 127) + { + _errors << "Poly Pressure parameter needs to be in range 0-127, param " << paramName << '\n'; + return; + } + } + + if(paramName.empty()) + { + _errors << "Target parameter name 'param' must not be empty\n"; + return; + } + + uint32_t paramIndex = 0; + + if(!getIndexByName(paramIndex, paramName)) + { + _errors << "Parameter with name " << paramName << " not found\n"; + return; + } + + if(cc != Invalid) + m_controllerMap[synthLib::M_CONTROLCHANGE][cc].push_back(paramIndex); + + if(pp != Invalid) + m_controllerMap[synthLib::M_POLYPRESSURE][pp].push_back(paramIndex); + } } diff --git a/source/jucePluginLib/parameterdescriptions.h b/source/jucePluginLib/parameterdescriptions.h @@ -50,11 +50,15 @@ namespace pluginLib void parseParameterRegions(std::stringstream& _errors, const juce::Array<juce::var>* _regions); void parseParameterRegion(std::stringstream& _errors, const juce::var& _value); + void parseControllerMap(std::stringstream& _errors, const juce::Array<juce::var>* _controllers); + void parseController(std::stringstream& _errors, const juce::var& _value); + std::unordered_map<std::string, ValueList> m_valueLists; std::vector<Description> m_descriptions; std::unordered_map<std::string, uint32_t> m_nameToIndex; std::unordered_map<std::string, MidiPacket> m_midiPackets; std::vector<ParameterLink> m_parameterLinks; std::unordered_map<std::string, ParameterRegion> m_regions; + std::unordered_map<uint8_t, std::unordered_map<uint8_t, std::vector<uint32_t>>> m_controllerMap; // type (control change, poly pressure) => index (modwheel, main vol, ...) => parameter index }; } diff --git a/source/mqJucePlugin/parameterDescriptions_mq.json b/source/mqJucePlugin/parameterDescriptions_mq.json @@ -2816,112 +2816,112 @@ {"type": "byte", "value": "f7"} ] }, - "midiMap": [ - {"cc": 3 , "param": "F1Cutoff"}, - {"cc": 3 , "param": "F2Cutoff"}, - {"cc": 6 , "param": "F1Resonance"}, - {"cc": 6 , "param": "F2Resonance"}, - {"cc": 12, "param": "ArpOctaveRange"}, - {"cc": 13, "param": "ArpLength"}, - {"cc": 14, "param": "ArpMode"}, - {"cc": 15, "param": "Lfo1Shape"}, - {"cc": 16, "param": "Lfo1Speed"}, - {"cc": 17, "param": "Lfo1Sync"}, - {"cc": 18, "param": "Lfo1Delay"}, - {"cc": 19, "param": "Lfo2Shape"}, - {"cc": 20, "param": "Lfo2Speed"}, - {"cc": 21, "param": "Lfo2Sync"}, - {"cc": 22, "param": "Lfo2Delay"}, - {"cc": 23, "param": "Lfo3Shape"}, - {"cc": 24, "param": "Lfo3Speed"}, - {"cc": 25, "param": "Lfo3Sync"}, - {"cc": 26, "param": "Lfo3Delay"}, - {"cc": 27, "param": "O1Octave"}, - {"cc": 28, "param": "O1Semi"}, - {"cc": 29, "param": "O1Detune"}, - {"cc": 30, "param": "O1FmAmount"}, - {"cc": 31, "param": "O1Shape"}, - {"cc": 33, "param": "O1PulseWidth"}, - {"cc": 34, "param": "O1Pwm"}, - {"cc": 35, "param": "O2Octave"}, - {"cc": 36, "param": "O2Semi"}, - {"cc": 37, "param": "O2Detune"}, - {"cc": 38, "param": "O2FmAmount"}, - {"cc": 39, "param": "O2Shape"}, - {"cc": 40, "param": "O2PulseWidth"}, - {"cc": 41, "param": "O2Pwm"}, - {"cc": 42, "param": "O3Octave"}, - {"cc": 43, "param": "O3Semi"}, - {"cc": 44, "param": "O3Detune"}, - {"cc": 45, "param": "O3FmAmount"}, - {"cc": 46, "param": "O3Shape"}, - {"cc": 47, "param": "O3PulseWidth"}, - {"cc": 48, "param": "O3Pwm"}, - {"cc": 49, "param": "Sync"}, - {"cc": 50, "param": "PitchModAmount"}, - {"cc": 51, "param": "GlideMode"}, - {"cc": 52, "param": "O1Level"}, - {"cc": 53, "param": "O1Balance"}, - {"cc": 54, "param": "RingModLevel"}, - {"cc": 55, "param": "RingModBalance"}, - {"cc": 56, "param": "O2Level"}, - {"cc": 57, "param": "O2Balance"}, - {"cc": 58, "param": "O3Level"}, - {"cc": 59, "param": "O3Balance"}, - {"cc": 60, "param": "NoiseLevel"}, - {"cc": 61, "param": "NoiseBalance"}, - {"cc": 66, "param": "GlideEnable"}, - {"cc": 67, "param": "FilterRouting"}, - {"cc": 68, "param": "F1Type"}, - {"cc": 69, "param": "F1Cutoff"}, - {"cc": 70, "param": "F1Resonance"}, - {"cc": 71, "param": "F1Drive"}, - {"cc": 72, "param": "F1KeyTrack"}, - {"cc": 73, "param": "F1EnvMod"}, - {"cc": 74, "param": "F1VelMod"}, - {"cc": 75, "param": "F1CutoffMod"}, - {"cc": 76, "param": "F1FmAmount"}, - {"cc": 77, "param": "F1Pan"}, - {"cc": 78, "param": "F1PanMod"}, - {"cc": 79, "param": "F2Type"}, - {"cc": 80, "param": "F2Cutoff"}, - {"cc": 81, "param": "F2Resonance"}, - {"cc": 82, "param": "F2Drive"}, - {"cc": 83, "param": "F2KeyTrack"}, - {"cc": 84, "param": "F2EnvMod"}, - {"cc": 85, "param": "F2VelMod"}, - {"cc": 86, "param": "F2CutoffMod"}, - {"cc": 87, "param": "F2FmAmount"}, - {"cc": 88, "param": "F2Pan"}, - {"cc": 89, "param": "F2PanMod"}, - {"cc": 90, "param": "AmpVolume"}, - {"cc": 91, "param": "AmpVelocity"}, - {"cc": 92, "param": "AmpModAmount"}, - {"cc": 93, "param": "FX1Mix"}, - {"cc": 94, "param": "FX2Mix"}, - {"cc": 95, "param": "FilterEnvAttack"}, - {"cc": 96, "param": "FilterEnvDecay"}, - {"cc": 97, "param": "FilterEnvSustain"}, - {"cc": 98, "param": "FilterEnvDecay2"}, - {"cc": 99, "param": "FilterEnvSustain2"}, - {"cc": 100, "param": "FilterEnvRelease"}, - {"cc": 101, "param": "AmpEnvAttack"}, - {"cc": 102, "param": "AmpEnvDecay"}, - {"cc": 103, "param": "AmpEnvSustain"}, - {"cc": 104, "param": "AmpEnvDecay2"}, - {"cc": 105, "param": "AmpEnvSustain2"}, - {"cc": 106, "param": "AmpEnvRelease"}, - {"cc": 107, "param": "Env3Attack"}, - {"cc": 108, "param": "Env3Decay"}, - {"cc": 109, "param": "Env3Sustain"}, - {"cc": 110, "param": "Env3Decay2"}, - {"cc": 111, "param": "Env3Sustain2"}, - {"cc": 112, "param": "Env3Release"}, - {"cc": 113, "param": "Env4Attack"}, - {"cc": 114, "param": "Env4Decay"}, - {"cc": 115, "param": "Env4Sustain"}, - {"cc": 116, "param": "Env4Decay2"}, - {"cc": 117, "param": "Env4Sustain2"}, - {"cc": 118, "param": "Env4Release"} - ] + "controllerMap": [ + {"cc": 3 , "param": "F1Cutoff"}, + {"cc": 3 , "param": "F2Cutoff"}, + {"cc": 6 , "param": "F1Resonance"}, + {"cc": 6 , "param": "F2Resonance"}, + {"cc": 12, "param": "ArpOctaveRange"}, + {"cc": 13, "param": "ArpLength"}, + {"cc": 14, "param": "ArpMode"}, + {"cc": 15, "param": "Lfo1Shape"}, + {"cc": 16, "param": "Lfo1Speed"}, + {"cc": 17, "param": "Lfo1Sync"}, + {"cc": 18, "param": "Lfo1Delay"}, + {"cc": 19, "param": "Lfo2Shape"}, + {"cc": 20, "param": "Lfo2Speed"}, + {"cc": 21, "param": "Lfo2Sync"}, + {"cc": 22, "param": "Lfo2Delay"}, + {"cc": 23, "param": "Lfo3Shape"}, + {"cc": 24, "param": "Lfo3Speed"}, + {"cc": 25, "param": "Lfo3Sync"}, + {"cc": 26, "param": "Lfo3Delay"}, + {"cc": 27, "param": "O1Octave"}, + {"cc": 28, "param": "O1Semi"}, + {"cc": 29, "param": "O1Detune"}, + {"cc": 30, "param": "O1FmAmount"}, + {"cc": 31, "param": "O1Shape"}, + {"cc": 33, "param": "O1PulseWidth"}, + {"cc": 34, "param": "O1Pwm"}, + {"cc": 35, "param": "O2Octave"}, + {"cc": 36, "param": "O2Semi"}, + {"cc": 37, "param": "O2Detune"}, + {"cc": 38, "param": "O2FmAmount"}, + {"cc": 39, "param": "O2Shape"}, + {"cc": 40, "param": "O2PulseWidth"}, + {"cc": 41, "param": "O2Pwm"}, + {"cc": 42, "param": "O3Octave"}, + {"cc": 43, "param": "O3Semi"}, + {"cc": 44, "param": "O3Detune"}, + {"cc": 45, "param": "O3FmAmount"}, + {"cc": 46, "param": "O3Shape"}, + {"cc": 47, "param": "O3PulseWidth"}, + {"cc": 48, "param": "O3Pwm"}, + {"cc": 49, "param": "Sync"}, + {"cc": 50, "param": "PitchModAmount"}, + {"cc": 51, "param": "GlideMode"}, + {"cc": 52, "param": "O1Level"}, + {"cc": 53, "param": "O1Balance"}, + {"cc": 54, "param": "RingModLevel"}, + {"cc": 55, "param": "RingModBalance"}, + {"cc": 56, "param": "O2Level"}, + {"cc": 57, "param": "O2Balance"}, + {"cc": 58, "param": "O3Level"}, + {"cc": 59, "param": "O3Balance"}, + {"cc": 60, "param": "NoiseLevel"}, + {"cc": 61, "param": "NoiseBalance"}, + {"cc": 66, "param": "GlideEnable"}, + {"cc": 67, "param": "FilterRouting"}, + {"cc": 68, "param": "F1Type"}, + {"cc": 69, "param": "F1Cutoff"}, + {"cc": 70, "param": "F1Resonance"}, + {"cc": 71, "param": "F1Drive"}, + {"cc": 72, "param": "F1KeyTrack"}, + {"cc": 73, "param": "F1EnvMod"}, + {"cc": 74, "param": "F1VelMod"}, + {"cc": 75, "param": "F1CutoffMod"}, + {"cc": 76, "param": "F1FmAmount"}, + {"cc": 77, "param": "F1Pan"}, + {"cc": 78, "param": "F1PanMod"}, + {"cc": 79, "param": "F2Type"}, + {"cc": 80, "param": "F2Cutoff"}, + {"cc": 81, "param": "F2Resonance"}, + {"cc": 82, "param": "F2Drive"}, + {"cc": 83, "param": "F2KeyTrack"}, + {"cc": 84, "param": "F2EnvMod"}, + {"cc": 85, "param": "F2VelMod"}, + {"cc": 86, "param": "F2CutoffMod"}, + {"cc": 87, "param": "F2FmAmount"}, + {"cc": 88, "param": "F2Pan"}, + {"cc": 89, "param": "F2PanMod"}, + {"cc": 90, "param": "AmpVolume"}, + {"cc": 91, "param": "AmpVelocity"}, + {"cc": 92, "param": "AmpModAmount"}, + {"cc": 93, "param": "FX1Mix"}, + {"cc": 94, "param": "FX2Mix"}, + {"cc": 95, "param": "FilterEnvAttack"}, + {"cc": 96, "param": "FilterEnvDecay"}, + {"cc": 97, "param": "FilterEnvSustain"}, + {"cc": 98, "param": "FilterEnvDecay2"}, + {"cc": 99, "param": "FilterEnvSustain2"}, + {"cc": 100, "param": "FilterEnvRelease"}, + {"cc": 101, "param": "AmpEnvAttack"}, + {"cc": 102, "param": "AmpEnvDecay"}, + {"cc": 103, "param": "AmpEnvSustain"}, + {"cc": 104, "param": "AmpEnvDecay2"}, + {"cc": 105, "param": "AmpEnvSustain2"}, + {"cc": 106, "param": "AmpEnvRelease"}, + {"cc": 107, "param": "Env3Attack"}, + {"cc": 108, "param": "Env3Decay"}, + {"cc": 109, "param": "Env3Sustain"}, + {"cc": 110, "param": "Env3Decay2"}, + {"cc": 111, "param": "Env3Sustain2"}, + {"cc": 112, "param": "Env3Release"}, + {"cc": 113, "param": "Env4Attack"}, + {"cc": 114, "param": "Env4Decay"}, + {"cc": 115, "param": "Env4Sustain"}, + {"cc": 116, "param": "Env4Decay2"}, + {"cc": 117, "param": "Env4Sustain2"}, + {"cc": 118, "param": "Env4Release"} + ] }