Spatial Audio — это захватывающий аудиоопыт, который помещает ваших пользователей в центр действия, делая ваш контент более реалистичным. Звук «пространственен» для создания эффекта нескольких динамиков, похожего на настройку объемного звука, но через наушники.
Например, в фильме звук от автомобиля может начинаться позади пользователя, двигаться вперед и затихать вдали. В видеочате голоса могут быть разделены и размещены вокруг пользователя, что упрощает идентификацию говорящих.
Если ваш контент использует поддерживаемый аудиоформат, вы можете добавить пространственное аудио в свое приложение, начиная с Android 13 (API уровня 33).
Запрос на возможности
Используйте класс Spatializer
для запроса возможностей и поведения пространственного устройства. Начните с получения экземпляра Spatializer
из AudioManager
:
Котлин
val spatializer = audioManager.spatializer
Ява
Spatializer spatializer = AudioManager.getSpatializer();
Получив Spatializer
, проверьте четыре условия, которые должны соблюдаться для того, чтобы устройство выводило пространственный звук:
Критерии | Проверять |
---|---|
Поддерживает ли устройство пространственную ориентацию? | getImmersiveAudioLevel() не является SPATIALIZER_IMMERSIVE_LEVEL_NONE |
Доступна ли пространственная ориентация? Доступность зависит от совместимости с текущей маршрутизацией аудиовыхода. | isAvailable() имеет true |
Включена ли пространственная ориентация? | isEnabled() — это true |
Можно ли сделать звуковую дорожку с заданными параметрами пространственной? | canBeSpatialized() — это true |
Эти условия могут не соблюдаться, например, если пространственная интерпретация недоступна для текущей звуковой дорожки или вообще отключена на устройстве вывода звука.
Отслеживание положения головы
С поддерживаемыми гарнитурами платформа может регулировать пространственное расположение звука на основе положения головы пользователя. Чтобы проверить, доступен ли трекер головы для текущего маршрута аудиовыхода, вызовите isHeadTrackerAvailable()
.
Совместимый контент
Spatializer.canBeSpatialized()
указывает, может ли аудио с заданными свойствами быть пространственно преобразовано с текущей маршрутизацией выходного устройства. Этот метод принимает AudioAttributes
и AudioFormat
, оба из которых более подробно описаны ниже.
AudioAttributes
Объект AudioAttributes
описывает использование аудиопотока (например, игрового звука или стандартного мультимедиа ), а также поведение его воспроизведения и тип содержимого .
При вызове canBeSpatialized()
используйте тот же экземпляр AudioAttributes
, который установлен для вашего Player
. Например, если вы используете библиотеку Jetpack Media3 и не настроили AudioAttributes
, используйте AudioAttributes.DEFAULT
.
Отключение пространственного звука
Чтобы указать, что ваш контент уже был пространственно преобразован, вызовите setIsContentSpatialized(true)
чтобы аудио не обрабатывалось дважды. В качестве альтернативы, настройте поведение пространственного преобразования, чтобы полностью отключить пространственное преобразование, вызвав setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
.
AudioFormat
Объект AudioFormat
описывает сведения о формате и конфигурации каналов звуковой дорожки.
При создании экземпляра AudioFormat
для передачи в canBeSpatialized()
установите кодировку , совпадающую с выходным форматом, ожидаемым от декодера. Вам также следует установить маску канала , соответствующую конфигурации канала вашего контента. Обратитесь к разделу Поведение пространственной обработки по умолчанию для получения рекомендаций по конкретным используемым значениям.
Прослушивание изменений Spatializer
Чтобы прослушивать изменения в состоянии Spatializer
, вы можете добавить прослушиватель с помощью Spatializer.addOnSpatializerStateChangedListener()
. Аналогично, чтобы прослушивать изменения в доступности трекера головы, вызовите Spatializer.addOnHeadTrackerAvailableListener()
.
Это может быть полезно, если вы хотите настроить выбор треков во время воспроизведения с помощью обратных вызовов слушателя. Например, когда пользователь подключает или отключает гарнитуру от устройства, обратный вызов onSpatializerAvailableChanged
указывает, доступен ли эффект spaceizer для новой маршрутизации аудиовыхода. На этом этапе вы можете рассмотреть возможность обновления логики выбора треков вашего проигрывателя для соответствия новым возможностям устройства. Подробную информацию о поведении выбора треков ExoPlayer см. в разделе ExoPlayer и пространственное аудио .
ExoPlayer и пространственный звук
Последние выпуски ExoPlayer облегчают принятие пространственного звука. Если вы используете автономную библиотеку ExoPlayer (имя пакета com.google.android.exoplayer2
), версия 2.17 настраивает платформу для вывода пространственного звука, а версия 2.18 вводит ограничения на количество аудиоканалов . Если вы используете модуль ExoPlayer из библиотеки Media3 (имя пакета androidx.media3
), версии 1.0.0-beta01
и более новые включают эти же обновления.
После обновления зависимости ExoPlayer до последней версии вашему приложению просто нужно включить контент, который можно пространственно расположить.
Ограничения по количеству аудиоканалов
Когда все четыре условия для пространственного звука выполнены, ExoPlayer выбирает многоканальную звуковую дорожку. Если нет, ExoPlayer выбирает стереодорожку. Если свойства Spatializer
изменяются, ExoPlayer активирует новый выбор дорожки, чтобы выбрать звуковую дорожку, которая соответствует текущим свойствам. Обратите внимание, что этот новый выбор дорожки может вызвать короткий период повторной буферизации.
Чтобы отключить ограничения по количеству аудиоканалов, установите параметры выбора дорожек на проигрывателе, как показано ниже:
Котлин
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Ява
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
Аналогичным образом вы можете обновить параметры существующего селектора дорожек, чтобы отключить ограничения по количеству аудиоканалов, выполнив следующие действия:
Котлин
val trackSelector = DefaultTrackSelector(context) ... trackSelector.parameters = trackSelector.buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Ява
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); ... trackSelector.setParameters( trackSelector .buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
Если ограничения на количество аудиоканалов отключены, если контент имеет несколько аудиодорожек, ExoPlayer изначально выбирает дорожку с наибольшим количеством каналов и воспроизводится на устройстве. Например, если контент содержит многоканальную аудиодорожку и стереодорожку, а устройство поддерживает воспроизведение обеих, ExoPlayer выбирает многоканальную дорожку. Подробнее о настройке этого поведения см. в разделе Выбор аудиодорожки .
Выбор аудиодорожки
Если поведение ограничений количества аудиоканалов ExoPlayer отключено, ExoPlayer не выбирает автоматически звуковую дорожку, которая соответствует свойствам пространственного преобразователя устройства. Вместо этого вы можете настроить логику выбора дорожек ExoPlayer, задав параметры выбора дорожек до или во время воспроизведения. По умолчанию ExoPlayer выбирает аудиодорожки, которые совпадают с исходной дорожкой с точки зрения типа MIME (кодировки), количества каналов и частоты дискретизации.
Изменение параметров выбора трека
Чтобы изменить параметры выбора дорожек ExoPlayer, используйте Player.setTrackSelectionParameters()
. Аналогично, вы можете получить текущие параметры ExoPlayer с помощью Player.getTrackSelectionParameters()
. Например, чтобы выбрать стереодорожку во время воспроизведения:
Котлин
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
Ява
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
Обратите внимание, что изменение параметров выбора треков во время воспроизведения может привести к прерыванию воспроизведения. Более подробная информация о настройке параметров выбора треков плеера доступна в разделе выбора треков в документации ExoPlayer.
Поведение пространственного размещения по умолчанию
Стандартное поведение пространственного позиционирования в Android включает следующие варианты поведения, которые могут быть настроены OEM-производителями:
Пространственно преобразуется только многоканальный контент, а не стереоконтент. Если вы не используете ExoPlayer, в зависимости от формата вашего многоканального аудиоконтента вам может потребоваться настроить максимальное количество каналов , которые может выводить аудиодекодер, на большое число. Это гарантирует, что аудиодекодер выводит многоканальный PCM для платформы для пространственного преобразования.
Котлин
val mediaFormat = MediaFormat() mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)
Ява
MediaFormat mediaFormat = new MediaFormat(); mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);
Для примера в действии см.
MediaCodecAudioRenderer.java
от ExoPlayer. Чтобы отключить пространственное звучание самостоятельно, независимо от настроек OEM, см. Отключение пространственного звука .AudioAttributes
: Звук может быть подвергнут пространственному преобразованию, если дляusage
установлено значениеUSAGE_MEDIA
илиUSAGE_GAME
.AudioFormat
: используйте маску канала, которая содержит как минимум каналыAudioFormat.CHANNEL_OUT_QUAD
(передний левый, передний правый, задний левый и задний правый), чтобы звук подлежал пространственному преобразованию. В примере ниже мы используемAudioFormat.CHANNEL_OUT_5POINT1
для аудиодорожки 5.1. Для стереодорожки используйтеAudioFormat.CHANNEL_OUT_STEREO
.Если вы используете Media3, вы можете использовать
Util.getAudioTrackChannelConfig(int channelCount)
для преобразования количества каналов в маску канала.Кроме того, установите кодировку
AudioFormat.ENCODING_PCM_16BIT
, если вы настроили декодер на вывод многоканального PCM.Котлин
val audioFormat = AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build()
Ява
AudioFormat audioFormat = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build();
Тест пространственного звука
Убедитесь, что на вашем тестовом устройстве включен пространственный звук:
- Для проводных гарнитур перейдите в Настройки системы > Звук и вибрация > Пространственный звук .
- Для беспроводных гарнитур перейдите в Настройки системы > Подключенные устройства > Значок шестеренки для вашего беспроводного устройства > Пространственный звук .
Чтобы проверить доступность Spatial Audio для текущего маршрута, выполните команду adb shell dumpsys audio
на вашем устройстве. Вы должны увидеть следующие параметры в выходных данных, пока воспроизведение активно:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)