1

SourceDataLineでマルチスレッド化された2つの異なるバッファー(バッファーAとB)を作成して、同時にサウンドを再生しようとしています。しかし、バッファAとバッファBを切り替え続けます。バッファをSourceDataLineに書き込む前に、バッファをマージする必要がありますか、それとも同期して再生する方法はありますか?

class PlayThread extends Thread {
    byte[] buffer = new byte[2 * 1024];

    @Override
    public void run() {
        try {
            while (true) {
                DatagramPacket receive = new DatagramPacket(buffer, buffer.length);
                mDatagramSocket.receive(receive);
                mSourceDataLine.write(receive.getData(), 0, receive.getData().length);

                System.out.println("Received!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

着信バッファが異なる2つのPlayThreadインスタンスがあります。以下は、SourceDataLineが初期化される関数です。

private void init() {
    try {
        DataLine.Info sourceDataLineInfo = new DataLine.Info(
                SourceDataLine.class, audioFormat);
        DataLine.Info targetDataLineInfo = new DataLine.Info(
                TargetDataLine.class, audioFormat);

        Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();

        Mixer mixer = AudioSystem.getMixer(mixerInfo[3]);
        mSourceDataLine = (SourceDataLine) AudioSystem
                .getLine(sourceDataLineInfo);
        mTargetDataLine = (TargetDataLine) mixer.getLine(targetDataLineInfo);

        mSourceDataLine.open(audioFormat, 2 * 1024);
        mSourceDataLine.start();

        mTargetDataLine.open(audioFormat, 2 * 1024);
        mTargetDataLine.start();
    } catch (LineUnavailableException ex) {
        ex.printStackTrace();
    }
}

ありがとうございました。

4

1 に答える 1

1

あなたは絶対にそれらをマージする必要があります。2つのスレッドからファイルに番号を書き込むことを想像してみてください。

123456...
123456...

になるかもしれない

11234235656...

それがあなたに起こっていることです。

もう1つの問題は、データがネットワークから着信するときにデータをバッファリングする必要があることです。そうしないと、データがドロップされる可能性があります。少なくとも2つのスレッドが必要です。1つは読み取り用で、もう1つはこれを機能させるための再生用です。ただし、あなたの場合、入力パケットストリームごとに1つのリーダースレッドを使用すると、運が良くなる可能性があります。(私のトークスライドを参照してください:http://blog.bjornroche.com/2011/11/slides-from-fundamentals-of-audio.html特にhttpからのストリーミングに関するスライドがあります。これもここに関連しています)

したがって、複数のPlayThreadsの代わりに、複数のReaderThreadsを作成します。これは、データを待機してから、ある種のバッファーに書き込みます( JavaPipedInputではPipedOutputStreamうまく機能します)。次に、バッファからデータを読み取り、COMBINEDデータをストリームに書き込むための別のスレッドが必要です。

これにより、データをどのように組み合わせるかについての元の質問が残ります。答えは、単一の答えはないということですが、通常、最も簡単な正しい方法は、サンプルごとにデータを平均化することです。ただし、正確にどのように行うかは、コードに含まれていないデータ形式によって異なります。ビッグエンディアンの16ビット整数であると仮定すると、着信生データをショートに変換し、ショートを平均化し、平均化されたショートをバイトに戻す必要があります。

byteto変換は、とshortを使用して最も簡単に実行できます。DataInputStreamDataOutputStream

于 2012-11-05T22:32:46.900 に答える