3

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!

Towni0
  • 87
  • 1
  • 6

1 Answers1

5

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();
    }
});
icza
  • 389,944
  • 63
  • 907
  • 827
  • Thanks for your quick comment! But is it possible to delay the close() operation? I tried Thread.sleep(sometime) and that played the sound but it also stopped the game thread. – Towni0 Aug 29 '14 at 09:13
  • Edited. Added proper way to close it when the clip ends. – icza Aug 29 '14 at 09:28
  • Thanks, so there are no ways to use try-with-resources? Frankly I would preffer to use a solution like yours but since my professor said we were to use try-with-resources for all(as much as possible) of our resources I would like to be real sure before I decide not to use it. Thanks – Towni0 Aug 29 '14 at 09:38
  • 2
    @Towni0 The Clip plays back on a separate thread so you can't use try-with-resources. If your professor suggested to use try-with-resources with a Clip in this way, they are wrong. In general try-with-resources is a good style but it won't work here. – Radiodef Aug 29 '14 at 09:42