1

(解決策を期待して、以前の質問をより一般的にしようとしています。)

JLayer ライブラリと sample.mp3 ファイルを使用しています。ファイルの再生とデコードを同時に行いたいと考えています。

ただし、それらを同期させたい-曲の一部がデコードされている場合は、それも再生されます。再生される前に何もデコードされず、その逆も同様です (もちろん、適度な程度で)。

敬意を表して、曲を再生してデコードする方法を次に示します。

Player p = new Player(InputStream mp3stream);
p.play();

Decoder d = new Decoder();
BitStream bs = new Bitstream(InputStream mp3stream);
SampleBuffer s = (SampleBuffer) d.decodeFrame(bs.readFrame(), bs);
// ... for processing the SampleBuffer but irrelevant for the question

私は現在使用しています:

InputStream mp3stream = new FileInputStream("sample.mp3");

しかし、これは曲全体を一度に使用するため、同期できません。sample.mp3 を両方のプロセスで操作できるように分割する方法はありますか? 十分に小さなピースがあれば、両方のピースをプロセスに実行し、両方が完了するまで待ってから、次の小さなピースをつかんで、小さなピースがなくなるまで繰り返します。

注: 私は ByteArrayInputStream を使用しようとしましたが、成功しませんでした。

4

1 に答える 1

1

これが正しいことを願っています:

  • 単一の入力ファイルがあります
  • 2 つの異なる入力ストリームが、ストリーム内で「同じ進行をしなければならない」という意味で同期されることを望みます。

これは興味深い質問です。次のスケッチを思いつきました (コンパイルはしますが、実行しませんでした。そのため、最初に少しテストを行ってください)。

  • 基礎となる入力へのアクセスを制御するラッパー オブジェクト「StreamSynchronizer」を作成します。すべての派生ストリームがこのバイトを読み取るまで、1 バイトだけが読み取られます。
  • これから、「読み取り」を StreamSynchronizer に委任する「SynchronizedStream」インスタンスをいくつでも派生させます。

package de.mit.stackoverflow;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class StreamSynchronizer {

    final private InputStream inputStream;

    private List activeStreams = new ArrayList();

    private int lastByte;

    private Set waitingStreams = new HashSet();

    private Object lock = new Object();

    public StreamSynchronizer(InputStream is) throws IOException {
        super();
        this.inputStream = is;
        lastByte = getInputStream().read();
    }

    public void close(SynchronizedStream stream) {
        activeStreams.remove(stream);
    }

    public SynchronizedStream createStream() {
        SynchronizedStream stream = new SynchronizedStream(this);
        activeStreams.add(stream);
        return stream;
    }

    public InputStream getInputStream() {
        return inputStream;
    }

    public int read(SynchronizedStream stream) throws IOException {
        synchronized (lock) {
            while (waitingStreams.contains(stream)) {
                if (waitingStreams.size() == activeStreams.size()) {
                    waitingStreams.clear();
                    lastByte = getInputStream().read();
                    lock.notifyAll();
                } else {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        throw new IOException(e);
                    }
                }
            }
            waitingStreams.add(stream);
            return lastByte;
        }
    }
}


package de.mit.stackoverflow;

import java.io.IOException;
import java.io.InputStream;

public class SynchronizedStream extends InputStream {

    final private StreamSynchronizer synchronizer;

    protected SynchronizedStream(StreamSynchronizer synchronizer) {
        this.synchronizer = synchronizer;
    }

    @Override
    public void close() throws IOException {
        getSynchronizer().close(this);
    }

    public StreamSynchronizer getSynchronizer() {
        return synchronizer;
    }

    @Override
    public int read() throws IOException {
        return getSynchronizer().read(this);
    }
}

于 2011-01-04T10:11:56.763 に答える