Playing a wav file in the study?

s00574926

Member
Joined
Dec 19, 2024
Posts
22
Likes
2
Tried JavaFx AudioClip and throws an exception which I wasn't able to figure out. The wav file is in the same location as the class
file. Any ideas or any code sample?
 
I literally did this yesterday :) (separate thread, supports (?) queuing, etc. - there were several attempts using both JavaFX and non-JavaFX and this one seems to do what I need for the moment)...

Java:
class SoundPlayer
{
  private static final BlockingQueue<String> soundQueue = new LinkedBlockingQueue<>();
  private static final ExecutorService soundExecutor = Executors.newSingleThreadExecutor();
  private static volatile boolean isRunning = true;
  private static volatile Clip currentClip = null;

  static {
    soundExecutor.execute(() -> {
      while (isRunning) {
        try {
          String soundFile = soundQueue.take();  // blocks until a sound is available
          playSoundInternal(soundFile);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          break;
        }
      }
    });
  }

  public static void playSound(String soundDir, String filePath)
  {
    if (soundDir.contains("\\")) { soundDir = soundDir.replace("\\", "/"); }
    filePath = soundDir + "/" + filePath;
    System.out.println("Queueing sound: " + filePath);
    soundQueue.add(filePath);
  }

  private static void playSoundInternal(String filePath)
  {
    try (AudioInputStream audioStream = AudioSystem.getAudioInputStream(new File(filePath))) {
      Clip clip = AudioSystem.getClip();
      clip.open(audioStream);
      currentClip = clip;

      // Add listener to handle when playback finishes
      clip.addLineListener(event -> {
        if (event.getType() == LineEvent.Type.STOP) {
          clip.close();
          currentClip = null;
          processNextSound();
        }
      });

      clip.start();  // play sound

    } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
      System.out.println("Error playing sound: " + e.getMessage());
      processNextSound();
    }
  }

  private static void processNextSound()
  {
    if (!soundQueue.isEmpty()) {
      soundExecutor.execute(() -> {
        try {
          String nextSound = soundQueue.take();
          playSoundInternal(nextSound);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
        }
      });
    }
  }

  public static void shutdown()
  {
    isRunning = false;
    soundExecutor.shutdownNow();
    if (currentClip != null && currentClip.isRunning()) {
      currentClip.stop();
      currentClip.close();
    }
  }
}

SoundPlayer.playSound(soundDir, "kaching.wav");

...as for exceptions, I did have to convert this one specific sound file to PCM (instead of compressed MPEG) using ffmpeg otherwise it wouldn't play so you may want to dig into the exception/error log if that's the case.

$ file *.wav
...
inactive.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
kaching.wav: RIFF (little-endian) data, WAVE audio, MPEG Layer 3, mono 16000 Hz

Per ChatGPT:
The "Compressed WAVE is not supported!" error occurs because JavaFX MediaPlayer does not support compressed WAV files (e.g., those using MP3 or ADPCM encoding). JavaFX only supports uncompressed PCM WAV files.

Solution 1: Convert WAV to PCM Format

You need to convert your WAV file to an uncompressed PCM format. You can do this using FFmpeg:

Command to Convert to PCM WAV
sh
ffmpeg -i "input.wav" -acodec pcm_s16le -ar 44100 -ac 2 "output.wav"
 
Last edited:
Top