Custom VST instrument MIDI channel routing

I’m developing a VST3 instrument plugin using DPF (DISTRHO Plugin Framework). The plugin is a 4-channel NES APU emulator — it receives on MIDI channels 1–4 and routes each channel to a different internal voice (two pulse waves, triangle, noise).

The plugin works correctly in Carla. All four MIDI channels route as expected. In Dorico 5, note preview (clicking notes in the score editor) works but everything is getting routed to a single square wave channel and playback is completely silent.

I’ve set up an endpoint configuration with 4 channels, assigned my four instruments (Pulse Wave 1, Pulse Wave 2, Triangle Wave, Noise) to channels 1–4 respectively with a custom expression map, and saved the endpoint. I created a playback template referencing this endpoint. When I apply the template and hit play, the playhead moves but no sound is produced.

The VST audio engine log shows “Server wants activation / => not applied or resumed (from activate)” every time playback starts. Is this a known DPF compatibility issue with Dorico’s activation handshake? And is there anything specific required to make a manually configured multi-timbral VST3 instrument receive MIDI on multiple channels during playback?

Hi, please load your project into Dorico and then do from Dorico’s menu Help > Create Diagnostic Report and post the corresponding zip file here. That will get me a first overview, and then I can give further advice.
Thanks

Dorico Diagnostics.zip (504.1 KB)

Hi @mjsyts, thanks for the data. Please also unzip it on your side and have a look inside, especially at the file /Dorico Diagnostics/AudioEngine/mixerdoc.txt
There you can see that you set up the endpoint in such a way, that your plug-in only exposes a single stereo output to the Dorico audio engine. Compare that to the HALionSonic instance that you can find in that mixerdoc right after your mjsysts plug-in.
Well, it’s not completely wrong to do it that way, others like e.g. NotePerformer do that as well, but then you need to have in the plug-in an own mixer that mixes down the multi timbral voices to one stereo channel. Do you understand what I’m talking about? Please don’t hesitate to ask.

1 Like

Hi @Ulf, thanks for the clarification. I’ve confirmed that Demnos follows the NotePerformer model (one stereo output, onboard mixer, single MIDI input port, multitimbral via MIDI channels 1–4). Looking at the eventdevicedoc.txt from the diagnostics, I notice the only event device listed is the IAC Driver Bus. Is Dorico routing playback MIDI directly to the Demnos VST3 instance, or is it going through the IAC Driver? Could the endpoint configuration not be correctly applied? I’ve also confirmed that the plugin works as expected as a multitimbral AU plugin in Logic, so I’m guessing I’ve done something wrong internally in Dorico.

Hi @mjsyts , no, Dorico does not use the IAC Bus, but sends MIDI directly to the plug-ins.
Maybe the routing from Dorico to your plug-in is wrong. Have a look at this screenshot:


I’ve created a Dorico project from Chamber Quartet Project Template and used NotePerformer as Playback Template. Then in the Play Mode you do the routing in the Track Inspector. Each Player there is assigned to it’s own MIDI channel, Violin 1 to MIDI Channel 1 and likewise the others. So the endpoint configuration looks like

So if you do it similarly with your plug-in, it should equally work in Dorico.

That’s what I have but it doesn’t seem to be working. Logic and Carla are both confirming the channels are routed correctly. The channel configuration I have should work, but somehow in the editor everything is being sent to channel 1 and on note preview in the editor, there’s no sound on playback from the transport.

I think there is something wrong with the expression mapping and endpoint configuration. If I set everything to use the default expression map, all four channels get routed to MIDI channel 1 and they start competing with each other. If I set the expression mapping to the one I made for the plugin, I get silence on playback.

The question is, do all MIDI events get delivered to your plug-in? In the top left area of the plug-in’s editor window is a “red LED” that flashes once with every MIDI note/event it receives. Does that do with your plug-in?
Also you should be able to debug your plug-in even when it is run in the VSTAudioEngine. You can still set breakpoints in the debug version of your plug-in, when you attach the debugger to the VSTAudioEngine process. Sure, you can’t make sense out of the code in the audio engine, and you don’t need to. Just concentrate on your code, see what MIDI comes in. On the output, make sure that you get the buffer switch interrupts and that you put the processed audio data into the appropriate output buffers.

1 Like

Thanks @Ulf. I tried attaching a debugger:

for (uint32_t i = 0; i < midiEventCount; i++)

        {
const MidiEvent &ev = midiEvents[i];

FILE *f = fopen("/tmp/demnos.log", "a");

fprintf(f, "MIDI: raw=0x%02X channel=0x%02X note=%d\n", ev.data[0], ev.data[0] & 0x0F, ev.data[1]);

fclose(f);

Every note is getting routed to channel 0x00, regardless of how I have it configured in the endpoint configuration.

I compared this with Carla and when I change channels it routes properly.

MIDI: raw=0x90 channel=0x00 note=69 MIDI: raw=0x80 channel=0x00 note=69 MIDI: raw=0x91 channel=0x01 note=72 MIDI: raw=0x81 channel=0x01 note=72

In Dorico, no matter what channel I have assigned that channel value always comes back as 0x00

I need to discuss this with another colleague and will come back to you asap.

1 Like

Does Dorico require a VST3 plugin to set kIsMultiTimbral in its class_flags in order to respect multi-channel MIDI routing from the endpoint setup?

That’s my best guess as to why it’s not working.

I could not reach my colleague, yet, but I also guess that you are right with your assumption. Have you tried it out?

I set kIsMultiTimbral (bit 3, value 8) in the class_flags field of both get_class_info_2 and get_class_info_utf16 in the VST3 factory, but it made no difference. Dorico still routes all notes to channel 0 regardless of the endpoint channel assignments.

I’m not a VST3 developer myself, but how about if you pose your question also in the VST3 Developer zone of this forum?

Great idea! Thanks Ulf!

IUnitInfo is required for Dorico to respect endpoint channel assignments, and critically, channel_count in getBusInfo for the event bus must match the number of MIDI channels a plugin uses, because Dorico uses that value to determine how many times to call get_unit_by_bus