Как динамически менять плееры в выводе AudioKit - PullRequest
2 голосов
/ 08 января 2020

Я реализую приложение, использующее AudioKit, которое позволяет воспроизводить большое количество аудиофайлов и переключаться между ними в любое время. Кроме того, нам необходим один аудиофайл для воспроизведения на l oop для фонового шума.

Как правильно динамически менять проигрыватели на выходе AudioKit? Или как правильно реализовать это поведение?

AudioKit требует, чтобы вы установили его output, который может быть AKPlayer, который воспроизводит один аудиофайл, или AKMixer с массивом AKPlayer s для пример. Вы не можете изменить output после запуска AudioKit , как я видел ранее . Поэтому в настоящее время мой подход заключается в использовании AKMixer для воспроизведения двух AKPlayer с - одного для текущего файла и одного для фонового шума. Когда пользователь нажимает кнопку «Далее» I stop() AudioKit, воссоздайте AKMixer с новым проигрывателем для аудиофайла следующей песни и проигрывателем окружающего шума, назначьте его на output, start() AudioKit и начните воспроизведение. оба игрока. Это приводит к нежелательному поведению, потому что воспроизведение окружающего шума останавливается при переключении песен, что приводит к короткой паузе.

Если это правильный подход, как мы можем обновить вывод, не останавливая AudioKit? Я задавался вопросом, можете ли вы инициализировать микшер с массивом игроков, который является сильным свойством, и просто добавлять / удалять игроков в массиве. Но это не работает - запуск нового плеера выдает ошибку player started when in a disconnected state, потому что этот узел не подключен к выходу.

Я создал пример проекта , чтобы продемонстрировать это поведение , При запуске приложение воспроизводит барабаны как окружающий шум и волны для текущей дорожки. Когда вы нажимаете Next, он переключается на следующую дорожку (которая в этом демонстрационном коде является тем же самым аудиофайлом), и вы можете услышать, как барабаны остановились, а затем возобновили, что нежелательно. Я включил код проекта ниже:

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()
    }

}
...