延迟时钟
合成器微型端口驱动程序模型旨在允许在多个设备之间同步音频输出。 因此,它包含比纯 UART 设备更复杂的计时模型。
使用关联的时间戳将事件传递到微型端口驱动程序(并从中捕获)。 此时间戳相对于主时钟。 主时钟是整个系统中所有排序使用的相同时钟。 主时钟时间以 100 纳秒刻度为单位测量。
微型端口驱动程序将调用 IMasterClock::GetTime 来从主时钟获取当前时间。 在创建引脚时,端口驱动程序将微型端口驱动程序的内核模式 IMasterClock 接口,作为其中一个输入参数传递给 IMiniportDMus::NewStream 方法。 目前,主时钟包装系统实时时钟。 当存在需要其处于 run 状态的引脚时,主时钟永远不会更改。 它是永不暂停的常量速率时钟。
所有呈现设备在接受事件的时间和可以听到事件的时间之间都有一定的延迟。 此延迟可以是常量或可变(如软件合成器的情况,其中延迟取决于音频缓冲区的当前播放位置)。 此延迟可通过以下方式得到补偿:
允许 DMus 微型端口驱动程序提前接收足够远的事件,以便可以及时播放事件,尽管设备存在延迟也是如此。 事件由 DMus 端口驱动程序中的排序器引擎为微型端口驱动程序排序。
在创建引脚时,端口驱动程序以 100 纳秒为单位查询微型端口驱动程序的增量时间。 此增量时间是微型端口驱动程序想要接收事件的每个事件的呈现时间的提前程度。 端口驱动程序会尽最大努力提前这么远交付事件。 为此增量指定非常大的值(由 IMiniportDMus::NewStream 的 SchedulePreFetch 参数指定)会使端口驱动程序在从用户模式传递到端口驱动程序后,立即将事件传递给微型端口驱动程序。
通知应用程序提前多远计划事件。 在这种情况下,不需要使用最大延迟。 由于提交事件后无法取消事件,因此可以将事件提交到其呈现时间越近,应用程序与合成器可以交互的响应就越快。 为了处理此要求,DirectMusic 引入了延迟时钟的概念。
延迟时钟提供了可以计划播放事件但仍按时播放的将来最接近时间。 换言之,如果应用程序根据延迟时钟计划将事件计划在当前时间之前播放,则事件将延迟播放。 合成器微型端口驱动程序会响应 KSPROPERTY_SYNTH_LATENCYCLOCK 属性项来提供延迟时钟。
针对 KSPROPSETID_Synth 和 KSPROPERTY_SYNTH_LATENCYCLOCK 查询微型端口驱动程序。 微型端口驱动程序的属性处理程序应返回延迟时钟,该时钟指定下次可以按时呈现数据的时间。 例如,如果主时钟当前读数为 50,并且当前有 25 个单位的延迟,则延迟时钟读数为 75。 通过这种方式实现时钟的原因是延迟不需要是常量,对应用程序而言,返回值比增量更有用。