Search code examples
javaaudiojavasoundcliptry-with-resources

Java Use a Clip and a Try - with - resources block which results with no sound


I am rewriting my AudioManager class for my school project and I encountered a problem. My professor told me to load all my resources with the Try-with-resources block instead of using try/catch ( See code below ). I am using the Clip class from javax.sound.sampled.Clip and everything works perfectly with my PlaySound(String path) method that uses try/catch/ if I don't close() the Clip. I know that if I close() the Clip I can't use it anymore. I have read the Oracle Docs for Clip and Try-with-resources but I could not find a solution. So What I would like to know is:

Is it possible to use the Try-with-resource block to play/hear the sound from the clip before it closes?

// Uses Try- with resources. This does not work.
public static void playSound(String path) {
try {
    URL url = AudioTestManager.class.getResource(path);
    try (Clip clip = AudioSystem.getClip()){
    AudioInputStream ais = AudioSystem.getAudioInputStream(url);
    clip.open(ais);
    clip.start();
    }
} catch( LineUnavailableException | UnsupportedAudioFileException  | IOException  e) {
    e.printStackTrace();}
}

// Does not use Try- with resources. This works.

public static void playSound2(String path) {
Clip clip = null;
try {
    URL url = AudioTestManager.class.getResource(path);
    clip = AudioSystem.getClip();
    AudioInputStream ais = AudioSystem.getAudioInputStream(url);
    clip.open(ais);
    clip.start();

}
catch( LineUnavailableException | UnsupportedAudioFileException  | IOException  e) {
    e.printStackTrace();}
finally {
   // if (clip != null) clip.close();
}
}

Thanks in advance!


Solution

  • The problem is that try-with-resources block will automatically close the Clip created in it when the block finishes causing the playback to stop.

    In your other example since you don't close it manually, the playback can continue.

    If you want to close the Clip when it finished playing, you can add a LineListener to it with the addLineListener() and close it when you receive a STOP event like this:

    final Clip clip = AudioSystem.getClip();
    // Configure clip: clip.open();
    clip.start();
    
    clip.addLineListener(new LineListener() {
        @Override
        public void update(LineEvent event) {
            if (event.getType() == LineEvent.Type.STOP)
                clip.close();
        }
    });