【问题标题】:Synchronizing AKPlayer with AKSampleMetronome将 AKPlayer 与 AKSampleMetronome 同步
【发布时间】:2018-08-13 07:39:55
【问题描述】:

我正在尝试在我的(某种)多音频文件播放项目中使用 AKSamplerMetronome 作为主时钟。我希望 AKPlayers 与 Metronome 的弱拍同步启动。将 AKPlayer 和 AKSamplerMetronome 混合为 AudioKit.output 是成功的,但是,我正在努力将 AKPlayer.start 与 AKSamplerMetronome.beatTime (或其他我还没弄清楚的东西)连接起来,所以播放开始时节拍器的强拍同步(并重复每个时间节拍器击中强拍)。这是我写的:

class ViewController: UIViewController {

let metronome = AKSamplerMetronome()
let player = AKPlayer(audioFile: try! AKAudioFile(readFileName: "loop.wav"))
let mixer = AKMixer()

func startAudioEngine() {
    do {
        try AudioKit.start()
    } catch {
        print(error)
        fatalError()
    }
}

func makeConnections() {
    player >>> mixer
    metronome >>> mixer
    AudioKit.output = mixer
}

func startMetronome() {

    metronome.tempo = 120.0
    metronome.beatVolume = 1.0
    metronome.play()
}

func preparePlayer() {

    player.isLooping = true
    player.buffering = .always
    player.prepare()
// I wanted AKPlayer to be repeated based on Metronome's downbeat.

}

func startPlayer() {

    let startTime = AVAudioTime.now() + 0.25
    player.start(at: startTime)

}

override func viewDidLoad() {
    super.viewDidLoad()

    makeConnections()
    startAudioEngine()
    preparePlayer()
    startPlayer()
    startMetronome()

}

}

我的问题是,AKPlayer 的起点(at:) 无法识别 AKSamplerMetronome 的属性,可能是因为它与 AVAudioTime 不兼容?我试过类似的东西:

let startTime = metronome.beatTime + 0.25
player.start(at: startTime)

但这似乎不是一个答案(因为“无法将值类型'Double'转换为预期的参数类型'AVAudioTime?')。如果有人可以帮助我探索Swift/AudioKit,那将非常有帮助。

【问题讨论】:

    标签: audiokit


    【解决方案1】:

    您正在使用 Double 参数调用 AVAudioTime 播放函数。这是不正确的。如果你想用秒参数启动AKPlayer,使用 player.play(when: time)

    一般来说,你很接近。这就是你的做法:

        let startTime: Double = 1
    
        let hostTime = mach_absolute_time()
        let now = AVAudioTime(hostTime: hostTime)
        let avTime = now.offset(seconds: startTime)
        metronome.setBeatTime(0, at: avTime)
        player.play(at: avTime)
    

    基本上你需要给每个单元一个共同的时钟(mach_absolute_time()),然后使用 AVAudioTime 在准确的时间启动它们。 Metronome.setBeatTime 告诉节拍器在传入的 avTime 处将其重置为 0 点。

    【讨论】:

    • 谢谢瑞恩。如果我可以再问一个,有没有一种方法可以根据节拍器的强拍而不是音频文件自身的长度来重复 loop.wav 音频文件?由于柱上有 4 个刻度,我希望在每个第一个刻度上重复 AKPlayer。我正在尝试几种不同的东西,但无法弄清楚如何处理“player.isLooping = true”部分......或其他东西。非常感谢。
    • 将 player.endTime = 设置为小节的持续时间。然后 player.buffering = .always,player.isLooping = true。请注意,您可以调用: player.preroll(from: 0, to: durationOfBar)。这将设置 endTime 并替换您的 player.prepare() 调用。
    • 120bpm 4 拍 = 2 秒
    • 其实我觉得用AKClipPlayer可能效果更好。我认为部分问题在于 AKPlayer 主要基于 hostTime,而同一个节拍器使用基于 sampleTime 的 AKTimeline。我让 AKPlayer 与视频同步,这似乎更容易通过 hostTime 完成。最近我让AKPlayer 与需要在内部切换到sampleTime 的离线渲染兼容——但从那时起我就没有尝试过与节拍器同步。绝对有可能,我只是最近没有。
    • 那些 cmets 是关于 AVAudioTime 调度的。
    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 2018-06-11
    • 2018-06-10
    • 2015-05-29
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多