

For VST3, you add code to the end of your process( ) method that generates Events. The bad news is that you have the same MIDI limitation that I outline in Chapter 2 and 3. You can only output a very limited set of Events, and only a few of them are MIDI Events. The IEventList interface allows you to get and set Events (you already have code for getting MIDI events in the Synth projects). The IEventList interface and the Event structure definitions are in \VST3 SDK\pluginterfaces\vst\ivstevents.h and the Event::type variable sets the kind of Event. The supported types are:
enum EventTypes
{
kNoteOnEvent = 0,
kNoteOffEvent,
kDataEvent,
kPolyPressureEvent,
kNoteExpressionValueEvent,
kNoteExpressionTextEvent,
kChordEvent,
kScaleEvent
}
To transmit a Note On event, you would add this to the end of the process( ) method:
// --- get the event list for output
IEventList* outputEvents = data.outputEvents;
if(outputEvents)
{
Event midiEvent = {0};
midiEvent.busIndex = 0;
midiEvent.sampleOffset = 0; // location within the buffer that this event occurs
midiEvent.type = Event::kNoteOnEvent;
// --- set the channel/note/vel
midiEvent.noteOn.channel = 0;
midiEvent.noteOn.pitch = 60.0; // MIDI note 60
midiEvent.noteOn.velocity = 1.0; // 127; velocity is [0,1]
midiEvent.noteOn.noteId = 60;
outputEvents->addEvent(midiEvent);
}
To transmit Sysex, see the definition for the DataEvent object in the same .h file:
struct DataEvent
{
uint32 size; ///< size in bytes of the data block bytes
uint32 type; ///< type of this data block
const uint8* bytes; ///< pointer to the data block
/** Value for DataEvent::type */
enum DataTypes
{
kMidiSysEx = 0 ///< for MIDI system exclusive message
};
};
You can see that they have only one enumeration for kMidiSysEx. Perhaps in the future they will add more. So, the limitation is in the VST3 API.
But in perspective: in RackAFX, you can not output MIDI at all. And in AU, there is an API for it, but apparently no host actually supports it.
Hope that helps -
Will


Hello Will
This is helping me immensely. I tried the note on message and it arrived in another VST.
The note keeps hanging though. I understand that I need to send a note off message was well.
Does that mean I just have to create a note off message and do an outputEvents->addEvent(midiEvent) again?
Thank you for the explanation with the sysex. All clear now. I just found out, that in certain sysex cases a checksum needs to be calculated and added to the sysex. Do you know if the VST SDK offers checksum functions?
I hope you can also tell me how to send a midi CC, because in the EventTypes I don't see the Control Change type.
Hi EZB
Yes, you need to send the note off message to prevent the stuck-note and you would do it the same way, here I am offsetting the note off event by 32 samples (arbitrarily):
// --- get the event list for output
IEventList* outputEvents = data.outputEvents;
if(outputEvents)
{
Event midiEvent = {0};
midiEvent.busIndex = 0;
midiEvent.sampleOffset = 32; // location within the buffer that this event occurs
midiEvent.type = Event::kNoteOffEvent;
// --- set the channel/note/vel
midiEvent.noteOff.channel = 0;
midiEvent.noteOff.pitch = 60.0; // MIDI note 60
midiEvent.noteOff.velocity = 0.0; // 0; velocity is [0,1]
midiEvent.noteOff.noteId = 60;
outputEvents->addEvent(midiEvent);
}
The Checksum is for Roland products, so if you are targeting a (hardware) Roland synth, then the checksum is needed. As far as I know, VST3 doesn't care about the checksum, just transmits the Sysex to the target synth.
And, unfortunately you can not send MIDI CCs (or NRPNs) - these events are not supported in the VST3 API for your MIDI output port.
- Will


Hello Will
I set up a connection to a midi log window. The log shows when it receives a note I am sending from my VST. But when I am sending a sysex message the log doesn't show anything. This means I must have a mistake somewhere, but I can't pinpoint it.
This is the code I use to send a sysex message. I hope you can help me pinpoint it.
Event midiEvent = {0};
midiEvent.busIndex = 0;
midiEvent.sampleOffset = 0; // location within the buffer that this event occurs
midiEvent.type = Event::kDataEvent;
DataEvent data;
midiEvent.data.size = 10;
midiEvent.data.type = DataEvent::kMidiSysEx;
uint8 buf[10] = {0xF0, 0x3e, 0x13, 0x00, 0x20, 0x00, 0x00, 0x02, 0x52, 0xF7};
midiEvent.data.bytes = (const uint8*)buf;
outputEvents->addEvent(midiEvent);
Not sure - have not been trying to send SysEx. Are you sure the message is well-formatted? And, you may need the checksum, but I don't think that would prevent the event from being logged. Have you tried one of these "stock" messages you can find here:
http://www.2writers.com/eddie/.....tsysex.htm
- Will
Hi EZB,
what host are you using? Maybe the host will not forward the SysEx it receives from your plugin (I read about a similar issue in the juce forums where it turned out, that the host did not forward the SysEx messages). Cubase e.g. will filter sysex messages in the default settings.
As Will already mentioned, raw MIDI is no longer supported in VST3 because from a design perspective they decided that it's the host's responsibility to integrate MIDI controllers and care for the binding to parameter values (which I agree on, but the VST3 hosts I know of did not fill in the gap that was produced by this decision yet). For "MIDI" plugins vst2 is more or less your only option IMO if you don't find a host that does the mapping.
Cheers
Tom


Hello Tom
I am using Presonus Studio One Pro 64bit. You might have a point there that it might filter sysex when a VST sends it. I do have confirmation that Studio One can receive sysex from midi ports and send them to other ports, though. Now that I think of it, the Moog Voyager PlugSE VST sends sysex to the Moog, but I do have to set a physical midi input and midi output port in the VST itself.
Will or Tom, I hope you can point me in the right direction regarding the setting of a physical midi input and midi output port in a VST and
sending sysex to it. This could be the solution to the problem I am facing.
Hi EZB,
the routing has to be done by the host. The Plugin does not know about the physical ports. The Moog Voyager PlugSE VST as far as the manual states is a VST2 plugin, which has "full" midi support. VST3 has no low-level midi support and I am not sure whether the SysEx data type will actually be sent out from the host. Technically it may also be, that the Voyager Plugin internally does directly connect to the Moog and may not be sending thru the host (the product page says "Direct MIDI connection" and in the manual they show how to setup a MIDI port for the plugin - which "normal" plugins would not do!). - Now re-reading your last post I think that's what you found out, too
Opening a midi port from within a plugin on windows first would require either a multi-client midi driver or you need a midi port dedicated exclusively for the plugin so that the host won't hold it open the same time as the plugin tries to.
Then you could try RtMidi or PortMidi library to access a midi port from within a VST. Though wihtin a plugin it can become difficult to load other DLLs so you should try to inline the midi library you use (if you want to release your work to a third party or to the public, you'll have to check whether this would be legal with the library). With RtMidi technically that's a no-brainer because you only need to include two files into your projects. I won't make a statement here about licensing issues, you'll have to check this .
Now that's the theory - I never actually tried to open devices from within a plugin myself. Let us know if it works - sounds like an exciting idea to me


Hello Tom
Thanks for the warning about multi-client Midi Drivers. I was not aware of them. When I use the Moog Voyager PlugSe in my host and set its ports to port X for example, I can still create an instrument track in the host that outputs notes to that same port X. Is that what you mean with multi-client?
Regarding the inlining of a midi library, can you explain to me what it exactly means? I don't know that technique.
Thanks for the tips for RtMidi and PortMidi. Now I can explorer that further. I will let you know my findings, because if I can't get this done my plugin project fails. My plugin needs to send sysex.
As for licensing issues, duly noted. Thanks for the heads up.
Hi EZB,
I just have tried it with a RackAFX project and it seems to work: I opened a midiport and send out a note-on to my stage piano - now each time the plugin loads, it plays a note 😉
Unfortunately RtMidi does not implement the MIDI protocol, it only sends the data you pass it out to the midi port. But if you want to do sysex, there's not that much to be added around the SysEx data itself AFAIR.
"Inlining" a library means to integrate the sourcecode directly into your project (vs. linking against a library).
One pitfall with RtMidi: you have to set a preprocessor variable (__WINDOWS_MM__ on windows) or it won't build with an actual implementation (then getPortCount() will just return 0 and it can take you quite some time to figure out why you seemingly can't open a port *g*)
I hope this will work for you!
- Tom


Hello Tom
I finally had sone time to test a little bit.
I managed to get a list of the ports.
One thing I did notice and that is that my Midi Yoke ports were not listed.
But this is already a good start. Tomorrow I am gonna connect my Blofeld synth and test the sysex. I will keep you posted. I am so excited right now.


Hello Tom
Today I wanted to open a port and I couldn't get it opened. Stepping into the RtMidi code I found out I get an error code MMSYSERR_ALLOCATED. This would indicate that my host has taken my port and therefore I can't open it. I am definitely sure my midi interface has a multiclient midi driver so something else might be going on.
I looked at the RtMidi tutorial and it mentioned 2 frameworks, namely winmm.lib and multithreaded. Now I am not sure what multithreaded is, but I take it it is a lib too.
My questions to you are the following
1. Did you build 32-bit or 64-bit?
2. Is multithreaded some kind of lib. I know what multithreading is, but I never dabbled with it, but I would definitely expect that multithreading is necessary for opening more midi connections.
Thank you in advance.
Most Users Ever Online: 152
Currently Online:
10 Guest(s)
Currently Browsing this Page:
1 Guest(s)
Top Posters:
Chaes: 56
Skyler: 48
StevieD: 46
Derek: 46
Frodson: 45
Peter: 43
TheSmile: 43
Nickolai: 43
clau_ste: 39
jeanlecode: 37
Member Stats:
Guest Posters: 1
Members: 775
Moderators: 1
Admins: 6
Forum Stats:
Groups: 13
Forums: 42
Topics: 846
Posts: 3353
Moderators: W Pirkle: 690