MIDIPacketList,numPackets始终为1

时间:2010-12-28 12:28:17

标签: cocoa ipad midi sysex coremidi

我正在iPad上处理Midi,一切正常,我可以记录所有内容,并且所有内容都按预期工作。但是,在尝试接收长消息(即Sysex)时,我只能获得一个最大为256字节的数据包,之后没有任何内容。

使用Apple提供的代码:

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

packetList->numPackets始终为1.在收到第一条消息后,在发送“新的”sysex消息之前,不会调用其他回调方法。我不认为我的MIDI处理方法将使用完整的packetList(可能是任何大小)调用。我原以为我会把数据作为一个流来接收。这是对的吗?

在挖掘我唯一可以找到的东西之后:http://lists.apple.com/archives/coreaudio-api/2010/May/msg00189.html,它提到完全相同的东西,但没有多大帮助。我知道我可能需要实现缓冲,但我甚至看不到前256个字节的内容,所以我不确定从哪里开始。

3 个答案:

答案 0 :(得分:2)

我的直觉是,系统要么将整个sysex消息塞入一个数据包,要么将其分解为多个数据包。根据{{​​3}}文档,MIDIPacket结构的data字段有一些有趣的属性:

  

可变长度的MIDI信息流。不允许运行状态。在系统专用消息的情况下,数据包可能只包含单个消息或一部分消息,而不包含其他MIDI事件。

     

数据包中的MIDI消息必须始终完整,系统专用除外。

     

(声明它的长度为256个字节,因此客户端不必在简单的情况下创建自定义数据结构。)

所以基本上,你应该查看length的声明MIDIPacket字段并查看它是否大于256.根据规范,256字节只是标准分配,但该数组如果有必要可以举行更多。您可能会发现整个消息已经塞进该数组中。

否则,似乎系统正在将sysex消息分解为多个数据包。由于规范说不允许运行状态,因此它必须发送多个数据包,每个数据包都有一个前导0xF0字节。然后,您需要创建自己的内部缓冲区来存储这些消息的内容,根据需要删除状态字节或标头,并将数据附加到缓冲区,直到您读取表示结束的0xF7字节为止。顺序。

答案 1 :(得分:1)

我在iOS上遇到过类似的问题。你是对的MIDI数据包总是1。

在我的情况下,当接收到具有相同时间戳的多个MIDI事件(同时收到的MIDI事件)时,iOS不会按预期在多个数据包中分割这些多个MIDI事件。

但幸运的是,什么都没有丢失!实际上,您不会接收具有正确字节数的多个数据包,而是会收到一个包含多个事件的数据包,并且字节数也会相应增加。

所以你要做的就是:

在您的MIDI IN回调中,解析收到的所有数据包(对于iOS总是1),然后对于收到的每个数据包,您必须检查数据包的长度以及MIDI状态,然后循环到该数据包以检索所有MIDI事件在当前数据包中。

例如,如果数据包包含9个字节,并且MIDI状态是音符ON(3字节消息),这意味着您当前数据包包含多个音符ON,则必须解析第一个音符ON(字节) 0到2)然后从字节3检查以下MIDI状态,依此类推..

希望这会有所帮助......

杰罗姆

答案 2 :(得分:0)

如何在GitHub项目的此文件中浏览MIDI​​数据包有一个很好的参考:https://github.com/krevis/MIDIApps/blob/master/Frameworks/SnoizeMIDI/SMMessageParser.m

(不是我的,但它帮助我解决了让我遇到这个问题的问题)