Áudio espacial

O áudio espacial é uma experiência de áudio imersiva que coloca os usuários no no centro da ação, tornando seu conteúdo mais realista. O som é "espacializado" para criar um efeito de vários alto-falantes, semelhante a um som surround mas por fones de ouvido.

Por exemplo, em um filme, o som de um carro pode começar atrás do usuário, se mover para a frente e desacelerar ao longo da distância. Em um chat por vídeo, é possível usar separadas e posicionadas ao redor do usuário, facilitando a identificação dos locutores.

Caso seu conteúdo use um formato de áudio compatível, é possível adicionar áudio espacial ao seu do app a partir do Android 13 (nível 33 da API).

Consultar recursos

Use a classe Spatializer para consultar os recursos e o comportamento de espacialização do dispositivo. Comece recuperando uma instância do Spatializer do AudioManager:

Kotlin

val spatializer = audioManager.spatializer

Java

Spatializer spatializer = AudioManager.getSpatializer();

Depois de receber o Spatializer, verifique as quatro condições que precisam ser mantidas true para que o dispositivo gere áudio espacializado:

Critérios conhecimento
O dispositivo é compatível com a espacialização? getImmersiveAudioLevel() não é SPATIALIZER_IMMERSIVE_LEVEL_NONE
A espacialização está disponível?
A disponibilidade depende da compatibilidade com o roteamento de saída de áudio atual.
isAvailable() está true
A espacialização está ativada? isEnabled() está true
Uma faixa de áudio com os parâmetros fornecidos pode ser espacial? canBeSpatialized() está true

Essas condições podem não ser atendidas, por exemplo, se a espacialização não estiver disponível. para a faixa de áudio atual ou desativado completamente no dispositivo de saída de áudio.

rastreamento da cabeça

Com fones de ouvido compatíveis, a plataforma pode ajustar a intensidade espacialização baseada na posição da cabeça do usuário. Para verificar se um rastreador da cabeça está disponível para o roteamento de saída de áudio atual, chame isHeadTrackerAvailable()

Conteúdo compatível

Spatializer.canBeSpatialized() indica se o áudio com as propriedades fornecidas pode ser espacializado com o roteamento de dispositivo de saída atual. Esse método recebe um objeto AudioAttributes e um AudioFormat, ambos são descritos em mais detalhes abaixo.

AudioAttributes

Um objeto AudioAttributes descreve o uso de um stream de áudio (por exemplo, áudio do jogo ou mídia padrão), além dos comportamentos de reprodução e do tipo de conteúdo.

Ao chamar canBeSpatialized(), use o mesmo AudioAttributes conforme definido para Player. Por exemplo, se você está usando a biblioteca Jetpack Media3 e não personalizou o AudioAttributes, use AudioAttributes.DEFAULT.

Como desativar o áudio espacial

Para indicar que seu conteúdo já foi espacializado, chame setIsContentSpatialized(true) para que o áudio não seja processado duas vezes. Como alternativa, ajuste o comportamento de espacialização para desativar totalmente a espacialização chamando setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)

AudioFormat

Um objeto AudioFormat descreve detalhes sobre o formato e a configuração do canal de uma faixa de áudio.

Ao instanciar o AudioFormat para transmitir ao canBeSpatialized(), defina a codificação para o mesmo formato de saída esperado do decodificador. Você também deve definir uma máscara de canal que corresponda à configuração do canal do seu conteúdo. Consulte a Seção Comportamento de espacialização padrão para orientações sobre valores específicos a serem usados.

Detectar mudanças no Spatializer

Para detectar mudanças no estado do Spatializer, adicione um listener. com Spatializer.addOnSpatializerStateChangedListener(). Da mesma forma, para detectar mudanças na disponibilidade de um tracker principal, chame Spatializer.addOnHeadTrackerAvailableListener().

Pode ser útil se você quiser ajustar a seleção de faixas durante a reprodução. usando os callbacks do listener. Por exemplo, quando um usuário conecta ou desconecta o fone de ouvido do dispositivo, o onSpatializerAvailableChanged callback indica se o efeito de espacialização está disponível para o novo roteamento de saída de áudio. Nesse ponto, considere atualizar o lógica de seleção de trilhas para corresponder aos novos recursos do dispositivo. Para detalhes sobre Comportamento de seleção de faixas do ExoPlayer, consulte a biblioteca ExoPlayer e áudio espacial (link em inglês). nesta seção.

ExoPlayer e áudio espacial

Os lançamentos recentes do ExoPlayer facilitam a adoção do áudio espacial. Se você usar a biblioteca autônoma do ExoPlayer (nome do pacote com.google.android.exoplayer2), a versão 2.17 configura a plataforma para produzir áudio espacial, e a versão A versão 2.18 apresenta restrições de contagem de canais de áudio. Se você usar o módulo ExoPlayer da biblioteca Media3, (nome do pacote androidx.media3), versão 1.0.0-beta01 e mais recentes incluem essas mesmas atualizações.

Depois de atualizar a dependência do ExoPlayer para a versão mais recente, o app apenas precisa incluir conteúdo que possa ser espacializado.

Restrições de contagem de canais de áudio

Quando todas as quatro condições do áudio espacial são atendidas, o ExoPlayer escolhe uma faixa de áudio multicanal. Caso contrário, o ExoPlayer escolhe uma faixa estéreo. Se as propriedades Spatializer mudarem, o ExoPlayer acionará uma nova seleção de faixa para escolher uma faixa de áudio que corresponda ao propriedades atuais. Essa nova seleção de faixa pode fazer com que um curto período de armazenamento em buffer.

Para desativar as restrições de contagem de canais de áudio, defina os parâmetros de seleção de faixa no player, como mostrado abaixo:

Kotlin

exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context)
  .setConstrainAudioChannelCountToDeviceCapabilities(false)
  .build()

Java

exoPlayer.setTrackSelectionParameters(
  new DefaultTrackSelector.Parameters.Builder(context)
    .setConstrainAudioChannelCountToDeviceCapabilities(false)
    .build()
);

Da mesma forma, você pode atualizar os parâmetros de um seletor de faixa existente para desativar de contagem de canais de áudio, da seguinte maneira:

Kotlin

val trackSelector = DefaultTrackSelector(context)
...
trackSelector.parameters = trackSelector.buildUponParameters()
  .setConstrainAudioChannelCountToDeviceCapabilities(false)
  .build()

Java

DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
...
trackSelector.setParameters(
  trackSelector
    .buildUponParameters()
    .setConstrainAudioChannelCountToDeviceCapabilities(false)
    .build()
);

Com as restrições de contagem de canais de áudio desativadas, se o conteúdo tiver vários áudios faixas, o ExoPlayer seleciona inicialmente a faixa que tem o maior número de canais e possa ser reproduzido no dispositivo. Por exemplo, se o conteúdo tiver um faixa de áudio multicanal e estéreo, e o dispositivo suporta reprodução de ambos, o ExoPlayer seleciona a faixa multicanal. Consulte a Seleção de faixa de áudio para detalhes sobre como personalizar esse comportamento.

Seleção de faixa de áudio

Quando as restrições de contagem de canais de áudio do ExoPlayer comportamento estiver desativado, o ExoPlayer não selecionará uma faixa de áudio automaticamente que corresponda às propriedades do espacializador do dispositivo. Em vez disso, você pode personalize a lógica de seleção de faixa do ExoPlayer definindo a seleção de faixa antes ou durante a reprodução. Por padrão, o ExoPlayer seleciona áudios faixas que são iguais à faixa inicial em relação ao tipo MIME (codificação), contagem de canais e taxa de amostragem.

Alterar os parâmetros de seleção de faixa

Para mudar os parâmetros de seleção de faixa do ExoPlayer, use Player.setTrackSelectionParameters() Da mesma forma, você pode obter os parâmetros atuais do ExoPlayer com Player.getTrackSelectionParameters() Por exemplo, para selecionar uma faixa de áudio estéreo no meio da reprodução:

Kotlin

exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters
  .buildUpon()
  .setMaxAudioChannelCount(2)
  .build()

Java

exoPlayer.setTrackSelectionParameters(
  exoPlayer.getTrackSelectionParameters()
    .buildUpon()
    .setMaxAudioChannelCount(2)
    .build()
);

Alterar os parâmetros de seleção de faixa durante a reprodução pode causar uma interrupção da reprodução. Mais informações sobre como ajustar a faixa do player parâmetros de seleção está disponível na seleção de faixas dos documentos do ExoPlayer.

Comportamento padrão de espacialização

O comportamento de espacialização padrão no Android inclui os seguintes comportamentos que podem ser personalizados por OEMs:

  • Somente o conteúdo multicanal é espacial, não o conteúdo estéreo. Se você não usa o ExoPlayer, dependendo do formato do seu aplicativo conteúdo de áudio, pode ser necessário configurar o número máximo de canais que pode ser saída por um decodificador de áudio para um grande número. Isso garante que o decodificador de áudio gera PCM multicanal para que a plataforma espacialize.

    Kotlin

    val mediaFormat = MediaFormat()
    mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)
    

    Java

    MediaFormat mediaFormat = new MediaFormat();
    mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);
    

    Para conferir um exemplo em ação, consulte o MediaCodecAudioRenderer.java do ExoPlayer. Desativar a espacialização, independente do OEM personalização, consulte Como desativar o áudio espacial.

  • AudioAttributes: o áudio está qualificado para espacialização se o usage está definido como USAGE_MEDIA. ou USAGE_GAME.

  • AudioFormat: use uma máscara de canal que contenha pelo menos o AudioFormat.CHANNEL_OUT_QUAD (frontal esquerdo, frontal direito, traseira e traseira) para o áudio elegíveis para a espacialização. No exemplo abaixo, usamos AudioFormat.CHANNEL_OUT_5POINT1 para uma faixa de áudio 5.1. Para uma faixa de áudio estéreo, use AudioFormat.CHANNEL_OUT_STEREO.

    Se você estiver usando a Media3, use o Util.getAudioTrackChannelConfig(int channelCount). para converter uma contagem de canais em uma máscara de canais.

    Além disso, defina a codificação como AudioFormat.ENCODING_PCM_16BIT se você configurou o decodificador para gerar PCM multicanal.

    Kotlin

    val audioFormat = AudioFormat.Builder()
      .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
      .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
      .build()
    

    Java

    AudioFormat audioFormat = new AudioFormat.Builder()
      .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
      .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
      .build();
    

Testar áudio espacial

Verifique se o áudio espacial está ativado no dispositivo de teste:

  • Para fones de ouvido com fio, acesse Configurações do sistema > Som e vibração > Espacial áudio.
  • Para fones de ouvido sem fio, acesse Configurações do sistema > Dispositivos conectados > Ícone de engrenagem para seu dispositivo sem fio > Áudio espacial.

Para verificar a disponibilidade do áudio espacial no trajeto atual, execute o adb shell dumpsys audio no dispositivo. Você verá o seguinte: na saída enquanto a reprodução estiver ativa:

Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)