yun.cloud yun.cloud - 2 months ago 21
iOS Question

iOS CoreMIDI Skipping MidiPackets

I'm having issues with implementing MIDI into my iOS app as the receiver callback seems to be skipping MIDI messages and packets. I'm using Midi Monitor to check what MIDI messages I'm missing, skipping over, etc.

So the million dollar question is why is iOS skipping certain MIDI messages? Sometimes it doesn't skip MIDI messages, but other times it does. I'm not sure how to approach debugging this as I have exhausted my brain at this point.

My receiver code:

void MidiReceiver(const MIDIPacketList *packets,
void *context, void *sourceContext) {
dispatch_async(dispatch_get_main_queue(), ^{
if (packets->numPackets > 0) {
MIDIPacket *packet = (MIDIPacket *)packets->packet;

// Loop through total number of packets
for (int i = 0; i < packets->numPackets; i++) {
// Go through each packet, iOS sometimes clumps all data into one packet
// if the MIDI messages are triggered at the same time
for (int j = 0; j < packet->length; j += 3) {
NSArray *array = [[NSArray alloc] initWithObjects:[NSNumber numberWithUnsignedInt:packet->data[j]],
[NSNumber numberWithUnsignedInt:packet->data[j+1]],
[NSNumber numberWithUnsignedInt:packet->data[j+2]], nil];

// Use the data to create do meaningful in the app
[myViewController processMidiData:array];
}

// Next packet
packet = MIDIPacketNext(packet);
}
}
});


The monitor code format is : (TIME) - (MIDI Command Type) - (CC Val or Velocity)

Midi Monitor Debug:

12:45:32.697 Control 0
12:45:32.720 Control 1
12:45:32.737 Control 1
12:45:32.740 Control 2
12:45:32.750 Control 3
12:45:32.763 Note Off A♯1 0
12:45:32.763 Note Off F2 0
12:45:32.763 Note Off D3 0
12:45:32.763 Control 4
12:45:32.770 Control 5
12:45:32.780 Control 6
12:45:32.790 Control 8
12:45:32.800 Control 9
12:45:32.810 Control 11
12:45:32.820 Control 13
12:45:32.832 Control 14
12:45:32.845 Control 16
12:45:32.850 Control 18
12:45:32.873 Control 21
12:45:32.883 Control 22
12:45:32.898 Control 24
12:45:32.913 Control 26
12:45:32.933 Control 27
12:45:32.948 Control 28
12:45:33.020 Control 27
12:45:33.030 Control 26
12:45:33.040 Control 25
12:45:33.050 Control 24
12:45:33.060 Control 22


My App's Debug Monitor:

12:45:33.050 Control 0
12:45:33.051 Control 1
12:45:33.051 Control 1
12:45:33.051 Control 2
12:45:33.051 Control 3
12:45:33.083 Note Off D3 0 <----- Where's A#1 and F2!!! :(
12:45:33.087 Control 4
12:45:33.087 Control 4
12:45:33.097 Control 5
12:45:33.100 Control 6
12:45:33.110 Control 8
12:45:33.120 Control 9
12:45:33.130 Control 11
12:45:33.140 Control 13
12:45:33.153 Control 14
12:45:33.165 Control 16
12:45:33.170 Control 18
12:45:33.193 Control 21
12:45:33.203 Control 22
12:45:33.218 Control 24
12:45:33.233 Control 26
12:45:33.256 Control 27
12:45:33.268 Control 28
12:45:33.341 Control 27
12:45:33.351 Control 26
12:45:33.361 Control 25
12:45:33.374 Control 24
12:45:33.381 Control 22

Answer

Got some help from Kurt Revis and it seemed like I was sending the packets too late due to my usage of dispatch_async.

My revised code (I parsed the packets first):

void MidiReceiver(const MIDIPacketList *packets, 
              void *context, void *sourceContext) {

    NSMutableArray *packetData = [[NSMutableArray alloc] init];

    if (packets->numPackets > 0 && object != nil) {
        MIDIPacket *packet = &packets->packet[0];
        // Loop through total number of packets
        for (int i = 0; i < packets->numPackets; ++i) {
             int idx = 0;
             while (idx < packet->length) {
                 NSArray *array = [[NSArray alloc] initWithObjects:[NSNumber numberWithUnsignedInt:packet->data[idx]],
                                  [NSNumber numberWithUnsignedInt:packet->data[idx+1]],
                                  [NSNumber numberWithUnsignedInt:packet->data[idx+2]], nil];

                [packetData addObject:array];
                idx += 3;
             }
             packet = MIDIPacketNext(packet); 
         }
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        for (NSArray *packet in packetData) {
            [object receiveMIDIInput:packet];
        }
    });
}
Comments