Неверное воспроизведение 24-битного звука на Java - PullRequest
2 голосов
/ 11 июня 2010

Я использую звуковой API javax для реализации простой программы воспроизведения с консоли на основе http://www.jsresources.org/examples/AudioPlayer.html.

Протестировав его с использованием файла 24-битного линейного изменения (каждый сэмпл является последним сэмплом плюс 1 во всем 24-битном диапазоне), становится очевидным, что во время воспроизведения происходит нечто странное. Записанный вывод не является содержимым файла (у меня есть цифровая петля для проверки этого).

Кажется, что это неправильно истолковывает сэмплы, из-за чего левый канал выглядит так, как будто к нему применен какой-то коэффициент усиления, а правый канал выглядит так, как будто он ослаблен.

Я изучил необходимость настройки элементов управления PAN и BALANCE, но они недоступны, и я проверил настройки звуковой системы windows xp. Любая другая форма воспроизведения этого файла рампы в порядке.

Если я выполню тот же тест с 16-битным файлом, он будет выполнен правильно, без повреждения потока.

Так кто-нибудь имеет представление, почему Java Sound API модифицирует мой аудиопоток?

1 Ответ

3 голосов
/ 27 сентября 2012

Проблема воспроизведения Java 24-битного звука на самом деле связана с Microsoft DirectSound и / или его реализацией в Windows Java Sound. При использовании Linux с Java Sound и ALSA 24-битное аудио воспроизводится идеально (запись выходных данных показывает немного идеальное совпадение с входным файлом).

Чтобы понять, почему это не работает в Windows, вы можете запросить поддерживаемые аудиоформаты выходной строки, которые вы хотите воспроизвести в Java, используя (где lineInfo - это Line.Info выходной строки):

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

с последующим циклом поддерживаемых форматов:

for (AudioFormat lineFormat : dataLineInfo.getFormats())

Для Windows я получаю что-то вроде:

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

Который не поддерживает 24 бит в качестве поддерживаемого формата. Но в Windows XP он по-прежнему позволяет воспроизводить 24-битное аудио, но, по-видимому, обрабатывается до 16 бит с помощью Java / DirectSound, а затем восстанавливается до 24 бит с помощью звуковой карты. Следовательно, почему вывод данных неверен. В Windows 7 я обнаружил, что он просто отказывался воспроизводить 24-битное аудио (возможно, более разумно, если все равно все, что он собирается сделать, - это падение до 16-битного).

Для Linux (Fedora 17) я получаю что-то вроде (с точно такой же звуковой картой, ESI Juli @, на том же ПК):

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, 

Который поддерживает 24 бита в качестве поддерживаемого формата. И как таковая, она работает как положено и без нежелательной дополнительной обработки.

Таким образом, кажется, что 24-битное воспроизведение работает с Java Sound, при условии, что его реализация зависит от конкретной ОС (и, возможно, от устройства, но я не нашел никаких изменений между устройствами, которые я до сих пор пробовал) перечисляет это как поддерживаемый аудиоформат. Мои тесты показывают, что Linux (ALSA) действительно поддерживает это, тогда как Windows (DirectSound) не поддерживает.

Надеюсь, это кому-нибудь пригодится; Я не мог найти что-то еще об этом в Интернете, поэтому я написал на такой старый вопрос.

Ниже был мой первоначальный вопрос, на который я только что ответил (я оставил его для справки):


Я не уверен, что это правильная процедура, чтобы поднять старые вопросы, но после прочтения FAQ кажется, что это предпочтительнее, чем публиковать новые. Я уже разместил эту проблему в нескольких других местах (включая форум Oracle Java Sound), но пока без ответов, и этот вопрос звучит точно так же, как и проблема, с которой я столкнулся:

Я использую Java Sound для воспроизведения аудиофайлов (в стандартном формате PCM), но я заметил, что он некорректно воспроизводит 24-битные данные, поскольку данные, выводимые с звуковой карты, не совпадают с данными из файла , Он отлично работает для 16-битных (и даже 8-битных) аудиоданных, но не для 24-битных (и предположительно 32-битных, но у меня нет реальных 32-битных аудиофайлов для тестирования) файлов. Из вывода видно, что Java Sound выполняет некоторую дополнительную (и нежелательную) обработку аудиоданных перед передачей их на звуковую карту. Я могу с уверенностью сказать, что это делает Java Sound, потому что, если я запускаю тот же тест с использованием ASIO для воспроизведения файла, проблем не возникает, и данные совпадают, как и ожидалось.

Немного больше информации о настройке: - Java JRE последняя версия (7u7, я думаю), работающая на Windows XP SP3. - Звук воспроизводился с помощью примера AudioPlayer (как упомянуто в основном вопросе) на jsresources.org (сначала я попытался использовать свой собственный код, но переключился на это, если допустил ошибку, результаты одинаковы для обоих). - Звук воспроизводится на звуковой карте M-Audio через цифровой (S / PDIF) выход, который напрямую подключен (через внешний кабель) к цифровому входу на звуковой карте Lynx (в том же ПК), где он находится. записано (с помощью Sony Sound Forge). - Записанный файл затем сравнивается с входным волновым файлом.

Для теста используются четыре разных входных файла Wave (сгенерированных из одного исходного файла): - 16 бит, 44,1 кГц; - 16 бит, 48 кГц; - 24 бита, 44,1 кГц; - 24 бита, 48 кГц.

Используя ASIO для воспроизведения тестовых файлов, все четыре файла выдали правильный вывод (записанные данные соответствуют байту данных входного файла Wave после выравнивания начальных позиций на время между нажатием записи и нажатием воспроизведения) .

Используя Java для воспроизведения тестовых файлов, 16-битные (44,1 кГц и 48 кГц) дают правильный выходной сигнал, тогда как 24-битные (44,1 кГц и 48 кГц) - нет. Не только это, но и то, как неправильный вывод является непоследовательным (если я запускаю тест два раза, он каждый раз выдает различный вывод, ни один из которых не приближается к совпадению с входным файлом). Так что не только звук Java неправильно воспроизводит 24-битные файлы, но и каждый раз по-разному. Если это поможет, я могу сделать снимки экрана с выводом звука Java по сравнению с входным файлом (ожидаемый вывод).

Самый простой способ воспроизвести это - использовать приведенный выше пример AudioPlayer, воспроизвести 24-битный файл и записать вывод (если у вас есть только одна звуковая карта, возможно, можно использовать ее микшер для соответствующей маршрутизации данных, чтобы это должно быть захвачено). Хотя это не так уж и неправильно, что я могу услышать какую-либо разницу, это в некоторой степени побеждает назначение звука высокого разрешения, если данные изменяются каким-то неожиданным образом (вы рискуете потерять любые выгоды от использования 24-битной над 16-битной, хотя на самом деле не хочу вдаваться в этот аргумент).

Итак, чтобы сформулировать это как вопрос - как я могу заставить Java Sound правильно воспроизводить 24-битный звук?

...