首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用GCD dispatch_after的swift计时精度

使用GCD dispatch_after的swift计时精度
EN

Stack Overflow用户
提问于 2015-12-24 13:02:09
回答 2查看 784关注 0票数 1

我正在尝试为Swift中的iOS创建一个节拍器。我正在使用GCD调度队列来为AVAudioPlayer计时。变量machineDelay被用来给播放器计时,但它的运行速度比我要求的时间要慢。

例如,如果我要求延迟1秒,它将以1.2秒的速度播放。0.749秒的播放速度约为0.92秒,0.5秒的播放速度约为0.652秒。我可以尝试通过调整这种差异来补偿,但我觉得这里我遗漏了一些东西。

如果有更好的方法来实现这一点,请给出建议。这是我的第一个个人项目,所以我欢迎你的想法。

以下是适用于此问题的各种函数:

代码语言:javascript
复制
func milliseconds(beats: Int) -> Double {

    let ms = (60 / Double(beats))
    return ms
}

func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
    if self.playState == false {
        return
    }

    playerPlay(playerTick, delay: NSTimeInterval(milliseconds(bpm)))
}

func playerPlay(player: AVAudioPlayer, delay: NSTimeInterval) {

    let machineDelay: Int64 = Int64((delay - player.duration) * Double(NSEC_PER_SEC))

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, machineDelay),dispatch_get_main_queue(), { () -> Void in

        player.play()    
    })
}
EN

回答 2

Stack Overflow用户

发布于 2015-12-24 14:09:47

我从来没有真正在iOS上做过任何关于声音的事情,但我可以告诉你为什么你会得到这些不一致的时间。

当你使用dispatch_after()时,在操作系统的某个地方设置了一些计时器,在它到期后不久的某个时候,它会将你的块放到队列中。“之后的某一时刻”将会很短,但根据操作系统正在做的事情,它几乎肯定不会接近于零。

主队列由主线程使用run循环提供服务。这意味着播放声音的任务正在竞争CPU与所有UI功能的使用。这意味着它立即播放声音的机会相当低。

最后,完成处理程序将在声音播放结束后的一段短时间内触发,但不一定立即触发。

所有这些小延迟加起来就是你看到的延迟。不幸的是,根据设备正在执行的操作,延迟可能会有所不同。对于需要精确计时的东西,这永远不会起作用。

我认为,有几种方法可以实现你想要的。然而,音频编程超出了我的专业领域。您可能希望从查看Core Audio开始。我的五分钟研究建议要么是音频队列服务,要么是OpenAL,但这五分钟实际上就是我在iOS上所知道的关于声音的一切。

票数 2
EN

Stack Overflow用户

发布于 2019-11-27 08:36:46

dispatch_after不适用于准确的回调示例。

如果您正在编写音频应用程序,则无法避免,您需要以这样或那样的方式实现一些CoreAudio代码。

它将“拉取”特定数量的样本。做数学运算(比喻;)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34447486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档