IMidiMapping parameter being absorbed

I have an effect which has one of its parameters linked to CC-64 (pedal), by default (using IMidiMapping). It works fine, but it seems to absorb this pedal controller, so later effects in the chain don’t see it.

How do I stop this from happening? I want the effect to read the pedal, and allow later effects to also read it.

AFAIU, I shouldn’t re-emit MIDI legacy events because (aside from feeling like a grody hack), the link to CC-64 is only a default hinted by IMidiMapping. The user could configure this parameter to come from elsewhere, and I certainly don’t want to generate new MIDI events.

Thanks!

So if you do not use the IMidiMapping the plug-ins later in the chain get the sustain pedal? By the way, which host are you talking about.
The SDK does not dictate how the event flow is happening in the host.

Hi @Arne_Scheffler - sorry for taking so long. I still have this issue.

I’m using REAPER.

If I don’t use IMidiMapping (and instead manually link the parameter to a CC), then following effects can still use the same CC. If I do use IMidiMapping, then the CC is empty for the following effects.

I wonder if the problem is the existence of “legacy MIDI events”. Since you added those to the SDK, hosts might assume that if I’m consuming MIDI CCs, then I’m also outputting legacy events.

There are two reasons I don’t want to do this:

  1. IMidiMapping is a default/suggested link to a particular MIDI CC. I can disconnect this, and automate it manually - but my effect doesn’t know this, so still outputs legacy MIDI events for a (now unrelated) CC.
  2. This loses resolution! REAPER treats MIDI CCs like automation - allowing smooth curves and high-precision values, which can be sample-accurate when sent to a VST3 plugin. But only the first one! :stuck_out_tongue: The second plugin gets 0-127 quantised values.

What I really hoped would work is copying all the automation over to “data.outputParameterChanges”. If the IMidiMapping link is being used, it would make sense for it to apply to the output as well! Unfortunately that doesn’t fix anything (and actually breaks some other small things).

This is a real pain, and I would really like a solution to this. Thanks!

Bump.

It really seems like you wanted to provide a more accurate future-compatible way to deal with MIDI CCs (by handling them as normal automation), but you’ve accidentally forced plugins to translate that high-quality automation back into MIDI events.

Unless I’ve misunderstood something, which I hope I have!

I think the issue here is in your setup in Reaper. Reaper seems to filter MIDI CC messages if an effect is handling it via IMidiMapping. This is nothing the VST3 API forces the host to do. Maybe you have to explicitly send the MIDI data (in Reaper) to the other effects in the chain.

OK - so what’s the correct way for a host to distinguish between the two situations:

  • a plugin is taking MIDI CCs using IMidiMapping, and outputting MIDI CCs using LegacyMIDICCOutEvent - but it’s currently deliberately holding the CC output flat, so isn’t emitting any CC-change events.
  • a plugin is taking MIDI CCs using IMidiMapping and wants the host to just pass the CC through unchanged

These look pretty similar from the outside (you’re getting CCs in, not giving any events out). The VST3 API doesn’t “force” the host to assume either one - but neither option is correct in all cases! What’s the ideal host behaviour here?

Is it something like: once you emit your first LegacyMIDICCOutEvent for a given CC, the host stops passing through that CC for you? Is it per-CC, or for all of them? Or something else?

Is there some documentation I can point the Reaper folks to, for how they should be handling this, instead of (apparently) defaulting to the first case all the time?

I think you just have to make the MIDI routing in the host. If you have a channel with Plug-in A and Plug-in B and want to have both receive MIDI, you should setup the host to send the MIDI data to A and B explicitly.
In Cubase you would use the MIDI Send slot for this. I don’t know how you would set this up in Reaper though.

The default behaviour in Reaper is for each effect to take the MIDI out of the previous effect. If an effect does not output MIDI, then the MIDI is passed through that effect unchanged.

This matches how audio input-only plugins (such as scopes etc.) behave. The audio is passed through unchanged to the next effect. Here’s a diagram:

Non-VST3 effects seem to handle this fine. For example, a VST2 plugin with “receiveVstMidiEvent” but not “sendVstMidiEvent” enabled would act like effect (3) in that diagram, where the MIDI is passed through unchanged to the next effect in the chain.

VST3 doesn’t provide a way to distinguish between effects (3) and (5) in the diagram. Before LegacyMIDICCOutEvent, all VST3 effects were handled like (3) - now that you’ve introduced it, they’re (maybe?) handled like (5) but the host has to guess, or something?

It sounds like you’re suggesting users should have to explicitly do this routing themselves (even while audio is routed automatically) - which seems like a bad user-experience specific to VST3 plugins.

Bump - @Arne_Scheffler is there an answer to how hosts should be handling this?

@Arne_Scheffler Is there an answer to this?

How should hosts distinguish between effects (3) and (5) on the diagram? How should my plugin help the host?

The VST3 API does not enforce a host how to connect audio or event buses between plug-ins. The host is free to design how it wants to do this. That said, some of the use-cases you provided will fail on some hosts while some other use-cases will fail on other hosts (even with other plug-in API’s like VST2 or AudioUnit).
And you’re missing other use-cases as well. Just one example: a plug-in that outputs event data and another plug-in is next in the chain, but the user does not want the next plug-in to receive the event data. Or the user may want to route the event data to a plug-in on another track. All this cannot be part of the VST3 API and must be handled at the host level.

You can always do manual routing for exceptional cases, but in most hosts, there is a default chain-like routing for audio in an effects chain.

This default chain-like routing can work fine for audio, and events (including notes) - but not MIDI CCs, because of the ambiguity I described.

I can’t tell if (1) I’ve failed to communicate the problem here, (2) I’ve communicated correctly, and your answer really is “Just route everything manually”. There’s a reason I don’t personally use Bidule, and it’s just as awkward to require that manual routing for MIDI.