基于计时器执行具有毫秒精度的功能

时间:2012-04-21 07:06:38

标签: 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

我现在想要启动一个计时器,当计时器达到1秒687毫秒(数组中的第一个位置)时,触发事件/方法执行。 当计时器达到2秒和337毫秒时,第二个方法执行将被触发,直到阵列中的最后一个元素为3秒,最后一个事件被触发56毫秒。

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

我想我最基本的问题是如何创建一个高精度方法调用的节拍器来按时播放声音?

3 个答案:

答案 0 :(得分:4)

  

...如何使用高精度方法调用创建节拍器以按时播放声音?

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

具体来说,你可以使用一个采样器(例如AudioUnit)并安排MIDI事件,或者你可以在音频流回调中用速度确定的样本位置用你的(预加载的)点击声音样本数据填充缓冲区。

要保持1ms或更长时间,您需要始终根据音频时钟进行定时。这真的很容易,因为你的节奏将决定帧的间隔。

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

答案 1 :(得分:2)

为了获得高精度定时,你必须跳过一两个编程水平并利用类似Core Audio Unit框架的东西,它提供样本精确定时(在44100kHz,样本应该每0.02ms左右发生一次)

这种方法的缺点是,为了获得这样的定时性能,Core Audio Unit编程避免使用Objective-C进行C / C ++方法,这在我看来比Objective-C更难以编码。 Core Audio Units的工作方式也非常混乱,特别是如果你没有音频DSP的背景。

保持Objective-C,你可能知道NSTimers不是一个选项。为什么不查看AVFoundation framework?它可以用于精确的媒体排序,并且通过一些创造性的侧面思考,以及AVURLAssetAVURLAssetPreferPreciseDurationAndTimingKey选项,您可以在不使用Core Audio Units的情况下实现您想要的功能。


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

使用iOS,如果你的应用程序将播放音频,你也可以在后台线程上运行这一切,这意味着你可以在你的应用程序处于后台时保持时间(虽然警告,如果它不播放音频,Apple可能不会使用此后台模式接受您的应用)。查看UIBackgroundModes docs了解详情。

答案 2 :(得分:2)

查看dispatch_after()。您可以使用dispatch_time(DISPATCH_TIME_NOW, 1.687000 * NSEC_PER_SEC)等内容为其创建目标时间。


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

我确信AVFoundation必须具有类似的设置,以便在特定时间安排播放,但我不熟悉它。