1

I have implemented a simple Java sound player (.wav) that works well, except that after playing 50-60 sounds it just stops working.

The code is similar to Playing .mp3 and .wav in Java?, but I will post mine here anyway:

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

public class NewWavPlayer {
    private URL url;
    private AudioInputStream audio;

    public NewWavPlayer(URL url) {
        this.url = url;
    }

    public void play() {
          try
          {
            InputStream audioSrc = url.openStream();
            InputStream bufferedIn = new BufferedInputStream(audioSrc);
            audio = AudioSystem.getAudioInputStream(bufferedIn);            
            Clip clip = AudioSystem.getClip();
            clip.open(audio);
            clip.start();
          } catch(Exception e) { 
              System.err.println(e);
          }
    }
}

The error that I get after a while is:

javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian not supported.

or

javax.sound.sampled.LineUnavailableException: line with format PCM_UNSIGNED 22050.0 Hz, 8 bit, mono, 1 bytes/frame,  not supported.

But it does not make sense, because the same sound was played before (or other sounds that already played correctly). I'm running it on a Linux Ubuntu 15.04, and other users experienced the same with other SOs.

I have tried reimplementing it with threads, but I got the same error. I would like to know which steps should I take next.

Community
  • 1
  • 1
Chaotic
  • 133
  • 7

2 Answers2

0

One of the things that I see is you are not closing your InputStreams. You may have run out of handles. Close the input streams in a finally clause i.e.

public void play() {
        InputStream audioSrc = null;
        InputStream bufferedIn = null;
      try {
        audioSrc = url.openStream();
        bufferedIn = new BufferedInputStream(audioSrc);
        audio = AudioSystem.getAudioInputStream(bufferedIn);            
        Clip clip = AudioSystem.getClip();
        clip.open(audio);
        clip.start();
      } catch(Exception e) { 
          System.err.println(e);
      } finally {
          if (bufferedIn != null) {
              bufferedIn.close();
          }
          if (audioSrc != null) {
              audioSrc.close();
          }
}

You may have to restart your system if your OS has run out of handles. The above will ensure it doesn't happen again.

Hope this helps!

Kabir
  • 860
  • 5
  • 11
  • Or you could just make your life simpler and use [The try-with-resources Statement](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) – MadProgrammer Nov 20 '15 at 05:51
  • This is a nice tip, but unfortunately it does not worked for me. The error persists. When I run again the app (via Eclipse or as a .jar outside) it works again, until it suddenly stops after reproducing the sound around 50-60 times (I counted). – Chaotic Nov 20 '15 at 05:52
  • It does sound like your OS is running out of handles. I would recommend to add the finally clauses, reboot and see if the problem exists. At worst, that would eliminate this theory. Just a suggestion :) – Kabir Nov 20 '15 at 05:58
0

I find the problem with the code. After some research I discovered that closing the Clip in a listener is the way to go. I got the code from here: https://stackoverflow.com/a/17277981/3552500

final Clip clip = AudioSystem.getClip();
clip.addLineListener(new LineListener() {
    @Override
    public void update(LineEvent event) {
        if (event.getType() == LineEvent.Type.STOP)
            clip.close();
    }
});     
Community
  • 1
  • 1
Chaotic
  • 133
  • 7