0

Well, the title says all, I tried playing a wav file using javax.sound and nothing is happening. I have tried many different files without any luck.

public static void main(String[] args) throws IOException, UnsupportedAudioFileException, LineUnavailableException
{

    File in = new File("C:\\Users\\Sandra\\Desktop\\music\\rags.wav");
    AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(in);
    Clip play = AudioSystem.getClip();
    play.open(audioInputStream);
    FloatControl volume= (FloatControl) play.getControl(FloatControl.Type.MASTER_GAIN);
    volume.setValue(1.0f); // Reduce volume by 10 decibels.
    play.start();

}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
user2453484
  • 1
  • 1
  • 1

6 Answers6

8

As, has already begin stated, you need to prevent the main thread from exiting, as this will cause the JVM to terminate.

Clip#start is not a blocking call, meaning that it will return (soon) after it is called.

I have no doubt that there are many ways to approach this problem and this is just a simple example of one of them.

public class PlayMusic {

    public static void main(String[] args) throws InterruptedException {
        Clip play = null;
        try {
            File in = new File("C:\\Users\\Public\\Music\\Sample Music\\Kalimba.wav");
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(in);
            play = AudioSystem.getClip();
            play.open(audioInputStream);
            FloatControl volume = (FloatControl) play.getControl(FloatControl.Type.MASTER_GAIN);
            volume.setValue(1.0f); // Reduce volume by 10 decibels.
            play.start();
            // Loop until the Clip is not longer running.
            // We loop this way to allow the line to fill, otherwise isRunning will
            // return false
            //do {
            //    Thread.sleep(15);
            //} while (play.isRunning());
            play.drain();
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex) {
            ex.printStackTrace();
        } finally {
            try {
                play.close();
            } catch (Exception exp) {
            }
        }
        System.out.println("...");
    }
}

The actual solution will depend on your needs.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • You have to appreciate blind downvoting without the simple cortesrty to explain why, so we all can learn what would make an answer better – MadProgrammer May 12 '14 at 09:24
  • 1
    @MadProgrammer `Clip` is a `DataLine` and as such, `start()` is non-blocking. However, it's explicitly stated in the interface that the method `drain()` _is_ blocking: _"This method blocks until the draining is complete."_ from [DataLine.drain()](http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/DataLine.html#drain()). Any solution which requires artificially stalling the program from exiting is incorrect. This is explicitly explained in the [Java Playing Back Audio Tutorial](http://docs.oracle.com/javase/tutorial/sound/playing.html). – Jared May 29 '14 at 07:18
  • 1
    @Jared Hmm, good to know - also, very every rule, there's an excepiton ;) – MadProgrammer May 29 '14 at 07:24
  • I've done some tests on (1) laptop (Linux Mint 18.0 64bit) with JDK 1.8.0_102-b14 64bit) and (2) an Orange Pi Zero running Armbian 5.25 (kernel 3.4.113) with JDK 1.8.0_121-b13 (from Oracle). I have found that on (2)-OrPi `drain()` seems to be **not blocking**, but doing a `System.out.println(...)` ("peasant debugging") before it makes it blocking. Unfortunately, on (1)-laptop it is just the other way around, the `println(...)` makes it **not blocking** were it was blocking without it. Most reliable way on (1) and (2) was to `Thread.sleep(clip.getMicrosecondLength() / 1000)` - heh, uggggly... – frIT Mar 23 '17 at 09:48
  • @fr13d Have to say I'm not a fan of `drain`, I prefer to use a `LineListener`, if you need to, you could then use a `ReentrantLock` or something to single the end of the clip – MadProgrammer Mar 23 '17 at 10:58
  • @MadProgrammer thanks. I have found that a `LineListener` that unblocks the main thread (done via `Object.wait()`/`Object.notify()` and also `Thread.join()`/`Thread.interrupt()`), causes an annoying "blip" sound at the end of playback on the Orange Pi (but not on the laptop).The `Thread.sleep()` technique still seems to function the best cross-platform (for my two platforms)... – frIT Mar 23 '17 at 18:36
  • @MadProgrammer I haven't looked at this in 7 years, but my god, if you preferred LineListestener, why not update your answer? – Jared Feb 27 '21 at 04:00
  • @fr13d You're doing it wrong, that's why you're having problems. Of course pausing your playback until it fully plays always works--you're not having a correct solution to your problem....and drain absolutely works--I'm also sure [LineListener](https://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/LineListener.html) does as well...you're not using them properly. – Jared Feb 27 '21 at 04:16
4

Java's sound Clip requires an active Thread to play the audio input file otherwise the application exits before the file can be played. You could add

JOptionPane.showMessageDialog(null, "Click OK to stop music");

after calling start.

Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • 1
    `Clip` is a `DataLine` and as such, `start()` is non-blocking. However, it's explicitly stated in the interface that the method `drain()` _is_ blocking: _"This method blocks until the draining is complete."_ from [DataLine.drain()](http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/DataLine.html#drain()). Any solution which requires artificially stalling the program from exiting is incorrect. This is explicitly explained in the [Java Playing Back Audio Tutorial](http://docs.oracle.com/javase/tutorial/sound/playing.html). – Jared May 29 '14 at 07:20
4

The proper way to play the audio clip is to drain the line as explained in Playing Back Audio.

So your main should look like this:

public static void main(String[] args) throws IOException,
    UnsupportedAudioFileException, LineUnavailableException
{
    File in = new File("C:\\Users\\Sandra\\Desktop\\music\\rags.wav");
    AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(in);
    Clip play = AudioSystem.getClip();
    play.open(audioInputStream);
    FloatControl volume= (FloatControl) play.getControl(FloatControl.Type.MASTER_GAIN);
    volume.setValue(1.0f); // Reduce volume by 10 decibels.
    play.start();
    play.drain();
    play.close();
}

play.drain() blocks until all the data is played.

Jared
  • 940
  • 5
  • 9
2

Here playing a clip

    public static void main(String[] args) throws Exception {
           File in = new File("C:\\Users\\Sandra\\Desktop\\music\\rags.wav");
           AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(in);
           Clip play = AudioSystem.getClip();
           play.open(audioInputStream);
           FloatControl volume= (FloatControl)play.getControl(FloatControl.Type.MASTER_GAIN);
           volume.setValue(1.0f); // Reduce volume by 10 decibels.
           play.start();
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    // A GUI element to prevent the Clip's daemon Thread
                    // from terminating at the end of the main()
                    JOptionPane.showMessageDialog(null, "Close to exit!");
                }
            });
        }
Community
  • 1
  • 1
nachokk
  • 14,363
  • 4
  • 24
  • 53
1

Your program is terminating before the sound has the time to be played. I would do play.start(); in some threading way (invokeLater, ...), and also find a way to wait until the sound has finished (Reimeus suggested one).

A lead :

public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {

          ...

          play.start();
          JOptionPane.showMessageDialog(null, "Click OK to stop music");
        }
    });

}
Gauthier Boaglio
  • 10,054
  • 5
  • 48
  • 85
0

If you just want to play an audio, here's a way.

The audioFileDirectory String variable needs the correct path to your audio file, otherwise an exception will be thrown and the program won't run.

Example of having the right audio file directory in a project if using an IDE:

  1. Make a folder inside src folder, e.g: "music" and put an audio file there
  2. audioFileDirectory = "/music/name_of_audio_file";

The important part for an audio to play is that the main thread of the program needs somehow to be "alive", so the line

Thread.sleep(audio.getMicrosecondLength()/1000);

is where the main thread is "alive", and the argument audio.getMicrosecondLength()/1000 is the time that will be "alive", which is the whole length of the audio file.

public class AudioTest
{
    void playAudio() throws Exception
    {
        String audioFileDirectory = "your_audioFileDirectory";
        InputStream is = getClass().getResourceAsStream(audioFileDirectory);
        BufferedInputStream bis = new BufferedInputStream(is);
        AudioInputStream ais = AudioSystem.getAudioInputStream(bis);
        Clip audio = AudioSystem.getClip();
        audio.open(ais);
        audio.loop(Clip.LOOP_CONTINUOUSLY);
        audio.start();
        Thread.sleep(audio.getMicrosecondLength()/1000);
        audio.close();
    } // end playAudio

    public static void main(String[] args) 
    {
        try 
        {
            new AudioTest().playAudio();
        } 
        catch (Exception e) 
        {
            System.out.println("Class: " + e.getClass().getName());
            System.out.println("\nMessage:\n" + e.getMessage() + "\n");
            e.printStackTrace();
        }
    } // end main
} // end class AudioTest
jsheeran
  • 2,912
  • 2
  • 17
  • 32