MIDIPacketList,numPackets 始终为 1
我正在 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 个字节之后的任何内容,所以我不知道从哪里开始。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的直觉是,系统要么将整个 sysex 消息塞进一个数据包,要么将其分解为多个数据包。根据 CoreMidi 文档,MIDIPacket 结构的
data
字段有一些有趣的属性:因此基本上,您应该查看 MIDIPacket 声明的
length
字段 并查看它是否大于 256。根据规范,256 字节只是标准分配,但如果需要,该数组可以容纳更多字节。您可能会发现整个消息已被塞入该数组中。否则,系统似乎将 sysex 消息分解为多个数据包。由于规范规定不允许运行状态,因此它必须发送多个数据包,每个数据包都有一个前导
0xF0
字节。然后,您需要创建自己的内部缓冲区来存储这些消息的内容,根据需要剥离状态字节或标头,并将数据附加到缓冲区,直到读取表示0xF7
字节序列的末尾。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:So basically, you should look at the declared
length
field of theMIDIPacket
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 a0xF7
byte which denotes the end of the sequence.我在 iOS 上也遇到了类似的问题。你是对的,MIDI 数据包编号始终为 1。
就我而言,当接收具有相同时间戳的多个 MIDI 事件(同时接收的 MIDI 事件)时,iOS 不会按照预期将这些多个 MIDI 事件拆分为多个数据包。
不过,幸运的是,什么都没有丢失!事实上,您将收到一个包含多个事件的单个数据包,而不是接收具有正确字节数的多个数据包,并且字节数将相应增加。
因此,您需要做的是:
在 MIDI IN 回调中,解析收到的所有数据包(对于 iOS,始终为 1),然后对于收到的每个数据包,您必须检查数据包的长度以及 MIDI 状态,然后循环到该数据包packet 来检索当前数据包中的所有 MIDI 事件。
例如,如果数据包包含 9 个字节,并且 MIDI 状态是音符 ON(3 字节消息),这意味着当前数据包包含多个音符 ON,则您必须解析第一个音符 ON(字节 0 到 2) )然后从字节 3 等检查以下 MIDI 状态。
希望这有帮助......
杰罗姆
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
在 GitHub 项目的此文件中,有一个关于如何遍历 MIDI 数据包的很好的参考:https://github.com/krevis/MIDIApps/blob/master/Frameworks/SnoizeMIDI/SMMessageParser.m
(不是我的,但它帮助我解决了让我进入这个线程的问题)
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)