我有一个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
相关的声音。但是,如果我快速反复按键,声音有时会无法播放。一段时间后这一点尤为明显(每次按键后问题似乎都会变得更糟)。
为什么会发生这种情况,我该如何规避这个问题?
答案 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
。此设置还允许实现平滑,实时的音量,平移和音调衰减。