9

次のコードを使用して、Java サウンド API を使用してサウンド ファイルを再生しています。

    Clip clip = AudioSystem.getClip();
    AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream);
    clip.open(inputStream);
    clip.start();

Clip.start() メソッドへのメソッド呼び出しはすぐに戻り、システムはサウンド ファイルをバックグラウンド スレッドで再生します。再生が完了するまでメソッドを一時停止したい。

それを行う良い方法はありますか?

編集: Uri からの回答に基づいて、私の最終的な解決策に関心のあるすべての人のために、以下のコードを使用しました:

private final BlockingQueue<URL> queue = new ArrayBlockingQueue<URL>(1);

public void playSoundStream(InputStream stream) {
    Clip clip = AudioSystem.getClip();
    AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream);
    clip.open(inputStream);
    clip.start();
    LineListener listener = new LineListener() {
        public void update(LineEvent event) {
                if (event.getType() != Type.STOP) {
                    return;
                }

                try {
                    queue.take();
                } catch (InterruptedException e) {
                    //ignore this
                }
        }
    };
clip.addLineListener(listener );
}
4

6 に答える 6

8

私はJava 8でこの方法を好みます:

CountDownLatch syncLatch = new CountDownLatch(1);

try (AudioInputStream stream = AudioSystem.getAudioInputStream(inStream)) {
  Clip clip = AudioSystem.getClip();

  // Listener which allow method return once sound is completed
  clip.addLineListener(e -> {
    if (e.getType() == LineEvent.Type.STOP) {
      syncLatch.countDown();
    }
  });

  clip.open(stream);
  clip.start();
}

syncLatch.await();
于 2017-10-13T07:38:19.873 に答える
7

代わりにこのコードを置くことができます:

クリップ 1 を再生していて、その直後にクリップ 2 を再生したい場合は、次のことができます。

clip1.start();
while(clip1.getMicrosecondLength() != clip1.getMicrosecondPosition())
{
}
clip2.loop(some int here);

そして、メインタスクを遅らせることなくこれを機能させるには (次の作業が何であれ、while ループによって作業が clip1 の終了を待たされるためです...)、新しいスレッドを作成することができます。それが起こることを望み、コードを run() メソッドに入れるだけです...頑張ってください!

于 2013-06-25T15:12:00.163 に答える
4

サウンドクリップはタイプまたはラインであるため、ラインリスナーをサポートします。

addLineListenerを使用する場合は、再生の開始時と停止時にイベントを取得する必要があります。ループに入っていない場合は、クリップが終了したときに停止する必要があります。ただし、他のイベントと同様に、実際の再生が終了して停止するまでに時間がかかる場合があります。

メソッドを待機させるのは少し注意が必要です。ビジーウェイトするか(お勧めできません)、他の同期メカニズムを使用することができます。長い操作を待って完了イベントをスローするパターンがあると思いますが(それについてはわかりません)、それはSOに個別に投稿することをお勧めする一般的な質問です。

于 2009-02-17T17:51:20.770 に答える
0

JDK8 の時点で、Clipのリスナーには一種のバグがあります (つまり、オーディオ ( ) の 1 回の再生に対して Type.STOP を 2 回起動することがあります.start())。

したがって、次のようなものを使用します。

Clip[] myBunchOfClipsToPlaySequentially=new Clip[A_BUNCH];
//
// [load actual clips...]
// [...]
//
for(Clip c: myBunchOfClipsToPlaySequentially)
    while(c.getFramePosition()<c.getFrameLength())
        Thread.yield(); // Note that if we simply put a NO-OP instead (like a
                        // semicolon or a {}), we make our CPU
                        // cry). Thread.yield() allows for almost 0% CPU consumption.

さらに、JFX8 が提供する新しいAudioClipクラスを調べることができます (いじるのに気の利いたメソッドがいくつかあります)。

于 2016-10-06T17:28:34.607 に答える