用Java演奏wavs

时间:2012-03-15 04:52:56

标签: java javasound background-music

所以,我正在开设一个课堂项目,我们必须要有一个背景音乐游戏。我正在尝试播放.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();
}

}

1 个答案:

答案 0 :(得分:1)

你非常接近,但有一些不寻常的事情可能导致性能问题。

首先,如果你只是回放一个.wav,那么真的不需要处理任何“读取点”但值为0,并且真的不需要“剩下的” “计算。执行写操作时,它应该与读入的字节数相同(read()方法的返回值)。

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

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

我很好奇您的音频文件来自哪里。你没有通过网络流媒体,是吗?

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