@dspk, really stupid question, but i have to ask: are you sure you’re not running a debug build of 0.7.1? (maybe a mislabeled one; if it’s debug, you should see some baudrate settings being printed on the screen at boot.)

otherwise, i agree with @ngwese that this sounds like a situation where the USB stack can’t keep up with the transfer requests.

i’m looking at some diffs and don’t think there was any change to the midi RX handling code itself. we added TX code but it shouldn’a have had an effect.

the most significant changes in 0.7.x were greg’s fixes to app pause/resume , especially nested calls. this greatly improved stability, but also means that interrupts are probably being disabled more often now. this gives the USB stack less opportunity to empty the MIDI RX buffer.

we could always try increasing the MIDI RX buffer size, but this is a sloppy band-aid at best.

i’ll look at it a bit more when i can and also checkout the fixes from earthsea.

While investigating what must be added to support midi clock to earthsea’s usb midi mode I think I might have found a potential source for the glitchy midi input (on both aleph and earthsea).

The code which parses USB-MIDI event packets and turns them into internal kEventMidiPacket seems like it might have a few kinks to work out. After staring at the code for a bit I’m starting to suspect that:

  • running status isn’t handled in all cases
  • the rxBuf contains 32 bit USB-MIDI event packets yet the parsing code is only skipping over the packet header of the first event. If there are multiple event packets the headers get interpreted as if they where midi data. (see section 4 of http://www.usb.org/developers/docs/devclass_docs/midi10.pdf)

…now off to confirm my suspicions.

https://github.com/monome/aleph/blob/dev/avr32_lib/src/usb/midi/midi.c#L67-L125

Well it would appear that USB-MIDI disallows running status which means that a greatly simplified “usb midi” specific variant of the midi_parse(...) function might be in order (little more than some bit shifting seems to be in order).

1 Like

Oh I think youre right, I would put it differently for my own understanding:

If the rx buffer contains more than one midi event, their data will be munged together into a single avr32 event, instead of posting 2. Right?

I guess this would happen more often in 0.7.1 for the reasons above

I think yr right that it could be much simplified… this looks like the aftermath of some messy refactor

Well if I’m running through things in my head correctly I think the following sequence is possible with two (or more) midi events in the rxBuf:

  • status byte is found => packet.data[0]
  • two data bytes found => packet.data[1] and packet.data[2]
  • start of next incoming midi packet
    • if midi packet header has CN value >= 0x8 then the header itself is interpreted as a status byte, the previous event is posted and all subsequent parsing is off by one byte
    • if midi packet header has CN value < 0x8 then header byte itself => packet.data[3]
      • if the next byte (which is the beginning of the actual payload for the next midi message) is a status byte then the previous event is posted with garbage in the LSB else the whole previous event is discarded because (dst > packetEnd)

…basically the first event will probably get posted, possibly with some garbage at the end. Subsequent events may be posted but are likely to be entirely corrupted.

I hope to have time tonight to test out an alternate version midi_parse along with one other tweak. If all goes well I’ll port over the changes to the aleph code base for testing.

… you’re right, the basic bug is that it assumes CN is always the first byte each time the endpoint is read. i think it was originally interrupt-driven…