【发布时间】:2012-12-10 01:57:01
【问题描述】:
有没有一个好的方法可以在 Java 中获得体面、可靠的数字采样声音播放?
我的请求列表很短:
- 从 .wav 文件之类的文件加载内存中的数字化样本(例如,从 jar 中捆绑的资源)
- 以非阻塞方式播放它们
- 当我同时播放多个样本并且它们在时间上相交时,它们应该得到适当的混合
如果有以下内容会很好,但事实上我可以没有它:
- 从 .ogg 或类似的压缩格式播放(显然没有在 Java 中实现占用大量 CPU 的解码器)
- 在播放同一样本时再次播放它不应停止给定样本的先前播放,但应开始第二个副本并与第一个正确混合
我尝试了臭名昭著的Java Sound API,但发现它完全不可靠,似乎无法满足我最小的愿望清单。我遇到的问题:
在带有 ALSA dmix (OpenJDK 6) 的 Linux 上,让任何其他应用程序在初始化 Java Sound API 时使用音频只会使 Java 应用程序中的所有声音消失,而不会出现任何错误/警告。
-
在 Linux (OpenJDK 6) 上,列出
MixerInfos 并尝试使用其中任何一个获取Clip对象会在尝试加载 wav 文件时引发以下异常:java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian因此,
AudioSystem.getClip(anySortOfMixer)似乎根本不起作用。只有AudioSystem.getClip()有效。 -
使用
李>Clip加载具有不同采样率/位/格式的文件失败并显示LineUnavailableException。似乎第一次调用clip.open将声音系统设置为特定的声音选项,然后调用以加载采样率略有不同的文件(例如,第一个是 44100,第二个是 48000) -
在 Linux (OpenJDK 6) 上初始化几个不同的
Clips 并尝试播放它们只会使最后加载的Clip可听 - 没有给出错误/警告,但仅在最后加载的Clip上使用play任何声音都没有 - 所有其他人都是沉默的:Clip loadSound(String name) { URL url = this.getClass().getResource("/" + name + ".wav"); Clip clip = AudioSystem.getClip(); AudioInputStream ais = AudioSystem.getAudioInputStream(url); clip.open(ais); return clip; } void playSound(Clip) { if (clip.isRunning()) clip.stop(); clip.setFramePosition(0); clip.start(); } ... Clip c1 = loadSound("foo"); Clip c2 = loadSound("bar"); ... playSound(c1); // silence ... playSound(c2); // audible使用此代码在 Windows 上一切正常 - 所有剪辑都可以正常播放、播放和混音。没有在 Mac 上测试过。
支持的文件格式(使用
AudioSystem.getAudioFileTypes分析)在 Linux/OpenJDK6 和 Windows/Oracle JDK 7 上都返回 wav / au / aif,因此没有 ogg 甚至 mp3 :(如果不将第二个副本加载为不同的
Clip,似乎没有简单的方法可以同时制作相同Clip声音的两个副本。
所以,问题是 - 是否有一个好的解决方案/解决方法来补救所有这些问题并使其更可靠?切换到其他声音系统(例如LWJGL OpenAL 或paulscode.com sound system)会有帮助吗?或者是否可以将 Java Sound API 包装在一些安全防护中并且它会正常工作?
我已经制作了一个小应用程序来测试以上所有内容,但它有点长,所以我想将它发布为gist,但不幸的是,GitHub 现在遇到了一些网络问题。所以,我想,我会稍后发布它。
【问题讨论】:
-
“简单的数字样本” “.ogg 或类似的压缩格式” 压缩的声音格式并不简单。 -- 也许JavaFX 提供了合适的控件或API。好问题顺便说一句。 +1
-
这取决于 simple 的定义 ;) 一般来说,如果我理解正确,即使在 Java Sound API 中,也可以为 mp3 或ogg,但我什至没有探索过这个机会,因为这对我的案子来说太麻烦了。我肯定会对只使用 wavs 感到满意。
-
“我肯定只对 wav 感到满意。”(耸耸肩)如果你能找到一个听起来可靠的 API,我怀疑它会支持压缩格式。我之前添加了 JMF 的
mp3plugin.jar以在 Java 声音应用程序中支持 MP3。我建议使用 JavaFX,希望它使用一些完全替代的 API 来替代 Java Sound(正如您所注意到的,它并不完全可靠)。但是说到 Linux 和声音,Linux 缺乏声音支持是导致Jamie Zawinski 为 Mac 折腾 Linux(为此他写了很多代码)的原因。 ;) -
我个人喜欢通过 LWJGL 使用 OpenAL
-
您可以尝试使用 gstreamer for Java。我过去使用过它,理解如何设置音频管道需要一些努力,但是一旦你让它运行它应该能够处理你扔给它的几乎任何东西。 code.google.com/p/gstreamer-java
标签: java lwjgl javasound openal alsa