AVAudioPlayerNode lastRenderTime

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

Поскольку для перебора всех узлов проигрывателя требуется время, я делаю снимок значения lastRenderTime первых узлов и использую его для вычисления времени начала для метода узлов play(at:), чтобы синхронизировать воспроизведение между узлами:

let delay = 0.0
let startSampleTime = time.sampleTime     // time is the snapshot value    
let sampleRate = player.outputFormat(forBus: 0).sampleRate
let startTime = AVAudioTime(
        sampleTime: startSampleTime + AVAudioFramePosition(delay * sampleRate),
        atRate: sampleRate)
player.play(at: startTime)

Проблема в текущем времени воспроизведения.

Я использую это вычисление для получения значения, где seekTime - это значение, которое я отслеживаю, если мы ищем игрока. Это 0.0 в начале:

private var _currentTime: TimeInterval {
    guard player.engine != nil,
          let lastRenderTime = player.lastRenderTime,
          lastRenderTime.isSampleTimeValid,
          lastRenderTime.isHostTimeValid else {
        return seekTime
    }

    let sampleRate = player.outputFormat(forBus: 0).sampleRate
    let sampleTime = player.playerTime(forNodeTime: lastRenderTime)?.sampleTime ?? 0
    if sampleTime > 0 && sampleRate != 0 {
        return seekTime + (Double(sampleTime) / sampleRate)
    }
    return seekTime
}

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

Заметная задержка составляет около 100 мс, что очень много, и мне нужно точное значение текущего времени, чтобы параллельно выполнять визуальный рендеринг.

Это, вероятно, не имеет значения, но каждый аудиофайл является аудио в формате AAC, и я планирую их сегменты в узлах проигрывателя, я не использую буферы напрямую. Длина сегментов может быть разной. Я также вызываю prepare(withFrameCount:) на каждом узле проигрывателя после того, как запланировал аудиоданные.

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

Когда я устанавливаю ответвительный блок на один AVAudioPlayerNode, блок вызывается с буфером длины 4410, а частота дискретизации равна 44100 Hz, это означает 0,1 с аудиоданных. Должен ли я полагаться на это при вычислении задержки?

Мне интересно, могу ли я доверять длине буфера, который я получаю в блоке ответвлений. В качестве альтернативы я пытаюсь вычислить общую задержку для своего аудиографа. Может ли кто-нибудь дать представление о том, как точно определить это значение?


person Vince    schedule 22.02.2017    source источник


Ответы (1)


Из сообщения theanalogkid на форумах разработчиков Apple:

В системе задержка измеряется:

Размер кадра буфера ввода / вывода аудиоустройства + смещение безопасности вывода + задержка выходного потока + задержка устройства вывода

Если вы пытаетесь рассчитать общую задержку в оба конца, вы можете добавить:

Задержка ввода + смещение безопасности ввода к указанному выше.

Отметка времени, которую вы видите в процессе рендеринга. учитывать размер кадра буфера и смещение безопасности, но не учитываются задержки потока и устройства.

iOS предоставляет вам доступ к наиболее важной из вышеуказанной информации через AVAudioSession, и, как уже упоминалось, вы также можете использовать предпочтительные настройки сеанса - setPreferredIOBufferDuration и preferredIOBufferDuration для дальнейшего управления.

/ The current hardware input latency in seconds. */
@property(readonly) NSTimeInterval inputLatency  NS_AVAILABLE_IOS(6_0);
/ The current hardware output latency in seconds. */
@property(readonly) NSTimeInterval outputLatency  NS_AVAILABLE_IOS(6_0);
/ The current hardware IO buffer duration in seconds. */
@property(readonly) NSTimeInterval IOBufferDuration  NS_AVAILABLE_IOS(6_0);

Аудиоустройства также имеют свойство kAudioUnitProperty_Latency, которое вы можете запросить.

person sbooth    schedule 08.01.2021