diff --git a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp index ad464e3625..7049f60b2e 100644 --- a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp @@ -437,7 +437,7 @@ public: Vst::ParamID getProgramParamID() const noexcept { return programParamID; } bool isBypassRegularParameter() const noexcept { return bypassIsRegularParameter; } - void setParameterValue (size_t paramIndex, float value) + void setParameterValue (Steinberg::int32 paramIndex, float value) { cachedParamValues.set (paramIndex, value); } @@ -445,7 +445,7 @@ public: template void forAllChangedParameters (Callback&& callback) { - cachedParamValues.ifSet ([&] (size_t index, float value) + cachedParamValues.ifSet ([&] (Steinberg::int32 index, float value) { callback (cachedParamValues.getParamID (index), value); }); @@ -1176,7 +1176,7 @@ public: endEdit (vstParamId); } - void paramChanged (int parameterIndex, Vst::ParamID vstParamId, double newValue) + void paramChanged (Steinberg::int32 parameterIndex, Vst::ParamID vstParamId, double newValue) { if (inParameterChangedCallback.get()) return; @@ -1189,7 +1189,7 @@ public: } else { - audioProcessor->setParameterValue ((size_t) parameterIndex, (float) newValue); + audioProcessor->setParameterValue (parameterIndex, (float) newValue); } } diff --git a/modules/juce_audio_processors/format_types/juce_VST3Common.h b/modules/juce_audio_processors/format_types/juce_VST3Common.h index 8ef0fe3e43..99355fdc6f 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3Common.h +++ b/modules/juce_audio_processors/format_types/juce_VST3Common.h @@ -991,6 +991,11 @@ private: We must iterate all parameters on each processBlock call to check whether any parameter value has changed. This class attempts to make this polling process as quick as possible. + + The indices here are of type Steinberg::int32, as they are expected to correspond + to parameter information obtained from the IEditController. These indices may not + match the indices of parameters returned from AudioProcessor::getParameters(), so + be careful! */ class CachedParamValues { @@ -1002,14 +1007,20 @@ public: size_t size() const noexcept { return floatCache.size(); } - Steinberg::Vst::ParamID getParamID (size_t index) const noexcept { return paramIds[index]; } + Steinberg::Vst::ParamID getParamID (Steinberg::int32 index) const noexcept { return paramIds[(size_t) index]; } - void set (size_t index, float value) { floatCache.set (index, value); } + void set (Steinberg::int32 index, float value) { floatCache.set ((size_t) index, value); } - float get (size_t index) const noexcept { return floatCache.get (index); } + float get (Steinberg::int32 index) const noexcept { return floatCache.get ((size_t) index); } template - void ifSet (Callback&& callback) { floatCache.ifSet (std::forward (callback)); } + void ifSet (Callback&& callback) + { + floatCache.ifSet ([&] (size_t index, float value) + { + callback ((Steinberg::int32) index, value); + }); + } private: std::vector paramIds; diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index 85c7caa89c..e60e327f22 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -103,7 +103,7 @@ class EditControllerParameterDispatcher : private Timer public: ~EditControllerParameterDispatcher() override { stopTimer(); } - void push (size_t index, float value) + void push (Steinberg::int32 index, float value) { if (controller == nullptr) return; @@ -123,7 +123,7 @@ public: void flush() { - cache.ifSet ([this] (size_t index, float value) + cache.ifSet ([this] (Steinberg::int32 index, float value) { controller->setParamNormalized (cache.getParamID (index), value); }); @@ -1839,7 +1839,7 @@ struct VST3ComponentHolder class ParamValueQueue : public Vst::IParamValueQueue { public: - ParamValueQueue (Vst::ParamID idIn, size_t parameterIndexIn) + ParamValueQueue (Vst::ParamID idIn, Steinberg::int32 parameterIndexIn) : paramId (idIn), parameterIndex (parameterIndexIn) {} virtual ~ParamValueQueue() = default; @@ -1849,7 +1849,7 @@ public: Vst::ParamID PLUGIN_API getParameterId() override { return paramId; } - size_t getParameterIndex() const noexcept { return parameterIndex; } + Steinberg::int32 getParameterIndex() const noexcept { return parameterIndex; } Steinberg::int32 PLUGIN_API getPointCount() override { return size; } @@ -1892,7 +1892,7 @@ public: private: const Vst::ParamID paramId; - const size_t parameterIndex; + const Steinberg::int32 parameterIndex; float cachedValue; Steinberg::int32 size = 0; Atomic refCount; @@ -1981,10 +1981,10 @@ public: void initialise (const std::vector& idsIn) { - size_t index = 0; + Steinberg::int32 index = 0; for (const auto& id : idsIn) - map.emplace (id, Entry { std::make_unique (id, index++) }); + map.emplace (id, Entry { std::make_unique (id, Steinberg::int32 { index++ }) }); queues.reserve (map.size()); queues.clear(); @@ -2014,7 +2014,7 @@ public: struct VST3Parameter final : public Parameter { VST3Parameter (VST3PluginInstance& parent, - int vstParameterIndex, + Steinberg::int32 vstParameterIndex, Steinberg::Vst::ParamID parameterID, bool parameterIsAutomatable) : pluginInstance (parent), @@ -2026,15 +2026,15 @@ public: float getValue() const override { - return pluginInstance.cachedParamValues.get ((size_t) vstParamIndex); + return pluginInstance.cachedParamValues.get (vstParamIndex); } /* The 'normal' setValue call, which will update both the processor and editor. */ void setValue (float newValue) override { - pluginInstance.cachedParamValues.set ((size_t) vstParamIndex, newValue); - pluginInstance.parameterDispatcher.push ((size_t) vstParamIndex, newValue); + pluginInstance.cachedParamValues.set (vstParamIndex, newValue); + pluginInstance.parameterDispatcher.push (vstParamIndex, newValue); } /* If the editor set the value, there's no need to notify it that the parameter @@ -2044,7 +2044,7 @@ public: */ void setValueFromEditor (float newValue) { - pluginInstance.cachedParamValues.set ((size_t) vstParamIndex, newValue); + pluginInstance.cachedParamValues.set (vstParamIndex, newValue); sendValueChangedMessageToListeners (newValue); } @@ -2122,7 +2122,7 @@ public: } VST3PluginInstance& pluginInstance; - const int vstParamIndex; + const Steinberg::int32 vstParamIndex; const Steinberg::Vst::ParamID paramID; const bool automatable; const bool discrete = getNumSteps() != AudioProcessor::getDefaultNumParameterSteps(); @@ -2373,10 +2373,18 @@ public: } //============================================================================== - VST3Parameter* getParameterForID (Vst::ParamID paramID) + /* Important: It is strongly recommended to use this function if you need to + find the JUCE parameter corresponding to a particular IEditController + parameter. + + Note that a parameter at a given index in the IEditController does not + necessarily correspond to the parameter at the same index in + AudioProcessor::getParameters(). + */ + VST3Parameter* getParameterForID (Vst::ParamID paramID) const { - const auto index = getIndexOfParamID (paramID); - return index < 0 ? nullptr : static_cast (getParameters()[index]); + const auto it = idToParamMap.find (paramID); + return it != idToParamMap.end() ? it->second : nullptr; } //============================================================================== @@ -2459,14 +2467,14 @@ public: associateWith (data, buffer); associateWith (data, midiMessages); - cachedParamValues.ifSet ([&] (size_t index, float value) + cachedParamValues.ifSet ([&] (Steinberg::int32 index, float value) { inputParameterChanges->set (cachedParamValues.getParamID (index), value); }); processor->process (data); - outputParameterChanges->forEach ([&] (size_t index, float value) + outputParameterChanges->forEach ([&] (Steinberg::int32 index, float value) { parameterDispatcher.push (index, value); }); @@ -2886,38 +2894,7 @@ private: StringArray programNames; Vst::ParamID programParameterID = (Vst::ParamID) -1; - std::map paramToIndexMap; - - int getMappedParamID (Vst::ParamID paramID) const - { - auto it = paramToIndexMap.find (paramID); - return it != paramToIndexMap.end() ? it->second : -1; - } - - int getIndexOfParamID (Vst::ParamID paramID) - { - if (editController == nullptr) - return -1; - - auto result = getMappedParamID (paramID); - - if (result < 0) - { - auto numParams = editController->getParameterCount(); - - for (int i = 0; i < numParams; ++i) - { - Vst::ParameterInfo paramInfo; - editController->getParameterInfo (i, paramInfo); - paramToIndexMap[paramInfo.id] = i; - } - - result = getMappedParamID (paramID); - } - - return result; - } - + std::map idToParamMap; EditControllerParameterDispatcher parameterDispatcher; //============================================================================== @@ -3045,6 +3022,19 @@ private: } setParameterTree (std::move (newParameterTree)); + + idToParamMap = [this] + { + std::map result; + + for (auto* parameter : getParameters()) + { + auto* vst3Param = static_cast (parameter); + result.emplace (vst3Param->getParamID(), vst3Param); + } + + return result; + }(); } void synchroniseStates() @@ -3216,12 +3206,12 @@ private: destination.processContext = &timingInfo; } - Vst::ParameterInfo getParameterInfoForIndex (int index) const + Vst::ParameterInfo getParameterInfoForIndex (Steinberg::int32 index) const { Vst::ParameterInfo paramInfo{}; if (processor != nullptr) - editController->getParameterInfo (index, paramInfo); + editController->getParameterInfo ((int32) index, paramInfo); return paramInfo; }