剪辑有时不播放

我有一个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相关的声音。 但是,如果我快速反复按键,声音有时会无法播放。 这在一段时间后尤为明显(似乎每次按键后问题都会变得更糟)。

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

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

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

 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(); 

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

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

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

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

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

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