1

所以,我正在做一个课堂项目,我们必须有一个带有背景音乐的游戏。我正在尝试播放 .wav 文件作为背景音乐,但由于我不能使用剪辑(对于音乐文件来说太短),我必须使用 AudioStream 播放。

在我的第一个实现中,游戏会一直挂起,直到歌曲完成,所以我将它放入自己的线程中以尝试缓解这种情况。目前,当歌曲播放时,游戏播放速度非常慢。我不确定我需要做些什么才能使这个线程与我的动画师线程配合得很好,因为我们从来没有正式教授过线程。下面是我的背景音乐播放器类,请有人告诉我我做错了什么,导致它占用了所有系统资源。

public class BGMusicPlayer implements Runnable {

File file;
AudioInputStream in;
SourceDataLine line;
int frameSize;
byte[] buffer = new byte [32 * 1024]; 
Thread player;
boolean playing = false;
boolean fileNotOver = true;

public BGMusicPlayer (File inputFile){
    try{
        file = inputFile;
        in = AudioSystem.getAudioInputStream (inputFile);
        AudioFormat format = in.getFormat();

        frameSize = format.getFrameSize(); 

        DataLine.Info info =new DataLine.Info (SourceDataLine.class, format); 
        line = (SourceDataLine) AudioSystem.getLine (info);

        line.open(); 

        player = new Thread (this);       
        player.start();
    }
    catch(Exception e){
        System.out.println("That is not a valid file. No music for you.");
    }
}


public void run() {
    int readPoint = 0;
    int bytesRead = 0;
    player.setPriority(Thread.MIN_PRIORITY);

        while (fileNotOver) {
            if (playing) {
                try {
                    bytesRead = in.read (buffer, 
                            readPoint, 
                            buffer.length - readPoint);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                if (bytesRead == -1) { 
                    fileNotOver = false; 
                    break;
                }

                int leftover = bytesRead % frameSize;

                // send to line
                line.write (buffer, readPoint, bytesRead-leftover);

                // save the leftover bytes
                System.arraycopy (buffer, bytesRead,
                        buffer, 0, 
                        leftover); 
                readPoint = leftover;
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

} 

public void start() {
    playing = true;
    if(!player.isAlive())
    player.start();
    line.start();
}

public void stop() {
    playing = false;
    line.stop();
}

}
4

1 回答 1

1

您已经很接近了,但是有一些不寻常的事情可能会导致性能问题。

首先,如果您只是播放 .wav,则实际上不需要处理任何“读取点”而是值 0,并且实际上不需要“剩余”计算。当您进行写入时,它应该与读取的字节数相同(read() 方法的返回值)。

我也不清楚你为什么要做 ArrayCopy。你能失去那个吗?

将线程设置为低优先级,并设置睡眠——我猜您希望这些会减慢音频处理速度以允许您处理更多游戏?我以前从未见过这样做过,如果真的需要,这真的很不寻常。我真的建议也摆脱这些。

我很好奇你的音频文件来自哪里。你不是通过网络流式传输的,是吗?

顺便说一句,您从 File 获取输入并将其放入 InputStream 的方式很可能不适用于 Java7。很多人都报告了一个错误。事实证明,从 File 生成 URL,然后使用 URL 作为参数而不是文件来获取 AudioInputStream 更为正确和高效。可能出现的错误是“标记/重置”错误。(对它的搜索会显示它在这里出现了很多次。)

于 2012-03-16T07:08:02.067 回答