3

下面的play方法来自一个类,该类在实例化时将 .wav 文件读入一个名为 的字节数组data,并将声音格式存储在一个AudioFormat名为 的对象中format

我有一个playjava.util.Timer. 当我进入包含所有相关 .class 文件的文件夹并使用命令运行程序时java MainClass,一切都按预期工作。但是,当我将所有 .class 文件放入可执行 .jar 并使用 command 运行程序时java -jar MyProgram.jar,使用该方法播放的声音会在play50 到 150 毫秒后被切断。

public void play() throws LineUnavailableException {
    final Clip clip = (Clip)AudioSystem.getLine(new DataLine.Info(Clip.class, format));
    clip.open(format, data, 0, data.length);
    new Thread() {
        public void run() {
            clip.start();
            try {
                Thread.sleep(300); // all sounds are less than 300 ms long
            } catch (InterruptedException ex) { /* i know, i know... */ }
            clip.close();
        }
    }.start();
}

几点评论:

  • 我尝试将play方法中的睡眠时间增加到 1000 毫秒,而行为没有改变。

  • 计时Thread.sleep使用System.nanoTime确认线程完全按照预期的时间休眠。

  • 由于要播放的声音文件已预先加载到内存中,因此我认为从 .jar 中提取声音资源的行为不会导致问题。

  • 我尝试使用内存池大小选项-Xms2m-Xmx64m(单独)从 jar 内部和外部运行程序,但行为没有变化。

我在 Ubuntu 11.04 上运行 OpenJDK Java 6。知道发生了什么吗?

4

3 回答 3

4

我不知道这是否与问题直接相关,但是每次播放该剪辑时都实例化一个新剪辑有点弄巧成拙。Clip 的重点是能够启动它而无需先加载它。根据您当前的设置,您的 Clip 在完全加载之前甚至不会开始播放。(当您包含实例化步骤时,SourceDataLines 开始播放比 Clips 更快,因为它们不会在开始之前等待所有数据加载。)

因此,作为解决此问题的第一步,我建议在播放调用之前实例化各种剪辑。我相信如果你做对了,并且剪辑开始在它自己的线程中,它可以被允许运行它的过程而不需要弄乱 Thread.sleep。您只需在下一次开始之前将剪辑重新定位回其起始帧。(可以在开始前的播放调用中完成。

一旦您对 Clip 的使用变得更加传统,可能会更容易确定是否还有其他事情发生。

我也不清楚为什么将源 .wav 文件作为中间步骤加载到字节数组中。不妨将它们直接加载到 Clips 中。考虑到 PCM 数据的优势,无论哪种方式,它们都会占用几乎相同数量的空间,并且在您调用它们时准备好使用。

禁用错误消息也是弄巧成拙。Java 可能试图给你一个非常好的诊断,也许不是在这个特定的睡眠调用中(我知道,我知道),但如果你经常这样做,谁知道呢。:)

于 2012-09-03T23:39:54.893 回答
4

放大@Anrew 和@Phil 的答案,下面有一个获取 aClip并异步播放它的大纲。这里有一个完整的例子。

AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(...);
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
...
// Play the sound in a separate thread.
private void playSound() {
    Runnable soundPlayer = new Runnable() {

        @Override
        public void run() {
            try {
                clip.setMicrosecondPosition(0);
                clip.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    new Thread(soundPlayer).start();
}
于 2012-09-23T01:11:27.623 回答
3

这很可能byte[]是问题的加载。

于 2012-09-22T23:11:25.247 回答