2

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

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

它似乎以某种方式误解了样本,导致左声道看起来像是应用了一些增益,而右声道看起来像是被衰减了。

我查看了是否需要设置 PAN 和 BALANCE 控件,但这些控件不可用,并且我检查了 windows xp 声音系统设置。此渐变文件的任何其他形式的播放都可以。

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

那么有人知道为什么 Java Sound API 会修改我的音频流吗?

4

1 回答 1

4

24 位音频的 Java 播放问题实际上与 Microsoft DirectSound 和/或它的 Windows Java Sound 实现有关。使用带有 Java Sound 和 ALSA 的 Linux,可以完美播放 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,前提是它的特定于操作系统的(也许是特定于设备的,但到目前为止我还没有发现我尝试过的设备之间有任何变化)实现将它列为支持的音频格式。我的测试表明 Linux (ALSA) 确实支持它,而 Windows (DirectSound) 不支持。

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

以下是我刚刚回答的最初问题(我已将其留作参考):


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

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

有关设置的更多信息: - Java JRE 最新版本(我认为是 7u7),在 Windows XP SP3 上运行。- 使用 jsresources.org 上的 AudioPlayer 示例(如主要问题中所述)播放的声音(我首先尝试使用自己的代码,但如果我犯了错误,则切换到此,两者的结果相同)。- 通过数字 (S/PDIF) 输出在 M-Audio 声卡上播放音频,该输出直接(通过外部电缆)连接到 Lynx 声卡(在同一台 PC)上的数字输入,它位于录制(使用 Sony Sound Forge)。- 然后将录制的文件与输入的 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 位可能会失去任何收益,但我真的不想在这里讨论那个论点)。

因此,将其表述为一个问题 - 如何让 Java Sound 正确播放 24 位音频?

于 2012-09-27T14:46:58.647 回答