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 uma configuração de som surround, mas com 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 se afastando muito à 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
:
val spatializer = audioManager.spatializer
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 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() está true |
É possível espacializar uma faixa de áudio com os parâmetros fornecidos? | 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 especificadas pode ser espacializado com o
encaminhamento atual do dispositivo de saída. 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 a mesma
instância AudioAttributes
definida para o Player
. Por exemplo, se
você estiver usando a biblioteca Jetpack Media3 e não tiver personalizado o
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 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. Também é necessário 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()
.
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 espacial está disponível para o novo
roteamento de saída de áudio. Nesse ponto, você pode atualizar a lógica de seleção de faixas
do player para corresponder aos novos recursos do dispositivo. Para detalhes sobre
Comportamento de seleção de faixa 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 ExoPlayer independente (nome do pacote com.google.android.exoplayer2
),
a versão 2.17 vai configurar a plataforma para gerar áudio espacializado, e a versão
2.18 vai introduzir restrições de contagem de canais de áudio.
Se você usar o módulo 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
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 causar um curto
período de rebufferização.
Para desativar as restrições de contagem de canais de áudio, defina os parâmetros de seleção de faixa no player, conforme mostrado abaixo:
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
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:
val trackSelector = DefaultTrackSelector(context) ... trackSelector.parameters = trackSelector.buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
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 de ambos, o ExoPlayer vai selecionar a faixa multicanal. Consulte a Seleção de faixa de áudio para saber como personalizar esse comportamento.
Seleção de faixa de áudio
Quando o comportamento das restrições de contagem de canais de áudio do ExoPlayer é desativado, ele não seleciona automaticamente uma faixa de áudio que corresponda às propriedades do spatializer do dispositivo. Em vez disso, você pode personalizar a lógica de seleção de faixas do ExoPlayer definindo parâmetros de seleção 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:
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
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 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 usa 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 gerados por um decodificador de áudio para um número grande. Isso garante que o decodificador de áudio gere PCM multicanal para que a plataforma seja espacializada.
val mediaFormat = MediaFormat() mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)
MediaFormat mediaFormat = new MediaFormat(); mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);
Para conferir um exemplo em ação, consulte
MediaCodecAudioRenderer.java
do ExoPlayer. Para desativar a espacialização, independente da personalização do OEM, consulte Como desativar o áudio espacial.AudioAttributes
: o áudio está qualificado para espacialização se ousage
está definido comoUSAGE_MEDIA
ouUSAGE_GAME
.AudioFormat
: use uma máscara de canal que contenha pelo menos oAudioFormat.CHANNEL_OUT_QUAD
(frontal esquerdo, frontal direito, traseira e traseira) para o áudio elegíveis para a espacialização. No exemplo abaixo, usamosAudioFormat.CHANNEL_OUT_5POINT1
para uma faixa de áudio 5.1. Para uma faixa de áudio estéreo, useAudioFormat.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ê tiver configurado o decodificador para gerar PCM multicanal.val audioFormat = AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build()
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. Os seguintes
parâmetros vão aparecer na saída enquanto a reprodução estiver ativa:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)