Adicionar áudio espacial ao seu app de XR

Com os recursos de áudio espacial do Jetpack SceneCore, você pode criar experiências de áudio imersivas nos seus aplicativos Android XR.

O Áudio Espacial simula como os usuários percebem o som em um ambiente 3D. Ele cria a sensação de que o som emana de todas as direções, inclusive acima e abaixo do usuário. O sistema faz isso simulando um ou mais "alto-falantes virtuais" em locais específicos no espaço 3D.

Os apps que não foram projetados ou modificados para o Android XR têm o áudio espacializado automaticamente no Android XR. À medida que o usuário se move pelo espaço, todo o áudio do app é emitido pelo painel em que a interface do app é renderizada. Por exemplo, se um timer de um app de relógio tocar, o áudio vai parecer que está vindo da posição do painel do app. O Android XR vai alterar automaticamente o som para realismo posicional. Por exemplo, a distância percebida entre o painel do app e o usuário afeta sutilmente o volume do áudio para uma maior sensação de realismo.

Para mais informações sobre como os apps atuais renderizam o áudio espacial, leia Adicionar som estéreo e surround ao seu app nesta página.

Se você estiver otimizando seu app para XR, o Jetpack SceneCore vai oferecer ferramentas para personalização avançada de áudio espacial. Você pode posicionar sons com precisão no ambiente 3D, usar áudio ambisonic para campos sonoros realistas e aproveitar a integração de som surround integrada.

Tipos de áudio espacial disponíveis no Android XR

O Android XR é compatível com áudio posicional, estéreo, surround e ambisonic.

Áudio posicional

Um áudio posicional pode ser posicionado para tocar de um ponto específico no espaço 3D. Por exemplo, é possível ter um modelo 3D de um cachorro latindo no canto do seu ambiente virtual. É possível ter várias entidades emitindo som de cada uma das respectivas posições. Para renderizar áudio posicional, os arquivos precisam ser mono ou estéreo.

Estéreo espacializado e som surround

Todos os formatos de mídia do Android são compatíveis com som posicional, estéreo e surround.

O áudio estéreo se refere a formatos com dois canais, e o som surround se refere a formatos com mais de dois canais, como configurações de som surround 5.1 ou 7.1. Os dados de som de cada canal são associados a um alto-falante. Por exemplo, ao tocar música em estéreo, o canal do alto-falante esquerdo pode emitir faixas de instrumentos diferentes do direito.

O som surround é usado com frequência em filmes e programas de televisão para aumentar o realismo e a imersão com vários canais de alto-falantes. Por exemplo, o diálogo geralmente é reproduzido em um canal de alto-falante central, enquanto o som de um helicóptero voando pode usar diferentes canais em sequência para dar a sensação de que o helicóptero está voando ao redor do seu espaço 3D.

Áudio ambisonic

O áudio ambisônico (ou ambisonics) é como uma skybox para áudio, oferecendo uma paisagem sonora imersiva para os usuários. Use ambisonics para sons ambientais de fundo ou outros cenários em que você quer replicar um campo sonoro esférico completo que envolve o ouvinte. O Android XR é compatível com o formato de áudio ambissônico AmbiX em ambissônicos de primeira, segunda e terceira ordem. Recomendamos os tipos de arquivo Opus (.ogg) e PCM/Wave (.wav).

Usar áudio espacial com o Jetpack SceneCore

A implementação do áudio espacial com o Jetpack SceneCore envolve verificar os recursos espaciais e escolher uma API para carregar o áudio espacial.

Verificar recursos espaciais

Antes de usar os recursos de áudio espacial, verifique se o Session é compatível com áudio espacial. Em todos os snippets de código nas seções a seguir, as funcionalidades são verificadas antes de tentar reproduzir áudio espacializado.

Carregar áudio espacial

Você pode usar qualquer uma das APIs a seguir para carregar áudio espacial e usar no Jetpack SceneCore.

  • SoundPool: ideal para efeitos sonoros curtos com menos de 1 MB. Eles são carregados com antecedência e podem ser usados várias vezes. Essa é uma ótima maneira de carregar áudio para áudio posicional.
  • ExoPlayer: ideal para carregar conteúdo de som estéreo e surround, como músicas e vídeos. Também permite a reprodução de mídia em segundo plano.
  • MediaPlayer: oferece a maneira mais simples de carregar áudio ambisonic.
  • AudioTrack: oferece mais controle sobre como carregar dados de áudio. Permite gravar diretamente buffers de áudio ou se você sintetizou ou decodificou seus próprios arquivos de áudio.

Adicionar áudio posicional ao seu app

As fontes de som posicionais são definidas por PointSourceParams e um Entity associado. A posição e a orientação do Entity determinam onde o PointSourceParams é renderizado no espaço 3D.

Exemplo de áudio posicional

O exemplo a seguir carrega um arquivo de áudio de efeito sonoro em um pool de sons e o reproduz na posição do 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
}

Pontos principais sobre o código

  • A primeira etapa é verificar se os recursos de áudio espacial estão disponíveis usando spatialCapabilities.
  • Definir o contentType como CONTENT_TYPE_SONIFICATION e o uso como USAGE_ASSISTANCE_SONIFICATION permite que o sistema trate esse arquivo de áudio como um efeito sonoro.
  • O exemplo anterior carrega o arquivo de áudio no pool imediatamente antes de usá-lo para manter o código junto por simplicidade. O ideal é carregar todos os efeitos sonoros de forma assíncrona ao carregar o app para que todos os arquivos de áudio estejam disponíveis no pool quando você precisar deles.

Adicionar som estéreo e surround ao seu app

A maneira recomendada de adicionar som estéreo e surround ao seu app é usando Exoplayer. Para mais informações sobre como usar o áudio espacial com Exoplayer, consulte o guia de áudio espacial.

Posicionamento de alto-falantes estéreo e de som surround

Com o posicionamento dos alto-falantes de som surround, os alto-falantes virtuais são posicionados e orientados em relação a um alto-falante central, ao redor do usuário em uma configuração ITU padrão.

Por padrão, o alto-falante do canal central é colocado no mainPanelEntity do app. Isso inclui apps para dispositivos móveis que têm o áudio espacializado automaticamente pelo Android XR.

Para estéreo, o posicionamento dos alto-falantes é semelhante ao som surround, exceto que apenas os canais esquerdo e direito são posicionados nos lados esquerdo e direito do painel, respectivamente.

Se você tiver vários painéis e quiser escolher qual deles emite áudio ou se quiser que o áudio estéreo ou surround seja renderizado em relação a outro Entity, use o PointSourceAttributes para definir o local do canal central. Os outros canais serão colocados como mencionado anteriormente. Nesses casos, também é necessário usar MediaPlayer.

À medida que o usuário se move pelo espaço, os alto-falantes virtuais estéreo e de som surround se movem e se ajustam para garantir que estejam sempre em uma posição ideal.

Se você tiver configurado o MediaPlayer ou o ExoPlayer para continuar reproduzindo som estéreo ou surround em segundo plano, o posicionamento virtual do alto-falante será alterado quando o app for colocado em segundo plano. Como não há um painel ou outro ponto no espaço para ancorar o som, o áudio espacial se move com o usuário (ou seja, ele é "fixado na cabeça").

Exemplo de som surround

O exemplo a seguir carrega um arquivo de áudio 5.1 usando MediaPlayer e define o canal central do arquivo como um 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
}

Pontos principais sobre o código

Adicionar campos de som ambisonic ao seu app

A maneira mais simples de reproduzir campos sonoros ambisônicos é carregar o arquivo com um MediaPlayer. Como o som ambisonic se aplica a toda a paisagem sonora, não é necessário especificar um Entity para fornecer uma posição. Em vez disso, crie uma instância de SoundFieldAttributes com a ordem ambissônica adequada, especificando o número de canais.

Exemplo da Ambionics

O exemplo a seguir reproduz um campo sonoro ambisonic usando 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
}

Pontos principais sobre o código

  • Assim como nos snippets anteriores, a primeira etapa é verificar se os recursos de áudio espacial estão disponíveis usando hasCapability().
  • O contentType e o uso são puramente informativos.
  • O AMBISONICS_ORDER_FIRST_ORDER sinaliza para o SceneCore que o arquivo de campo sonoro define quatro canais.