10

I'm trying to play a

PCM_UNSIGNED 11025.0 Hz, 8 bit, mono, 1 bytes/frame

file as described here (1) and here(2).

The first approach works, but I don't want to depend on sun.* stuff. The second results in just some leading frames being played, that sounds more like a click. Can't be an IO issue as I'm playing from a ByteArrayInputStream.

Why might this happen?

halfer
  • 19,824
  • 17
  • 99
  • 186
yanchenko
  • 56,576
  • 33
  • 147
  • 165

1 Answers1

32

I'm not sure why the second approach you linked to starts another thread; I believe the audio will be played in its own thread anyway. Is the problem that your application finishes before the clip has finished playing?

import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.LineEvent.Type;

private static void playClip(File clipFile) throws IOException, 
  UnsupportedAudioFileException, LineUnavailableException, InterruptedException {
  class AudioListener implements LineListener {
    private boolean done = false;
    @Override public synchronized void update(LineEvent event) {
      Type eventType = event.getType();
      if (eventType == Type.STOP || eventType == Type.CLOSE) {
        done = true;
        notifyAll();
      }
    }
    public synchronized void waitUntilDone() throws InterruptedException {
      while (!done) { wait(); }
    }
  }
  AudioListener listener = new AudioListener();
  AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(clipFile);
  try {
    Clip clip = AudioSystem.getClip();
    clip.addLineListener(listener);
    clip.open(audioInputStream);
    try {
      clip.start();
      listener.waitUntilDone();
    } finally {
      clip.close();
    }
  } finally {
    audioInputStream.close();
  }
}
rogerdpack
  • 62,887
  • 36
  • 269
  • 388
McDowell
  • 107,573
  • 31
  • 204
  • 267
  • In fact I don't run it in a separate thread, just linked that for brevity. THANKS A LOT!!! – yanchenko Feb 23 '09 at 15:37
  • @Jataro - you are correct; I had missed that call in the API; I'll update the code. – McDowell Jul 29 '09 at 09:22
  • drain() doesn't seem to be applicable to Clips according to http://download.oracle.com/javase/tutorial/sound/playing.html – lucks May 11 '11 at 01:16
  • 1
    @lucks - thanks! I've corrected the code. From the doc: _Once you have started a sound playing, how do you find when it's finished? We saw one solution above—invoking the drain method after writing the last buffer of data—but that approach is applicable only to a SourceDataLine. Another approach, which works for both SourceDataLines and Clips, is to register to receive notifications from the line whenever the line changes its state. These notifications are generated in the form of LineEvent objects, of which there are four types: OPEN, CLOSE, START, and STOP._ – McDowell May 11 '11 at 09:45
  • So it appears that you must play it in its own thread, which thread doesn't terminate until the file is over? (i.e. if the application's main thread exits, the program will exit, unlike most java threaded apps). – rogerdpack Sep 26 '11 at 21:33
  • Thanks for the example code. When i try the same code, i don't see it playing the Wav file. It just waits and there is no sound. I'm trying to run the program on my Windows TP. Is there any setting or player that i need to select? Please advise. – Sathish Jul 15 '16 at 05:13