I am creating a VST3 host on macOS (v12.7, ARM), and mostly I’ve got it all working. I am using the SDK Example plugins for testing, primarily the AGain example.
I’m passing in MIDI control changes events via audioClient->onEvent(e, 0)
to AGain, and control change 7 successfully changes the gain of the audio passing through the plugin. (I see it on the VU meter and can hear the change.)
However, the components of the GUI (slider, numeric indication of gain, etc.) are not updating to reflect this change visually – which is what I would have expected.
Note that adjusting the GUI slider with my mouse works fine: the volume of the sound is changed, and the numeric representation of the gain also changes after moving the slider.
I would think the plugin architecture would take care of notifying the GUI elements that they need to be redraw after a MIDI message changes the value of a parameter, but maybe I’m wrong? Is it the responsibility of the host to do this?
Thanks for any insights you can offer.
Best Wishes,
Mark
Hi,
first of all, you need to map MIDI control changes to parameter changes, see [3.0.1] Parameter MIDI Mapping - VST 3 Developer Portal and send a parameter change instead of an event.
Second, you need to inform the edit controller of the plug-in about this parameter change too via IEditController::setParameterNormalized().
Cheers
I am confused. In the VST3 SDK sample code, in the function int JackClient::processMidi (jack_nframes_t nframes)
in jackclient.cpp
, you see this code
auto midiData = in_event.buffer;
\Steinberg::Vst::IMidiClient::MidiData channel = midiData[0] & kChannelMask;
Steinberg::Vst::IMidiClient::MidiData status = midiData[0] & kStatusMask;
Steinberg::Vst::IMidiClient::MidiData data0 = midiData[1];
Steinberg::Vst::IMidiClient::MidiData data1 = midiData[2];
midiClient->onEvent ({status, channel, data0, data1, in_event.time}, portIndex);
Not only would this code not seem to be processing the MIDI data as a parameter change, but it is likely that it would not be called from the main thread. Is this code example invalid?
Best Wishes,
Mark
I think you mix up the private API of the example app to communicate with Jack and the API of the VST3 SDK.
In the code from jackclient.cpp
above, midiClient->onEvent()
calls bool AudioClient::onEvent (const IMidiClient::Event& event, int32_t port)
, which is in the audioclient.cpp in the audiohost example.
Is audioclient.cpp
not part of the SDK?
Thanks in Advance,
Mark
I noticed you quoted some code from the audioclient.cpp file and thought it was how MIDI CC messages are handled. But I just wanted to clarify that’s not the case. The VST3 API specifies a MIDI-CC to Parameter mapping interface (see IMidiMapping) that the host needs to use to convert incoming MIDI CC messages into parameter changes.
Thank you for your reply.
The code I’m quoting is in audioclient.cpp is is included in the VST 3 SDK as an example of how to pass incoming MIDI messages and to a plugin. My assumption about all code in the official SDK is that it reflects the correct procedure and follows best practices of how one should communicate with VST3 plugins.
If I understand you, you are saying that this example code does not follow the correct procedure for passing incoming MIDI to the plugin. Am I understanding you correctly?
If so, then I will add an issue to the GitHub asking that the code be updated to reflect the officially recognized method of passing MIDI to a plugin.
If the code in audioclient.cpp is not correct, I would ask you for an example of how the code should be updated to handle the incoming MIDI messages properly, including how the would be passed to the GUI on the main thread.
Thanks,
Mark
No, what I was talking about was that the VST3 API does not handle MIDI directly.
You are talking about an example in the VST3 SDK (note the difference of API and SDK) which uses the JACK API, which handles MIDI directly and converts this to what the VST3 API expects and it does it correctly.
As the audioclient example does not support showing the UI of the plug-in, it does not need to implement synchronizing parameter changes back to the edit controller of the plug-in.
As far as I know, the SDK has no example showing this. Normally people implementing VST3 hosting functionality already have the foundation to pass data between threads.