Plug->host MIDI-out possible with AU/RTAS?


#1

I’m doing my first baby steps with JUCE, writing a MIDI effect plugin. I’m blown away by the quality and ease of use of this library! Thanks for making this!

However, I have a small question: my plug needs to send MIDI-out back to the host. For VSTs no problem, but apparently from what I can glance from processBufferLists() in juce_AudioUnitWrapper.cpp, this is not implemented yet for AU plugs. Same thing for RTAS.

I’m not that familiar with AU and RTAS. Do AU and/or RTAS actually support MIDI-out from plug to host in their architectures?

thanks
mucoder


#2

how did you send MIDI Events in a VST plug with JUCE, did you do it in eth process() method, is there a wrapper for

bool AudioEffectX::sendVstEventsToHost  ( VstEvents *  events   )  

VST method to send MIDI events to the host in different methods?

(i can’t find how to send MIDI events to the HOST in JUCE).


#3

[quote=“atomix1040”]how did you send MIDI Events in a VST plug with JUCE, did you do it in eth process() method, is there a wrapper for

bool AudioEffectX::sendVstEventsToHost  ( VstEvents *  events   )  

VST method to send MIDI events to the host in different methods?

(i can’t find how to send MIDI events to the HOST in JUCE).[/quote]

atomix1040, in your JUCE VST filter you normally already implemented this function:

void DemoJuceFilter::processBlock (const AudioSampleBuffer& input,
AudioSampleBuffer& output,
const bool accumulateOutput,
MidiBuffer& midiMessages)

the last parameter is a reference to a midi input buffer. But on return that buffer also becomes an output buffer. Just clear out the input messages from the buffer, then insert your own. The VST wrapper then sends them to the host for you.

Also, do not forget to set this preprocessor symbol in your JucePluginCharacteristics.h file:

#define JucePlugin_ProducesMidiOutput 1

the DemoJuceFilter VST shows how to do it.


#4

it kinda didn’t make sense to me after looking into the wrppaer implementation, but apparently i’m just more stupid than i thought.

thanks.


#5

nah, don’t be too hard on yourself. Wasn’t that obvious to me either at first. :slight_smile: But I like the way JUCE solves it. Nice and clean


#6

I was wondering about SysEx support

                if (midiEventSize <= 4)
                {
                    VstMidiEvent* const vme = (VstMidiEvent*) outgoingEvents->events [outgoingEvents->numEvents++];

                    memcpy (vme->midiData, midiEventData, midiEventSize);
                    vme->deltaFrames = midiEventPosition;

                    jassert (vme->deltaFrames >= 0 && vme->deltaFrames < numSamples);
                }

the <=4 size worries me, does that mean that nothing larger than 4 bytes will pass to the host ? The latest SDK has VstMidiSysexEvent, will this be implemented (or maybe it is?).


#7

mmm, looks like you’re right. I have no experience with sending SysEx back to hosts yet, but it could be an interesting thing to have.

Maybe Jules can help out?


#8

VST never used to support sysex - I’ll have a look at adding it with the new VSTSDK, but there’s probably no hurry, because until all the hosts implement it, using sysex would probably just make most of them crash.


#9

propably yes :slight_smile:

but i don’t see why it wasn’t implemented in the old days.
i mean most of old synthesizers/samplers and other gear use this, i own some of this hardware and have to write my own VST plugs (thanks to the wonders of JUCE) to control it from my DAW of choice. Not only it does not support SysEx internally (it’s own native controllers) but it wont send any MIDI message larger than 3bytes (i tired). It sucks. A lot of people own for ex. the Oberheim Matrix 1000 synth, cheap analog and sounds great, but all the editing is made with sysex.

i hope to see this sometime during my lifetime.


#10

important question:

sice the sending of MIDI messages and receiving them is placed in the process() method, will it be possible to send and recevice MIDI while the host is stopped (and thus not calling the process() method) ?


#11

yes, you can send vst events to the host with delta 0 (with sendVstEventsToHost)… and even from the gui !


#12

but the Juce VST wrapper does not include this method (this is the VST method i used it when i was coding in pure VST). So i need to write my own wrapper method (modify jules’s code) ?


#13

You can’t send midi when the filters are stopped - that would make about as much sense as trying to send audio data when they’re stopped.

Remember that this isn’t midi that’s going to a live midi output - it’s just a set of midi messages that get passed into the downstream filter’s process() method, along with the audio data. If no process methods are running, where would the messages go? What would act on them?

Of course most hosts do still keep all the process methods running when stopped, so you can send messages as normal.


#14

hardware connected to the DAW’s MIDI Outputs.

a controller surface should be able to send midi messages when stopped, messages like program/bank change or even CC’s. Very often you stop to check how something sounds with your MIDI controller. So it should both receive and send MIDI when stopped.

that seems logical to me.


#15

[quote=“atomix1040”]hardware connected to the DAW’s MIDI Outputs.

a controller surface should be able to send midi messages when stopped, messages like program/bank change or even CC’s. Very often you stop to check how something sounds with your MIDI controller. So it should both receive and send MIDI when stopped.

that seems logical to me.[/quote]

…yes, but I think you’re confused between sending midi directly to an output port and sending it out of a filter and down the signal chain. You can send it to a physical port any time you like, but that’s got nothing to do with filters or the host app.


#16

actually i’m not confusing the two. i am more than enough aware and frustrated with the limits of both concepts.

imagine you have 2 midi outputs (physical), each has 3 devices in a midi chain, on one output you have to send midi sync on both, to sync up LFO’s seqencers whatever. Now if you open theese ports in your DAW so it can send notes and sync to them you loose those outputs, you can’t re-open then in the plugin (without a special driver thing that usually just hangs everything or is not free). So you can choose

a) don’t open MIDI Outs in the DAW, leave the whole thng to the plug (that requires more code, esepcially for the SYNC feature, also you have to route notes from the DAW through the plug outside, it goes for any other DAW generated MIDI)

b) open them in DAW and the plug sends controller messages down the VST chain and the DAW sends them to the physical outputs (that sucks, cause you can’t do SysEx, witch is what most old synths use, and that’s the main reason i’m writing my plugin anyway)

so it’s VERY important to send MIDI when stopped and playing. that’s what i’m stuck with right now.


#17

Hmm. Well there’s no solution really. But surely most hosts will continuously run the filters even when it’s not playing? In tracktion there’s a option for doing that.


#18

well if that will work that’s nice. but is it also possible to explicitly call a VST method? cause i think that it might help in thos DAW’s that don’t do proces() on stop. I’m talikng about the sendVstEventToHost method.


#19

No - the sendVstEventToHost is just there to pass the next block of events to the host, it doesn’t actually send them anywhere. I’d expect that if the filters aren’t running, a host would either ignore that call, or stick the events in a buffer somewhere ready for the next process call. It can’t do anything else with them, because it can’t pass them to the downstream filters if they’re not running. I’m pretty sure tracktion will just throw the events away in this case.


#20

I wrote a VST last Oct -not with JUCE, but using Steinberg VST sdk directly- that sends MIDI back to host in a similar way JUCE will do it.

Among the tested hosts where Ableton Live 5.2, Cubase LE, Cubase SX 3, EnergyXT, SAVIHost, Fruity Loops Studio 6 & Sonar 6. All of them kept calling the ProcessReplacing() continuously, also when transports where stopped, and all of them were accepting MIDI output from the plug continuously. So I guess you will be OK then with JUCE too. Unless you explicitly disable the plug in the host, but then it’s not really part of the chain any more, so it’s intentional then.

One gotcha though: my main debugging/development was done with Live. If I remember correctly I did have to produce some fake audio-out for Live for it to keep processing. Maybe due to some optimization thing in that host? Or maybe I did something wrong with plug configuration? Anyhow, my latest attempts with JUCE’s demofilter in Live do not show this problem, so maybe this is moot by now.

What I didn’t test yet is what is being done to the MIDI down the plugin chain. I was sending very straight note-on/off messages on channel 0 only, certainly no sysex. I believe there was an issue with Live stripping/ignoring other channels, but I could be mistaken. Is on my list to check this out some time.