简体   繁体   English

如何无延迟播放WAV文件?

[英]How to play a wav file with no lag?

I've looked around the internet on ways to play wav files, but I have found that they do not play on a separate thread and so cause the program to halt until the song is done, which does not work for a game. 我已经在网上寻找了播放wav文件的方法,但是我发现它们无法在单独的线程上播放,因此导致程序停止运行,直到完成歌曲为止,这对游戏不起作用。 However, when I try to play everything on a separate thread, it lags. 但是,当我尝试在单独的线程上播放所有内容时,它会滞后。 Does anyone have a fix for this? 有人对此有解决办法吗?

Note: I also am painting on to the background continuously: 注意:我也不断在背景上绘画:

public class DrawThread extends Thread {

    JFrame j;

    public DrawThread(JFrame frame) {
        j = frame;
    }

    public void run() {
        while (!(isInterrupted())) {
            if (j.isDisplayable() && j.isActive() && j.isEnabled())
            j.update(j.getGraphics());
        }
    }

}

and update just calls paint which is: 和更新只是调用画图是:

public void paint(Graphics g) {
            Graphics2D bg = (Graphics2D) g;
    bg.setBackground(Color.black);
    int w = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
    int h = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
    if (time < 500) {
        x[time] = r.nextInt(w) + 150;
        y[time] = h;
        z[time] = r.nextInt(w) + 150;
        time++;
    }
    for (int i = 0; i < time; i++) {
        y[i] -= forward;
        x[i] -= right;
        if (y[i] < 1) {
            x[i] = r.nextInt(400) - 200;
            y[i] = 300;
            z[i] = r.nextInt(400) - 200;
        } else if (y[i] > 300) {
            x[i] = r.nextInt(400) - 200;
            y[i] = 1;
            z[i] = r.nextInt(400) - 200;
        }
        if (x[i] > 200)
            x[i] = -200;
        else if (x[i] < -200)
            x[i] = 200;
        bg.setColor(color);
        bg.drawLine(
                getWidth() / 2 + (int) Math.round(x[i] * 200 / y[i]),
                getHeight() / 2 + (int) Math.round(z[i] * 200 / y[i]),
                getWidth()
                        / 2
                        + (int) Math.round((x[i] + right) * 200
                                / Math.abs(y[i] + forward)),
                getHeight()
                        / 2
                        + (int) Math.round((z[i]) * 200
                                / Math.abs(y[i] + forward)));
    }
}

EDit: Adding the music player class I'm using (I've switched to BigClip): EDit:添加我正在使用的音乐播放器类(我已切换到BigClip):

import java.io.File;
import java.util.Collection;
import java.util.HashMap;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

import org.crystalix.util.SoundListener;

public class MSHandler {
public static boolean pause = false;
public static boolean stop = false;
private static HashMap<String, BigClip> clips = new HashMap<String, BigClip>();

public static void stopAll() {
    Collection<BigClip> c = clips.values();
    for (BigClip b : c) {
        System.out.println("Stopping "+b.toString());
        b.stop();
        System.out.println("Stopped "+b.toString());
    }
}

public static void playMusic(File file) {
    try {
        AudioInputStream audioIn = AudioSystem.getAudioInputStream(file);
        BigClip clip = new BigClip();
        clip.open(audioIn);
        clip.addLineListener(new SoundListener());
        clip.loop(1);
        clip.start();
        clips.put(file.getName(), clip);
    } catch (Exception e) {
        System.err.println("Sound could not be started!");
        e.printStackTrace(System.err);
    }
}
}

You haven't shown the code you are using for the wav file playback. 您尚未显示用于wav文件播放的代码。 That makes it a bit hard to diagnose what might be going wrong! 这使得很难诊断出问题所在!

1) The wav should simply be on its own thread. 1)wav应该只是在其自己的线程上。 If you do so correctly, it will not block anything else. 如果操作正确,它不会阻止任何其他操作。 The Java sound tutorials don't do a particularly good job of pointing this out. Java声音教程在指出这一点方面做得并不出色。 So: put the code that calls the wav playback in its own runnable and you should be okay. 所以:将调用wav回放的代码放在自己的可运行位置,您应该可以。

2) You can "open" the wav prior to the time when you wish to play it. 2)您可以在想要播放之前先“打开” wav。 Then, it should "start" right away when you finally tell it to go. 然后,当您最终告诉它执行时,它应该立即“启动”。

Another note: the code that plays back a wav file runs more quickly if it is already in memory. 另一个注意事项:播放wav文件的代码如果已经在内存中,则运行速度会更快。 So, sometimes the first wav playback only starts after a slight hesitation. 因此,有时第一次WAV播放只会在稍有犹豫之后才开始。 But it is possible to combat this by playing another sound at zero volume to get the sound playback code into memory. 但是可以通过以零音量播放另一个声音以将声音播放代码存储到内存中来解决此问题。 I often do this at the start of programs that have sound. 我经常在有声音的程序开始时执行此操作。

The continuous painting in the background is only an issue if you are using up so many cpus that the JVM doesn't have time to process the sound. 仅当您使用了太多的CPU来使JVM没有时间处理声音时,在后台连续绘画才是问题。 I'd really be surprised if that was the issue. 如果那是问题,我真的会感到惊讶。 If it were, what you'd probably hear is the sound playback with lots of clicks in it. 如果是的话,您可能会听到的声音是带有很多点击的声音回放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM