Generating MIDI messages within a VST plugin and passing them to the host

windows
midi

#1

As I understand it, a VST plugin receives a stream of audio and midi buffers from the host, and processBlock() in the AudioProcessor is used to make modifications to those buffers before they are passed back to the host. It is then up to the host to take care of routing the audio and midi messages (to external devices, to other plugins, to other tracks, etc.).

What I am having trouble grasping is how to inject a new midi message generated within the plugin itself into the stream. Let’s say I have a button in my editor, and that when it is clicked it creates a new midi note on message. Where can I put that message so that it is passed on to the host? Any suggestions will be appreciated!


#2

You need to check out the tutorials; there is on covering exactly that in detail: https://docs.juce.com/master/tutorial_midi_message.html


#3

Thanks for taking the time to respond tomto66, I think I have it straight in my head now.

Let me try to put this concept into words for the benefit of others who are new to VST programming and may have the same confusion: What was tripping me up here was thinking in terms of sending a midi message to an output device, as you would in a stand-alone application. A VST does not communicate with external devices, that is the domain of the host application. The host has a buffer where it stores incoming midi messages. That buffer is passed by reference (as “MidiBuffer& midiMessages”) to the VST’s processBlock method, which has the opportunity to modify the messages in the buffer or add new messages to it. The modified buffer is then passed on by the host to whatever is next in line (another plugin, an output device, etc.).

Let’s say you have a MidiBuffer object in your processor called “myBuffer.”
New midi messages generated by the VST should be added to myBuffer. In processBlock, iterate through the events stored in myBuffer and add them to midiMessages to pass them to the host.

I hope that makes sense! :grinning:


#4

That is all correct, however it’s also totally possible for an audio plugin to send messages directly to a MIDI device, bypassing the host.


#5

Well, yes, it is possible to send directly to MIDI devices, but you are not sure when your plugin code that generates the MIDI message will run. This means that your MIDI messages will suffer from timing jitter (unless you do some very fancy scheduling using timestamps from a reference clock etc…) That jitter will depend on the audio buffer size, and if it’s 32 samples or so at say 44100 Hz, that might not be detectable.

If you use the MIDIBuffer you get from the host, then you can add your MIDI events with a specific sampleNumber, so that they will be synchronized to the audio buffer of that same process call, which means that the message should play exactly at the moment the audio sample you specified is sounding out of your speakers (assuming the host does a good job of compensating for IO delays of the sound card I suppose). At least, there shouldn’t be any jitter related to the moment your plugin happens to get processed.

Just thought I’d add that for good measure :wink:


#6

Yes, all true and well explained. Our use case was for communicating with a MIDI device (to switch LED’s on and off) so sample accuracy was not important.


#7

@KoenT, @adamski Thank you, that is all great information! Another consideration about generating MIDI within VSTs that I have run into is that Steinberg originally designed VST3 without support for MIDI controller messages. They back-pedaled a bit on this last year, and now plugins built with Juce will receive incoming controller messages in the processBlock. However, VST3 still will not send controller messages out to the host. This is frustrating for me because I am trying to create a plugin that generates NRPN messages for editing a hardware synthesizer. Apparently the latest VST build (3.6.12) now includes a LegacyMIDICCOutEvent which sounds like it would help me, but I don’t know how long it is going to be before Juce incorporates it. I will probably have to go the route of directly addressing an external device.


#8

My 2 cents: If the messages are not timing-sensitive, why not go directly to the MIDI device rather than via the host? Unless you are allowing users to automate parameters in the host which then get sent out as NRPN messages…