MIDIPacketList, numPackets always 1

I process Midi on the iPad and everything works fine, and I can record everything that comes in and everything works as expected. However, trying to get long messages (like 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 always 1. After I receive this first message, no other callback methods are called until a "new" sysex message is sent. I don’t think my MIDI processing method will be called with the full List package (which could potentially be of any size). I would think that I am receiving data as a stream. Is it correct?

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

+4
source share
3 answers

Here I feel that the system either overflows all the sysex messages in one package, or splits it into several packages. According to the CoreMidi documentation, the data field of the MIDIPacket structure has some interesting properties:

A stream of MIDI messages of variable length. Startup status is not allowed. In the case of system exclusive messages, a packet may contain only one message or part of one of them without any other MIDI events.

MIDI messages in a packet should always be complete, except for the system one.

(declared as 256 bytes in length, so clients do not need to create their own data structures in simple situations.)

So basically you should look at the declared MIDIPacket length MIDIPacket and see if it is greater than 256. According to the specification, 256 bytes is just a standard distribution, but this array can contain more if necessary. You may find that the entire message has been crowded into this array.

Otherwise, it seems that the system is breaking sysex messages into several packages. Since the specification says that the execution status is not allowed, then it will have to send several packets, each of which has a leading byte of 0xF0 . Then you need to create your own internal buffer to hold the contents of these messages, if necessary, delete the status or header bytes and add data to the buffer until you read byte 0xF7 , which marks the end of the sequence.

+2
source

I had a similar problem with iOS. You are right, the number of MIDI packets is always 1.

In my case, when you receive multiple MIDI events with the same timestamp (received MIDI events at the same time), iOS does not break these few MIDI events in multiple packets as expected.

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

So here is what you need to do:

In your MIDI IN callback, analyze all the packets received (always 1 for iOS), then for each packet you receive, you need to check the packet length and MIDI status, and then loop into that packet to get all the MIDI events in the current packet.

For example, if a packet contains 9 bytes, and the MIDI status is an ON note (3 byte message), it means that your current packet contains more than one ON note, you should then parse the first ON note (bytes 0 to 2), then check MIDI state from byte 3, etc.

Hope this helps ...

Jerome

+1
source

There is a good recommendation on how to get through the MIDI package in this GitHub project file: https://github.com/krevis/MIDIApps/blob/master/Frameworks/SnoizeMIDI/SMMessageParser.m

(Not mine, but it helped me solve the problems that led me to this topic)

0
source

Source: https://habr.com/ru/post/1333564/


All Articles