MIDI Program Change forwarding for VST3


I get relatively frequent support questions about why the VST3 version of my plugin is not receiving MIDI program changes messages, while the VST2 gets them. Right now, JUCE uses the vst3 program change messages to switch the presets is the vst3 program list.

Would it be possible to have an option to just forward these messages as MIDI messages just like it is done for other MIDI messages ?


I’m not sure there’s a good way of doing this directly in JUCE. A VST3 plugin doesn’t receive a raw MIDI stream. The API allows for a plugin to emit program change events by outputting LegacyMIDICCOutEvents and setting the controlNumber to kCtrlProgramChange. The docs for LegacyMIDICCOutEvent say:

This kind of event is reserved for generating MIDI CC as output event for kEvent Bus during the process call.

It seems that it’s not valid for a host to provide this event type as an input to the plugin. That being said, toMidiBuffer in juce_VST3Common.h does translate LegacyMIDICCOutEvents to equivalent program change messages where possible, so this would work if a host were to provide this event type as input.

I think that the only way the host can communicate a program change event to the plugin is via the program parameter. You could try listening to the program parameter and translating this back to a MIDI program change event as appropriate. (I’m not sure there’s a general way we can do this in JUCE. How should the parameter translate to MIDI if the parameter has fewer than 128 values?) If the host doesn’t convert MIDI-program-changes into program-parameter-changes then I don’t think this is possible at all.

Please let me know if I overlooked something and you think there is a safe way of implementing the desired functionality.

Does VST3 know about “Midi” at all ? (I did do some tests - only with CC message - with Juce and Juce seems to recreate those in a VST2 compatible way for the user software)
Hence converting a Midi stream to VST3-API-Events seems to be the task of the host.
Is this the same with sending “Midi” to the host ?
While this might be required to overcome some shortcomings of Midi 1.0, What about Midi 2.0 ? Any thoughts how that is going to affect Juce ?

No, VST3 doesn’t have raw MIDI input/output. Any messages that the plugin sends/receives must be formatted as VST3 events. It’s up to the host to convert MIDI messages into VST3 events that will be received by the plugin.

JUCE already converts VST3 events to MIDI at the plugin’s input, and then converts outgoing MIDI back to VST3 events at the output. When JUCE adopts MIDI 2 more comprehensively, I expect that it will use a similar (potentially higher-resolution) mapping between VST3 events and MIDI 2 messages. There’s a bit more information in the Steinberg VST3 documentation.

You could try listening to the program parameter and translating this back to a MIDI program change event as appropriate.

You mean override AudioProcessor::getNumPrograms to return 128 and then react to calls to setCurrentProgram(n) by translating it into a program change message ?

I’m not sure I want to take that road ! I’m pretty sure we would get spurious program change message that are not triggered by an actual midi message.

I guess the confusion of our users comes from these kind of posts from Steinberg developers No Program Changes in VST3 - regrettable decision - #7 by nylonius - Cubase - Steinberg Forums where there is, I think, a confusion between being able to control VST programs with MIDI program change, and just receiving MIDI program change to control anything inside the VST.

If you need to differentiate between program change events that were triggered by MIDI, and those triggered by some other process, then unfortunately I don’t think that’s possible.