AVAudioPlayerNode playAt () не синхронизирован - PullRequest
0 голосов
/ 31 августа 2018

У меня есть один основной AVAudioPlayerNode, который играет постоянно. И есть другие игроки, которые ставятся в очередь и играют, когда основной игрок достигает определенной точки. Эти AVAudioPlayerNode должны быть синхронизированы с точностью до миллисекунды. Иногда можно запустить 4-10 штук одновременно.

Как это работает - я сохраняю lastRenderTime основного игрока на момент, когда нужно запустить всех запланированных игроков, а затем запустить всех необходимых игроков с player.start(at: lastRenderTime)

Обычно он работает хорошо и без задержки между звуками.

Но у меня есть задержка в этом случае:

  1. Работает на старых устройствах (iPad 2, iPhone 5 и т. Д.)
  2. ТОЛЬКО когда МНОГИЕ проигрыватели в первый раз после запуска приложения (например, на iPhone 7 я запускаю 8 проигрывателей одновременно после запуска приложения и слышу десинхронизацию между звуками), но все проигрыватели работают с одинаковым player.start(at: lastRenderTime) временем ,

Все действия игрока, которые я запускаю асинхронно с настраиваемой параллельной очередью.

Потратьте 3 дня, пытаясь это исправить. Я хотел бы за любые советы.

Код: Вот как я начинаю основного игрока -

self.scheduleBuffer(audioFileBuffer, at: nil, options: [], completionHandler: {
    lastRenderTime = lastRenderTime + audioBufferLength //Schematic showing logic that after each loop I calculate current render time value.

    if self.isStopPressed == false { //Run fileEndCompletion only when player seek to end.
        fileEndCompletionHandler() //here is callback that running all scheduled players.
        if loop { // Recursive play this file again.
            self.playAudioBuffer(audioFileBuffer: audioFileBuffer, loop: loop, fileEndCompletionHandler: fileEndCompletionHandler)
        }
    }
})

Пример кода, на котором запущены все запланированные проигрыватели.

AudioEnginePlayer.sharedInstance.audioQueue.async {
    if !self.isPlaying {
        self.volume = 1.0
        self.audioFile.framePosition = frameCount.startingFrame
        self.prepare(withFrameCount: frameCount.frameCount)
        self.play(at: AudioEnginePlayer.sharedInstance.loopMsLastStartRenderTime) //Calculated lastRenderTime
    }

    self.scheduleSegment(self.audioFile, startingFrame: frameCount.startingFrame, frameCount: frameCount.frameCount, at: nil) {
        //WARNING: COMPLETION HANDLER RUNNING EARLY THEN FILE IS COMPLETED

        if self.isStopPressed == false { //Run fileEndCompletion only when player seek to end.
            fileEndCompletionHandler()
            if loop {
                self.playAudioFile(loop: loop, startTime: 0, fileEndCompletionHandler: fileEndCompletionHandler)
            }
        }
    }
}
...