与CoreMIDI有一些麻烦。我希望使用不同的时间戳在一个MIDIPacketList中发送少量量化的midi消息。这是我的代码
MIDITimeStamp triggerHostTime = gridModel->gridRows[rowIndex]->framesPerTrigger * PB_AUDIO_FRAMES_TO_HOSTTICK_FACTOR;
Byte note = PB_MIDI_NOTES[rowIndex];
MIDIPacketList *packetList = (MIDIPacketList *)malloc(PB_MIDI_PACKETLIST_SIZE);
MIDIPacket *curPacket = MIDIPacketListInit(packetList);
MIDITimeStamp packetHostTime = mach_absolute_time();
Byte off_message[3] = {MIDI_NOTE_OFF, note, 0};
for (int i = 0; i < item->trigger; i++) {
Byte on_message[3] = {MIDI_NOTE_ON, note, 127};
curPacket = MIDIPacketListAdd(packetList, PB_MIDI_PACKETLIST_SIZE, curPacket,
packetHostTime,
3, on_message);
packetHostTime += triggerHostTime;
curPacket = MIDIPacketListAdd(packetList, PB_MIDI_PACKETLIST_SIZE, curPacket,
packetHostTime - 1e6 * PB_AUDIO_NS_TO_HOSTTICK_FACTOR,
3, off_message);
}
pb_midi_manager_send_packet_list(packetList);
free(packetList);
framesPerTrigger 是音频帧中的量化长度。例如,我有 framesPerTrigger = 22050 ,所以我需要0.5秒的量化。 item-&gt;触发器是准备发送的备注数。我正在添加带有note_on消息的数据包,然后计算下一个时间戳并提前1ms添加note_off。 PB_MIDI_PACKETLIST_SIZE = 512
发送功能:
void pb_midi_manager_send_packet_list(MIDIPacketList* packetList) {
for (ItemCount index = 0; index < MIDIGetNumberOfDestinations(); ++index) {
MIDIEndpointRef MIDIEndpoint = MIDIGetDestination(index);
if (MIDIEndpoint) {
MIDISend(MIDIOutput, MIDIEndpoint, packetList);
}
}
}
我读过关于在主机时间刻度和实时时间之间的转换,以纳秒为单位,所以:
mach_timebase_info_data_t tinfo;
mach_timebase_info(&tinfo);
PB_AUDIO_HOSTTICK_TO_NS_FACTOR = ((double)tinfo.numer / tinfo.denom);
PB_AUDIO_NS_TO_HOSTTICK_FACTOR = 1.0 / PB_AUDIO_HOSTTICK_TO_NS_FACTOR;
PB_AUDIO_FRAMES_TO_HOSTTICK_FACTOR = 1e9 * PB_AUDIO_NS_TO_HOSTTICK_FACTOR / PB_AUDIO_SAMPLE_RATE;
在MIDIMonitor中,一切看起来都不错:
但是在DAW(Ableton)中,我只收到一个非常简短的音符。 DAW是否有可能无法从数据包列表中解压缩midi音符?我想不..那我的问题在哪里?是否有其他方式来安排输出midi音符?我已经尝试将时间戳直接设置为 curPacket-&gt; timeStamp 并收到一些笔记,但是延迟时间很长,并且交换了note_on和note_off消息。
我正在使用iOS模拟器并使用网络midi连接。
感谢您的关注和可能的答案!