Ubuntu16.4,Java,WAV文件播放

Ubuntu 16.4, Java, WAV file playback

这是一件奇怪的事情。我正在尝试通过 Java AudioSystem 和 AudioSystem.getClip() 播放一些声音。文件都是"PCM_SIGNED, 22.050.0 Hz, 16 bit, mono, 2 bytes/frame, little endian".

在几个 Ubuntu 16.4 LTS Linux 盒子上,这种格式被 PulseAudio 拒绝 Invalid Format Exception,因为唯一接受的格式似乎是 "PCM_SIGNED, unknown sample rate, 16 bit, stereo, 4 bytes/frame, big endian".

我已经尝试重新采样我的 WAV 以匹配这个奇怪的约束,但无济于事。 AudioSystem.getAudioInputStream()

甚至不再接受这些

不用说,同样适用于 Mac OS 和 Windows。而且使用sox库和play file.wav

播放这些文件也没有问题

好的,解决了。

通常如果有人问,如何使用Java播放WAV,这是最常见的答案:

AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(DragonflyApp.class.getResource("/resources/" + soundFile));
clip = AudioSystem.getClip();
clip.addLineListener(e -> {
    if (e.getType() == LineEvent.Type.STOP) {
        // Do something on end of playback
    }
});
clip.open(audioInputStream);
clip.start();

不幸的是,在某些 Linux 系统上,这最终会导致 "Invalid Format" 异常,由 PulseAudio 抛出,它声称无法播放最简单的 WAV 文件(见上文)。

解决方法是在 Linux 下使用此序列。它通常也适用于 MacOS,但最终的 "STOP" 指示来得很晚(播放结束后大约 5 秒),所以我在这里进行条件执行:

这适用于 Linux(至少在 Ubuntu 16.04 上),带有剪辑,以前被 PulseAudio 拒绝:

DataPusher datapusher = null;
DataLine.Info lineinfo = null;
SourceDataLine sourcedataline = null;
lineinfo = new DataLine.Info(SourceDataLine.class, audioInputStream.getFormat());
if (!(AudioSystem.isLineSupported(lineinfo))) {
    return;
}
sourcedataline = (SourceDataLine) AudioSystem.getLine(lineinfo);
sourcedataline.addLineListener(e -> {
    if (e.getType() == LineEvent.Type.STOP) {
        // Do something on end of playback
    }
});
datapusher = new DataPusher(sourcedataline, audioInputStream);
datapusher.start();

有条件地使用两个代码片段:

if (System.getProperty("os.name").equals("Mac OS X")) {
    // The clip solution
}
else {
    // The datapusher solution
}

希望,这可以帮助其他人,他们也会遇到这个问题。