Objective c 基于计时器以毫秒精度执行功能

Objective c 基于计时器以毫秒精度执行功能,objective-c,timer,precision,Objective C,Timer,Precision,我有一个浮动数组,它表示基于事件在一段时间内被触发的时间值 0: time stored: 1.68 1: time stored: 2.33 2: time stored: 2.47 3: time stored: 2.57 4: time stored: 2.68 5: time stored: 2.73 6: time stored: 2.83 7: time stored: 2.92 8: time stored: 2.98 9: time stored: 3.05 我现在想启动一个计

我有一个浮动数组,它表示基于事件在一段时间内被触发的时间值

0: time stored: 1.68
1: time stored: 2.33
2: time stored: 2.47
3: time stored: 2.57
4: time stored: 2.68
5: time stored: 2.73
6: time stored: 2.83
7: time stored: 2.92
8: time stored: 2.98
9: time stored: 3.05
我现在想启动一个计时器,当计时器达到1秒687毫秒(数组中的第一个位置)时,触发事件/方法执行。 当计时器达到2秒337毫秒时,将触发第二个方法执行,直到数组中的最后一个元素达到3秒56毫秒时,将触发最后一个事件

我怎么能模仿这样的东西?我需要高精度的东西

我想我本质上想问的是,如何创建一个节拍器,通过高精度的方法调用来按时播放声音

…如何创建具有高精度方法调用的节拍器以按时播放声音

您可以使用音频时钟,它具有您通常想要的所有精度(音频播放的采样率——例如44.1kHz)——而不是
NSTimer

具体来说,您可以使用采样器(例如AudioUnit)并安排MIDI事件,或者您可以在音频流回调中的采样位置(由节拍确定)使用(预加载的)click sounds的采样数据填充缓冲区

要保持1ms或更高,您需要始终根据音频时钟计时。这真的很容易,因为你的节奏决定了一个帧的间隔


困难的部分(对大多数人来说)是习惯于在实时环境中工作和使用音频框架,如果你以前没有在该领域工作过。

要获得高精度计时,你必须跳下一两个编程级别,并使用类似框架的东西,该框架提供精确的计时示例(在44100kHz时,应每隔0.02ms进行一次采样)

这种方法的缺点是,为了获得这样的定时性能,核心音频单元编程避开了C/C++方法中的Objective-C,这(在我看来)比Objective-C更难编码。除此之外,核心音频单元的工作方式也非常混乱,特别是如果您没有音频DSP方面的背景

在Objective-C中,您可能知道NSTimer在这里不是一个选项。为什么不检查一下?它可以用于精确的媒体排序,并带有一点创造性的横向思维,以及的
avurlassetpreferprecurisedurationandTIMINGkey
选项,您可能可以在不使用核心音频单元的情况下实现您想要的功能


只需填写有关
AVFoundation
的更多信息,您可以将
AVAsset
的实例放入
AVMutableComposition
(通过
AVMutableCompositionTrack
对象),然后使用带有
AVPlayer
实例的
AVPlayerItem
对象来控制结果。AVPlayerItem通知
AVPlayerItemDidPlayToEndTimeNotification
()可用于确定单个资产何时完成,AVPlayer方法
addBoundaryTimeObserverForTimes:queue:usingBlock:
addPeriodicTimeObserverForInterval:queue:usingBlock:
可以在任意时间提供通知

使用iOS,如果你的应用程序将播放音频,你也可以在后台线程上运行这一切,这意味着你可以在应用程序处于后台时保持时间(尽管有一个警告,如果它不播放音频,苹果可能不接受使用此后台模式的应用程序)。查看更多信息。

查看。您可以使用类似于
调度时间(现在调度时间,1.687000*NSEC\u/秒)的方法为其创建目标时间。


更新:如果你只想在特定时间播放声音,而不是做任意的工作,那么你应该使用一个音频API,允许你在特定时间安排播放。我最熟悉的是。你可以创建一个队列并创建2或3个缓冲区。(2如果音频总是相同的。3如果动态加载或计算它。)然后,使用
audioqueuenbufferwithparameters()
以特定的开始时间对每个缓冲区进行排队。然后音频队列将尽可能地在请求的开始时间附近播放。我怀疑手动编码替代方案是否会超过精度。当队列将处理过的缓冲区返回给您时,您可以在必要时重新填充并在下次排队


我确信它一定有一个类似的工具,用于在特定时间安排播放,但我不熟悉。

dispatch\u after()
是一个大中心调度函数。最好查看大中心调度文档,而不是
dispatch\u after()的手册页我不认为这是一个非常精确的替代品。这里的原因是:在指定的时间过去之后,实现简单地异步地将块添加到队列中。考虑这样的方式:如果队列(甚至系统)有很多工作要做,那么在块(或工作)之前可能需要相当长的时间。实际上是执行的。因此,它不能替代音频计时器。但是,音频回调在实时高优先级线程上运行,并且具有稳定的时间表示。即使在高工作负载下,使用音频回调的机会也会更好。(续)(续)此外,音频在其自身的时基上运行。这意味着在许多情况下,这种方法的准确性也受到渲染块大小的限制——因为它们使用不同的时基。人们会试图通过减少缓冲区大小来补偿这种不准确(需要更多的资源,通常会导致更多的问题,如辍学)。在未正确同步时,减少缓冲区大小以提高准确性是一个强力解决方案。(续)将这两个问题结合起来,偏差/错误可能超过100ms(并且可能更大)。@Justin,您可以将
dispatch\u after()
定位到高优先级全局队列。