Pergunta

Estou usando a API javax sound para implementar um programa simples de reprodução de console baseado em http://www.jsresources.org/examples/AudioPlayer.html.

Depois de testá-lo usando um arquivo de rampa de 24 bits (cada amostra é a última amostra mais 1 em toda a faixa de 24 bits), fica evidente que algo estranho está acontecendo durante a reprodução.A saída gravada não é o conteúdo do arquivo (tenho um loopback digital para verificar isso).

Parece estar interpretando mal as amostras de alguma forma que faz com que o canal esquerdo pareça estar recebendo algum ganho aplicado a ele e o canal direito pareça estar sendo atenuado.

Verifiquei se os controles PAN e BALANCE precisam ser configurados, mas eles não estão disponíveis e verifiquei as configurações do sistema de som do Windows XP.Qualquer outra forma de reprodução deste arquivo de rampa é adequada.

Se eu fizer o mesmo teste com um arquivo de 16 bits, ele funcionará corretamente, sem corrupção do fluxo.

Alguém tem alguma ideia de por que a API Java Sound está modificando meu fluxo de áudio?

Foi útil?

Solução

O problema com a reprodução Java de áudio de 24 bits está, na verdade, no Microsoft DirectSound e/ou na implementação do Windows Java Sound.Usando Linux com Java Sound e ALSA, o áudio de 24 bits é reproduzido perfeitamente (a gravação da saída mostra uma correspondência perfeita com o arquivo de entrada).

Para ver por que não funciona no Windows, você pode consultar os formatos de áudio suportados da linha de saída que deseja reproduzir em Java usando (onde lineInfo é o Line.Info da linha de saída):

DataLine.Info dataLineInfo = (DataLine.Info) lineInfo;

e, em seguida, percorrer os formatos suportados:

for (AudioFormat lineFormat : dataLineInfo.getFormats())

Para Windows, recebo algo como:

Format #1: PCM_UNSIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame,
Format #2: PCM_SIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame,
Format #3: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, little-endian
Format #4: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, big-endian
Format #5: PCM_UNSIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame,
Format #6: PCM_SIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame,
Format #7: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, little-endian
Format #8: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian

Que não tem 24 bits como formato suportado.Mas no Windows XP ainda me permite reproduzir áudio de 24 bits, mas presumivelmente processado até 16 bits por Java/DirectSound e depois voltar para 24 bits pela placa de som.Daí porque a saída de dados está incorreta.No Windows 7, descobri que ele simplesmente se recusava a reproduzir áudio de 24 bits (provavelmente mais sensato se tudo o que fosse necessário fosse cair para 16 bits, de qualquer maneira).

Para Linux (Fedora 17) recebo algo como (com exatamente a mesma placa de som, um ESI Juli@, no mesmo PC):

Format #1: PCM_SIGNED unknown sample rate, 32 bit, mono, 4 bytes/frame, little-endian
Format #2: PCM_SIGNED unknown sample rate, 32 bit, mono, 4 bytes/frame, big-endian
Format #3: PCM_SIGNED unknown sample rate, 32 bit, stereo, 8 bytes/frame, little-endian
Format #4: PCM_SIGNED unknown sample rate, 32 bit, stereo, 8 bytes/frame, big-endian
Format #5: PCM_SIGNED unknown sample rate, 24 bit, mono, 4 bytes/frame, little-endian
Format #6: PCM_SIGNED unknown sample rate, 24 bit, mono, 4 bytes/frame, big-endian
Format #7: PCM_SIGNED unknown sample rate, 24 bit, stereo, 8 bytes/frame, little-endian
Format #8: PCM_SIGNED unknown sample rate, 24 bit, stereo, 8 bytes/frame, big-endian
Format #9: PCM_SIGNED unknown sample rate, 24 bit, mono, 3 bytes/frame, little-endian
Format #10: PCM_SIGNED unknown sample rate, 24 bit, mono, 3 bytes/frame, big-endian
Format #11: PCM_SIGNED unknown sample rate, 24 bit, stereo, 6 bytes/frame, little-endian
Format #12: PCM_SIGNED unknown sample rate, 24 bit, stereo, 6 bytes/frame, big-endian
Format #13: PCM_SIGNED unknown sample rate, 20 bit, mono, 3 bytes/frame, little-endian
Format #14: PCM_SIGNED unknown sample rate, 20 bit, mono, 3 bytes/frame, big-endian
Format #15: PCM_SIGNED unknown sample rate, 20 bit, stereo, 6 bytes/frame, little-endian
Format #16: PCM_SIGNED unknown sample rate, 20 bit, stereo, 6 bytes/frame, big-endian
Format #17: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, little-endian
Format #18: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, big-endian
Format #19: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, little-endian
Format #20: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian
Format #21: PCM_SIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame,
Format #22: PCM_UNSIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame,
Format #23: PCM_SIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame,
Format #24: PCM_UNSIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 

Que tem 24 bits como formato suportado.E, como tal, funciona conforme o esperado e sem o processamento extra indesejado.

Portanto, parece que a reprodução de 24 bits funciona com Java Sound, desde que a implementação específica do sistema operacional (e talvez específica do dispositivo, mas não encontrei nenhuma variação entre os dispositivos que tentei até agora) liste-o como um formato de áudio compatível.Meus testes sugerem que o Linux (ALSA) oferece suporte, enquanto o Windows (DirectSound) não.

Espero que isto ajude alguém;Não consegui encontrar mais nada sobre isso on-line e é por isso que postei uma pergunta tão antiga.

A seguir foi minha pergunta inicial, que acabei de responder (deixei para referência):


Não tenho certeza se este é o procedimento correto para resolver questões antigas, mas ao ler o FAQ, parece que é preferível postar uma nova.Já postei esse problema em alguns outros lugares (incluindo o fórum Oracle Java Sound), mas sem respostas até agora e esta pergunta parece exatamente igual ao problema que estou tendo:

Estou usando o Java Sound para reproduzir arquivos de áudio (no formato PCM padrão), mas percebi que ele não reproduz corretamente dados de 24 bits, pois a saída de dados da placa de som não corresponde à entrada do arquivo.Funciona bem para dados de áudio de 16 bits (e até 8 bits), mas não para arquivos de 24 bits (e presumivelmente 32 bits, mas não tenho arquivos de áudio reais de 32 bits para testar).A partir da saída, parece que o Java Sound está realizando algum processamento extra (e indesejado) nos dados de áudio antes de passá-los para a placa de som.Posso dizer com certeza que é o Java Sound que está fazendo isso porque se eu executar o mesmo teste usando ASIO para reproduzir o arquivo, não haverá problema e os dados corresponderão conforme o esperado.

Um pouco mais de informações sobre a configuração:- Versão mais recente do Java JRE (acho 7u7), rodando no Windows XP SP3.- Som reproduzido usando o exemplo do AudioPlayer (conforme mencionado na pergunta principal) em jsresources.org (primeiro tentei usar meu próprio código, mas mudei para este caso tivesse cometido um erro, os resultados são os mesmos em ambos).- O áudio é reproduzido em uma placa de som M-Audio através da saída digital (S/PDIF), que está diretamente conectada (através de um cabo externo) a uma entrada digital em uma placa de som Lynx (no mesmo PC), onde é gravado (usando Sony Sound Forge).- O arquivo gravado é então comparado com o arquivo Wave de entrada.

Para o teste, são usados ​​quatro arquivos Wave de entrada diferentes (gerados a partir do mesmo arquivo de origem):- 16 bits, 44,1 kHz;- 16 bits, 48kHz;- 24 bits, 44,1 kHz;- 24 bits, 48 ​​kHz.

Usando ASIO para reproduzir os arquivos de teste, todos os quatro arquivos produziram a saída correta (os dados gravados correspondem aos dados do arquivo Wave de entrada byte por byte, após alinhar as posições iniciais para o tempo entre pressionar gravar e pressionar reproduzir).

Usando Java para reproduzir os arquivos de teste, os de 16 bits (44,1 kHz e 48 kHz) produzem a saída correta, enquanto os de 24 bits (44,1 kHz e 48 kHz) não.Não apenas isso, mas a forma como a saída está incorreta é inconsistente (se eu executar o teste duas vezes, ele produzirá uma saída diferente a cada vez, nenhuma das quais chegando perto de corresponder ao arquivo de entrada).Portanto, o som Java não apenas reproduz os arquivos de 24 bits de maneira errada, mas também de uma maneira diferente a cada vez.Se ajudar, posso fazer capturas de tela da saída de som Java em comparação com o arquivo de entrada (saída esperada).

A maneira mais fácil de reproduzir isso seria usar o exemplo do AudioPlayer mencionado acima, reproduzir um arquivo de 24 bits e gravar a saída (se você tiver apenas uma placa de som, talvez seja possível usar seu mixer para rotear os dados adequadamente para permitir que sejam capturado).Embora não seja errado o suficiente para que eu possa ouvir qualquer diferença, isso anula o propósito do áudio de alta resolução se os dados estiverem sendo alterados de alguma forma inesperada (você corre o risco de perder quaisquer ganhos ao usar 24 bits em vez de 16 bits, embora eu realmente não quero entrar nessa discussão aqui).

Então, para formular isso como uma pergunta - como posso fazer com que o Java Sound reproduza áudio de 24 bits corretamente?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top