【问题标题】:Does AudioKit provide a high precision timer?AudioKit 是否提供高精度计时器?
【发布时间】:2023-03-25 08:29:01
【问题描述】:

AudioKit 是否提供high precision timer?我看了一下发现AKSheduledAction,它基于Timer,似乎是唯一的默认选项:

https://github.com/AudioKit/Playgrounds/blob/master/iPad/AudioKit.playgroundbook/Contents/Modules/AudioKit.playgroundmodule/Internals/AKScheduledAction.swift

另外,对于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


    【解决方案1】:

    我已经完成了我的研究,但遗憾的是没有或找不到关于提供精确计时器的方法的太多信息。

    我发现的最佳结果基于以下技术,该技术拥有迄今为止最好的结果*,audioFile 的长度为4.666667

        let info = ProcessInfo.processInfo
        let begin = info.systemUptime
        self.audioBufferPlayerNode.scheduleBuffer(self.file.pcmBuffer, at: nil, options: .interruptsAtLoop, completionHandler: {
            let elapsedTime = info.systemUptime - begin
            print("elapsedTime \(elapsedTime)")
        })
        self.audioBufferPlayerNode.play()
    

    输出:

    elapsedTime 4.691985241952352
    elapsedTime 4.662765832967125
    elapsedTime 4.664656096952967
    elapsedTime 4.664366245968267
    elapsedTime 4.666537321987562
    elapsedTime 4.666480115964077
    elapsedTime 4.659072204027325
    elapsedTime 4.665851002908312
    

    请记住,您需要在调用前计算 AVAudioPlayerNode 的初始化过程并将其连接到 mixer,否则,如果您在一次调用中计算所有内容,则会得到:

    elapsedTime 4.701177543029189
    elapsedTime 4.7050989009439945
    elapsedTime 4.702830816968344
    elapsedTime 4.695075194002129
    elapsedTime 4.708125164033845
    elapsedTime 4.700082497904077
    elapsedTime 4.695926539017819
    elapsedTime 4.711938992026262
    

    您可能需要研究 .prepare 方法来改进计时 (https://developer.apple.com/documentation/avfoundation/avaudioplayernode)

    另外,请注意这在线程上运行:

    AVAudioPlayerNodeImpl.CompletionHandlerQueue
    

    希望这对将来的其他人有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多