Browse Source

Add program change parameter to VST-3 plug-ins

tags/2021-05-28
hogliux 9 years ago
parent
commit
8cd6f49ea0
1 changed files with 108 additions and 17 deletions
  1. +108
    -17
      modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp

+ 108
- 17
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -81,12 +81,6 @@ using namespace Steinberg;
extern JUCE_API void setNativeHostWindowSizeVST (void* window, Component*, int newWidth, int newHeight, bool isNSView);
#endif
enum
{
kJuceVST3BypassParamID = 0x62797073, // 'byps'
kMidiControllerMappingsStartID = 0x6d636d00 // 'mdm*'
};
//==============================================================================
class JuceAudioProcessor : public FUnknown
{
@@ -197,6 +191,13 @@ public:
}
//==============================================================================
enum InternalParameters
{
paramPreset = 0x70727374, // 'prst'
paramBypass = 0x62797073, // 'byps'
paramMidiControllerOffset = 0x6d636d00 // 'mdm*'
};
struct Param : public Vst::Parameter
{
Param (AudioProcessor& p, int index, Vst::ParamID paramID) : owner (p), paramIndex (index)
@@ -350,6 +351,79 @@ public:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BypassParam)
};
//==============================================================================
struct ProgramChangeParameter : public Vst::Parameter
{
ProgramChangeParameter (AudioProcessor& p) : owner (p)
{
jassert (owner.getNumPrograms() > 1);
info.id = paramPreset;
toString128 (info.title, "Program");
toString128 (info.shortTitle, "Program");
toString128 (info.units, "");
info.stepCount = owner.getNumPrograms() - 1;
info.defaultNormalizedValue = static_cast<Vst::ParamValue> (owner.getCurrentProgram()) / static_cast<Vst::ParamValue> (info.stepCount);
info.unitId = Vst::kRootUnitId;
info.flags = Vst::ParameterInfo::kIsProgramChange | Vst::ParameterInfo::kCanAutomate;
}
virtual ~ProgramChangeParameter() {}
bool setNormalized (Vst::ParamValue v) override
{
Vst::ParamValue program = v * info.stepCount;
if (! isPositiveAndBelow ((int) program, owner.getNumPrograms()))
return false;
if (valueNormalized != v)
{
valueNormalized = v;
changed();
return true;
}
return false;
}
void toString (Vst::ParamValue value, Vst::String128 result) const override
{
Vst::ParamValue program = value * info.stepCount;
toString128 (result, owner.getProgramName ((int) program));
}
bool fromString (const Vst::TChar* text, Vst::ParamValue& outValueNormalized) const override
{
const String paramValueString (getStringFromVstTChars (text));
const int n = owner.getNumPrograms();
for (int i = 0; i < n; ++i)
{
if (paramValueString == owner.getProgramName (i))
{
outValueNormalized = static_cast<Vst::ParamValue> (i) / info.stepCount;
return true;
}
}
return false;
}
static String getStringFromVstTChars (const Vst::TChar* text)
{
return juce::String (juce::CharPointer_UTF16 (reinterpret_cast<const juce::CharPointer_UTF16::CharType*> (text)));
}
Vst::ParamValue toPlain (Vst::ParamValue v) const override { return v * info.stepCount; }
Vst::ParamValue toNormalized (Vst::ParamValue v) const override { return v / info.stepCount; }
private:
AudioProcessor& owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgramChangeParameter)
};
//==============================================================================
tresult PLUGIN_API setComponentState (IBStream* stream) override
{
@@ -362,6 +436,10 @@ public:
setParamNormalized (getVSTParamIDForIndex (i), (double) pluginInstance->getParameter (i));
setParamNormalized (bypassParamID, audioProcessor->isBypassed ? 1.0f : 0.0f);
const int numPrograms = pluginInstance->getNumPrograms();
if (numPrograms > 1)
setParamNormalized (paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram()) / static_cast<Vst::ParamValue> (numPrograms - 1));
}
return Vst::EditController::setComponentState (stream);
@@ -459,6 +537,13 @@ public:
void audioProcessorChanged (AudioProcessor*) override
{
if (AudioProcessor* pluginInstance = getPluginInstance())
{
if (pluginInstance->getNumPrograms() > 1)
EditController::setParamNormalized (paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram())
/ static_cast<Vst::ParamValue> (pluginInstance->getNumPrograms() - 1));
}
if (componentHandler != nullptr)
componentHandler->restartComponent (Vst::kLatencyChanged | Vst::kParamValuesChanged);
}
@@ -531,12 +616,15 @@ private:
parameters.addParameter (new Param (*pluginInstance, i, vstParamID));
}
bypassParamID = static_cast<Vst::ParamID> (usingManagedParameter ? kJuceVST3BypassParamID : numParameters);
bypassParamID = static_cast<Vst::ParamID> (usingManagedParameter ? paramBypass : numParameters);
parameters.addParameter (new BypassParam (*pluginInstance, bypassParamID));
if (pluginInstance->getNumPrograms() > 1)
parameters.addParameter (new ProgramChangeParameter (*pluginInstance));
}
#if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
parameterToMidiControllerOffset = static_cast<Vst::ParamID> (usingManagedParameter ? kMidiControllerMappingsStartID
parameterToMidiControllerOffset = static_cast<Vst::ParamID> (usingManagedParameter ? paramMidiControllerOffset
: parameters.getParameterCount());
initialiseMidiControllerMappings ();
@@ -1357,7 +1445,7 @@ public:
{
if (listIndex == 0)
{
info.id = paramPreset;
info.id = JuceVST3EditController::paramPreset;
info.programCount = (Steinberg::int32) getPluginInstance().getNumPrograms();
toString128 (info.name, TRANS("Factory Presets"));
@@ -1372,7 +1460,7 @@ public:
tresult PLUGIN_API getProgramName (Vst::ProgramListID listId, Steinberg::int32 programIndex, Vst::String128 name) override
{
if (listId == paramPreset
if (listId == JuceVST3EditController::paramPreset
&& isPositiveAndBelow ((int) programIndex, getPluginInstance().getNumPrograms()))
{
toString128 (name, getPluginInstance().getProgramName ((int) programIndex));
@@ -1722,6 +1810,15 @@ public:
else if (juceVST3EditController->isMidiControllerParamID (vstParamID))
addParameterChangeToMidiBuffer (offsetSamples, vstParamID, value);
#endif
else if (vstParamID == JuceVST3EditController::paramPreset)
{
const int numPrograms = pluginInstance->getNumPrograms();
const int programValue = static_cast<int> (std::round (value * static_cast<Vst::ParamValue> (numPrograms)));
if (numPrograms > 1 && isPositiveAndBelow (programValue, numPrograms)
&& programValue != pluginInstance->getCurrentProgram())
pluginInstance->setCurrentProgram (programValue);
}
else
{
const int index = getJuceIndexForVSTParamID (vstParamID);
@@ -1972,12 +2069,6 @@ private:
return AudioBusPointerHelper<FloatType>::impl (data);
}
//==============================================================================
enum InternalParameters
{
paramPreset = 'prst'
};
void preparePlugin (double sampleRate, int bufferSize)
{
AudioProcessor& p = getPluginInstance();
@@ -1996,7 +2087,7 @@ private:
const int numParameters = pluginInstance->getNumParameters();
usingManagedParameter = (pluginInstance->getParameters().size() == numParameters);
vstBypassParameterId = static_cast<Vst::ParamID> (usingManagedParameter ? kJuceVST3BypassParamID : numParameters);
vstBypassParameterId = static_cast<Vst::ParamID> (usingManagedParameter ? JuceVST3EditController::paramBypass : numParameters);
for (int i = 0; i < numParameters; ++i)
{


Loading…
Cancel
Save