Win32 MIDI API无法接收无0xF7的SYSEX,如何改为单字节触发?
解决Win32 MIDI API接收无0xF7结尾的SYSEX消息问题
要让Win32 MIDI接口在有字节可用时立即通知你,而非等待完整的SYSEX消息(0xF7结尾),核心是禁用API默认的SYSEX自动组装功能,具体操作如下:
1. 修改设备打开参数,启用流式状态通知
在调用midiInOpen时添加MIDI_IO_STATUS标志,这个标志会强制API在缓冲区有数据写入时就触发回调或更新状态,不再等待SYSEX结束符0xF7:
midiInOpen(&device_in, selected_midi_in_interface, (DWORD_PTR)midi_in_callback, 0, CALLBACK_FUNCTION | MIDI_IO_STATUS);
2. 调整缓冲区处理逻辑
- 启用
MIDI_IO_STATUS后,midiHdr_in.dwBytesRecorded会实时更新,只要有新字节写入就会变化,无需等待完整消息; - 每次处理完当前缓冲区的数据后,必须重新调用
midiInAddBuffer把缓冲区提交回设备,才能继续接收后续数据:// 处理缓冲区数据的示例逻辑 if (midiHdr_in.dwBytesRecorded > 0) { // 读取lpData中的字节,自行解析AKAI S900的SYSEX内容 process_akai_sysex(midiHdr_in.lpData, midiHdr_in.dwBytesRecorded); // 重置记录长度,重新提交缓冲区 midiHdr_in.dwBytesRecorded = 0; midiInAddBuffer(device_in, &midiHdr_in, sizeof(MIDIHDR)); }
3. 自行判断SYSEX消息的结束
因为AKAI S900的采样转储没有0xF7结尾,你需要根据设备文档处理结束判断:
- AKAI S900的采样转储SYSEX通常包含固定长度字段,解析头部的长度值即可判断是否接收完成;
- 或查找设备定义的采样数据末尾标识字节。
注意事项
- 缓冲区大小要合理:太小会频繁触发回调,太大则增加延迟,建议匹配AKAI S900的数据包尺寸;
- 若使用回调函数,触发的消息类型为
MIM_LONGDATA,可在回调内直接处理数据并重新提交缓冲区。
内容的提问来源于stack exchange,提问作者Andy Paumann
相关产品推荐
相关产品推荐

