OpenSL ES для Android

ВНИМАНИЕ: OpenSL ES устарел . Разработчикам следует использовать библиотеку Oboe с открытым исходным кодом, доступную на GitHub . Гобой — это оболочка C++, предоставляющая API, очень похожий на AAudio . Гобой вызывает AAudio, когда AAudio доступен, и возвращается к OpenSL ES, если AAudio недоступен.

На этой странице представлена ​​подробная информация о том, чем реализация OpenSL ES™ NDK отличается от эталонной спецификации OpenSL ES 1.0.1. При использовании примера кода из спецификации вам может потребоваться изменить его для работы на Android.

Если не указано иное, все функции доступны в Android 2.3 (уровень API 9) и более поздних версиях. Некоторые функции доступны только для Android 4.0 (уровень API 14); это отмечено.

Примечание. В документе определения совместимости Android (CDD) перечислены требования к аппаратному и программному обеспечению совместимого устройства Android. См. «Совместимость Android» для получения дополнительной информации об общей программе совместимости и CDD для фактического документа CDD.

OpenSL ES предоставляет интерфейс языка C, который также доступен с помощью C++. Он предоставляет функции, аналогичные аудиочастям этих API-интерфейсов Android Java:

Как и в случае со всеми Android Native Development Kit (NDK), основная цель OpenSL ES для Android — облегчить реализацию общих библиотек, которые будут вызываться с использованием собственного интерфейса Java ( JNI ). NDK не предназначен для написания приложений на чистом C/C++. Однако OpenSL ES — это полнофункциональный API, и мы ожидаем, что вы сможете удовлетворить большинство своих потребностей в аудио, используя только этот API, без дополнительных вызовов кода, выполняющегося во время выполнения Android.

Примечание. Несмотря на то, что API собственного аудио (высокопроизводительное аудио) Android основан на OpenSL ES, он не является соответствующей реализацией какого-либо профиля OpenSL ES 1.0.1 (игра, музыка или телефон). Это связано с тем, что Android не реализует все функции, необходимые ни одному из профилей. Все известные случаи, когда поведение Android отличается от спецификации, описаны на странице расширений Android .

Функции, унаследованные из эталонной спецификации

Реализация OpenSL ES в Android NDK наследует большую часть набора функций из эталонной спецификации с некоторыми ограничениями.

Глобальные точки входа

OpenSL ES для Android поддерживает все глобальные точки входа в спецификации Android. К этим точкам входа относятся:

  • slCreateEngine
  • slQueryNumSupportedEngineInterfaces
  • slQuerySupportedEngineInterfaces

Объекты и интерфейсы

В следующей таблице показаны объекты и интерфейсы, которые поддерживает реализация OpenSL ES в Android NDK. Если в ячейке отображается «Да» , значит, эта функция доступна в этой реализации.

Поддержка Android NDK для объектов и интерфейсов.

Особенность Аудиоплеер Аудио рекордер Двигатель Выходной микс
Усиление басов Да Нет Нет Да
Буферная очередь Да Нет Нет Нет
Локатор данных очереди буфера Да: Источник Нет Нет Нет
Динамическое управление интерфейсом Да Да Да Да
Отправка эффекта Да Нет Нет Нет
Двигатель Нет Нет Да Нет
Экологическая реверберация Нет Нет Нет Да
Эквалайзер Да Нет Нет Да
Локатор данных устройства ввода-вывода Нет Да: Источник Нет Нет
Извлечение метаданных Да: декодировать в PCM Нет Нет Нет
Без звука соло Да Нет Нет Нет
Объект Да Да Да Да
Локатор выходного микса Да: Раковина Нет Нет Нет
Играть Да Нет Нет Нет
Скорость воспроизведения Да Нет Нет Нет
Статус предварительной выборки Да Нет Нет Нет
Предустановленная реверберация Нет Нет Нет Да
Записывать Нет Да Нет Нет
Искать Да Нет Нет Нет
Указатель данных URI Да: Источник Нет Нет Нет
Виртуализатор Да Нет Нет Да
Объем Да Нет Нет Нет

В следующем разделе объясняются ограничения некоторых из этих функций.

Ограничения

К функциям, указанным в Таблице 1, применяются определенные ограничения. Эти ограничения представляют собой отличия от справочной спецификации. Оставшаяся часть этого раздела содержит информацию об этих различиях.

Динамическое управление интерфейсом

OpenSL ES для Android не поддерживает RemoveInterface или ResumeInterface .

Комбинации эффектов: реверберация окружающей среды и предустановленная реверберация.

Вы не можете одновременно использовать реверберацию окружающей среды и предустановленную реверберацию в одном выходном миксе.

Платформа может игнорировать запросы на эффекты, если посчитает, что загрузка ЦП будет слишком высокой.

Отправка эффекта

SetSendLevel() поддерживает один уровень отправки для каждого аудиоплеера.

Экологическая реверберация

Реверберация среды не поддерживает поля reflectionsDelay , reflectionsLevel или reverbDelay структуры SLEnvironmentalReverbSettings .

Формат данных MIME

Формат данных MIME можно использовать только с локатором данных URI и только для аудиоплеера. Вы не можете использовать этот формат данных для аудиорекордера.

Реализация OpenSL ES для Android требует, чтобы вы инициализировали mimeType значением NULL или допустимой строкой UTF-8. Вы также должны инициализировать containerType допустимым значением. При отсутствии других соображений, таких как переносимость на другие реализации или форматы контента, которые приложение не может идентифицировать по заголовку, мы рекомендуем установить для mimeType значение NULL и containerType значение SL_CONTAINERTYPE_UNSPECIFIED .

OpenSL ES для Android поддерживает следующие аудиоформаты, если платформа Android их также поддерживает:

  • WAV PCM.
  • WAV да.
  • WAV улав.
  • MP3 Огг Ворбис.
  • ААК ЛК.
  • HE-AACv1 (AAC+).
  • HE-AACv2 (расширенный AAC+).
  • АМР.
  • ФЛАК.

Примечание. Список аудиоформатов, поддерживаемых Android, см. в разделе Поддерживаемые медиаформаты .

Следующие ограничения применяются к обработке этих и других форматов в этой реализации OpenSL ES:

  • Форматы AAC должны находиться в контейнере MP4 или ADTS.
  • OpenSL ES для Android не поддерживает MIDI .
  • WMA не является частью AOSP , и мы не проверяли его совместимость с OpenSL ES для Android.
  • Реализация OpenSL ES в Android NDK не поддерживает прямое воспроизведение DRM или зашифрованного контента. Чтобы воспроизвести защищенный аудиоконтент, вы должны расшифровать его в своем приложении перед воспроизведением, при этом ваше приложение применяет все ограничения DRM.

OpenSL ES для Android не поддерживает следующие методы управления объектами:

  • Resume()
  • RegisterCallback()
  • AbortAsyncOperation()
  • SetPriority()
  • GetPriority()
  • SetLossOfControlInterfaces()

Формат данных PCM

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

  • 8-битный беззнаковый или 16-битный знаковый.
  • Моно или стерео.
  • Порядок байтов с прямым порядком байтов.
  • Примерные ставки:
    • 8000 Гц.
    • 11025 Гц.
    • 12 000 Гц.
    • 16 000 Гц.
    • 22050 Гц.
    • 24 000 Гц.
    • 32 000 Гц.
    • 44 100 Гц.
    • 48 000 Гц.

Конфигурации, которые OpenSL ES for Android поддерживает для записи, зависят от устройства; обычно моно/16-битный сигнал с частотой 16 000 Гц доступен независимо от устройства.

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

Android 5.0 (уровень API 21) и выше поддерживают данные с плавающей запятой .

Скорость воспроизведения

Скорость воспроизведения OpenSL ES указывает скорость, с которой объект представляет данные, выраженную в тысячных долях нормальной скорости или в промилле . Например, скорость воспроизведения 1000 промилле — это 1000/1000 или нормальная скорость. Диапазон скоростей — это закрытый интервал, выражающий диапазон возможных скоростей воспроизведения.

Поддержка диапазонов скорости воспроизведения и других возможностей может различаться в зависимости от версии и реализации платформы. Ваше приложение может определить эти возможности во время выполнения, используя PlaybackRate::GetRateRange() или PlaybackRate::GetCapabilitiesOfRate() для запроса устройства.

Устройство обычно поддерживает один и тот же диапазон скоростей для источника данных в формате PCM и диапазон единичных скоростей от 1000 до 1000 промилле для других форматов; то есть диапазон единичных ставок фактически представляет собой одно значение.

Записывать

OpenSL ES для Android не поддерживает события SL_RECORDEVENT_HEADATLIMIT или SL_RECORDEVENT_HEADMOVING .

Искать

Метод SetLoop() обеспечивает циклическое выполнение всего файла. Чтобы включить цикл, установите для параметра startPos значение 0, а для параметра endPos — значение SL_TIME_UNKNOWN .

Локатор данных очереди буфера

Аудиоплеер или рекордер с локатором данных для очереди буфера поддерживает только формат данных PCM.

Локатор данных устройства ввода-вывода

OpenSL ES для Android поддерживает использование локатора данных устройства ввода-вывода только в том случае, если вы указали локатор в качестве источника данных для Engine::CreateAudioRecorder() . Инициализируйте локатор данных устройства, используя значения, содержащиеся в следующем фрагменте кода:

SLDataLocator_IODevice loc_dev =
  {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
  SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};

Указатель данных URI

OpenSL ES для Android может использовать локатор данных URI только с форматом данных MIME и только для аудиоплеера. Вы не можете использовать локатор данных URI для аудиорекордера. URI может использовать только схемы http: и file: Другие схемы, такие как https: , ftp: или content: не допускаются.

Мы не проверяли поддержку rtsp: со звуком на платформе Android.

Структуры данных

Android поддерживает следующие структуры данных OpenSL ES 1.0.1:

  • SLDataFormat_MIME
  • SLDataFormat_PCM
  • SLDataLocator_BufferQueue
  • SLDataLocator_IODevice
  • SLDataLocator_OutputMix
  • SLDataLocator_URI
  • SLDataSink
  • SLDataSource
  • SLEngineOption
  • SLEnvironmentalReverbSettings
  • SLInterfaceID

Конфигурация платформы

OpenSL ES для Android предназначен для многопоточных приложений и является потокобезопасным. Он поддерживает один движок для каждого приложения и до 32 объектов на движок. Доступная память устройства и ЦП могут еще больше ограничить полезное количество объектов.

Эти параметры движка распознаются, но игнорируются slCreateEngine :

  • SL_ENGINEOPTION_THREADSAFE
  • SL_ENGINEOPTION_LOSSOFCONTROL

OpenMAX AL и OpenSL ES можно использовать вместе в одном приложении. В этом случае внутри имеется один общий объект механизма, а ограничение в 32 объекта является общим для OpenMAX AL и OpenSL ES. Приложение должно создать оба механизма, использовать оба механизма и, наконец, уничтожить оба механизма. Реализация поддерживает счетчик ссылок на общем механизме, чтобы он был правильно уничтожен во время второй операции уничтожения.

Замечания по программированию

Примечания по программированию OpenSL ES предоставляют дополнительную информацию для обеспечения правильной реализации OpenSL ES.

Примечание. Для вашего удобства мы включили копию спецификации OpenSL ES 1.0.1 в NDK в docs/opensles/OpenSL_ES_Specification_1.0.1.pdf .

Проблемы с платформой

В этом разделе описаны известные проблемы в первоначальной версии платформы, поддерживающей эти API.

Динамическое управление интерфейсом

DynamicInterfaceManagement::AddInterface не работает. Вместо этого укажите интерфейс в массиве, который передается в Create() , как показано в примере кода для реверберации окружающей среды.

Планируйте будущие версии OpenSL ES

Высокопроизводительные аудио API Android основаны на Khronos Group OpenSL ES 1.0.1 . Khronos выпустил обновленную версию стандарта 1.1. Пересмотренная версия включает новые функции, пояснения, исправления опечаток и некоторые несовместимости. Большинство ожидаемых несовместимостей относительно незначительны или относятся к областям OpenSL ES, которые не поддерживаются Android.

Приложение, разработанное с использованием этой версии, должно работать на будущих версиях платформы Android при условии, что вы будете следовать рекомендациям, изложенным в разделе «План обеспечения двоичной совместимости» ниже.

Примечание. Совместимость с будущими источниками не является целью. То есть при обновлении до более новой версии NDK вам может потребоваться изменить исходный код приложения, чтобы он соответствовал новому API. Мы ожидаем, что большинство таких изменений будут незначительными; подробности см. ниже.

Планируйте двоичную совместимость

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

  • Используйте только документированное подмножество поддерживаемых Android функций OpenSL ES 1.0.1.
  • Не зависьте от конкретного кода результата неудачной операции; будьте готовы иметь дело с другим кодом результата.
  • Обработчики обратного вызова приложения обычно выполняются в ограниченном контексте. Им следует написать, чтобы они выполнили свою работу быстро, а затем вернулись как можно скорее. Не выполняйте сложные операции внутри обработчика обратного вызова. Например, в обратном вызове завершения очереди буферов вы можете поставить в очередь другой буфер, но не создавать аудиоплеер.
  • Обработчики обратного вызова должны быть готовы к более или менее частому вызову, к получению дополнительных типов событий и игнорировать типы событий, которые они не распознают. Обратные вызовы, настроенные с маской событий, состоящей из включенных типов событий, должны быть готовы к вызову с одновременным набором битов нескольких типов событий. Используйте «&» для проверки каждого бита события, а не случая переключения.
  • Используйте статус предварительной выборки и обратные вызовы в качестве общих индикаторов прогресса, но не зависьте от конкретных жестко запрограммированных уровней заполнения или последовательностей обратных вызовов. Значение уровня заполнения статуса предварительной выборки и поведение ошибок, обнаруженных во время предварительной выборки, могут измениться.

Примечание. Дополнительные сведения см. в разделе «Поведение очереди буфера» ниже.

Планируйте совместимость источников

Как уже упоминалось, в следующей версии OpenSL ES от Khronos Group ожидаются несовместимости исходного кода. Вероятные области изменений включают в себя:

  • Ожидается, что интерфейс буферной очереди претерпит существенные изменения, особенно в области BufferQueue::Enqueue , списка параметров для slBufferQueueCallback и имени поля SLBufferQueueState.playIndex . Мы рекомендуем вместо этого использовать в коде вашего приложения простые буферные очереди Android. По этой причине в примере кода, поставляемом с NDK, мы использовали для воспроизведения простые буферные очереди Android. (Мы также используем простую буферную очередь Android для записи и декодирования в PCM, но это связано с тем, что стандарт OpenSL ES 1.0.1 не поддерживает запись или декодирование в приемник данных буферной очереди.)
  • Будет добавлено const ко входным параметрам, передаваемым по ссылке, и к полям структуры SLchar * , используемым в качестве входных значений. Это не должно требовать каких-либо изменений в вашем коде.
  • Произойдет замена беззнаковых типов на некоторые параметры, которые в данный момент подписаны. Возможно, вам придется изменить тип параметра с SLint32 на SLuint32 или аналогичный или добавить приведение.
  • Equalizer::GetPresetName копирует строку в память приложения вместо возврата указателя на память реализации. Это будет существенное изменение, поэтому мы рекомендуем вам либо избегать вызова этого метода, либо изолировать его использование.
  • В типах структур появятся дополнительные поля. Для выходных параметров эти новые поля можно игнорировать, но для входных параметров новые поля необходимо будет инициализировать. К счастью, ожидается, что все эти поля будут находиться в областях, которые не поддерживаются Android.
  • GUID интерфейса изменится. Чтобы избежать зависимости, обращайтесь к интерфейсам по символическому имени, а не по GUID.
  • SLchar изменится с unsigned char на char . В первую очередь это влияет на локатор данных URI и формат данных MIME.
  • SLDataFormat_MIME.mimeType будет переименован в pMimeType , а SLDataLocator_URI.URI будет переименован в pURI . Мы рекомендуем инициализировать структуры данных SLDataFormat_MIME и SLDataLocator_URI используя список значений, заключенный в фигурные скобки и разделенных запятыми, а не имя поля, чтобы изолировать ваш код от этого изменения. Этот метод используется в примере кода.
  • SL_DATAFORMAT_PCM не позволяет приложению указывать представление данных в виде целого числа со знаком, целого числа без знака или числа с плавающей запятой. Реализация Android предполагает, что 8-битные данные представляют собой целое число без знака, а 16-битные — целое число со знаком. Кроме того, использование поля samplesPerSec является неправильным, поскольку фактические единицы измерения — миллиГц. Ожидается, что эти проблемы будут решены в следующей версии OpenSL ES, которая представит новый расширенный формат данных PCM, который позволит приложению явно указывать представление и корректировать имя поля. Поскольку это будет новый формат данных, а текущий формат данных PCM по-прежнему будет доступен (хотя и устарел), он не потребует каких-либо немедленных изменений в вашем коде.