Java - 频繁播放短音频片段时滞后

时间:2018-03-28 13:24:57

标签: java audio wav clip

经过几天的互联网研究,我来到这里寻求帮助。我正在为朋友开发一款简短的2D游戏(而且真的只是为了好玩),而且我几天前就学会了Clips。在这个游戏中,玩家可以收集物体(几乎像马里奥的硬币)。我的问题是,我收集硬币时播放的声音非常短(约为1秒,50kB),如果播放器在1秒内收集3个硬币,则Clip会使游戏滞后。如果先前的Clip已经结束,那么就没有滞后。但如果先前的Clip还没有结束,那么试图再次播放Clip会让游戏延迟(非常多)。

我有一台非常小的电脑,功能不是很强大,但这个问题真的很烦人。当玩家投掷武器时,我得到完全相同的声音问题。我有一个短片,如果玩家太快扔这个武器,游戏就会滞后......

以下是我已经尝试过的事情:

  • 使用一组剪辑(具有相同的声音),并播放当前未播放的剪辑
  • 使用不同的剪辑(同一个声音),和以前一样
  • 制作多份(同一声音)并将其加载到不同的片段
  • 制作一个单独的线程来播放声音,但我对线程感到不舒服:/

但这些都没有改变这个问题......

现在这是我的代码的一部分。首先是我用来将声音加载到Clip中的类。

package sound;

import java.io.IOException;
import java.net.URL;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
// My own package
import utils.Utils;

public class SoundLoader {

public static Clip loadSound(String path) {
    Utils.log("Loading " + path + " ... ");

    try {
        URL url = SoundLoader.class.getResource(path);
        AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
        AudioFormat format = audioIn.getFormat();

        DataLine.Info info = new DataLine.Info(Clip.class, format);
        Clip clip = (Clip)AudioSystem.getLine(info);
        clip.open(audioIn);

        Utils.log("success\n");
        return clip;
    } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
        e.printStackTrace();
        Utils.log("failed !\n");
        return null;
    }
}   
}

现在是我将管理所有声音的课程:

package sound;

import javax.sound.sampled.Clip;
// My own package   
import principal.Handler;

public class SoundManager {

    private Clip woosh;
    private Clip coin1;
    private Clip coin2;

    public SoundManager(Handler handler) {
        woosh = SoundLoader.loadSound("/resources/sounds/woosh2.wav");
        coin1 = SoundLoader.loadSound("/resources/sounds/coin1.wav");
        coin2 = SoundLoader.loadSound("/resources/sounds/coin2.wav");
    }

    public void wooshClip() {
        startClip(woosh);
    }
    public void coin1Clip() {
        startClip(coin1);
    }
    public void coin2Clip() {
        startClip(coin2);
    }   
    public synchronized void startClip(Clip clip) {
        clip.stop();
        clip.setFramePosition(0);
        clip.start();
    }
    public void loopClip(Clip clip) {
        clip.loop(Clip.LOOP_CONTINUOUSLY);
    }
    public void stopClip(Clip clip) {
        clip.stop();
    }

}

最后,当我想播放一个Clip时,我使用来自我的“Player”类的公共方法startClip()(显然代表播放器)。

handler.getSoundManager().wooshClip();

当我看到我的代码时,如果Clip已经在播放,那么方法starClip()应该停止它并重放它。为什么这么滞后?即使我使用不同的剪辑,为什么它会滞后?如果我只是停止一个Clip并重播它会让我的游戏滞后是什么?

我希望你能帮助我......我很少在网上找到答案。如果您需要更多信息来回答我,请告诉我!

感谢您在这个长期问题上花费的时间!

编辑:我在功能强大的计算机上尝试过我的游戏,因为音频剪辑绝对没有滞后......但我的问题仍然存在!一个50kB的剪辑怎么会这么滞后?我真的不明白这个问题......

1 个答案:

答案 0 :(得分:0)

使用JavaFX的javafx.scene.media.AudioClip代替javax.sound.sampled.Clip。 AudioClip具有较低的延迟。