Я работаю над приложением для iOS, которое позволяет пользователям воспроизводить песню с несколькими треками.Каждый трек воспроизводится одновременно, и громкость каждого трека может управляться независимо.Задержка между всеми игроками хорошая, когда песня воспроизводится впервые в течение жизненного цикла приложения.Однако задержка между всеми игроками увеличивается, когда пользователь останавливает воспроизведение всех дорожек и затем возобновляет его.
Я создаю AVAudioPlayer для каждой дорожки в моем классе MusicPlayer:
do {
let data = try Data.init(contentsOf: url, options: NSData.ReadingOptions.alwaysMapped )
let player = try AVAudioPlayer(data: data)
player.prepareToPlay()
self.audioPlayers.append(player)
}
После загрузки проигрывателей воспроизведение песни запускается с помощью метода playSong:
playerSemaphore.wait()
NotificationCenter.default.post(playerDidReceiveCommand.getNotification())
for item in self.audioPlayers {
item.prepareToPlay()
}
let time = self.audioPlayers[0].deviceCurrentTime + 0.2
for item in self.audioPlayers {
item.play(atTime: time)
}
DispatchQueue.main.async {
NotificationCenter.default.post(playerFinishedCommand.getNotification())
}
playerSemaphore.signal()
Когда пользователь решает приостановить воспроизведение песни или AudioSession прерывается, метод pauseSong приостанавливает все проигрыватель установкойих громкость до 0, приостанавливая их, синхронизируя время воспроизведения и сбрасывая нужную громкость:
func pauseSong() {
playerSemaphore.wait()
NotificationCenter.default.post(playerDidReceiveCommand.getNotification())
DispatchQueue.global().async {
// Set volumes of all audio tracks to 0, so delay on pause is not noticed
for audioTrackPlayer in self.audioPlayers {
audioTrackPlayer.volume = 0
}
// Update Times and reset the volumes now the tracks are paused
for (index, audioTrackPlayer) in self.audioPlayers.enumerated() {
audioTrackPlayer.pause()
audioTrackPlayer.currentTime = self.audioPlayers[0].currentTime
if let currentSongID = self.loadedSongID, let currentVolume = sharedSongManager.getVolumeOfTrackOfSongID(id: currentSongID, track: index), let currentActivation = sharedSongManager.getActivationStatusOfTrackOfSongID(id: currentSongID, track: index) {
if currentActivation == true {
audioTrackPlayer.volume = currentVolume
}
}
}
DispatchQueue.main.async {
NotificationCenter.default.post(playerFinishedCommand.getNotification())
}
}
playerSemaphore.signal()
}
Для записи времени проигрывания я написал метод, который возвращает все значения времени проигрывания и разницу максимального значения иминимальное значение этого массива.Он работает со смещением по времени, чтобы получить точные значения для времен игрока:
let startTime = CACurrentMediaTime()
var playerTimes = [TimeInterval]()
var delay: Double?
for item in self.audioPlayers.enumerated() {
let playerTime = item.element.currentTime
let currentTime = CACurrentMediaTime()
let timeOffset = currentTime - startTime
let correctedPlayerTime = playerTime - timeOffset
playerTimes.append(correctedPlayerTime)
}
if let maxTime = playerTimes.max(), let minTime = playerTimes.min() {
delay = Double(maxTime) - Double(minTime)
}
return (delay, playerTimes)
Вот список задержки (максимальное значение - минус значение времени игрока) до и после паузы:

А вот время проигрывания для одного бревна до и после паузы:

Все журналы были созданы на iPhone X с последней версией iOS.
После загрузки новой песни жизненный цикл перезапускается, и яимеют низкую задержку, пока пользователь не остановит песню в первый раз.Мне не нравится идея создания новых AVAudioPlayers после каждого взаимодействия, но я пробовал много вещей, таких как вычисление задержки, как я делал в функции регистрации, или асинхронный вызов экземпляров проигрывателя.Однако в большинстве случаев это даже увеличивало задержку.Кто-нибудь знает способ правильной синхронизации проигрывателей после возобновления песни?