java - 在 Java 中播放 wavs

标签 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();
}

}

最佳答案

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

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

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

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

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

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

关于java - 在 Java 中播放 wavs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9714183/

相关文章:

java - 如何使用匹配器知道是否有不需要的字符?

java - AudioSystem.getMixerInfo() 在 Java/gentoo 中什么也得不到

java - Java 应用程序如何播放声音片段?

java - 如何使用 Java 写入麦克风输入?

java - 在 Android 中跨 Activity 播放 BG 音乐

java - 在 UsernamePasswordAuthenticationFilter 或 Controller 中创建 JWT token ?

java - 从已部署的 Web 应用程序获取 Tomcats webapps 目录中文件的相对路径

android - 如何使用Kotlin在所有 Activity 中播放背景音乐?

c# - 不使用 MediaPlayer 或 XACT 在 C# 中播放 mp3

java - 自定义 PropertyPlaceholderConfigurer 无法解析嵌入的属性值