我正在尝试为Swift中的iOS创建一个节拍器。我正在使用GCD调度队列来为AVAudioPlayer计时。变量machineDelay被用来给播放器计时,但它的运行速度比我要求的时间要慢。
例如,如果我要求延迟1秒,它将以1.2秒的速度播放。0.749秒的播放速度约为0.92秒,0.5秒的播放速度约为0.652秒。我可以尝试通过调整这种差异来补偿,但我觉得这里我遗漏了一些东西。
如果有更好的方法来实现这一点,请给出建议。这是我的第一个个人项目,所以我欢迎你的想法。
以下是适用于此问题的各种函数:
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()
})
}发布于 2015-12-24 14:09:47
我从来没有真正在iOS上做过任何关于声音的事情,但我可以告诉你为什么你会得到这些不一致的时间。
当你使用dispatch_after()时,在操作系统的某个地方设置了一些计时器,在它到期后不久的某个时候,它会将你的块放到队列中。“之后的某一时刻”将会很短,但根据操作系统正在做的事情,它几乎肯定不会接近于零。
主队列由主线程使用run循环提供服务。这意味着播放声音的任务正在竞争CPU与所有UI功能的使用。这意味着它立即播放声音的机会相当低。
最后,完成处理程序将在声音播放结束后的一段短时间内触发,但不一定立即触发。
所有这些小延迟加起来就是你看到的延迟。不幸的是,根据设备正在执行的操作,延迟可能会有所不同。对于需要精确计时的东西,这永远不会起作用。
我认为,有几种方法可以实现你想要的。然而,音频编程超出了我的专业领域。您可能希望从查看Core Audio开始。我的五分钟研究建议要么是音频队列服务,要么是OpenAL,但这五分钟实际上就是我在iOS上所知道的关于声音的一切。
发布于 2019-11-27 08:36:46
dispatch_after不适用于准确的回调示例。
如果您正在编写音频应用程序,则无法避免,您需要以这样或那样的方式实现一些CoreAudio代码。
它将“拉取”特定数量的样本。做数学运算(比喻;)
https://stackoverflow.com/questions/34447486
复制相似问题