Avatar

Please consider registering
Guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed sp_TopicIcon
How to send a Midi message (sysex, CC and NRPN)
No permission to create posts
September 23, 2015
9:43 pm
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

Hello

I was wondering if someone could provide me with a sample on how to send a midi message.
I added event output to my plugin and I want to send a midi message after I turn a knob.
I want to be able to send sysex, CC and NRPN.

September 24, 2015
4:45 am
Avatar
W Pirkle
Admin
Forum Posts: 140
Member Since:
January 28, 2017
sp_UserOnlineSmall Online

Is this for RackAFX, VST3 or AU?

September 24, 2015
5:42 am
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

Will said

Is this for RackAFX, VST3 or AU?

At this moment for VST3.

September 24, 2015
6:27 pm
Avatar
W Pirkle
Admin
Forum Posts: 140
Member Since:
January 28, 2017
sp_UserOnlineSmall Online

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

September 24, 2015
11:06 pm
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

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.

September 25, 2015
1:10 am
Avatar
W Pirkle
Admin
Forum Posts: 140
Member Since:
January 28, 2017
sp_UserOnlineSmall Online

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

October 1, 2015
7:51 pm
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

Hello Will

Thank you for the information. You have saved me valuable time.

It is quite surprising to find out that VST3 SDK doesn't support MIDI CCs and NRPNs for the MIDI output port.
But the Sysex is definitely cool. I can work with that.

October 29, 2015
6:16 pm
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

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);

November 2, 2015
9:05 pm
Avatar
W Pirkle
Admin
Forum Posts: 140
Member Since:
January 28, 2017
sp_UserOnlineSmall Online

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

November 10, 2015
3:11 am
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

Hello Will

The message is well-formatted, because I took it straight from my midi controller that sends sysex to my Blofeld synth.
The Blofeld doesn't need a checksum.

Does my code look ok? You don't see anything strange there?

November 10, 2015
6:18 pm
Avatar
W Pirkle
Admin
Forum Posts: 140
Member Since:
January 28, 2017
sp_UserOnlineSmall Online

The code looks fine as far as I can tell. I have not been sending SysEx myself in VST3.

- Will

November 11, 2015
2:03 am
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

Hello Will

Thanks for your reply. I will look some more into it.

November 15, 2015
7:08 pm
Avatar
Tom
Admin
Forum Posts: 65
Member Since:
April 3, 2014
sp_UserOfflineSmall Offline

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

November 28, 2015
7:58 pm
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

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.

December 3, 2015
4:10 pm
Avatar
Tom
Admin
Forum Posts: 65
Member Since:
April 3, 2014
sp_UserOfflineSmall Offline

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 Wink

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 Wink.
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 Cool

December 3, 2015
5:40 pm
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

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.

December 5, 2015
12:48 am
Avatar
Tom
Admin
Forum Posts: 65
Member Since:
April 3, 2014
sp_UserOfflineSmall Offline

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

December 9, 2015
12:54 am
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

Hello Tom

I didn't manage to get to it. 🙁 Too many obligations at the moment.
I want to thank you for discovering the __WINDOWS_MM___ variable. That would have definitely caused me trouble.
I will definitely let you know how it goes. I can't wait to start on it.

December 10, 2015
3:44 am
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

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.

December 10, 2015
10:50 pm
Avatar
EZB
Member
Members
Forum Posts: 24
Member Since:
September 14, 2015
sp_UserOfflineSmall Offline

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.

No permission to create posts
Forum Timezone: America/New_York

Most Users Ever Online: 36

Currently Online: W Pirkle
3 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

Skyler: 47

Derek: 41

Peter: 41

clau_ste: 39

Frodson: 38

Gwen: 32

EZB: 24

lppier: 23

Msaldaña: 18

Jorge: 17

Member Stats:

Guest Posters: 1

Members: 478

Moderators: 1

Admins: 4

Forum Stats:

Groups: 11

Forums: 29

Topics: 479

Posts: 1870

Newest Members:

certvalue111, sobhana s, sam, annaharris, Marie Weaver, kev, Steven, Mr Anderson, mguy, omelc

Moderators: W Pirkle: 140

Administrators: Tom: 65, JD Young: 80, Will Pirkle: 0, W Pirkle: 140