Understanding host NoteOn/NoteOff noteId behaviour

I’m writing a VST3 instrument plugin for the first time, and in testing I see inconsistent behaviour from various hosts in regards to note on and note off events, and I wanted to see if anybody has any tips on how they’ve handled this.

In the VSTPluginTestHost, for each note event I receive a valid noteId. I use this to corelate note on and off events and manage my polyphony.

However I’m making an effort to by cross-platform, and to test in multiple hosts, so I’ve been working in Linux using the “Carla” host which works with Jack there and its VST3 hosting seems to be based on pieces from JUCE. In that implementation the noteId on NoteOnEvent is always “-1”, which isn’t great, but is acceptable according to the comments in NoteEvent:

int32 noteId; ///< note identifier (if not available then -1)

So in my code what I’ve attempted to do is look for -1 and if it’s there, substitute the pitch value for the ID, which isn’t ideal because in that case a “release phase” for a given note can’t happen for multiple strikes of the same key. But it works, at least for testing. The only confusing thing is that the noteId I’m receiving on the NoteOffEvent is “0”, not -1, which is not consistent with the documentation.

However, coming back to testing in VSTPluginTestHost now I’m finding that it also sometimes sends -1 for the note ID. Or sometimes just 0 for note off. Just not most of the time. But worse, the note off events with 0 do not have a valid pitch to use to correlate with. So I have no idea of knowing which note on event this note-off may be a response to.

Basically in a nutshell: the behaviour to handle -1/0 pairs for the JUCE VST host causes stuck notes on VSTPluginTestHost .

So I guess my question generally is a) WTF? b) how are people handling note on / note off, polyphony, voice stealing, etc. in the context of multiple hosts which seem to have different behaviours. What is the “right” way to corelate events?

I have yet to try this under other hosts on my machine (I have Cakewalk SONAR and Tracktion on here at least), I’m afraid to see what they do, too.

Update: Looking deeper, it seems like with VSTPluginTestHost what I’m actually seeing is note-ons with a “0” noteId, followed by another “0” for note off, so in fact it’s entirely correct behaviour, it’s just the first note received on start is a “0”.

Which just happens to conflict with the fact that Carla seems to maybe sometimes send “0” for noteoff when it means “-1”.