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 f88bf8adad2daaf030097491213d4c204dcc03eb
parent 9f12d2676b04923dfcb323e2bd26a140846492af
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Thu, 26 May 2022 02:26:58 +0200

add support for parameter default values in parameter descriptions json

Diffstat:
Msource/jucePlugin/CMakeLists.txt | 2--
Msource/jucePlugin/VirusController.cpp | 8--------
Msource/jucePlugin/VirusController.h | 1-
Msource/jucePlugin/parameterDescriptions_C.json | 12++++++------
Msource/jucePluginLib/controller.cpp | 5+++++
Msource/jucePluginLib/controller.h | 2+-
Msource/jucePluginLib/parameter.cpp | 7+++++++
Msource/jucePluginLib/parameter.h | 7+++++++
Msource/jucePluginLib/parameterdescription.h | 3+++
Msource/jucePluginLib/parameterdescriptions.cpp | 31+++++++++++++++++++++++++++++--
10 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/source/jucePlugin/CMakeLists.txt b/source/jucePlugin/CMakeLists.txt @@ -21,8 +21,6 @@ set(SOURCES PluginProcessor.h VirusController.cpp VirusController.h - VirusParameter.cpp - VirusParameter.h VirusParameterBinding.cpp VirusParameterBinding.h version.h diff --git a/source/jucePlugin/VirusController.cpp b/source/jucePlugin/VirusController.cpp @@ -2,9 +2,6 @@ #include <fstream> -#include "VirusParameter.h" - -#include "BinaryData.h" #include "ParameterNames.h" #include "PluginProcessor.h" @@ -557,11 +554,6 @@ namespace Virus return sendSysEx(MidiPacketType::ParameterChange, data); } - pluginLib::Parameter* Controller::createParameter(pluginLib::Controller& _controller, const pluginLib::Description& _desc, uint8_t _part, int _uid) - { - return new Parameter(_controller, _desc, _part, _uid); - } - std::vector<uint8_t> Controller::createSingleDump(uint8_t _part, uint8_t _bank, uint8_t _program) { pluginLib::MidiPacket::Data data; diff --git a/source/jucePlugin/VirusController.h b/source/jucePlugin/VirusController.h @@ -52,7 +52,6 @@ namespace Virus // this is called by the plug-in on audio thread! void dispatchVirusOut(const std::vector<synthLib::SMidiEvent> &); - pluginLib::Parameter* createParameter(pluginLib::Controller& _controller, const pluginLib::Description& _desc, uint8_t _part, int _uid) override; std::vector<uint8_t> createSingleDump(uint8_t _part, uint8_t _bank, uint8_t _program); std::vector<uint8_t> createSingleDump(uint8_t _bank, uint8_t _program, const pluginLib::MidiPacket::ParamValues& _paramValues); std::vector<uint8_t> modifySingleDump(const std::vector<uint8_t>& _sysex, virusLib::BankNumber _newBank, uint8_t _newProgram, bool _modifyBank, bool _modifyProgram); diff --git a/source/jucePlugin/parameterDescriptions_C.json b/source/jucePlugin/parameterDescriptions_C.json @@ -32,7 +32,7 @@ {"page":112, "index":18, "name":"Osc1 Pulsewidth", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":19, "name":"Osc1 Wave Select", "min":0, "max":63, "toText":"oscWave", "isPublic":true, "isDiscrete":true, "isBool":false}, {"page":112, "index":20, "name":"Osc1 Semitone", "min":16, "max":112, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, - {"page":112, "index":21, "name":"Osc1 Keyfollow", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, + {"page":112, "index":21, "name":"Osc1 Keyfollow", "min":0, "max":127, "default":96, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":22, "name":"Osc2 Shape", "min":0, "max":127, "toText":"oscShape", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":23, "name":"Osc2 Pulsewidth", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":24, "name":"Osc2 Wave Select", "min":0, "max":63, "toText":"oscWave", "isPublic":true, "isDiscrete":true, "isBool":false}, @@ -42,17 +42,17 @@ {"page":112, "index":28, "name":"Osc2 Sync", "min":0, "max":1, "isPublic":true, "isDiscrete":false, "isBool":true}, {"page":112, "index":29, "name":"Osc2 Filt Env Amt", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":30, "name":"FM Filt Env Amt", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, - {"page":112, "index":31, "name":"Osc2 Keyfollow", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, + {"page":112, "index":31, "name":"Osc2 Keyfollow", "min":0, "max":127, "default":96, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":32, "name":"Bank Select", "min":0, "max":8, "toText":"bank", "isPublic":false, "isDiscrete":true, "isBool":false}, {"page":112, "index":33, "name":"Osc Balance", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":34, "name":"Suboscillator Volume", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":35, "name":"Suboscillator Shape", "min":0, "max":1, "toText":"suboscShape", "isDiscrete":true, "isBool":true, "isBipolar":false}, - {"page":112, "index":36, "name":"Osc Mainvolume", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, + {"page":112, "index":36, "name":"Osc Mainvolume", "min":0, "max":127, "default":64, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":37, "name":"Noise Volume", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":38, "name":"Ringmodulator Volume", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":39, "name":"Noise Color", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, - {"page":112, "index":40, "name":"Cutoff", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, - {"page":112, "index":41, "name":"Cutoff2", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, + {"page":112, "index":40, "name":"Cutoff", "min":0, "max":127, "default":127, "isPublic":true, "isDiscrete":false, "isBool":false}, + {"page":112, "index":41, "name":"Cutoff2", "min":0, "max":127, "default":64, "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":42, "name":"Filter1 Resonance", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":43, "name":"Filter2 Resonance", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":44, "name":"Filter1 Env Amt", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, @@ -101,7 +101,7 @@ {"page":112, "index":88, "name":"Cutoff1 Lfo2 Amount", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":89, "name":"Cutoff2 Lfo2 Amount", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":90, "name":"Pan Lfo2 Amount", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, - {"page":112, "index":91, "name":"Patch Volume", "min":0, "max":127, "isPublic":true, "isDiscrete":false, "isBool":false}, + {"page":112, "index":91, "name":"Patch Volume", "min":0, "max":127, "default":100, "isPublic":true, "isDiscrete":false, "isBool":false}, {"page":112, "index":92, "name":"A_Undefined92", "min":0, "max":127, "toText":"unsignedZero", "isPublic":false, "isDiscrete":false, "isBool":false}, {"page":112, "index":93, "name":"Transpose", "min":0, "max":127, "toText":"signed", "isPublic":true, "isDiscrete":false, "isBool":false, "isBipolar":true}, {"page":112, "index":94, "name":"Key Mode", "min":0, "max":5, "toText":"keyMode", "isPublic":true, "isDiscrete":true, "isBool":false}, diff --git a/source/jucePluginLib/controller.cpp b/source/jucePluginLib/controller.cpp @@ -227,4 +227,9 @@ namespace pluginLib } return false; } + + Parameter* Controller::createParameter(Controller& _controller, const Description& _desc, uint8_t _part, int _uid) + { + return new Parameter(_controller, _desc, _part, _uid); + } } diff --git a/source/jucePluginLib/controller.h b/source/jucePluginLib/controller.h @@ -31,7 +31,7 @@ namespace pluginLib bool parseMidiPacket(std::string& _name, MidiPacket::Data& _data, MidiPacket::ParamValues& _parameterValues, const std::vector<uint8_t>& _src) const; protected: - virtual Parameter* createParameter(Controller& _controller, const Description& _desc, uint8_t _part, int _uid) = 0; + virtual Parameter* createParameter(Controller& _controller, const Description& _desc, uint8_t _part, int _uid); void registerParams(juce::AudioProcessor& _processor); private: diff --git a/source/jucePluginLib/parameter.cpp b/source/jucePluginLib/parameter.cpp @@ -109,6 +109,13 @@ namespace pluginLib return juce::String::formatted("%d_%d_%d", static_cast<int>(d.page), part, d.index); } + uint8_t Parameter::getDefault() const + { + if(m_desc.defaultValue != Description::NoDefaultValue) + return static_cast<uint8_t>(m_desc.defaultValue); + return 0; + } + void Parameter::addLinkedParameter(Parameter* _param) { if (_param == this) diff --git a/source/jucePluginLib/parameter.h b/source/jucePluginLib/parameter.h @@ -42,6 +42,13 @@ namespace pluginLib return convertTo0to1(static_cast<float>(res)); } + float getDefaultValue() const override + { + return convertTo0to1((float)getDefault()); + } + + virtual uint8_t getDefault() const; + juce::String getText(float normalisedValue, int /*maximumStringLength*/) const override { const auto v = convertFrom0to1(normalisedValue); diff --git a/source/jucePluginLib/parameterdescription.h b/source/jucePluginLib/parameterdescription.h @@ -36,12 +36,15 @@ namespace pluginLib }; struct Description { + static constexpr int NoDefaultValue = std::numeric_limits<int>::max(); + uint8_t page; uint8_t index; int classFlags; std::string name; std::string displayName; juce::Range<int> range; + int defaultValue = NoDefaultValue; ValueList valueList; bool isPublic; bool isDiscrete; diff --git a/source/jucePluginLib/parameterdescriptions.cpp b/source/jucePluginLib/parameterdescriptions.cpp @@ -136,13 +136,13 @@ namespace pluginLib continue; } - auto readProperty = [&](const char* _key) + auto readProperty = [&](const char* _key, bool _faiIfNotExisting = true) { auto result = props[_key]; if (!result.isVoid()) return result; result = defaultProperties[_key]; - if (result.isVoid()) + if (_faiIfNotExisting && result.isVoid()) errors << "Property " << _key << " not found for parameter description " << name << " and no default provided" << std::endl; return result; }; @@ -167,6 +167,16 @@ namespace pluginLib return static_cast<int>(res); }; + auto readPropertyIntWithDefault = [&](const char* _key, const int _defaultValue) + { + const auto res = readProperty(_key, false); + + if (!res.isInt()) + return _defaultValue; + + return static_cast<int>(res); + }; + auto readPropertyBool = [&](const char* _key) { const auto res = readProperty(_key); @@ -183,6 +193,7 @@ namespace pluginLib const auto minValue = readPropertyInt("min"); const auto maxValue = readPropertyInt("max"); + const auto defaultValue = readPropertyIntWithDefault("default", Description::NoDefaultValue); if (minValue < 0 || minValue > 127) { @@ -200,6 +211,12 @@ namespace pluginLib continue; } + if(defaultValue != Description::NoDefaultValue && (defaultValue < minValue || defaultValue > maxValue)) + { + errors << name << ": default value must be within parameter range " << minValue << " to " << maxValue << " but default value is specified as " << defaultValue << std::endl; + continue; + } + const auto valueList = readPropertyString("toText"); const auto it = m_valueLists.find(valueList); @@ -232,6 +249,16 @@ namespace pluginLib d.range.setStart(minValue); d.range.setEnd(maxValue); + d.defaultValue = defaultValue; + + if(defaultValue == Description::NoDefaultValue) + { + if(d.isBipolar) + d.defaultValue = juce::roundToInt((minValue + maxValue) * 0.5f); + else + d.defaultValue = minValue; + } + d.valueList = it->second; {