MIDI Program Change forwarding for VST3

Hi,

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 ?

2 Likes

bump

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 ?
-Michael

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.

2 Likes

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.

Hi,
I’m building VST2 and VST3 from the same code using JUCE7(7.0.5). In VST2 the program changes sent by a MIDI controller are received in the MidiBuffer argument of processBlock. In VST3 they aren’t received. This happens in both Studio One and Reaper (latest versions on both).
CC changes are received correctly. It’s only the program changes that are being ignored.
Can anyone confirm? Is this a JUCE bug? Does anybody have a fix? Is there a fix in a more recent version of JUCE?
Thanks!

I notice that JUCE has a class: ’ ProgramChangeParameter’

So it look like JUCE does support this. Have a search through the JUCE code for that symbol

1 Like

I can’t find it in JUCE: Tags :frowning:

JUCE\modules\juce_audio_plugin_client\juce_audio_plugin_client_VST3.cpp line 904

Thanks Jeff.

So what I’m seeing is that Program Changes are not included in the MidiBuffer argument of processBlock but trigger instead AudioProcessor::setCurrentProgram(int index) if AudioProcessor::getNumPrograms() returns >1, which is not backwards compatible with VST2.

This is different to the approach taken with CC where the flag JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS is enabled by default.

The result is that if you compile the same code as VST2 and VST3, VST2 and VST3 behave in the same way for input CCs but behave differently for input ProgramChanges (the latter are not included in the MidiBuffer argument of processBlock). This is not what I would expect from JUCE. I would expect it to generate different plugin formats which react to the same input in the same way.

A quick way to prove it is by coding in JUCE a plugin that forwards the input MIDI to the output. In the VST2 version input ProgramChanges will be forwarded to the output. In the VST3 version input ProgramChanges won’t be included in the output.

IMHO in JuceVST3Component::processParameterChanges (Vst::IParameterChanges& paramChanges), addParameterChangeToMidiBuffer() should also be called from modifications in the parameter instance of ProgramChangeParameter. In other words, there should also be a JUCE_VST3_EMULATE_MIDI_PROGRAM_CHANGES_WITH_PARAMETER flag enabled by default.

Summing up, in my view, this is a bug in JUCE.

Correct, VST3 does not support MIDI PC as raw messages, only CC. PC are used to recall VST3 “programs” that are available through the “setCurrentProgram” function in plugin processor.

It is actually possible but JUCE doesn’t implement it. As discussed in VST3, Programs and MIDI Program Changes I ended creating a patch to include those Program Chanes as MIDI messages in channel 1. This could be extended to other MIDI channels if anybody finds the time to do so. I’ve documented the problem in this same thread (VST3, Programs and MIDI Program Changes - #3 by Qfactor).

Hi, I’m new to Juce and this is my first post :slight_smile:
I wanted to develop a small utility to save MIDI PG and CC data for hardware gear with a song in Reaper. I also stumbled on this PG issue.
But I noticed that using the Juce plugin host, the program change are received in the midi message buffer, whereas in Reaper they are not. Why this difference ?