Воспроизведение аудио с низкой задержкой на Android
В настоящее время я пытаюсь минимизировать задержку звука для простого приложения:
У меня есть видео на ПК, и я передаю аудио видео через RTP на мобильный клиент. С очень похожим алгоритмом буферизации я могу добиться задержки в 90 мс на iOS, но ужасной ±180 мс на Android.
Я предполагаю, что разница связана с известными проблемами с задержкой на Android.
Однако, прочитав немного, я наткнулся на эту статью, в которой говорится, что:
Аудио с низкой задержкой доступно на некоторых устройствах начиная с Android 4.1/4.2.
Аудио с низкой задержкой может быть достигнуто с помощью libpd, библиотеки Pure Data для Android.
У меня есть 2 вопроса, непосредственно связанных с этими двумя утверждениями:
Где я могу найти больше информации о новом аудио с низкой задержкой в Jellybean? Это все, что я могу найти, но ему крайне не хватает конкретной информации. Должны ли изменения быть прозрачными для меня или есть какие-то новые вызовы класса /API, которые я должен реализовать, чтобы заметить какие-либо изменения в моем приложении? Я использую AudioTrack API, и я даже не уверен, должен ли он извлечь выгоду из этого улучшения, или мне нужно искать какой-то другой механизм для воспроизведения аудио.
Должен ли я посмотреть на использование libpd? Мне кажется, что это единственный шанс добиться меньших задержек, но поскольку я всегда думал о PD как о утилите синтеза звука, она действительно подходит для проекта, который просто захватывает кадры из сетевого потока и воспроизводит их? Я не занимаюсь синтезом. Я иду по неверному пути?
В качестве дополнительного примечания, прежде чем кто-то упомянет OpenSL ES, эта статья проясняет, что от его использования нельзя ожидать улучшения задержки:
"Поскольку OpenSL ES является нативным C API, потоки приложений, не относящиеся к Dalvik, которые вызывают OpenSL ES, не имеют никаких накладных расходов, связанных с Dalvik, таких как паузы при сборке мусора. Однако никакого дополнительного преимущества в производительности при использовании OpenSL ES нет, кроме этого. в частности, использование OpenSL ES не приводит к более низкой задержке звука, более высокому приоритету планирования и т. д., чем обычно обеспечивает платформа ".
7 ответов
Для самой низкой задержки на Android начиная с версии 4.2.2, вы должны сделать следующее, упорядоченное от наименее до наиболее очевидного:
Выберите устройство, которое поддерживает FEATURE_AUDIO_PRO, если это возможно, или FEATURE_AUDIO_LOW_LATENCY, если нет. ("Низкая задержка" составляет 50 мс в одну сторону; "про" составляет <20 мс в оба конца.)
Используйте OpenSL. Dalvik GC имеет низкую амортизированную стоимость, но когда он работает, он занимает больше времени, чем может позволить аудиопоток с низкой задержкой.
Обработка аудио в обратном вызове очереди буфера. Система выполняет обратные вызовы очереди буфера в потоке, который имеет более благоприятное планирование, чем обычные потоки пользовательского режима.
Сделайте ваш размер буфера кратным AudioManager.getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER). В противном случае ваш обратный вызов будет иногда получать два звонка на один временной интервал, а не один. Если ваш процессор не очень легкий, это может привести к сбоям. (На Android M очень важно использовать ТОЧНО размер системного буфера из-за ошибки в коде обработки буфера.)
Используйте частоту дискретизации, предоставленную AudioManager.getProperty(PROPERTY_OUTPUT_SAMPLE_RATE). В противном случае ваши буферы идут в обход системного ресамплера.
Никогда не выполняйте системный вызов и не блокируйте объект синхронизации внутри обратного вызова буфера. Если вам нужно синхронизировать, используйте структуру без блокировки. Для достижения наилучших результатов используйте полностью свободную от ожидания структуру, такую как кольцевой буфер с одним устройством чтения и одним устройством записи. Многие разработчики понимают это неправильно и в результате получают непредсказуемые сбои, которые трудно отладить.
Используйте векторные инструкции, такие как NEON, SSE или любой другой эквивалентный набор команд, на вашем целевом процессоре.
Протестируйте и измерьте свой код. Отследите, сколько времени потребуется для запуска, и помните, что вам нужно знать производительность в худшем случае, а не в среднем, потому что именно в худшем случае возникают глюки. И будь консерватором. Вы уже знаете, что если для обработки аудио потребуется больше времени, чем для его воспроизведения, вы никогда не получите низкую задержку. Но на Android это еще важнее, потому что частота процессора сильно колеблется. Вы можете использовать, возможно, 60-70% ЦП для аудио, но имейте в виду, что это изменится, когда устройство нагревается или охлаждается, или когда радио и Wi-Fi запускаются и останавливаются, и так далее.
Аудио с низкой задержкой больше не является новой функцией для Android, но для этого все же требуются изменения в аппаратном обеспечении, драйверах, ядре и инфраструктуре для конкретного устройства. Это означает, что существует большая разница в задержке, которую вы можете ожидать от разных устройств, и, учитывая сколько ценовых точек продают телефоны Android, вероятно, всегда будут различия. Найдите FEATURE_AUDIO_PRO или FEATURE_AUDIO_LOW_LATENCY, чтобы определить устройства, которые соответствуют критериям задержки, требуемым вашим приложением.
При использовании OpenSL ES вы должны удовлетворять следующим требованиям, чтобы получить низкую задержку на Jellybean и более поздних версиях Android:
Звук должен быть моно или стерео, линейный PCM.
Частота дискретизации звука должна совпадать с частотой дискретизации выходного сигнала (на некоторых устройствах это может не потребоваться, поскольку
FastMixer
способен выполнять повторную выборку, если поставщик настраивает его для этого. Но в моих тестах я получил очень заметные артефакты при повышении частоты с 44,1 до 48 кГц вFastMixer
).Ваш
BufferQueue
должно иметь как минимум 2 буфера. (Это требование с тех пор было смягчено. См. Этот коммит Гленна Кастена. Я не уверен, в какой версии Android это впервые появилось, но предположение было бы 4.4).Вы не можете использовать определенные эффекты (например, Reverb, Bass Boost, Equalization, Virtualization, ...).
SoundPool
класс также попытается использовать быстрый AudioTrack
внутренне, когда это возможно (применяются те же критерии, что и выше, за исключением BufferQueue
часть).
По ссылке в вашей точке 1:
"Аудио с низкой задержкой
В Android 4.2 улучшена поддержка воспроизведения аудио с низкой задержкой, начиная с улучшений, сделанных в выпуске Android 4.1 для задержки вывода звука с использованием OpenSL ES, Soundpool и API тонального генератора. Эти улучшения зависят от аппаратной поддержки - устройства, которые предлагают эти аудиофункции с низкой задержкой, могут объявить о своей поддержке приложений через постоянную аппаратную функцию ".
Ваша цитата в полной форме:
"Спектакль
Поскольку OpenSL ES является нативным C API, потоки приложений, не относящиеся к Dalvik, которые вызывают OpenSL ES, не имеют никаких накладных расходов, связанных с Dalvik, таких как паузы сборки мусора. Тем не менее, нет никакого дополнительного выигрыша в производительности при использовании OpenSL ES, кроме этого. В частности, использование OpenSL ES не приводит к меньшей задержке звука, более высокому приоритету планирования и т. Д., Чем обычно обеспечивает платформа. С другой стороны, поскольку платформы Android и реализации конкретных устройств продолжают развиваться, приложение OpenSL ES может рассчитывать на выгоды от любых будущих улучшений производительности системы ".
Итак, API для связи с драйверами, а затем hw - это OpenSl (точно так же, как Opengl и с графикой). Более ранние версии Android имеют плохой дизайн драйверов и / или hw. Эти проблемы были решены и исправлены в версиях 4.1 и 4.2, поэтому, если у hd есть мощность, вы получаете низкую задержку, используя OpenSL.
Опять же, из этого примечания на веб-сайте библиотеки puredata видно, что библиотека использует сам OpenSL для достижения низкой задержки:
Поддержка низкой задержки для совместимых устройств. Последняя версия Pd для Android (от 28.12.2012) поддерживает аудио с низкой задержкой для совместимых устройств Android. При обновлении вашей копии, убедитесь, что вы извлекли последнюю версию pd-for-android и субмодуля libpd из GitHub.
На момент написания статьи Galaxy Nexus, Nexus 4 и Nexus 10 обеспечивают низкую задержку для вывода звука. Чтобы попасть на дорожку с низкой задержкой, приложение должно использовать OpenSL, и оно должно работать с правильной частотой дискретизации и размером буфера. Эти параметры зависят от устройства (Galaxy Nexus и Nexus 10 работают на частоте 44100 Гц, в то время как Nexus 4 работает на частоте 48000 Гц; размер буфера различен для каждого устройства).
Как и всегда, Pd для документов Android в максимально возможной степени преодолевает все эти сложности, предоставляя доступ к новым функциям с малой задержкой, когда они доступны, и при этом остается обратно совместимым с более ранними версиями Android. Под капотом аудиокомпоненты Pd для Android будут использовать OpenSL на Android 2.3 и более поздних версиях, в то время как в Java на Android 2.2 и более ранних версиях использовался старый API AudioTrack / AudioRecord.
Те из вас, кого больше интересует проблема Android в 10 миллисекунд, т.е. звук с низкой задержкой на Android. Мы в Superpowered создали Android Lactcy Explainer. Пожалуйста, смотрите здесь:
Другая база данных о задержках звука и используемых размерах буфера:
http://superpowered.com/latency/
Исходный код:
Есть новая библиотека C++ Oboe, которая помогает уменьшить задержку звука. Я использовал его в своих проектах, и он работает хорошо. У этого есть эти особенности, которые помогают в сокращении задержки звука:
- Автоматическая настройка задержки
- Выбирает аудио API (OpenSL ES на API 16+ или AAudio на API 27+)
Приложение для измерения sampleRate и bufferSize: https://code.google.com/p/high-performance-audio/source/checkout и http://audiobuffersize.appspot.com/ БД результатов