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

Bumping this just to check if anything has been done to incorporate LegacyMIDICCOutEvent into Juce, or if anyone has found a workaround for passing CC messages from a VST3 to its host. I’ve noticed that pretty much every VST3 that I have from other developers (Arturia, Eventide, U-he, Audio Thing, etc.) allows incoming CC messages to pass through and on to the next plugin or the host (Reaper in my case), unlike the VST3s I create with Juce, which block those messages. Is there any word on this @jules or @t0m ?

3 Likes

Here’s something weird that I stumbled upon which might be of interest: in processBlock(), if I add a noteOn or noteOff message to the MidiBuffer when an incoming CC message is received, the CC message also gets passed through to the host (I’m using Reaper). Here’s my code:

void CcpassThruTestAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    buffer.clear();

    MidiMessage msg;
    int time;
    MidiBuffer myBuffer;
    for (MidiBuffer::Iterator i(midiMessages); i.getNextEvent(msg, time);)
    {
        if (msg.isController())
        {
            MidiMessage myNoteOff(MidiMessage::noteOff(16, 127));
            myBuffer.addEvent(myNoteOff, time);
        }
    }

    midiMessages.swapWith(myBuffer);
}
1 Like

Testing my VST3 plugin in the AudioPluginHost, it would appear that JUCE VST3 plugins output pitch bend and CC messages just fine. But many hosts don’t forward them - at least not Ableton Live and Studio One.

But perhaps Reaper does?

[Edit] the VST3s I create all block CC messages, including pitch bend, when run in Reaper, which is why it’s so weird that adding in a note on/off lets the CCs pass through.[/Edit]

Reaper claimed that their latest version supports LegacyMidiCCOutEvent, but I tried out Steinberg’s testing plugin and it failed to output anything. I was in contact with one of Reaper’s developers a couple of days ago and he claims to have fixed the issue, so hopefully it will be working in their next update.

Does that happen in other hosts?

I don’t have any other hosts to confirm with :frowning_face:

What happens with the JUCE AudioPluginHost if your plugin generates CC’s, but no notes? Do they get out?

I tried a version which adds a controller message to the buffer rather than a note off. In Reaper, neither the generated CC nor the CC from the device are passed through. I also tried a version that adds both a note off and a CC to the buffer. In Reaper, the CCs from the device would once again pass through but the generated CC would not.

In AudioPluginHost, unlike Reaper, all my plugins pass along incoming CC messages. However, controller messages generated within a plugin are still not passed along.

Really? That’s odd… does your plugin receive the CC messages from the AudioPluginHost or do they just magically appear at the output?

Rather confusing isn’t it!

Hard to diagnose when daws are all handling it differently, some of them using hacks to play well with vst2 instead of moving to full and complete vst3 compliance.

How Studio One handles CC ...

I noticed with studio one, for example, that if I set up a chain of midi plugins in studio one that generate midi cc’s with vst2 and feed that into a vst3 plugin, the vst3 doesn’t see the generated cc’s. On the other hand if I add midi cc events to a controller lane in studio one, then those do show up as parameters to the vst3 plugin.

My feeling is that studio one is actually being very true to the vst3 approach. It’s keeping the cc controller lane data seperate from midi notes in a separate queue and then when calling back to vst3, it already has the cc’s ready to go as parameters for the vst3 plugin. But since it handles it that way it does not bother to look at the normal midi stream going through earlier vst2 plugins to see if there are cc’s there too. So the vst3 never sees them.

In truth they are handling it the way steinberg wants it to be handled, but that also means vst2 generated cc’s can’t be passed along the midi signal chain in studio one.

How Cubase handles it ...

Ironically, cubase does grab cc’s out of the midi stream before calling back into vst3’s, so at least for now they support that but according to many comments I have seen from a Arne, I suspect they might remove that at any time because it’s not officially supported by the api.

So anyway reaper could be doing who knows what to distinguish between cc’s recorded in the controller lane (or coming from your midi controller), versus midi cc generated via vst2 midi plugin (which is not a supported feature by steinberg even in vst2 by the way). In the past we got away with it because vst2 had all midi in one queue but since people are now trying to be more compliant with vst3, there is no core single midi queue anymore. So it makes sense that generated cc’s might not get through with totally undependable behavior per host and they happen to be rolling out their vst3 support.

On top of that you have juce which is trying to convert back and forth between the vst2 concept we see inside juce plugins as a single midi buffer with all midi, and the vst3 concept where there is no midi stream inside the plugin.

Juce SHOULD be converting cc Based parameters into cc events in the processblock midi buffer. And it SHOULD be doing something after the callback so that IF the host is using the LegacyCC the cc’s in the buffer will be handed to the host that way. But that assumes juce is doing its job, it assumes the host is looking for the LegacyCC conversion and it assumes there is nothing in the host or juce that would prevent that from happening in the case when there are also not at least some notes generated and added to the buffer by the plugin.

Someone needs to diagram all this out so we can all get in the same page about what is happening where.

Audiopluginhost is something by juce and we can debug the source so we should start there to see what is going whether there can be solved through improvements to juce or if simpley audiopluginhost needs to be updated, as do some of the daws

1 Like

Does it have something to do with the macro JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS:

This is because of the lack of support for LegacyMIDICCOutEvent, as I mentioned before:

In the cases above, I was only adding a Juce controller message to the buffer, not a LegacyMIDICCOutEvent. I’m not going to experiment with that until Reaper releases their update and I can confirm that Steinberg’s testing VST3 works within it.

When you add a CC to the buffer inside VST3, it doesn’t make it out to the host, EXCEPT if and only if JUCE is copying it from there to the LegacyCC out feature. VST3 does not add CC’s to that buffer, nor look for them after callback. That is the VST2 way.

Juce is attempting to give you the same JUCE api of seeing both midi and cc in that midi buffer, but unless JUCE moves those to the VST3 way of getting them, then NO host will get them.

So fundamentally JUCE has to use legacy feature to get those CC events out…and not all DAW’s will support that legacyCC feature.

You don’t add a LegacyMIDICCOutEvent anywhere.

You modify the JUCE Audio Plugin Host code to process LegacyMIDICCOutEvents as I explained in that other thread. Then, when you insert controller messages into a JUCE buffer, they come out of the VST3 plugin.

But as has been explained, this only fixes it in the JUCE PluginHost and not in any DAWs that are out there, so it’s really just an exercise for the curious at this point.

But as has been explained, this only fixes it in the JUCE PluginHost and not in any DAWs that are out there, so it’s really just an exercise for the curious at this point.

As well as a way to verify that JUCE is actually doing what its supposed to be doing in terms of moving or copying CC’s from the midi buffer to the legacyMIDICCOUT queue. Once we know for sure JUCE is handling that, then we can blame everything after that on the various DAW’s

I am still not clear, some here said things work when there are notes added to the buffer, but not until then. So either that is JUCE not moving/copying the CC’s from the midi buffer to the legacy Cue, unless there is at least some notes added…or something is strange about that report. So… Fix AudioPluginHost to work as all hosts are supposed to work with legacyCC, then we can see for ourselves whether JUCE is to blame for any of the problems people are having or not.

Hi,

I’m trying to make a plugin that generates and sends MIDI note messages and MIDI CCs to control a piece of hardware, much the same as @1gn4ci0. I understand that MIDI messages are generated/sent out of the plugin by copying the buffer received from the host, modifying the copy and passing it to the host which passes to the MIDI device. After a while of searching google and finding this post, I was made aware that VST3 don’t play well with MIDI CCs. @1gn4ci0 is there any reason why you aren’t creating a standard VST instead of VST3? I’ve been trying to figure out how to make a very simple plugin creates and outputs MIDI CCs for a while and I feel like that there should be a simple way of doing this. I’ve scoured the JUCE tutorials and I cannot find a straightforward way of simply creating MIDI CCs and sending them to a MIDI device. All I need is to output the values of a few sliders and buttons as MIDI messages but it seems near impossible to find any info on how to actually implement this. I’m hoping you’ve got an idea.

Thanks for any help in advance!

The reason many people aren’t making a VST2 is that, unless you already have a license for VST2 from Steinberg, you no longer can get one and are not legally allowed to release a VST2. If you are making this plugin for your own use only, then by all means you can make a VST2, and have easily usable MIDI - unlike VST3. Just enable JUCE_PLUGINHOST_VST in the Projucer juce_audio_processors module settings.

2 Likes

Hi - someone has indicated to me that it’s possible to share the MIDI ports opened by a host directly, but I’m not aware of this… Is this possible?

I have had limited success with sending MIDI messages directly to an output port from a VST3. I was experimenting with sending out CC messages when an AudioProcessorParameter was changed. In the parameterValueChanged() function in the processor, I included the following code:

auto deviceIdentifier{ MidiOutput::getAvailableDevices()[1].identifier };
midiOutput = MidiOutput::openDevice(deviceIdentifier);
if (midiOutput != nullptr)
    midiOutput->sendBlockOfMessagesNow(pluginMidiBuf);

I did manage to send CC messages out, but the plugin was unstable. In fact, if I remember correctly, the plugin would only work when I was in debug mode in VisualStudio and attached to the host process (Reaper). Long story short: it is indeed possible to directly access MIDI ports from a VST3, but there are a bunch of obscure issues related to it and I have neither the skill nor the motivation to work them out.

I hit upon a way to output CC messages from a VST3 which doesn’t require LegacyMidiCCOutEvent. Detailed here.

2 Likes