Синхронизация нескольких AKPlayers

Я боролся с этим некоторое время. У меня есть множество AKPlayers.

var players = [AKPlayer]()

Я искал много и много других вопросов в Интернете по той же проблеме, и все они предлагают использовать: AKPlayer.play(atTime: AVAudioTime)

Я пробовал это, делая (и другие подобные попытки):

    var sampleRate = selectedSong!.channels[0].audioFile!.sampleRate
    var sampleTime = players[0].audioTime(at: players[0].currentTime)?.sampleTime
    var startTime = AVAudioTime(sampleTime: sampleTime! + Int64(0.25*sampleRate), atRate: sampleRate)

    for audioPlayer in players {
        audioPlayer.play(at: startTime)
    }

и другие подобные вещи, такие как:

 for audioPlayer in players {
     audioPlayer.play(when: 0, hostTime: mach_absolute_time())
 }

но ни один из них не работал. Заметна разница во времени воспроизведения. (Аудиофайлы имеют одинаковую длину и формат).

Если это полезно, моя установка выглядит следующим образом:

AKPlayer -> AKPitchShifter 
                            > AKMixer > AudioKit.output
                  AKPlayer       

** Все указанные выше AKPlayer были добавлены к массиву players.

Возможно, это связано с тем, что я не понимаю, что такое AVAudioTime и как он работает.

Заранее спасибо.

******* ПРИМЕЧАНИЯ ****** документы для AKPlayer say

Игроки могут быть привязаны к общим часам, а также к видео, используя hostTime в различных функциях воспроизведения.

Но не предоставляет пример синхронизации с hostTime.


person AntiStrike12    schedule 23.02.2018    source источник


Ответы (2)


Вы были на правильном пути. Вам просто нужно получить текущее время, а не получать его с помощью audioTime(at:), что полезно только для уже играющего проигрывателя.

// .now() is a convenience extension and AVAudioTime + Double is overloaded.
var startTime = AVAudioTime.now() + 0.25 

Если произвольный буфер 0,25 не сокращает его, попробуйте зациклить своих игроков, вызывающих player.prepare(), прежде чем получить now() для начала планирования.

person dave234    schedule 25.02.2018
comment
Не могли бы вы подробнее объяснить свою реализацию расширения .now()? Последняя часть «AudioTime + Double is перегружена» вызывает у меня некоторую путаницу. - person AntiStrike12; 25.02.2018
comment
Неважно. С некоторыми испытаниями я обнаружил это. Я отредактировал ваш пост, чтобы включить его, чтобы будущие люди могли его найти. Если есть лучшая реализация, пожалуйста, измените ее и дайте мне знать. - person AntiStrike12; 25.02.2018

У меня такая же проблема, я использую mr. Решение Dave234: первое воспроизведение синхронизировано, но кажется, что второй цикл имеет небольшую заметную задержку. вот мой код.

playerOne.looping = true
playerTwo.looping = true
playerThree.looping = true
playerFour.looping = true
playerFive.looping = true

let startTime = AVAudioTime.now() + 0.25
playerOne.play(at: startTime)
playerTwo.play(at: startTime)
playerThree.play(at: startTime)
playerFour.play(at: startTime)
playerFive.play(at: startTime)
person Tristan Angelo C. Galang    schedule 26.02.2018
comment
Попробуйте вызвать prepare() для игроков перед получением startTime. - person dave234; 26.02.2018
comment
Вы имеете в виду расписание (от:, до:, avTime:)? AKAudioPlayers не имеет функции prepare() - person Tristan Angelo C. Galang; 27.02.2018
comment
AKAudioPlayer заменяется на AKPlayer. - person dave234; 27.02.2018
comment
используйте player.buffering = .always для плавного зацикливания. - person Ryan Francesconi; 13.08.2018