MIDIPacketList, numPackets is always 1
Asked Answered
H

3

6

I'm processing Midi on the iPad and everything is working fine and I can log everything that comes in and all works as expected. However, in trying to recieve long messages (ie Sysex), I can only get one packet with a maximum of 256 bytes and nothing afterwards.

Using the code provided by Apple:

MIDIPacket *packet = &packetList->packet[0];
for (int i = 0; i > packetList->numPackets; ++i) {
    // ...
    packet = MIDIPacketNext (packet);
}

packetList->numPackets is always 1. After I get that first message, no other callback methods are called until a 'new' sysex message is sent. I don't think that my MIDI processing method would be called with the full packetList (which could potentially be any size). I would have thought I would recieve the data as a stream. Is this correct?

After digging around the only thing I could find was this: http://lists.apple.com/archives/coreaudio-api/2010/May/msg00189.html, which mentions the exact same thing but was not much help. I understand I probably need to implement buffering, but I can't even see anything past the first 256 bytes so I'm not sure where to even start with it.

Hofmannsthal answered 28/12, 2010 at 12:28 Comment(2)
Note that Apple's code has a little bug in it - the > in the conditional part of the for loop should be a <. It won't help fix your issue unfortunately.Gandzha
NOTE: the plot thickens. On iOS using an external hardware device like the Line 6 MIDI Mobilizer II (or the iRig or the iConnect), the sysex isn't just broken up into multiple packets. It's broken up into multiple packet lists, each of which contains a single pack with a length of 3. This is my personal hell which I just discovered today.Gorse
N
4

My gut feeling here is that the system is either cramming the entire sysex message into one packet, or breaking it up into multiple packets. According to the CoreMidi documentation, the data field of the MIDIPacket structure has some interesting properties:

A variable-length stream of MIDI messages. Running status is not allowed. In the case of system-exclusive messages, a packet may only contain a single message, or portion of one, with no other MIDI events.

The MIDI messages in the packet must always be complete, except for system-exclusive.

(This is declared to be 256 bytes in length so clients don't have to create custom data structures in simple situations.)

So basically, you should look at the declared length field of the MIDIPacket and see if it is larger than 256. According to the spec, 256 bytes is just the standard allocation, but that array can hold more if necessary. You might find that the entire message has been crammed into that array.

Otherwise, it seems that the system is breaking the sysex messages up into multiple packets. Since the spec says that running status is not allowed, then it would have to send multiple packets, each with a leading 0xF0 byte. You would then need to create your own internal buffer to store the contents of these messages, stripping away the status bytes or header as necessary, and appending the data to your buffer until you read a 0xF7 byte which denotes the end of the sequence.

Nubbin answered 29/12, 2010 at 15:45 Comment(5)
Thanks Nick, but hasn't helped me. When looking at the length of the MIDIPacket, on smaller messages it is as you would expect, but on longer messages it gets to 256 and not beyond no matter how big the Sysex message I send it. I thought it must be splitting it into packets but the MIDIPacketList's I'm getting only ever have one packet. After that first 256 packet is sent I get nothing at all.Hofmannsthal
After some more testing, I have found that the exact same code compiled for Mac OS X (rather than iOS) works as I want it to, so it appears to be a bug/limitation with iOS. FYI, each part of the messages were split into separate MIDIPacketLists with each have 1 MIDIPacket of 256 bytes. iOS only ever seems to see the first MIDIPacketList for some reason.Hofmannsthal
@Domestic Cat, do you happen to know if this is still the same?Gorse
@Yar I am having the same issue with iOS 5.0, so I guess it still hasn't been fixed. At least it is relatively easy to work around.Gandzha
@TimKemp so far this has not caused me any timing issues... um, I think ;)Gorse
T
3

I had a similar issue on iOS. You are right MIDI packets number is always 1.

In my case, when receiving multiple MIDI events with the same timestamp (MIDI events received at the same time), iOS does not split those multiple MIDI events in multiple packets, as expected.

But, fortunately nothing is lost ! Indeed instead of receiving multiple packets with their correct number of bytes, you will receive a single packet with multiple events in it and the number of bytes will be increased accordingly.

So here what you have to do is:

In your MIDI IN callback, parse all packets received (always 1 for iOS), then for each packet received you must check the length of the packet as well as the MIDI status, then loop into that packet to retrieve all MIDI events in the current packet.

For instance, if the packet contains 9 bytes, and the MIDI status is a note ON (3 bytes message), that means your current packet contains more than a single note ON, you must then parse the first Note ON (bytes 0 to 2) then check the following MIDI status from byte 3 and so on ..

Hope this helps ...

Jerome

Turboprop answered 17/1, 2014 at 10:17 Comment(0)
D
1

There is a good reference of how to walk through a MIDI packet in this file of a GitHub project : https://github.com/krevis/MIDIApps/blob/master/Frameworks/SnoizeMIDI/SMMessageParser.m

(Not mine, but it helped me solve the problems that got me to this thread)

Dactyl answered 26/2, 2014 at 14:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.