【问题标题】:Proper use of MIDIPacketListAdd (CoreMIDI)正确使用 MIDIPacketListAdd (CoreMIDI)
【发布时间】:2013-04-02 03:21:51
【问题描述】:

我正在尝试通过这样做(在 Mac 上)使用 CoreAudio 的 MIDIPacketListAdd:

MIDIPacketListAdd(packetList, PACKETLIST_SIZE, currentPacket, mach_absolute_time, len, data);

我正在考虑在发送之前多次调用该方法,以便我的 packetList 中包含 > 1 个数据包。 但是,当我这样做时,numPackets 永远不会增加,而我得到的是 packetList->packet[0] 和一个不断增加的 packet[0].data。

1) 使用此方法的正确方法是什么?我看过几个例子,包括“Learning Core Audio”中的一个——它们似乎都只发送一个数据包。

2) 如果我在 1 个数据包列表中打包多个数据包,而不是多次发送 1 个数据包列表和 1 个数据包,是否有任何性能改进?

谢谢,感谢您对此提供的任何帮助。

编辑跟进:这是我如何初始化数据包列表

#define PACKETLIST_SIZE 512

- (void) initPacketList {

    if (packetList) {
        free(packetList);
        packetList = NULL;
    }

    packetList = (MIDIPacketList *)malloc(PACKETLIST_SIZE * sizeof(char));
    currentPacket = MIDIPacketListInit(packetList);
}

- (void) clearPacketList {

    packetList->numPackets = 0;
        currentPacket = MIDIPacketListInit(packetList);
}

- (void) addPacketToPacketList:(Byte*) data ofLength:(int) len {

    NSLog(@"length %d", len); 
    //NSLog(@"%lld", mach_absolute_time());
    currentPacket = MIDIPacketListAdd(packetList, PACKETLIST_SIZE, currentPacket, mach_absolute_time, len, data);

    //if (!currentPacket) exit(1);

}

【问题讨论】:

    标签: macos core-audio coremidi


    【解决方案1】:

    The answer is in the documentation for MIDIPacketListAdd.

    返回值

    如果数据包中没有空间用于事件,则返回 null;否则返回一个数据包指针,该指针应在后续调用此函数时作为 curPacket 传递。

    所以你可能想要这样的东西:

    currentPacket = MIDIPacketListAdd(packetList, PACKETLIST_SIZE, currentPacket, mach_absolute_time, len, data);
    

    每次之后一定要检查currentPacket是否为NULL。

    如果您将多个数据包放在一个数据包列表中,性能应该会更好,因为您向 MIDI 服务器发出的跨进程请求更少,但老实说,这在现代 Mac 上不太可能引起注意。

    编辑:这就是你做错了什么。

    packetList = (MIDIPacketList *)malloc(PACKETLIST_SIZE * sizeof(char));
    

    sizeof(char) 在 C 语言中始终为 1,根据定义。 malloc(PACKETLIST_SIZE) 就是你所需要的。

    currentPacket = MIDIPacketListAdd(packetList, PACKETLIST_SIZE, currentPacket, mach_absolute_time, len, data);
    

    这给了我一个编译器警告,因为您传递的是mach_absolute_time 函数的地址,而不是调用该函数。你的意思是:

    currentPacket = MIDIPacketListAdd(packetList, PACKETLIST_SIZE, currentPacket, mach_absolute_time(), len, data);
    

    一旦我这样做了,我看到packetList->numPackets 按预期增加了。

    但是,请注意两点:

    • 如果您想立即发送 MIDI 数据,只需提供0 的时间戳即可。

    • 如果您调用 MIDIPacketListAdd 时的时间戳与前一个调用相同,那么它只会将您的数据连接到前一个数据包。你会看到packetList->numPacketscurrentPacket 保持不变,但currentPacket->length 会增加。

    这就是你没有看到packetList->numPackets增加的原因:mach_absolute_time的地址是一个常数,所以你的“时间戳”每次都是一样的。

    【讨论】:

    • 嗨,Kurt,我正在执行上述操作,但是当我使用调试器检查数据时,我的数据仍被塞入一个数据包中。 packetList->packet[0]->当下一条数据应该在下一个数据包packet[1]中时,数据会变长。
    • 另一个问题是,如果我的 packetList->packet[0]->data 是 9 个字节,我发送到的合成器/虚拟仪器会忽略最后 6 个字节吗?
    • 调试器误导了你。 MIDIPacket 是一个可变长度结构——它有 6 个字节的标头(4 个字节 timeStamp,2 个字节 length),然后是 1 到 65535 个字节的数据。 MIDIPacketList 只是一个或多个MIDIPackets 连续存储在内存中。问题是:你不能真正用 C 表示可变长度结构。所以,你不能说packet[1] 来获取第二个数据包——编译器和调试器都不会做正确的事情。使用MIDIPacketListNext,或者直接查看原始内存。
    • 另外,您的数据包的length 应该是您要发送的数据的确切长度。如果你希望它发送 3 个字节,那么长度应该是3。我完全不知道为什么要将其设置为9,然后添加 6 个额外字节的垃圾。 CoreMIDI 会(可能)按原样发送它,但如果它不是有效的 MIDI,接收器几乎可以做任何事情。
    • 啊我c..我觉得奇怪的另一件事。即使我在发送数据包列表之前调用 currentPacket = MIDIPacketListAdd(packetList, PACKETLIST_SIZE, currentPacket, mach_absolute_time, len, data) 3 次,但每次打印时 packetlist->numPackets 仍然为 1。这是我自己更新的东西吗?
    猜你喜欢
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多