Android: звуковой API (детерминированный, низкая задержка) - PullRequest
35 голосов
/ 01 сентября 2011

Я рассматриваю все виды звукового API для Android и хотел бы знать, какой из них мне следует использовать. Моя цель - получить звук с низкой задержкой или, по крайней мере, детерминированное поведение в отношении задержки воспроизведения.

У нас было много проблем, и кажется, что Android Sound API - это дерьмо, поэтому я изучаю возможности.

Проблема, с которой мы столкнулись, заключается в том, что между sound_out.write(sound_samples); и реальным звуком, воспроизводимым через динамики, имеется значительная задержка. Обычно это около 300 мс. Проблема в том, что на всех устройствах это отличается; некоторые не имеют такой проблемы, но большинство покалечены (однако CS-вызов имеет нулевую задержку). Самая большая проблема с этой нелепой задержкой заключается в том, что на некоторых устройствах эта задержка представляется случайной величиной (то есть она не всегда составляет 300 мс).

Я читаю об OpenSL ES, и я хотел бы знать, имел ли кто-нибудь опыт работы с ним, или это то же самое дерьмо, но упакованное в другую упаковку?

Я предпочитаю иметь собственный доступ, но я не возражаю против косвенного обращения к уровню Java, если могу получить детерминированное поведение: либо задержка должна быть постоянной (для данного устройства), либо я хочу получить доступ в текущую позицию воспроизведения вместо угадывания с диапазоном ошибок ± 300 мс ...

РЕДАКТИРОВАТЬ:
1,5 года спустя я попробовал несколько телефонов Android, чтобы увидеть, как я могу получить максимально возможную задержку для голосовой связи в реальном времени. Используя специализированные инструменты, я измерил задержку волнового пути. Лучшие результаты были более 100 мс, большинство телефонов были в диапазоне 180 мс. У кого-нибудь есть идеи?

Ответы [ 5 ]

27 голосов
/ 07 сентября 2012

SoundPool - это интерфейс с наименьшей задержкой на большинстве устройств, поскольку пул хранится в аудиопроцессе. Все другие аудиоканалы требуют межпроцессного взаимодействия. OpenSL - лучший выбор, если SoundPool не соответствует вашим потребностям.

Почему OpenSL? AudioTrack и OpenSL имеют одинаковые задержки с одним важным отличием: обратные вызовы буфера AudioTrack обслуживаются в Dalvik, а обратные вызовы OpenSL обслуживаются в собственных потоках. Текущая реализация Dalvik не способна обслуживать обратные вызовы с чрезвычайно низкой задержкой, потому что нет способа приостановить сборку мусора во время аудио-обратных вызовов. Это означает, что минимальный размер для буферов AudioTrack должен быть больше минимального размера для буферов OpenSL, чтобы обеспечить воспроизведение без сбоев.

В большинстве выпусков Android эта разница между AudioTrack и OpenSL не имеет никакого значения. Но с Jellybean Android теперь имеет аудиотракт с малой задержкой. Фактическая задержка все еще зависит от устройства, но она может быть значительно ниже, чем ранее. Например, http://code.google.com/p/music-synthesizer-for-android/ использует 384-кадровые буферы на Galaxy Nexus для общей задержки вывода менее 30 мс. Это требует, чтобы аудиопоток обслуживал буферы примерно один раз каждые 8 ​​мс, что было невозможно в предыдущих выпусках Android. Это все еще невозможно в ветке Dalvik.

Это объяснение предполагает две вещи: во-первых, вы запрашиваете наименьшие возможные буферы из OpenSL и выполняете свою обработку в обратном вызове буфера, а не с буферной очередью. Во-вторых, ваше устройство поддерживает путь с низкой задержкой. На большинстве современных устройств вы не увидите большой разницы между AudioTrack и OpenSL ES. Но на устройствах, которые поддерживают Jellybean + и аудио с низкой задержкой, OpenSL ES обеспечит вам путь с самой низкой задержкой.

2 голосов
/ 11 июня 2012

IIRC, OpenSL передается через тот же интерфейс, что и AudioTrack, поэтому в лучшем случае он будет соответствовать AudioTrack. (FWIW, в настоящее время я использую OpenSL для вывода с «низкой задержкой»)

Печальная правда в том, что на Android нет такой вещи, как звук с низкой задержкой. Нет даже правильного способа помечать и / или фильтровать устройства по задержке звука.

Какой интерфейс вы хотите использовать для минимизации задержки, будет зависеть от того, что вы пытаетесь сделать. Если вы хотите иметь аудиопоток, вы будете смотреть либо на OpenSL, либо на AudioTrack.

Если вы хотите вызвать статические выстрелы, вы можете использовать SoundPool. Для статических ударов SoundPool будет иметь низкую задержку, поскольку сэмплы предварительно загружены в аппаратное обеспечение. Я думаю, что есть возможность предварительно загружать снимки с помощью OpenSL, но я не пробовал.

1 голос
/ 27 сентября 2011

Самая низкая задержка, которую вы можете получить от SoundPool.Существует ограничение на то, насколько велик звук, который вы можете воспроизводить таким образом, но если вы находитесь ниже лимита (1Mb, IIRC), это довольно низкая задержка.Даже если это, вероятно, не 40 мс.

Но это быстрее, чем то, что вы можете получить с помощью потоковой передачи, по крайней мере, по моему опыту.

Предупреждение: вы можете увидеть случайные сбои в SoundPool на устройствах Samsung,У меня есть теория, что это происходит только тогда, когда вы получаете доступ к SoundPool из нескольких потоков, но я не проверял это.

РЕДАКТИРОВАТЬ: OpenSL ES, очевидно, имеет очень высокую задержку на Kindle Fire, в то время как SoundPool очень многолучше, но обратное может быть верно для других платформ.

0 голосов
/ 02 ноября 2018

Лучший способ получить низкую задержку для нативного кода на Android - это использовать Oboe.

https://github.com/google/oboe

Гобой переносит AAudio на новые устройства. AAudio предлагает пути с наименьшей возможной задержкой. Если AAudio недоступен, то Oboe вызывает OpenSL ES. Гобой гораздо проще в использовании, чем OpenSL ES.

AAudio вызывает либо через AudioTrack, либо через новый путь данных MMAP. AAudio облегчает получение дорожки FAST, потому что вы можете оставить некоторые параметры неуказанными. Затем AAudio выберет правильные параметры, необходимые для быстрой дорожки.

0 голосов
/ 17 июля 2018

О проблеме детерминированной / постоянной задержки, здесь вы можете найти интересную статью:

ПОДХОДЫ ДЛЯ ПОСТОЯННОЙ АУДИО-ЛАТЕНЦИИ НА ANDROID

Суть их исследований заключается в следующем: поскольку Audio HAL, являющийся одним из более глубоких уровней аудиопатра и отвечающий за синхронизацию событий аудио-обратного вызова, реализуется поставщиком, относительные задержки могут варьироваться, особенно в дешевое железо. Таким образом, они предлагают два подхода к снижению дисперсии задержки. Один из них заключается в том, чтобы позаботиться о времени обратного вызова, вставляя звук с фиксированными интервалами, другой - отфильтровать время обратного вызова, чтобы оценить время, в которое должен был произойти обратный вызов с постоянной задержкой, применяя фильтр сглаживания. С помощью этих двух подходов можно значительно уменьшить дисперсию задержки.

Следует также отметить, что существует новый нативный Android-Audio-API, AAudio.

AAudio API

Доступно / стабильно с Android Oreo 8.1 (API уровень 27). Существует также оболочка, которая динамически выбирает между OpenSL ES и AAudio и намного проще кодировать OpenSL ES. Это все еще в предварительном просмотре разработчика.

Аудио библиотека гобоя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...