O Áudio Espacial é uma experiência de áudio imersiva que coloca os usuários no centro da ação, tornando o som do conteúdo mais realista. O som é "espacializado" para criar um efeito de vários alto-falantes, semelhante a uma configuração de som surround, mas usando fones de ouvido.
Por exemplo, em um filme, o som de um carro pode começar atrás do usuário, avançar e desaparecer à distância. Em um chat por vídeo, as vozes podem ser separadas e colocadas ao redor do usuário, facilitando a identificação de quem está falando.
Se o conteúdo usar um formato de áudio compatível, você poderá adicionar o áudio espacial ao 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 verdadeiras para que o dispositivo produza áudio espacializado:
| Critérios | Cheque |
|---|---|
| O dispositivo oferece suporte à 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() é true |
| A espacialização está ativada? | isEnabled() é true |
| Uma faixa de áudio com os parâmetros especificados pode ser espacializada? | canBeSpatialized() é 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 se estiver desativada no dispositivo de saída de áudio.
Rastreamento da Cabeça
Com fones de ouvido compatíveis, a plataforma pode ajustar a espacialização do áudio com base na posição da cabeça do usuário. Para verificar se um rastreador de 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 especificadas pode ser espacializado com o roteamento do dispositivo de saída atual. Esse método usa um AudioAttributes
e um AudioFormat, ambos
descritos com mais detalhes abaixo.
AudioAttributes
Um AudioAttributes objeto
descreve o uso de um
stream de áudio (por exemplo, áudio de jogo
ou mídia padrão),
além dos comportamentos de reprodução e do tipo de conteúdo.
Ao chamar canBeSpatialized(), use a mesma
AudioAttributes instância definida para o Player. Por exemplo, se
você estiver usando a biblioteca Media3 do Jetpack e não tiver personalizado os
AudioAttributes, use AudioAttributes.DEFAULT.
Como desativar o Áudio Espacial
Para indicar que o 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 a espacialização completamente chamando
setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER).
AudioFormat
Um AudioFormat objeto descreve
detalhes sobre o formato e a configuração de canal de uma faixa de áudio.
Ao instanciar o AudioFormat para transmitir ao canBeSpatialized(),
defina a codificação
como a mesma do formato de saída esperado do decodificador. Você também precisa definir
uma máscara de canal
que corresponda à configuração de canal do 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 rastreador de cabeça,
chame Spatializer.addOnHeadTrackerAvailableListener().
Isso 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 momento, você pode atualizar a lógica de seleção de faixas do player para corresponder aos novos recursos do dispositivo. Para detalhes sobre
o comportamento de seleção de faixas do ExoPlayer, consulte a seção ExoPlayer e Áudio Espacial.
ExoPlayer e Áudio Espacial
As versões recentes do ExoPlayer facilitam a adoção do Áudio Espacial. Se você usar
a biblioteca independente do ExoPlayer (nome do pacote com.google.android.exoplayer2),
a versão 2.17 vai configurar a plataforma para produzir áudio espacializado, e a versão
2.18 vai introduzir restrições de contagem de canais de áudio.
Se você usar o módulo do ExoPlayer da biblioteca Media3 (nome do pacote
androidx.media3), as versões 1.0.0-beta01
e mais recentes vão incluir essas mesmas atualizações.
Depois de atualizar a dependência do ExoPlayer para a versão mais recente, o app só 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 vai acionar uma nova seleção de faixas para escolher uma faixa de áudio que corresponda às propriedades atuais. Essa nova seleção de faixas pode causar um breve período de rebuffer.
Para desativar as restrições de contagem de canais de áudio, defina os parâmetros de seleção de faixas no player, conforme 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, é possível atualizar os parâmetros de um seletor de faixas atual para desativar as restrições 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árias faixas de áudio, o ExoPlayer vai selecionar inicialmente a faixa com o maior número de canais e que pode ser reproduzida no dispositivo. Por exemplo, se o conteúdo tiver uma faixa de áudio multicanal e uma faixa de áudio estéreo, e o dispositivo oferecer suporte à reprodução das duas, o ExoPlayer vai selecionar a faixa multicanal. Consulte a seção Seleção de faixa de áudio para detalhes sobre como personalizar esse comportamento.
Seleção de faixa de áudio
Quando o comportamento de restrição de contagem de canais de áudio do ExoPlayer está desativado, o ExoPlayer não seleciona automaticamente uma faixa de áudio que corresponda às propriedades do espacializador do dispositivo. Em vez disso, é possível personalizar a lógica de seleção de faixas do ExoPlayer definindo parâmetros de seleção de faixas antes ou durante a reprodução. Por padrão, o ExoPlayer seleciona faixas de áudio iguais à faixa inicial em relação ao tipo MIME (codificação), contagem de canais e taxa de amostragem.
Como mudar os parâmetros de seleção de faixas
Para mudar os parâmetros de seleção de faixas do ExoPlayer, use
Player.setTrackSelectionParameters().
Da mesma forma, é possível receber 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() );
A mudança dos parâmetros de seleção de faixas no meio da reprodução pode causar uma interrupção. Mais informações sobre como ajustar os parâmetros de seleção de faixas do player estão disponíveis na seção de seleção de faixas da documentação do ExoPlayer.
Comportamento de espacialização padrã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 é espacializado, não o conteúdo estéreo. Se você não usar o ExoPlayer, dependendo do formato do conteúdo de áudio multicanal, talvez seja necessário configurar o número máximo de canais que podem ser produzidos por um decodificador de áudio para um número grande. Isso garante que o decodificador de áudio produza PCM multicanal para a plataforma espacializar.
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 um exemplo em ação, consulte
MediaCodecAudioRenderer.javado ExoPlayer. Para desativar a espacialização, independentemente da personalização do OEM, consulte Como desativar o Áudio Espacial.AudioAttributes: o áudio é qualificado para espacialização se ousageestiver definido comoUSAGE_MEDIAouUSAGE_GAME.AudioFormat: use uma máscara de canal que contenha pelo menos os canaisAudioFormat.CHANNEL_OUT_QUAD(frontal esquerdo, frontal direito, traseiro esquerdo e traseiro direito) para que o áudio seja qualificado para espacialização. No exemplo abaixo, usamosAudioFormat.CHANNEL_OUT_5POINT1para uma faixa de áudio 5.1. Para uma faixa de áudio estéreo, useAudioFormat.CHANNEL_OUT_STEREO.Se você estiver usando o Media3, poderá usar
Util.getAudioTrackChannelConfig(int channelCount)para converter uma contagem de canais em uma máscara de canal.Além disso, defina a codificação como
AudioFormat.ENCODING_PCM_16BITse você tiver configurado o decodificador para produzir 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 o Á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 > Áudio Espacial.
- Para fones de ouvido sem fio, acesse Configurações do sistema > Dispositivos conectados > Ícone de engrenagem do dispositivo sem fio > Áudio Espacial.
Para verificar a disponibilidade do Áudio Espacial para o roteamento atual, execute o comando adb shell dumpsys audio no dispositivo. Você vai encontrar os seguintes parâmetros na saída enquanto a reprodução estiver ativa:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)