Проблема воспроизведения 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-битный звук?