Аудио буферизация в Android
Я пытаюсь реализовать эффективный аудио буфер для потоковой передачи. Изначально я пытался сделать буферизацию следующим образом
Так что изначально у меня есть мой InputStream
который взят из HttpUrlConnection
, Данные считываются из входного потока циклическим буфером, который заполняет буферы. В этом случае у меня есть 3 буфера, но количество и размер буферов можно легко изменить. Поэтому после того, как все буферы заполнены, я начинаю записывать данные из моего первого буфера в OutputStream
который связан с InputStream
так что всякий раз, когда я пишу что-то OutputStream
это можно затем прочитать из InputStream
, MediaCodec
отвечает за чтение данных из InputStream
и декодирование данных, которые затем передаются AudioTrack
,
Проблема с этой настройкой заключается в том, что через некоторое время OutputStream в конце концов достигает конца циклического буфера, поэтому между ними больше нет "дополнительного буфера" "OutputStream.giveMeNextBufferWithData"
а также "CircularBuffer.readDataFromInputStreamAndCreateBuffer"
(псевдокод).
Я пытался увеличить количество и размер каждого буфера, но это не помогло. Это просто задерживает количество времени, прежде чем OutputStream
становится "голодным" для получения дополнительных данных.
Есть одна очень хорошая библиотека https://code.google.com/p/aacdecoder-android/ которая очень хорошо работает, когда дело доходит до буферизации аудио, но, к сожалению, я не мог понять, как там делается буферизация, и она не не работает так хорошо при некоторых обстоятельствах.
Так есть ли "идеальный" алгоритм для такой задачи? Я думал о двойной / тройной буферизации, но я не слишком уверен в этом и, учитывая, что я искал в сети и безуспешно внедрял различные решения в течение последних нескольких дней, я в конце концов решил спросить ее.
Надеюсь, я все хорошо объяснил.
Спасибо всем заранее!
1 ответ
Буферизация сама по себе в конечном счете недостаточна для потоковых источников с фиксированной скоростью передачи (по запросу), где вы не можете гарантировать, что частота дискретизации источника и устройства абсолютно одинакова.
Для коротких программ вы можете буферизовать секунду или две аудио, и если ваша скорость воспроизведения будет высокой, вы начнете погружаться в этот резерв, но, надеюсь, не превысите его. Точно так же вам нужна избыточная емкость буфера, если вы воспроизводите данные медленнее, чем они генерируются. Но они в конечном итоге потерпят неудачу, когда разница в частоте дискретизации накапливается больше, чем размер резервного буфера.
Вместо этого, чтобы потоковая передача работала "вечно", вам нужен способ выровнять нормы производства и потребления.
"Ленивый" способ сделать это состоит в том, чтобы иметь логику, которая добавляет или отбрасывает одну выборку за более длительную единицу времени, в зависимости от направления, в котором произошла ошибка. Но это технически вносит искажения.
"Причудливый" способ сделать это состоит в том, чтобы иметь преобразователь с переменной частотой дискретизации, соотношение которого может быть скорректировано с течением времени, чтобы противодействовать ошибке между уровнем потребления аудио и скоростью производства.