Ios 如何在AudioKit输出中动态更改播放器

Ios 如何在AudioKit输出中动态更改播放器,ios,swift,audiokit,Ios,Swift,Audiokit,我正在使用AudioKit实现一个应用程序,它允许您播放大量音频文件并随时在它们之间切换。此外,我们还需要一个音频文件来播放环境噪声循环 动态更改AudioKit输出中播放器的正确方法是什么?或者,实施这种行为的正确方式是什么 AudioKit要求您设置其输出,该输出可以是播放一个音频文件的AKPlayer,也可以是给定AKPlayer数组的AKMixer。启动AudioKit后,您无法更改输出。因此,目前我的方法是使用AKMixer播放两个AKPlayers-一个用于当前文件,另一个用于环境噪

我正在使用AudioKit实现一个应用程序,它允许您播放大量音频文件并随时在它们之间切换。此外,我们还需要一个音频文件来播放环境噪声循环

动态更改AudioKit输出中播放器的正确方法是什么?或者,实施这种行为的正确方式是什么

AudioKit要求您设置其
输出
,该输出可以是播放一个音频文件的
AKPlayer
,也可以是给定
AKPlayer
数组的
AKMixer
。启动AudioKit后,您无法更改
输出。因此,目前我的方法是使用
AKMixer
播放两个
AKPlayer
s-一个用于当前文件,另一个用于环境噪声。当用户点击“下一步”按钮I
stop()
AudioKit时,为下一首歌曲的音频文件和环境噪声播放器重新创建一个带有新播放器的
AKMixer
,将其分配给
output
start()
AudioKit,并播放两个播放器。这会导致不良行为,因为切换歌曲时会停止播放环境噪声,从而导致短暂的暂停

如果这是正确的方法,我们如何在不停止AudioKit的情况下更新输出?我想知道您是否可以使用一个强持有属性的播放器数组初始化混音器,并简单地在数组中添加/删除播放器。但这不起作用-启动一个新的播放器会在处于断开连接状态时抛出一个错误
player start
,因为此节点未连接到输出

我创建了一个示例来演示这种行为。启动时,该应用程序会播放当前曲目的鼓声作为环境噪音和波浪。当你点击“下一步”时,它将切换到下一个曲目(在这个演示代码中,它只是同一个音频文件),你可以听到鼓停止,然后继续,这是不可取的。我已将项目代码包括在下面:

final class Maestro: NSObject {

    static let shared = Maestro()

    private var audioPlayer: AKPlayer?
    private var ambientPlayer: AKPlayer = {
        let player = AKPlayer(url: Bundle.main.url(forResource: "drums", withExtension: "wav")!)!
        player.isLooping = true
        return player
    }()
    private var mixer: AKMixer?

    private let audioFileURL = Bundle.main.url(forResource: "waves", withExtension: "mp3")!

    func play() {
        playNewPlayer(fileURL: audioFileURL)
    }

    func next() {
        //In the real app we'd play the next audio file in the playlist but for the demo we'll just play the same file
        playNewPlayer(fileURL: audioFileURL)
    }

    private func playNewPlayer(fileURL: URL) {
        audioPlayer?.stop()
        audioPlayer = nil

        do {
            try AudioKit.stop()
        } catch {
            print("Maestro AudioKit.stop error: \(error)")
        }

        audioPlayer = AKPlayer(url: fileURL)!
        mixer = AKMixer([audioPlayer!, ambientPlayer])
        AudioKit.output = mixer

        do {
            try AudioKit.start()
        } catch {
            print("Maestro AudioKit.start error: \(error)")
        }

        if ambientPlayer.isPlaying {
            //need to resume playback from current position
            let pos = ambientPlayer.currentTime
            ambientPlayer.stop()
            ambientPlayer.play(from: pos)
        } else {
            ambientPlayer.play()
        }

        audioPlayer?.play()
    }

}