java - Java播放的24位音频不正确

标签 java audio 24-bit

我正在使用javax声音API来实现基于http://www.jsresources.org/examples/AudioPlayer.html的简单控制台回放程序。

使用24位渐变文件对其进行测试(每个样本是最后一个样本,再加上整个24位范围内的1个样本),很明显在播放过程中发生了一些奇怪的事情。记录的输出不是文件的内容(我有一个数字环回来验证这一点)。

似乎是以某种方式误解了样本,从而导致左声道看起来好像已经对其施加了一些增益,而右声道看起来好像正在被衰减。

我调查了PAN和BALANCE控件是否需要设置,但是这些设置不可用,并且检查了Windows XP声音系统设置。可以使用此斜坡文件的任何其他播放形式。

如果我对16位文件执行相同的测试,则它可以正确执行而不会损坏流。

那么,有谁知道Java Sound API为什么要修改我的音频流?

最佳答案

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位音频,但是大概是由Java / DirectSound处理到16位,然后由声卡恢复到24位。因此,为什么数据输出不正确。在Windows 7中,我发现它只是拒绝播放24位音频(如果它要做的只是将其降低到16位,则可能更明智)。

对于Linux(Fedora 17),我得到类似的信息(在同一台PC上具有完全相同的声卡,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一起使用,但前提是特定于OS的(可能是特定于设备的,但到目前为止我还没有发现设备之间的任何差异)将其列出为支持的音频格式。我的测试表明Linux(ALSA)确实支持它,而Windows(DirectSound)不支持。

希望这对某人有帮助;我在网上找不到关于此的其他信息,这就是为什么我发布了这么一个老问题。

以下是我最初的问题,我已经回答了(我留作引用):

我不确定这是否是解决旧问题的正确方法,但是从阅读FAQ来看,这似乎比发布新问题更为可取。我已经在其他几个地方(包括Oracle Java Sound论坛)发布了此问题,但是到目前为止没有任何响应,这个问题听起来与我遇到的问题完全相同:

我正在使用Java Sound播放音频文件(标准PCM格式),但是我注意到它不能正确播放24位数据,因为声卡输出的数据与文件输入不匹配。它适用于16位(甚至8位)音频数据,但不适用于24位(大概32位,但是我没有真正的32位音频文件要测试)文件。从输出中可以看出,Java Sound在将音频数据传递到声卡之前,正在对音频数据进行一些额外(和不需要的)处理。我可以肯定地说这是Java Sound的原因,因为如果我使用ASIO运行相同的测试来播放文件,那么就没有问题,并且数据符合预期。

有关设置的更多信息:
-在Windows XP SP3上运行的Java JRE最新版本(我认为是7u7)。
-使用jsresources.org上的AudioPlayer示例(如主要问题中所述)播放声音(我首先尝试使用自己的代码,但是如果我弄错了,请切换到该代码,两者的结果相同)。
-音频通过数字(S / PDIF)输出在M-Audio声卡上播放,该输出直接(通过外部电缆)连接到Lynx声卡(在同一台PC上)的数字输入。录制(使用Sony Sound Forge)。
-然后将记录的文件与输入的Wave文件进行比较。

对于测试,使用了四个不同的输入Wave文件(从相同的源文件生成):
-16位,44.1 kHz;
-16位,48 kHz;
-24位,44.1 kHz;
-24位,48 kHz。

使用ASIO播放测试文件时,所有四个文件均产生正确的输出(在对齐按记录和按播放之间的时间的起始位置之后,记录的数据逐字节与输入的Wave文件数据相匹配)。

使用Java播放测试文件时,16位(44.1 kHz和48 kHz)均产生正确的输出,而24位(44.1 kHz和48 kHz)均不正确。不仅如此,而且输出错误的方式也是不一致的(如果我运行两次测试,则每次都会产生不同的输出,而这两个输出都不接近匹配输入文件)。因此,Java声音不仅会错误地播放24位文件,而且每次都会以不同的方式错误地播放。如果有帮助,我可以将Java声音输出的截图与输入文件(预期的输出)进行比较。

最简单的方法是使用上面提到的AudioPlayer示例,播放一个24位文件并记录输出(如果您只有一个声卡,则可以使用其混音器适当地路由数据以使其成为捕获)。虽然我听不到任何区别还不够错,但是如果以某种意外的方式更改数据(确实冒着因使用24位超过16位而失去任何 yield 的风险),那的确会破坏高分辨率音频的目的。并不想在这里进入那个论点)。

因此,用一个问题来回答这个问题-我如何才能使Java Sound正确播放24位音频?

关于java - Java播放的24位音频不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3024622/

相关文章:

java - 由于可选对象的属性也是可选的,如何优化 if-else 语句?

java - 具有动态参数的 Spring-Boot @Bean 生产者

algorithm - 改变声音文件的速度

c - bmp 24 位文件格式上的蓝色 channel

java - 尽管不在任何框架或 iframe 或窗口内,但无法单击链接

java - 如何以编程方式在Android中制作水平线

java - 尝试在 JFrame 上播放声音时出现 AudioClip 问题

iphone - 录制的音频文件

c++ - 如何让 CMFCToolBar 识别图像 mask ?

c - 如何在 C 中将 RGB565 转换为 HSL 颜色