Open scottyeager opened 3 years ago
This depends on this piece of code in jack.c:
static
void
a2j_input_event(
struct a2j * self,
snd_seq_event_t * alsa_event)
{
...
// fixup NoteOn with vel 0
if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) {
data[0] = 0x80 + (data[0] & 0x0F);
data[2] = 0x40;
}
...
}
I think we could add a build time configuration to opt-in (or opt-out) filtering note on with 0 velocity, or better a run time option.
Worth noting that at least LV2 does not allow zero-velocity note ons. http://lv2plug.in/ns/ext/midi#MidiEvent
JACK requires messages to be in complete form, no running status allowed. So it will always have to "uninterpolate" data.
But this note-on-0 could be made optional yes.
Thanks guys. I'll try compiling a version without that bit for my own use for now. A run time option would be great, especially if it's easily toggled from Cadence :)
I'm working on this at least for stand alone program. DBus version is not done yet. I will publish a new branch for this.
Awesome, thanks again for the attention on this. I have succeeded in building and running a version with the filtering manually removed, so all is well for me.
Worth noting that at least LV2 does not allow zero-velocity note ons. http://lv2plug.in/ns/ext/midi#MidiEvent
JACK requires messages to be in complete form, no running status allowed. So it will always have to "uninterpolate" data.
But this note-on-0 could be made optional yes.
Then LV2 is broken and should be fixed. a2jmidid should NOT be trying to fix a deficiency in LV2. BTW, this same code has been copied into jack1 and jack2 in the sequencer code.
The MIDI 1.0 specification states the following about NoteOn and NoteOff commands:
VELOCITY Interpretation of the Velocity byte is left up to the receiving instrument. Generally, the larger the numeric value of the message, the stronger the velocity-controlled effect. If velocity is applied to volume (output level) for instance, then higher Velocity values will generate louder notes. A value of 64 (40H) would correspond to a mezzo-forte note and should also be used by device without velocity sensitivity. Preferably, application of velocity to volume should be an exponential function. This is the suggested default action; note that an instrument may have multiple tables for mapping MIDI velocity to internal velocity response.
vvvvvvv = 64: if not velocity sensitive vvvvvvv = 0: Note-Off (with velocity of 64)
NOTE-OFF MIDI provides two roughly equivalent means of turning off a note (voice). A note may be turned off either by sending a Note-Off message for the same note number and channel, **or by sending a Note-On message for that note and channel with a velocity value of zero.
In the first sentence it says "Interpretation of the Velocity byte is left up to the receiving instrument.", which means that it is possible to have a NoteOn with velocity=0 mean something completely different from a NoteOff in the receiving instrument!
The rest of the quote is basically talking about the SENDING INSTRUMENT, and what it should do with the velocity value. The "vvvvvvv = 64: if not velocity sensitive" is a suggestion for the sender, not a constraint! The "vvvvvvv = 0: Note-Off (with velocity of 64)" is a suggestion of how a receiver MIGHT interpret a velocity value of 0, again, it's NOT a constraint.
It also EXPLICITLY states that sending a NoteOn with a velocity of 0 is perfectly legal, so there is absolutely no reason for a2jmidid to change the MIDI packet from a NoteOn to a NoteOff.
It also means that LV2 should support it. It would be maybe 3 lines of code to do so.
BTW, one easy way to handle this would be to create a MIDI filter that could be inserted between a MIDI sender and LV2 that would simply change NoteOn/Velocity=0 into NoteOff commands, and the rest of the world would be a happier place for not having this egregious hack in a2jmidid...
After some discussion and thought, you are right that a2jmidid should not be doing this. It is still useful in some cases, but it should at minimum be an option.
LV2 restricting note-on with 0 velocity is quite valid, it is within the spec to dictate what messages or data plugins can use.
I understand your point, it may be technically valid to do what they did, but is it reasonable if the fix is a couple of lines of code? To me it seems like someone is just too lazy to copy the 3 line fix from a2jmidid and add it to LV2... If there is a technical reason why they can't do that I'd really love to know what it is.
It is 3 lines for every single plugin. But anyway, LV2 is off-topic, I mentioned it only as it seemed relevant and I had the wrong idea that this is something people usually wanted (the 0 velo converts to off).
There exist hardware devices that need note-on with velocity 0, with no possible workarounds. As others said, this is not within the intention of the MIDI specs.
If backwards compatibility of JACK is a concern (which I don't think it is. This is a bugfix) then an elegant solution would be to create a new jack midi ouput port METADATA flag that sets the auto-conversion behaviour to "don't convert, send velocity 0", in opposite to the current default "convert to note off".
All other solutions, such as command line flags or compile flags are a burden to the user.
When passing note on messages with velocity zero,
a2jmidid
converts them to note off messages. For example, a note consisting of bytes [144, 56, 0] is converted to [128, 56, 64] while passing through the bridge. This behavior may be harmless or even desirable in many cases, but it's interfering with my ability to control the lights on my APC Mini. The Mini will only turn off it's lights if it receives a note on message with zero velocity in the form given in my example above. Note off messages won't work.Midi is ultimately a byte wise low level protocol that's not always used to control synths in the way the spec suggests. Why not just pass through the messages as received and leave interpretation to the end points?