剪辑有时无法播放

时间:2015-05-04 18:03:46

标签: java audio clip javax.sound.sampled

我有一个Sound类,其中包含一个方法,在调用时,使用Clip对象播放声音(在本例中为clip)。

public static void play() {
    clip.stop();                // The purpose of the first three lines
    clip.flush();               // is to restart the Clip object so it
    clip.setFramePosition(0);   // can be played multiple times.
    clip.start();
}

Clip对象的实例化发生在一个单独的静态方法中,该方法在此方法之前调用,这就是上述方法可以声明为静态的原因。

另一个实现KeyListener的类包含以下代码:

public void keyPressed(KeyEvent e) {
    Sound.play(); // Sound is the class that implements the previous method.
}

因此,每次按下某个键时,我的代码都应播放与clip相关的声音。但是,如果我快速反复按键,声音有时会无法播放。一段时间后这一点尤为明显(每次按键后问题似乎都会变得更糟)。

为什么会发生这种情况,我该如何规避这个问题?

2 个答案:

答案 0 :(得分:1)

过去我遇到过同样的问题,对我来说有用的事情就是在线路完成并关闭它时添加线路监听器。

下面的代码是我使用的简化版本:

music = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(Sound.class.getResource("/sounds" + filename));
music.open(ais);

music.addLineListener(new LineListener(){
    public void update(LineEvent e){
        if(e.getType() == LineEvent.Type.STOP){
            e.getLine().close();
        }
    }
});

music.start();

创建剪辑时,只需添加线条侦听器即可。使用播放功能重置剪辑时,它应该正常播放。我希望这适合你!

答案 1 :(得分:0)

我通过类似问题的引用来看到这篇文章。

是的,一次播放的剪辑数量可能会导致延迟,但我不知道如何预测会产生多大影响,因为这取决于JVM如何与操作系统交互。

您可以通过缩小Clip的缓冲区大小来帮助解决问题。 SourceDataLine和Clip似乎只允许与缓冲区边界的传入请求进行交互(我不确定这是100%准确的语句)。指定Clip的缓冲区大小有点迂回,因为它需要将数据作为PCM阵列获取。但是,如果您想尝试一下,API就是here

减少行数的一个好方法是使用像TinySound这样的声音库。 Java-gaming.org的许多程序员都成功地使用了这个库。

我推广的另一个替代方案是AudioCue,这是我最近为并发Clip回放编写的一个类。许可证是BCD,提供源代码,因此可以随意检查,修改和使用代码。 AudioCue不会减少输出行数(尚未)。但是如果你正在做管理同一个cue的多个副本的常见事情,那么在这方面可能会有所帮助,因为所有并发实例都混合到一个输出。基本原理:文件被加载到一个数组中并通过游标回放,迭代数组并将其输出合并到SourceDataLine。此设置还允许实现平滑,实时的音量,平移和音调衰减。