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 );
}
Look into the DataLine. stop() method.
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.
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!
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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With