Disclaimer: This is not a feature that exists today. We’re looking for feedback on this idea to gauge interest.
Context:
VST3 doesn’t currently support MIDI messages. Instead, it uses a variety of different mechanisms, as detailed here, to offer functionality similar to that offered by MIDI.
Some of the mechanisms, such as the IEventQueue for note and other events, allow a fairly seamless conversion between MIDI events and VST3 events. However, MIDI CCs and program change messages are passed as parameter changes rather than being part of the main event queue. This can be problematic because the relative order of paramter-change events with the same timestamp is lost, so it’s not possible to convert CC/PC messages to VST3 events without losing some information from the original MIDI stream.
Additionally, in order for the plugin to receive all possible CCs, it must declare 128 parameters for each of 16 MIDI channels, which can hurt the user experience if these parameters are also displayed to users e.g. in parameter automation lists.
Writing a VST3 plugin that only manipulates note events or other MIDI concepts is quite difficult, as the plugin must implement all of these disparate mechanisms/interfaces (parameters, IMidiMapping, plugin units per-channel), which is significantly more complex than writing a single function that consumes and produces MIDI events.
Plugins/hosts that want to provide full MIDI support have other options, such as AU MIDI FX on macOS, or CLAP. However, for projects that already support VST3, the support and maintenance overhead of adding this feature to such a project will be much lower than adding support for a whole new plugin format.
Proposal
I believe that support for MIDI events could be added to VST3 non-intrusively as a third-party header. An initial draft of the proposed interface is shown below. As long as hosts and plugins that want to support native MIDI all agree to use this header, MIDI can be added to VST3 without requiring an update to the core VST3 spec.
There is precedent for this approach: Presonus has a set of VST3 extensions, as does REAPER.
The header would be licensed permissively (BSD/MIT or similar) to allow maximal adoption.
namespace vst3_ext_midi
{
namespace sb = Steinberg;
namespace sbv = sb::Vst;
/// An event representing a Universal MIDI Packet.
/// This is intended to be passed between host and client using the IEventQueue
/// mechanism.
struct UMPEvent
{
/// A stand-in EventType value for this event.
/// Event::type should be set to this value to indicate that the payload is
/// a UMPEvent.
static constexpr auto kType = 0x100;
/// Words of a Universal MIDI Packet.
/// A UMPEvent will only ever contain a single packet, which means that
/// the words at indices 2 and 3 may not be used for some events.
/// Check the first word to find the real length of the packet, and avoid
/// reading or writing to words that are not contained in the packet.
sb::uint32 words[4];
/// If the event is a UMPEvent, returns that event.
/// Otherwise, returns nullopt.
static std::optional<UMPEvent> fromEvent (const sbv::Event& e)
{
if (e.type != kType)
return {};
UMPEvent result;
memcpy (&result, &e.noteOn, sizeof (UMPEvent));
return result;
}
/// Returns an Event with this UMPEvent as the payload.
sbv::Event toEvent (sb::int32 busIndex,
sb::int32 sampleOffset,
sbv::TQuarterNotes ppqPos,
sb::uint16 flags) const
{
sbv::Event result { busIndex, sampleOffset, ppqPos, flags, kType, {} };
memcpy (&result.noteOn, this, sizeof (UMPEvent));
return result;
}
};
// UMPEvent will re-use the storage of NoteOnEvent.
static_assert (sizeof (UMPEvent) <= sizeof (sbv::NoteOnEvent));
static_assert (alignof (UMPEvent) <= alignof (sbv::NoteOnEvent));
} // namespace vst3_ext_midi
This only shows the general idea for passing UMP events through the IEventQueue. The full extension would likely need an additional interface to extend the processor/edit-controller so that the host can query the plugin to check whether it implements UMP support, and then inform the plugin if it intends to use this new functionality. I imagine that some plugins may opt to hide CC and PC parameters in the case that native MIDI support is available, so the new interface would likely include a function implemented by the plugin, to be called by the host early on in the plugin’s initialisation, so that the plugin can configure itself properly. I haven’t worked out the specifics here yet - we want to ensure that there is interest before spending too much time working out the fine details.
Obviously, not all hosts will support this new feature, so plugins would need to incorporate some fall-back behaviour using the existing VST3 API, even if this means operating in a reduced-functionality mode.
Next steps
If you are a plugin developer, do you have a use-case for native VST3 MIDI that is not covered by the existing VST3 API? We’d be interested to know your requirements, and whether the proposed extension would work for you.
If you develop a plugin host, would you consider implementing an extension like this, or do you foresee any potential issues? Please let us know!

