Добавьте пространственный звук в свое приложение XR. Добавьте пространственный звук в свое приложение XR.

Функции пространственного звука в Jetpack SceneCore позволяют вам создавать захватывающие звуковые эффекты в приложениях Android XR.

Пространственный звук имитирует восприятие звука пользователями в трёхмерном пространстве. Он создаёт ощущение звука, исходящего со всех сторон, в том числе сверху и снизу от пользователя. Система делает это, имитируя один или несколько «виртуальных динамиков» в определённых точках трёхмерного пространства.

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

Дополнительную информацию о том, как существующие приложения воспроизводят пространственный звук, можно найти в статье «Добавление стерео и объемного звука в ваше приложение» на этой странице.

Если вы оптимизируете своё приложение для XR, Jetpack SceneCore предоставляет инструменты для расширенной настройки пространственного звука. Вы можете точно позиционировать звуки в трёхмерной среде, использовать объемный звук для создания реалистичных звуковых полей и воспользоваться встроенной интеграцией объёмного звука.

Типы пространственного звука, доступные в Android XR

Android XR поддерживает позиционный, стерео, объемный и объемный звук.

Позиционный звук

Позиционный звук можно позиционировать для воспроизведения из определённой точки трёхмерного пространства. Например, можно разместить 3D-модель лающей собаки в углу виртуальной среды. Можно создать несколько объектов, издающих звук из каждой точки. Для рендеринга позиционного звука файлы должны быть моно или стерео.

Пространственное стерео и объемное звучание

Поддерживаются все медиаформаты Android для позиционного, стерео и объемного звука. Помимо этих форматов, устройства Android XR могут поддерживать аудиоформаты Dolby Atmos , Dolby Digital и Dolby Digital+ .

Стереоаудио относится к аудиоформатам с двумя каналами, а объёмный звук — к аудиоформатам с более чем двумя каналами, например, конфигурации объёмного звука 5.1 или 7.1 . Звуковые данные каждого канала связаны с одним динамиком. Например, при воспроизведении музыки в стереорежиме левый канал динамика может воспроизводить разные инструментальные дорожки, чем правый.

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

Амбисонический звук

Амбисонический звук (или амбисоника) — это своего рода «небоскрёб» для звука, создающий для ваших пользователей захватывающий звуковой ландшафт. Используйте амбисонику для фоновых звуков окружающей среды или в других ситуациях, когда вам нужно воссоздать сферическое звуковое поле, окружающее слушателя. Android XR поддерживает формат амбисонического звука AmbiX в амбисонике первого, второго и третьего порядка. Мы рекомендуем файлы форматов Opus ( .ogg ) и PCM/Wave ( .wav ).

Используйте пространственный звук с Jetpack SceneCore

Реализация пространственного звука с помощью Jetpack SceneCore включает проверку пространственных возможностей и выбор API для загрузки пространственного звука.

Проверка пространственных возможностей

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

Загрузить пространственное аудио

Для загрузки пространственного звука для использования в Jetpack SceneCore можно использовать любой из следующих API.

  • SoundPool : Идеально подходит для коротких звуковых эффектов размером менее 1 МБ. Они загружаются заранее и могут использоваться повторно. Это отличный способ загрузки аудио для позиционного аудио.
  • ExoPlayer : Идеально подходит для загрузки стерео и объёмного звука, такого как музыка и видео. Также поддерживает фоновое воспроизведение медиаконтента.
  • MediaPlayer : обеспечивает самый простой способ загрузки объемного звука.
  • AudioTrack : обеспечивает максимальный контроль над загрузкой аудиоданных. Позволяет напрямую записывать буферы аудио, а также синтезировать или декодировать собственные аудиофайлы.

Проверьте поддержку формата носителя

Платформа Android поддерживает некоторые медиаформаты. Однако некоторые устройства Android XR могут поддерживать и другие форматы, например, Dolby Atmos . Чтобы узнать о поддержке медиаформатов, воспользуйтесь AudioCapabilities в ExoPlayer:

val audioCapabilities = AudioCapabilities.getCapabilities(context, androidx.media3.common.AudioAttributes.DEFAULT, null)
if (audioCapabilities.supportsEncoding(C.ENCODING_AC3)) {
    // Device supports playback of the Dolby Digital media format.
}
if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3)) {
    // Device supports playback of the Dolby Digital Plus media format.
}
if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3_JOC)) {
    // Device supports playback of the Dolby Digital Plus with Dolby Atmos media format.
}

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

Добавьте позиционное аудио в ваше приложение

Позиционные источники звука определяются параметрами PointSourceParams и связанной с Entity . Положение и ориентация Entity определяют, где PointSourceParams отображается в трёхмерном пространстве.

Пример позиционного звука

В следующем примере аудиофайл со звуковым эффектом загружается в звуковой пул и воспроизводится в позиции Entity .

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities
    .hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)
) { // The session has spatial audio capabilities
    val maxVolume = 1F
    val lowPriority = 0
    val infiniteLoop = -1
    val normalSpeed = 1F

    val soundPool = SoundPool.Builder()
        .setAudioAttributes(
            AudioAttributes.Builder()
                .setContentType(CONTENT_TYPE_SONIFICATION)
                .setUsage(USAGE_ASSISTANCE_SONIFICATION)
                .build()
        )
        .build()

    val pointSource = PointSourceParams(entity)

    val soundEffect = appContext.assets.openFd("sounds/tiger_16db.mp3")
    val pointSoundId = soundPool.load(soundEffect, lowPriority)

    soundPool.setOnLoadCompleteListener { soundPool, sampleId, status ->
        // wait for the sound file to be loaded into the soundPool
        if (status == 0) {
            SpatialSoundPool.play(
                session = session,
                soundPool = soundPool,
                soundID = pointSoundId,
                params = pointSource,
                volume = maxVolume,
                priority = lowPriority,
                loop = infiniteLoop,
                rate = normalSpeed
            )
        }
    }
} else {
    // The session does not have spatial audio capabilities
}

Ключевые моменты кода

  • Первый шаг — проверить, доступны ли в данный момент возможности пространственного звука, с помощью spatialCapabilities .
  • Установка contentType на CONTENT_TYPE_SONIFICATION и usage на USAGE_ASSISTANCE_SONIFICATION позволяет системе обрабатывать этот аудиофайл как звуковой эффект.
  • В предыдущем примере аудиофайл загружается в пул непосредственно перед его использованием, чтобы сохранить целостность кода и упростить его. В идеале следует загружать все звуковые эффекты асинхронно по мере загрузки приложения, чтобы все аудиофайлы были доступны в пуле в нужный момент.

Добавьте стерео и объемный звук в свое приложение

Рекомендуемый способ добавления стерео и объёмного звука в приложение — использовать Exoplayer . Подробнее об использовании пространственного звука с Exoplayer см. в руководстве по пространственному звуку .

Расположение динамиков стерео и объемного звучания

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

По умолчанию динамик центрального канала расположен на mainPanelEntity приложения. Это касается и мобильных приложений, в которых Android XR автоматически меняет пространственное звучание звука.

Для стереосистемы расположение динамиков аналогично размещению объемного звука, за исключением того, что левый и правый каналы располагаются на левой и правой стороне панели соответственно.

Если у вас несколько панелей и вы хотите выбрать, какая из них будет воспроизводить звук, или если вы хотите, чтобы стерео или объёмный звук отображался относительно другой Entity , вы можете использовать PointSourceAttributes для определения местоположения центрального канала. Остальные каналы будут размещены, как описано ранее. В таких случаях необходимо также использовать MediaPlayer .

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

Если вы настроили MediaPlayer или ExoPlayer на воспроизведение стерео или объёмного звука в фоновом режиме, положение виртуальных динамиков изменится при переходе приложения в фоновый режим. Поскольку нет панели или другой точки в пространстве, к которой можно было бы привязать звук, пространственный звук перемещается вместе с пользователем (другими словами, он «привязан к голове»).

Пример объемного звука

В следующем примере загружается аудиофайл 5.1 с помощью MediaPlayer , а центральный канал файла устанавливается как Entity .

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val pointSourceAttributes = PointSourceParams(session.scene.mainPanelEntity)

    val mediaPlayer = MediaPlayer()

    val fivePointOneAudio = appContext.assets.openFd("sounds/aac_51.ogg")
    mediaPlayer.reset()
    mediaPlayer.setDataSource(fivePointOneAudio)

    val audioAttributes =
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()

    SpatialMediaPlayer.setPointSourceParams(
        session,
        mediaPlayer,
        pointSourceAttributes
    )

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()
} else {
    // The session does not have spatial audio capabilities
}

Ключевые моменты кода

Добавьте объемные звуковые поля в свое приложение

Самый простой способ воспроизвести звуковые поля с эффектом амбисонического звучания — загрузить файл с помощью MediaPlayer . Поскольку амбисоническое звучание применяется ко всему звуковому ландшафту, вам не нужно указывать Entity для определения позиции. Вместо этого вы создаёте экземпляр SoundFieldAttributes с соответствующим порядком амбисонического звучания, определяющим количество каналов.

Пример амбионики

В следующем примере воспроизводится объемное звуковое поле с помощью MediaPlayer .

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val soundFieldAttributes =
        SoundFieldAttributes(SpatializerConstants.AMBISONICS_ORDER_FIRST_ORDER)

    val mediaPlayer = MediaPlayer()

    val soundFieldAudio = appContext.assets.openFd("sounds/foa_basketball_16bit.wav")

    mediaPlayer.reset()
    mediaPlayer.setDataSource(soundFieldAudio)

    val audioAttributes =
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()

    SpatialMediaPlayer.setSoundFieldAttributes(
        session,
        mediaPlayer,
        soundFieldAttributes
    )

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()
} else {
    // The session does not have spatial audio capabilities
}

Ключевые моменты кода

  • Как и в предыдущих фрагментах, первым шагом является проверка доступности возможностей пространственного звука с помощью hasCapability() .
  • Тип contentType и использование носят исключительно информационный характер.
  • AMBISONICS_ORDER_FIRST_ORDER сигнализирует SceneCore о том, что файл звукового поля определяет четыре канала.