异步播放单独 MIDI 消息的最佳实践?
Best practice to async play separate MIDI messages?
我已经将一个 MIDI 文件解析为一组音符(键、速度、时间,还有 MIDI 文件的速度及其变化事件)。我需要以 GUI (LCL) 应用程序的异步方式播放它们(我不能使用 MCISendString
,因为我需要处理这些消息)。问题是,在 MIDI 中通常有数千个音符。您认为播放它们的最佳方式是什么?
我有一些想法,但它们很慢且不切实际:
- 使用等待(
Sleep
或 Delay
)指定时间量并播放音符的函数一次调用一堆 BeginThread
s(有一个限制线程,它真的很不稳定)。
- 对时间戳进行排序,然后 运行 它们通过一个线程 Sleep/Delay
currentNoteTime-previousNoteTime
并播放音符。可能会很慢,尤其是在尝试对所有内容进行排序时。
- 写另一个应用程序作为后台进程并完成这项工作(不专业的bodging)。
我正在使用 Lazarus (Object Pascal),但如果需要,我也可以使用 Delphi 代码。谢谢你的时间。
所有线程方法(睡眠、延迟等)都将在 Windows 上失败,因为您不会获得优于 16 毫秒(最好的情况)的准确度,这将导致您的数据回放不正确,大潜伏。已知问题,您可以在网上搜索。
我是 DryWetMIDI C# 库的作者,该库具有播放功能。我的做法是:
- 按时间对所有事件排序并将指针设置为 MIDI 数据的开始
- 运行 使用 Windows Multimedia Timers API 的高精度定时器,每 1ms 滴答一次
- 在每个刻度上查看当前时间应播放的事件并将这些事件发送到输出设备
- 根据播放的事件向前移动指针
但请注意,此方法仅适用于 Windows。对于其他系统,您需要使用 OS 特定的 API 到 运行 高精度计时器。
我已经将一个 MIDI 文件解析为一组音符(键、速度、时间,还有 MIDI 文件的速度及其变化事件)。我需要以 GUI (LCL) 应用程序的异步方式播放它们(我不能使用 MCISendString
,因为我需要处理这些消息)。问题是,在 MIDI 中通常有数千个音符。您认为播放它们的最佳方式是什么?
我有一些想法,但它们很慢且不切实际:
- 使用等待(
Sleep
或Delay
)指定时间量并播放音符的函数一次调用一堆BeginThread
s(有一个限制线程,它真的很不稳定)。 - 对时间戳进行排序,然后 运行 它们通过一个线程 Sleep/Delay
currentNoteTime-previousNoteTime
并播放音符。可能会很慢,尤其是在尝试对所有内容进行排序时。 - 写另一个应用程序作为后台进程并完成这项工作(不专业的bodging)。
我正在使用 Lazarus (Object Pascal),但如果需要,我也可以使用 Delphi 代码。谢谢你的时间。
所有线程方法(睡眠、延迟等)都将在 Windows 上失败,因为您不会获得优于 16 毫秒(最好的情况)的准确度,这将导致您的数据回放不正确,大潜伏。已知问题,您可以在网上搜索。
我是 DryWetMIDI C# 库的作者,该库具有播放功能。我的做法是:
- 按时间对所有事件排序并将指针设置为 MIDI 数据的开始
- 运行 使用 Windows Multimedia Timers API 的高精度定时器,每 1ms 滴答一次
- 在每个刻度上查看当前时间应播放的事件并将这些事件发送到输出设备
- 根据播放的事件向前移动指针
但请注意,此方法仅适用于 Windows。对于其他系统,您需要使用 OS 特定的 API 到 运行 高精度计时器。