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 663aecbbabe6907eeaeb3cf9d5f2aec2ec069b9c
parent c877bc5acfa8efeab169630d4e9f0c90dbfd1540
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Sat, 16 Nov 2024 23:58:55 +0100

fix DSP crash when switching preset with locked parameters

Diffstat:
Msource/virusJucePlugin/VirusController.cpp | 28++++++++++++++++++++--------
Msource/virusJucePlugin/VirusController.h | 2+-
2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/source/virusJucePlugin/VirusController.cpp b/source/virusJucePlugin/VirusController.cpp @@ -424,14 +424,30 @@ namespace virus const auto locked = m_locking.getLockedParameterNames(ch); - for(auto it = _parameterValues.begin(); it != _parameterValues.end(); ++it) + // if there are locked parameters and the current values in the received preset do not match + // the values of the parameters that are locked, create a new preset that contains all + // locked parameter values and send it back to the device + std::unordered_set<const pluginLib::Parameter*> lockedParamsToApply; + + for (const auto& parameterValue : _parameterValues) { - auto* p = getParameter(it->first.second, ch); + auto* p = getParameter(parameterValue.first.second, ch); + // if a parameter is not locked, apply it if(locked.find(p->getDescription().name) == locked.end()) - p->setValueFromSynth(it->second, pluginLib::Parameter::Origin::PresetChange); + p->setValueFromSynth(parameterValue.second, pluginLib::Parameter::Origin::PresetChange); + // otherwise, remember the locked parameter if the locked value doesn't match the preset value + else if (parameterValue.second != p->getUnnormalizedValue()) + lockedParamsToApply.insert(p); } + // if we have any locked parameters that need to be applied, create a new preset and send it to the device + if (!lockedParamsToApply.empty()) + { + auto newDump = createSingleDump(patch.progNumber == virusLib::SINGLE ? 0 : patch.progNumber, virusLib::toMidiByte(virusLib::BankNumber::EditBuffer), patch.progNumber); + sendSysEx(newDump); + } + getProcessor().updateHostDisplay(juce::AudioProcessorListener::ChangeDetails().withProgramChanged(true)); if(m_currentPresetSource[ch] != PresetSource::Browser) @@ -520,7 +536,7 @@ namespace virus } } - bool Controller::parseControllerDump(const synthLib::SMidiEvent& m) + bool Controller::parseControllerDump(const synthLib::SMidiEvent& m) const { const uint8_t status = m.a & 0xf0; const uint8_t part = m.a & 0x0f; @@ -823,10 +839,6 @@ namespace virus sendSysEx(msg); - // if we have locked parameters, get them, send the preset and then send each locked parameter value afterward. - // Modifying the preset directly does not work because a preset might be an old version that we do not know - sendLockedParameters(static_cast<uint8_t>(_part == virusLib::SINGLE ? 0 : _part)); - requestSingle(toMidiByte(virusLib::BankNumber::EditBuffer), program); setCurrentPartPresetSource(program == virusLib::ProgramType::SINGLE ? 0 : program, PresetSource::Browser); diff --git a/source/virusJucePlugin/VirusController.h b/source/virusJucePlugin/VirusController.h @@ -173,7 +173,7 @@ namespace virus void parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _parameterValues); void parseParamChange(const pluginLib::MidiPacket::Data& _data); - bool parseControllerDump(const synthLib::SMidiEvent&); + bool parseControllerDump(const synthLib::SMidiEvent&) const; VirusProcessor& m_processor; virusLib::DeviceModel m_defaultModel;