Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zero velocity note on messages converted to note off #14

Open
scottyeager opened this issue Jan 4, 2021 · 10 comments
Open

Zero velocity note on messages converted to note off #14

scottyeager opened this issue Jan 4, 2021 · 10 comments

Comments

@scottyeager
Copy link

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?

@tartina
Copy link
Contributor

tartina commented Jan 4, 2021

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.

@falkTX
Copy link
Member

falkTX commented Jan 4, 2021

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.

@scottyeager
Copy link
Author

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 :)

@tartina
Copy link
Contributor

tartina commented Jan 4, 2021

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.

tartina added a commit that referenced this issue Jan 4, 2021
Only for standalon program, dbus is not done yet.
See #14
tartina added a commit that referenced this issue Jan 4, 2021
Only for standalone program, dbus is not done yet.
See #14
@scottyeager
Copy link
Author

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.

@alamaral
Copy link

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...

@falkTX
Copy link
Member

falkTX commented Jan 29, 2021

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.

@alamaral
Copy link

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.

@falkTX
Copy link
Member

falkTX commented Jan 30, 2021

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).

@diovudau
Copy link

diovudau commented Nov 27, 2021

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.

nedko pushed a commit to LADI/a2jmidid that referenced this issue May 4, 2023
Only for standalone program, dbus is not done yet.
See jackaudio/a2jmidid#14

(cherry picked from commit ee48ecee4d2cf2cd73ca29cbc2bf0b709de150fe)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants