Browse Source

VST3: Add AudioProcessorParameter behind the scenes in the VST3 wrapper to manage program parameter changes

tags/2021-05-28
ed 4 years ago
parent
commit
dd1ec144c4
1 changed files with 87 additions and 54 deletions
  1. +87
    -54
      modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp

+ 87
- 54
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -231,6 +231,11 @@ public:
return getParamForVSTParamID (bypassParamID);
}
AudioProcessorParameter* getProgramParameter() const noexcept
{
return getParamForVSTParamID (JuceAudioProcessor::paramPreset);
}
static Vst::UnitID getUnitID (const AudioProcessorParameterGroup* group)
{
if (group == nullptr || group->getParent() == nullptr)
@@ -336,6 +341,20 @@ private:
vstParamIDs.add (vstParamID);
paramMap.set (static_cast<int32> (vstParamID), juceParam);
}
auto numPrograms = audioProcessor->getNumPrograms();
if (numPrograms > 1)
{
ownedProgramParameter = std::make_unique<AudioParameterInt> ("juceProgramParameter", "Program",
0, numPrograms - 1,
audioProcessor->getCurrentProgram());
juceParameters.params.add (ownedProgramParameter.get());
vstParamIDs.add (JuceAudioProcessor::paramPreset);
paramMap.set (static_cast<int32> (JuceAudioProcessor::paramPreset), ownedProgramParameter.get());
}
}
Vst::ParamID generateVSTParamIDForParam (AudioProcessorParameter* param)
@@ -363,7 +382,7 @@ private:
//==============================================================================
LegacyAudioParametersWrapper juceParameters;
HashMap<int32, AudioProcessorParameter*> paramMap;
std::unique_ptr<AudioProcessorParameter> ownedBypassParameter;
std::unique_ptr<AudioProcessorParameter> ownedBypassParameter, ownedProgramParameter;
Array<const AudioProcessorParameterGroup*> parameterGroups;
JuceAudioProcessor() = delete;
@@ -379,8 +398,7 @@ class JuceVST3EditController : public Vst::EditController,
public Vst::IMidiMapping,
public Vst::IUnitInfo,
public Vst::ChannelContext::IInfoListener,
public AudioProcessorListener,
private AudioProcessorParameter::Listener
public AudioProcessorListener
{
public:
JuceVST3EditController (Vst::IHostApplication* host)
@@ -594,12 +612,16 @@ public:
bool setNormalized (Vst::ParamValue v) override
{
if (! isPositiveAndBelow ((int) toPlain (v), owner.getNumPrograms())
|| v == valueNormalized)
auto programValue = roundToInt (toPlain (v));
if (! isPositiveAndBelow (programValue, owner.getNumPrograms())
|| programValue == owner.getCurrentProgram())
return false;
valueNormalized = v;
owner.setCurrentProgram (programValue);
changed();
return true;
}
@@ -678,17 +700,8 @@ public:
tresult PLUGIN_API setComponentState (IBStream* stream) override
{
// Cubase and Nuendo need to inform the host of the current parameter values
if (auto* pluginInstance = getPluginInstance())
{
for (auto vstParamId : audioProcessor->vstParamIDs)
setParamNormalized (vstParamId, audioProcessor->getParamForVSTParamID (vstParamId)->getValue());
auto numPrograms = pluginInstance->getNumPrograms();
if (numPrograms > 1)
setParamNormalized (JuceAudioProcessor::paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram())
/ static_cast<Vst::ParamValue> (numPrograms - 1));
}
for (auto vstParamId : audioProcessor->vstParamIDs)
setParamNormalized (vstParamId, audioProcessor->getParamForVSTParamID (vstParamId)->getValue());
if (auto* handler = getComponentHandler())
handler->restartComponent (Vst::kParamValuesChanged);
@@ -906,7 +919,7 @@ public:
}
//==============================================================================
void paramChanged (Vst::ParamID vstParamId, float newValue)
void paramChanged (Vst::ParamID vstParamId, double newValue)
{
if (inParameterChangedCallback.get())
{
@@ -915,8 +928,8 @@ public:
}
// NB: Cubase has problems if performEdit is called without setParamNormalized
EditController::setParamNormalized (vstParamId, (double) newValue);
performEdit (vstParamId, (double) newValue);
EditController::setParamNormalized (vstParamId, newValue);
performEdit (vstParamId, newValue);
}
//==============================================================================
@@ -939,17 +952,17 @@ public:
if (auto* pluginInstance = getPluginInstance())
{
auto numPrograms = pluginInstance->getNumPrograms();
if (numPrograms > 1)
if (audioProcessor->getProgramParameter() != nullptr)
{
auto paramValue = static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram())
/ static_cast<Vst::ParamValue> (numPrograms - 1);
auto currentProgram = pluginInstance->getCurrentProgram();
auto paramValue = roundToInt (EditController::normalizedParamToPlain (JuceAudioProcessor::paramPreset,
EditController::getParamNormalized (JuceAudioProcessor::paramPreset)));
if (paramValue != EditController::getParamNormalized (JuceAudioProcessor::paramPreset))
if (currentProgram != paramValue)
{
beginEdit (JuceAudioProcessor::paramPreset);
paramChanged (JuceAudioProcessor::paramPreset, (float) paramValue);
paramChanged (JuceAudioProcessor::paramPreset,
EditController::plainParamToNormalized (JuceAudioProcessor::paramPreset, currentProgram));
endEdit (JuceAudioProcessor::paramPreset);
flags |= Vst::kParamValuesChanged;
@@ -969,19 +982,6 @@ public:
componentHandler->restartComponent (flags);
}
void parameterValueChanged (int, float newValue) override
{
// this can only come from the bypass parameter
paramChanged (audioProcessor->bypassParamID, newValue);
}
void parameterGestureChanged (int, bool gestureIsStarting) override
{
// this can only come from the bypass parameter
if (gestureIsStarting) beginEdit (audioProcessor->bypassParamID);
else endEdit (audioProcessor->bypassParamID);
}
//==============================================================================
AudioProcessor* getPluginInstance() const noexcept
{
@@ -1008,6 +1008,37 @@ private:
MidiController parameterToMidiController[(int) numMIDIChannels * (int) Vst::kCountCtrlNumber];
Vst::ParamID midiControllerToParameter[numMIDIChannels][Vst::kCountCtrlNumber];
//==============================================================================
struct OwnedParameterListener : public AudioProcessorParameter::Listener
{
OwnedParameterListener (JuceVST3EditController& editController,
AudioProcessorParameter& juceParameter,
Vst::ParamID paramID)
: owner (editController),
vstParamID (paramID)
{
juceParameter.addListener (this);
}
void parameterValueChanged (int, float newValue) override
{
owner.paramChanged (vstParamID, newValue);
}
void parameterGestureChanged (int, bool gestureIsStarting) override
{
if (gestureIsStarting)
owner.beginEdit (vstParamID);
else
owner.endEdit (vstParamID);
}
JuceVST3EditController& owner;
Vst::ParamID vstParamID;
};
std::vector<std::unique_ptr<OwnedParameterListener>> ownedParameterListeners;
//==============================================================================
std::atomic<bool> vst3IsPlaying { false },
inSetupProcessing { false };
@@ -1024,10 +1055,11 @@ private:
{
pluginInstance->addListener (this);
// as the bypass is not part of the regular parameters
// we need to listen for it explicitly
// as the bypass is not part of the regular parameters we need to listen for it explicitly
if (! audioProcessor->bypassIsRegularParameter)
audioProcessor->getBypassParameter()->addListener (this);
ownedParameterListeners.push_back (std::make_unique<OwnedParameterListener> (*this,
*audioProcessor->getBypassParameter(),
audioProcessor->bypassParamID));
if (parameters.getParameterCount() <= 0)
{
@@ -1036,6 +1068,10 @@ private:
for (int i = 0; i < n; ++i)
{
auto vstParamID = audioProcessor->getVSTParamIDForIndex (i);
if (vstParamID == JuceAudioProcessor::paramPreset)
continue;
auto* juceParam = audioProcessor->getParamForVSTParamID (vstParamID);
auto* parameterGroup = pluginInstance->getParameterTree().getGroupsForParameter (juceParam).getLast();
auto unitID = JuceAudioProcessor::getUnitID (parameterGroup);
@@ -1044,8 +1080,14 @@ private:
(vstParamID == audioProcessor->bypassParamID)));
}
if (pluginInstance->getNumPrograms() > 1)
if (auto* programParam = audioProcessor->getProgramParameter())
{
ownedParameterListeners.push_back (std::make_unique<OwnedParameterListener> (*this,
*programParam,
JuceAudioProcessor::paramPreset));
parameters.addParameter (new ProgramChangeParameter (*pluginInstance));
}
}
#if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
@@ -2580,20 +2622,11 @@ public:
{
auto vstParamID = paramQueue->getParameterId();
if (vstParamID == JuceAudioProcessor::paramPreset)
{
auto numPrograms = pluginInstance->getNumPrograms();
auto programValue = roundToInt (value * (jmax (0, numPrograms - 1)));
if (numPrograms > 1 && isPositiveAndBelow (programValue, numPrograms)
&& programValue != pluginInstance->getCurrentProgram())
pluginInstance->setCurrentProgram (programValue);
}
#if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
else if (juceVST3EditController != nullptr && juceVST3EditController->isMidiControllerParamID (vstParamID))
if (juceVST3EditController != nullptr && juceVST3EditController->isMidiControllerParamID (vstParamID))
addParameterChangeToMidiBuffer (offsetSamples, vstParamID, value);
#endif
else
#endif
{
auto floatValue = static_cast<float> (value);


Loading…
Cancel
Save