How can I wait for the java sound clip to finish playing?

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

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

The method of calling the Clip.start () method immediately returns, and the system plays the sound file in the background stream. I want my method to pause until playback finishes.

Is there a good way to do this?

EDIT: for anyone interested in my final solution, based on a response from Uri, I used the following code:

 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 ); } 
+6
java javasound
source share
5 answers

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

If you use addLineListener, you should receive events when the game starts and stops; if you are not in a loop, you should stop when the clip ends. However, as with any event, lag may occur before the actual end of playback and stop.

Making the method wait a little harder. You can either do it - wait on it (not a good idea), or use other synchronization mechanisms. I think there is a template (not sure about this) for waiting on a long operation to throw a completion event, but this is a common question that you can send separately to SO.

+4
source share

you can just put this code:

Suppose your clip1 is playing, and you want clip2 to play 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 the clip to finish, no matter what the next work is ...) you can create a new thread in where you want it to happen , and just put the code in your run () method ... GOOD LUCK!

+6
source share

I prefer this method 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(); 
+1
source share

Like in JDK8, the Clip listener is a kind of error (that is, it may happen that it launches Type.STOP twice for one sound playback ( .start() ).

So I would use something like:

 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. 

Alternatively, you can take a look at the new AudioClip class that JFX8 provides (has some great methods for violin)

0
source share

I used wait / notify to implement it. Just for reference.

  final Clip clip = AudioSystem.getClip(mixerInfo); clip.addLineListener(new LineListener(){ @Override public void update(LineEvent e) { if (e.getType()==LineEvent.Type.STOP){ synchronized(clip){ clip.notifyAll(); } System.err.println("STOP!"); } } }); clip.open(as); clip.start(); while (true){ synchronized(clip){ clip.wait(); } if (!clip.isRunning()){ break; } } clip.drain(); clip.stop(); clip.close(); 
0
source share

All Articles