java - 如何在播放完毕后立即有效地关闭大量剪辑?

标签 java

我有一个游戏,使用这种方法播放音效:

 AudioInputStream inputStream = AudioSystem.getAudioInputStream(
          TheGame.class.getResource(url));
          Clip clip = AudioSystem.getClip();


           clip.open(inputStream);
           clip.start(); 

但是,不关闭剪辑显然会增加内存,并且我尝试过的修复会导致游戏偶尔卡住。 我尝试过:

  1. 为每个剪辑创建一个新的 LineListener,在剪辑停止时关闭该剪辑。游戏经常卡住。
  2. 拥有一个 LineListener,用于监听每个剪辑,并在它们停止时关闭它们。也经常卡住。
  3. 与 #2 相同,但将剪辑分配给多个 LineListener,我尝试过 4、6 和 10 个,所有这些都至少使游戏卡住一次。
  4. 永远不要关闭剪辑,最终游戏将停止播放声音并卡住
  5. 打开剪辑后立即将其设置为 null,结果与 #4 相同

我不知道为什么关闭剪辑似乎要花很多时间,以至于整个游戏都卡住了,有没有更省时的方法?

这是我正在使用的 LineListener 更新方法的代码:

    @Override
public void update(LineEvent event) {
     if (event.getType() == LineEvent.Type.STOP){
               Clip c = (Clip) event.getSource();
               c.close();
               c.removeLineListener(this);
     }
}

最佳答案

根据我上面的评论,您应该重用现有的 Clip 对象。

Map<String, Clip> clips = new HashMap<String, Clip>();

public synchronized void play(String url) {
    Clip clip = clips.get(url);
    if(clip == null) {
        AudioInputStream inputStream = AudioSystem.getAudioInputStream(
            TheGame.class.getResource(url));
        Clip clip = AudioSystem.getClip();
        clip.open(inputStream);
        clips.put(url, clip);
    }
    if(clip.isRunning())
        clip.stop();
    clip.setFramePosition(0);
    clip.start(); 
}

如果您需要将相同的声音与其自身重叠,您将需要更有创意。请注意,如果您碰巧从多个线程调用此方法,我已将其放置在 synchronized 方法中,以保护 Map 免受并发修改。

关于java - 如何在播放完毕后立即有效地关闭大量剪辑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50378794/

相关文章:

java - 我正在尝试创建一个数字键盘,它有一个清晰的按钮,顶部有一个显示单击的数字的部分。到目前为止我已经

java - 使用 IntStream 的 flatMap 方法打印二维数组

java - 如何从扫描仪获取多个输入并将数字分配给一个值?

java - 如何从个人我的商店检索证书

java - 如何更改 Intellij IDEA 项目中所有文件中导入的命名空间

java - 为什么java中不允许分配给 'this'?

Java继承最大化重用

java - 在没有 Jackson 的情况下将 Retrofit2 响应反序列化为 JSON

java - EJB 计时器忽略 TransactionTimeout

java - 给 JList 的消息