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

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

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

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

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

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

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

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

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

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

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

Все медиаформаты Android поддерживаются для позиционного, стерео и объемного звука.

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

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

Амбисоник аудио

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

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

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

Проверьте пространственные возможности

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

Загрузить пространственный звук

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

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

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

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

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

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

// Check spatial capabilities before using spatial audio
if (xrSession.getSpatialCapabilities().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 = PointSourceAttributes(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 = xrSession,
                soundPool = soundPool,
                soundID = pointSoundId,
                attributes = pointSource,
                volume = maxVolume,
                priority = lowPriority,
                loop = infiniteLoop,
                rate = normalSpeed
            )
        }
    }
} else {
    // The session does not have spatial audio capabilities
}

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

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

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

Рекомендуемый способ добавить стерео и объемный звук в ваше приложение — использовать Exoplayer . Для получения дополнительной информации о том, как использовать Spatial Audio с Exoplayer , обратитесь к руководству Spatial Audio .

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

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

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

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

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

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

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

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

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

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

    val pointSourceAttributes = PointSourceAttributes(xrSession.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.setPointSourceAttributes(
        xrSession,
        mediaPlayer,
        pointSourceAttributes)

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()

} else {
    // The session does not have spatial audio capabilities
}

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

  • Как и в примере с позиционным звуком , первым шагом является проверка доступности пространственных аудиовозможностей в данный момент с помощью getSpatialCapabilities() .
  • Установка для contentType значения CONTENT_TYPE_MUSIC и использования USAGE_MEDIA позволяет системе рассматривать этот аудиофайл как объемный звук.

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

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

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

В следующем примере воспроизводится звуковое поле с эффектом ambisonic с помощью MediaPlayer .

// Check spatial capabilities before using spatial audio
if (xrSession.getSpatialCapabilities().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(
        xrSession,
        mediaPlayer,
        soundFieldAttributes)

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()

} else {
    // The session does not have spatial audio capabilities
}

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

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

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

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

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

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

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

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

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

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

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

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

Все медиаформаты Android поддерживаются для позиционного, стерео и объемного звука.

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

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

Амбисоник аудио

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

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

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

Проверьте пространственные возможности

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

Загрузить пространственный звук

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

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

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

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

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

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

// Check spatial capabilities before using spatial audio
if (xrSession.getSpatialCapabilities().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 = PointSourceAttributes(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 = xrSession,
                soundPool = soundPool,
                soundID = pointSoundId,
                attributes = pointSource,
                volume = maxVolume,
                priority = lowPriority,
                loop = infiniteLoop,
                rate = normalSpeed
            )
        }
    }
} else {
    // The session does not have spatial audio capabilities
}

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

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

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

Рекомендуемый способ добавить стерео и объемный звук в ваше приложение — использовать Exoplayer . Для получения дополнительной информации о том, как использовать Spatial Audio с Exoplayer , обратитесь к руководству Spatial Audio .

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

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

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

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

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

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

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

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

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

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

    val pointSourceAttributes = PointSourceAttributes(xrSession.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.setPointSourceAttributes(
        xrSession,
        mediaPlayer,
        pointSourceAttributes)

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()

} else {
    // The session does not have spatial audio capabilities
}

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

  • Как и в примере с позиционным звуком , первым шагом является проверка, доступны ли в данный момент возможности пространственного звука, с помощью getSpatialCapabilities() .
  • Установка для contentType значения CONTENT_TYPE_MUSIC и использования USAGE_MEDIA позволяет системе рассматривать этот аудиофайл как объемный звук.

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

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

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

В следующем примере воспроизводится звуковое поле с эффектом ambisonic с помощью MediaPlayer .

// Check spatial capabilities before using spatial audio
if (xrSession.getSpatialCapabilities().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(
        xrSession,
        mediaPlayer,
        soundFieldAttributes)

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()

} else {
    // The session does not have spatial audio capabilities
}

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

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