I am using the following code to play a sound file using the java sound API.
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioS
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();
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!
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.
As of JDK8, Clip
's listener is kind of buggy (i.e. it can happen that it fires the Type.STOP twice for a single reproduction of the audio (.start()
).
I would therefore 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.
In addition, you could take a look to the new AudioClip class that JFX8 provides (has some nifty methods to fiddle with)
I have used a wait/notify to implement this. Just for your 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();