Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how can I wait for a java sound clip to finish playing back?

Tags:

java

javasound

I am using the following code to play a sound file using the java sound API.

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

The method call to the Clip.start() method returns immediately, and the system playbacks the sound file in a background thread. I want my method to pause until the playback has completed.

Is there any nice way to do it?

EDIT: For everyone interested in my final solution, based on the answer from Uri, I used the code below:

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 );
}
like image 617
Panagiotis Korros Avatar asked Feb 17 '09 17:02

Panagiotis Korros


People also ask

How do I stop a clip from playing in Java?

Look into the DataLine. stop() method.

Can you play audio in Java?

Following steps are to be followed to play a clip object.Create an object of AudioInputStream by using AudioSystem. getAudioInputStream(File file). AudioInputStream converts an audio file into stream. Get a clip reference object from AudioSystem.


3 Answers

you can just put this code instead:

assume your clip1 is playing and you want a clip2 to be played right after that, you can:

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

and, to make this work without delaying your main task (I say this because the while loop makes the work wait for clip1 to finish, no matter what the next work is...) you can make a new thread in the point where you want it to happen, and just put the code in its run() method... GOOD LUCK!

like image 84
Arash Tarafar Avatar answered Oct 24 '22 17:10

Arash Tarafar


I prefer this way in 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();
like image 44
sancho21 Avatar answered Oct 24 '22 16:10

sancho21


A sound clip is a type or Line and therefore supports Line listeners.

If you use addLineListener, you should get events when play starts and stops; if you're not in a loop, you should get a stop when the clip ends. However, as with any events, there might be a lag before the actual end of playback and the stopping.

Making the method wait is slightly trickier. You can either busy-wait on it (not a good idea) or use other synchronization mechanisms. I think there is a pattern (not sure about it) for waiting on a long operation to throw a completion event, but that's a general question you may want to post separately to SO.

like image 20
Uri Avatar answered Oct 24 '22 16:10

Uri