monome/norns

MIDI clock input responds to all endpoints

catfact opened this issue · 3 comments

thanks to user "2197" on lines for pointing this out:
https://llllllll.co/t/norns-midi-tempo-is-tripled-from-ext-sync/64036/12

apparently there are a significant number of MIDI clock producing devices out there, that enumerate as multiple source endpoints (user-facing software "devices") and send clock messages on more than one endpoint simultaneously.

in device_midi, it seems to me that we are handling all clock messages equally regardless of the endpoint of origin:
https://github.com/monome/norns/blob/main/matron/src/device/device_midi.c#L284C1-L284C1

so this would explain some reported issues with doubled/tripled tempo and jittery clock when following MIDI.

any solution that i can think of involves some new connections between lua and device_midi, one way or another.

(1) from a UI design perspective, the easiest solution i can think of is to treat vport assignment as "enabling" input from a device, including clock input. this would require no new UI elements, but would slightly change the UX behavior if a user was relying on a device for clock while explicitly excluding it from vport assignment list.

(2) the other solution that comes to mind is having an explicit clock device selection, including a default "all" setting. this would have the benefit of not changing any user experience by default.

either one requires some new FFI glue. (2) probably a bit easier in that regard, but designing the lua side is more involved. (e.g., should it be a system parameter representing device name with a string? in that case, need to manage the device name list... should it take vport numbers instead? then need to communicate those to C anyways... etc)


and maybe worth saying that passing clock through lua event loop would make things simpler, but is not desirable for performance.

another possibility, sort of combine the two: implement solution 1, and additionally add a toggled "all clock" mode that is exposed as a system PARAM and defaults to true.

minmal impact on UI, doesn't break existing UX, should be pretty easy for affected users.

a bit clunky maybe?

the only use case that is still broken is pretty niche:

  • i have a device that always sends clock on both endpoints A and B simultaneously
  • i want to follow clock
  • i want to simultaneously receive other input from both A and B, so they are both in the vports list

... hm. maybe midi_clock source param is, like... an integer? where -1 is all devices, 0 is no devices, 1+ is a vport index?

here's a work in progress:

https://github.com/catfact/norns/tree/midi_clock_filter

it doesn't crash, and the lua parameter exists, but i haven't actually tested the C layer functionality (need to dig up multiple clock sender hardwares, or 4x MIDI interfaces, or something.) sharing here just in case anyone wishes to test it before i get a chance.

a minor complaint might be that the clock input selection parameter shows vport indices and not device names for specific device selection. (it's an option type, and i suppose the option table could be made dynamic if it seems important enough that the UI match better between clock input and output.)