【发布时间】:2023-03-25 08:29:01
【问题描述】:
AudioKit 是否提供high precision timer?我看了一下发现AKSheduledAction,它基于Timer,似乎是唯一的默认选项:
另外,对于Timer 的用法,我写了一个scheduler,它在audio thread 中运行(* 下面看不到),如果有错误请纠正我。我已经测试过,它不是很精确,因为产生的时差会有所不同:
func schedule(timeOut: Double, onComplete: @escaping () -> Void) -> Void {
do {
let file = try AKAudioFile.silent(samples: Int64(defaultSampleRate * timeOut))
let audioPlayer = try AKAudioPlayer(file: file)
audioPlayer >>> self.mainMixer
audioPlayer.completionHandler = {
onComplete()
}
audioPlayer.play()
} catch {
print(error.localizedDescription)
}
}
输出:
elapsedTime 4.715054468018934
elapsedTime 4.712334129028022
elapsedTime 4.71259418700356
elapsedTime 4.712263747991528
测试通过以下方法在主线程中运行:
func test() {
let info = ProcessInfo.processInfo
let begin = info.systemUptime
self.schedule(timeOut: 4.666667) {
let elapsedTime = info.systemUptime - begin
print("elapsedTime \(elapsedTime)")
}
}
我将不得不对.completionHandler 是什么做更多研究,但我首先假设为AVAudioPlayerNode.scheduleBuffer:
AVAudioPlayerNode.scheduleBuffer(AVAudioPCMBuffer, at: nil, options: .interruptsAtLoop, completionHandler: nil)
查看completionHandler的来源,也就是AKCallback,我们可以看到它运行在主线程中(https://github.com/AudioKit/AudioKit/blob/master/AudioKit/Common/Nodes/Playback/Players/AKAudioPlayer.swift#L692):
/// Triggered when the player reaches the end of its playing range
fileprivate func internalCompletionHandler() {
DispatchQueue.main.async {
if self.isPlaying {
self.stop()
self.completionHandler?()
}
}
}
所以,我会尝试重写它以使用 AVAudioPlayerNode.scheduleBuffer,希望这会有所帮助。
参考:
https://developer.apple.com/documentation/foundation/timer https://developer.apple.com/library/archive/technotes/tn2169/_index.html
【问题讨论】:
标签: audiokit