什么样的定时器最适合做MIDI定时?
What kind of timer is most suitable for MIDI timing?
我正在用 C# 和 .NET 编写一个简单的 MIDI 应用程序供自己使用 4.x。
我假设商业 DAW(在 Windows 平台上)使用 Windows Multimedia Timers 来计时 MIDI 数据的播放。但我无法验证这一点,因为商业内容是封闭源代码。
我希望有人在这方面有知识,可以告诉我我的假设是否正确。或者,这些 DAW 是否使用了我不知道的定时器?我想确保没有任何我忽略的更合适的东西。
虽然我没有专门为商业 DAW 项目编码的特权,但我确实有为事件的准确计时很重要的场景编码的经验,包括 MIDI processing/routing。
你的假设是正确的。编码良好的 MIDI 音序器使用 Windows 多媒体计时器来安排将 MIDI 消息发送到 MIDI 设备。
Microsoft 的 Multimedia Timer Reference actually mentions MIDI 排序示例使用:
These timer services are useful for applications that demand high-resolution timing. For example, a MIDI sequencer requires a high-resolution timer because it must maintain the pace of MIDI events within a resolution of 1 millisecond.
定时器的使用是另外一个话题,这里不再赘述。但我想指出几点:
所有现代硬件都支持 1 毫秒的计时器分辨率,这基本上是给定的,但您仍然应该在调用 timeBeginPeriod
.[=16 之前调用 timeGetDevCaps
以确保=]
使用分辨率为 1 毫秒的多媒体计时器,可以将您的 MIDI 消息量化为 1 毫秒网格 +/- 一些 variance/jitter。在绝大多数情况下,这不是问题,因为就音乐计时而言,这仍然是一个足够精细的分辨率来提供合理细微的计时。如果您绝对需要亚毫秒计时,则必须按照@iinspectable 的建议进行 - 使用计时器“关闭”然后旋转以精确计时发送 MIDI 消息。然而,这种方法是有代价的。我不知道您对该应用程序的意图是什么,但是如果您同时播放多个 MIDI 曲目,每个曲目都有连续的控制器和弯音,您会发现您的应用程序一直在旋转,并且您会看到 CPU 核心到 100%,这很糟糕。
请查看 Windows' Multimedia Class Scheduler Service 以优先访问 CPU MIDI 播放线程的资源。
不要因为@iinspectable 的评论而气馁。您绝对可以使用 C#/.NET 进行高性能 MIDI 排序。您唯一需要担心的是垃圾收集器意外地暂停您的应用程序。您始终可以以最小化 GC 的方式进行编码(例如,使用结构而不是 类,在播放期间不要 create/destroy 任何东西)。例如,还可以考虑使用 GC.TryStartNoGCRegion 来防止 GC 在播放期间暂停。
我正在用 C# 和 .NET 编写一个简单的 MIDI 应用程序供自己使用 4.x。
我假设商业 DAW(在 Windows 平台上)使用 Windows Multimedia Timers 来计时 MIDI 数据的播放。但我无法验证这一点,因为商业内容是封闭源代码。
我希望有人在这方面有知识,可以告诉我我的假设是否正确。或者,这些 DAW 是否使用了我不知道的定时器?我想确保没有任何我忽略的更合适的东西。
虽然我没有专门为商业 DAW 项目编码的特权,但我确实有为事件的准确计时很重要的场景编码的经验,包括 MIDI processing/routing。
你的假设是正确的。编码良好的 MIDI 音序器使用 Windows 多媒体计时器来安排将 MIDI 消息发送到 MIDI 设备。
Microsoft 的 Multimedia Timer Reference actually mentions MIDI 排序示例使用:
These timer services are useful for applications that demand high-resolution timing. For example, a MIDI sequencer requires a high-resolution timer because it must maintain the pace of MIDI events within a resolution of 1 millisecond.
定时器的使用是另外一个话题,这里不再赘述。但我想指出几点:
所有现代硬件都支持 1 毫秒的计时器分辨率,这基本上是给定的,但您仍然应该在调用
timeBeginPeriod
.[=16 之前调用timeGetDevCaps
以确保=]使用分辨率为 1 毫秒的多媒体计时器,可以将您的 MIDI 消息量化为 1 毫秒网格 +/- 一些 variance/jitter。在绝大多数情况下,这不是问题,因为就音乐计时而言,这仍然是一个足够精细的分辨率来提供合理细微的计时。如果您绝对需要亚毫秒计时,则必须按照@iinspectable 的建议进行 - 使用计时器“关闭”然后旋转以精确计时发送 MIDI 消息。然而,这种方法是有代价的。我不知道您对该应用程序的意图是什么,但是如果您同时播放多个 MIDI 曲目,每个曲目都有连续的控制器和弯音,您会发现您的应用程序一直在旋转,并且您会看到 CPU 核心到 100%,这很糟糕。
请查看 Windows' Multimedia Class Scheduler Service 以优先访问 CPU MIDI 播放线程的资源。
不要因为@iinspectable 的评论而气馁。您绝对可以使用 C#/.NET 进行高性能 MIDI 排序。您唯一需要担心的是垃圾收集器意外地暂停您的应用程序。您始终可以以最小化 GC 的方式进行编码(例如,使用结构而不是 类,在播放期间不要 create/destroy 任何东西)。例如,还可以考虑使用 GC.TryStartNoGCRegion 来防止 GC 在播放期间暂停。