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 では機能しない可能性が非常に高くなります。多くの人がそれに関するバグを報告しています。ファイルから URL を生成し、ファイルではなく URL を引数として使用して AudioInputStream を取得する方が、より正確で効率的であることがわかります。発生する可能性のあるエラーは、「マーク/リセット」エラーです。(それを検索すると、ここに何度も出てくることがわかります。)

于 2012-03-16T07:08:02.067 に答える