MIDIPacketList,numPackets 始终为 1

发布于 2024-10-09 14:12:49 字数 743 浏览 5 评论 0原文

我正在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

下壹個目標 2024-10-16 14:12:49

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

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

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

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

因此基本上,您应该查看 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:

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.

走走停停 2024-10-16 14:12:49

我在 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

楠木可依 2024-10-16 14:12:49

在 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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文