58

I am trying to play a *.wav file with Java. I want it to do the following:
When a button is pressed, play a short beep sound.

I have googled it, but most of the code wasn't working. Can someone give me a simple code snippet to play a .wav file?

Sender
  • 6,660
  • 12
  • 47
  • 66
greenLizard
  • 2,326
  • 5
  • 24
  • 30

10 Answers10

46

Finally I managed to do the following and it works fine

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class MakeSound {

    private final int BUFFER_SIZE = 128000;
    private File soundFile;
    private AudioInputStream audioStream;
    private AudioFormat audioFormat;
    private SourceDataLine sourceLine;

    /**
     * @param filename the name of the file that is going to be played
     */
    public void playSound(String filename){

        String strFilename = filename;

        try {
            soundFile = new File(strFilename);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        try {
            audioStream = AudioSystem.getAudioInputStream(soundFile);
        } catch (Exception e){
            e.printStackTrace();
            System.exit(1);
        }

        audioFormat = audioStream.getFormat();

        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
        try {
            sourceLine = (SourceDataLine) AudioSystem.getLine(info);
            sourceLine.open(audioFormat);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        sourceLine.start();

        int nBytesRead = 0;
        byte[] abData = new byte[BUFFER_SIZE];
        while (nBytesRead != -1) {
            try {
                nBytesRead = audioStream.read(abData, 0, abData.length);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (nBytesRead >= 0) {
                @SuppressWarnings("unused")
                int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
            }
        }

        sourceLine.drain();
        sourceLine.close();
    }
}
m13r
  • 2,458
  • 2
  • 29
  • 39
greenLizard
  • 2,326
  • 5
  • 24
  • 30
  • 12
    This one doesn't work for me. I recommend a very simple one : [http://alvinalexander.com/java/java-audio-example-java-au-play-sound](http://alvinalexander.com/java/java-audio-example-java-au-play-sound) – duleshi Aug 11 '13 at 14:00
  • 11
    Seriously if this is what's required to play a wav sound in Java then I'm going to stop using Java, fortunately I doubt this is right. – Bjorn Apr 28 '14 at 03:10
  • if you try this in a gameloop it freezes the game – florentin nica May 17 '21 at 14:21
  • Your code works one time. When you try and execute the code a second time, the file is not played because the `AudioInputStream` from the first time through was never closed. – Gilbert Le Blanc Dec 28 '22 at 21:04
  • @Gilbert Le Blanc, that is wrong. Not closing a file does not prevent anyone else to open it later again, nor does it make it magically disappear from the file system when the program terminates. AND: when a program terminates: all fils it has open get closed by the OS ... – Angel O'Sphere Jun 25 '23 at 10:17
  • This is a fine example HOW TO NOT USE EXCEPTIONS. You should have one single try and one single catch block and handle or not handle all exceptions in that catch block. – Angel O'Sphere Jun 25 '23 at 10:19
41

Here is the most elegant form I could come up without using sun.*:

import java.io.*;
import javax.sound.sampled.*;

try {
    File yourFile;
    AudioInputStream stream;
    AudioFormat format;
    DataLine.Info info;
    Clip clip;

    stream = AudioSystem.getAudioInputStream(yourFile);
    format = stream.getFormat();
    info = new DataLine.Info(Clip.class, format);
    clip = (Clip) AudioSystem.getLine(info);
    clip.open(stream);
    clip.start();
}
catch (Exception e) {
    //whatevers
}
tschwab
  • 1,056
  • 1
  • 12
  • 27
  • 1
    I could not hear any audio coming out using this sample codes. Is there anything i'm missing out? – Bryan May 12 '17 at 08:47
  • 1
    It should be complete, but it is also five years old, and ugly. I'm sure there are nicer ways of doing it, using nice Java libraries. – tschwab Jun 26 '17 at 18:05
  • 5
    To hear the output, you should delay the application termination for a playback duration. Try put `Thread.sleep(1000)` after the `clip.start()`. – Metaphore Oct 04 '17 at 12:47
  • You probably need a 'clip.loop(0);' (or to play it twice a clip.loop(1);) before clip.start(). – Angel O'Sphere Jun 25 '23 at 10:20
19

Shortest form (without having to install random libraries) ?

public static void play(String filename)
{
    try
    {
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(new File(filename)));
        clip.start();
    }
    catch (Exception exc)
    {
        exc.printStackTrace(System.out);
    }
}

The only problem is there is no good way to make this method blocking to close and dispose the data after *.wav finishes. clip.drain() says it's blocking but it's not. The clip isn't running RIGHT AFTER start(). The only working but UGLY way I found is:

// ...
clip.start();
while (!clip.isRunning())
    Thread.sleep(10);
while (clip.isRunning())
    Thread.sleep(10);
clip.close();
mini-me
  • 221
  • 2
  • 3
16

You can use an event listener to close the clip after it is played

import java.io.File;
import javax.sound.sampled.*;

public void play(File file) 
{
    try
    {
        final Clip clip = (Clip)AudioSystem.getLine(new Line.Info(Clip.class));

        clip.addLineListener(new LineListener()
        {
            @Override
            public void update(LineEvent event)
            {
                if (event.getType() == LineEvent.Type.STOP)
                    clip.close();
            }
        });

        clip.open(AudioSystem.getAudioInputStream(file));
        clip.start();
    }
    catch (Exception exc)
    {
        exc.printStackTrace(System.out);
    }
}
mkdev
  • 972
  • 9
  • 12
  • Renember that you could add after the start the sentence "clip.drain()" if you want to wait until the stream of audio is processed by the Line. – Victor Oct 14 '13 at 22:44
4

The snippet here works fine, tested with windows sound:

public static void main(String[] args) {
        AePlayWave aw = new AePlayWave( "C:\\WINDOWS\\Media\\tada.wav" );
        aw.start();     
}
stacker
  • 68,052
  • 28
  • 140
  • 210
  • If you still have issues with that try to change the sound device. See also the tool recommended here http://stackoverflow.com/questions/2175318/how-to-change-default-sound-playback-device-programatically/2216886#2216886 – stacker Mar 10 '10 at 13:32
2

A class that will play a WAV file, blocking until the sound has finished playing:

class Sound implements Playable {

    private final Path wavPath;
    private final CyclicBarrier barrier = new CyclicBarrier(2);

    Sound(final Path wavPath) {

        this.wavPath = wavPath;
    }

    @Override
    public void play() throws LineUnavailableException, IOException, UnsupportedAudioFileException {

        try (final AudioInputStream audioIn = AudioSystem.getAudioInputStream(wavPath.toFile());
             final Clip clip = AudioSystem.getClip()) {

            listenForEndOf(clip);
            clip.open(audioIn);
            clip.start();
            waitForSoundEnd();
        }
    }

    private void listenForEndOf(final Clip clip) {

        clip.addLineListener(event -> {
            if (event.getType() == LineEvent.Type.STOP) waitOnBarrier();
        });
    }

    private void waitOnBarrier() {

        try {

            barrier.await();
        } catch (final InterruptedException ignored) {
        } catch (final BrokenBarrierException e) {

            throw new RuntimeException(e);
        }
    }

    private void waitForSoundEnd() {

        waitOnBarrier();
    }
}
John Nash
  • 58
  • 2
  • 8
1

Another way of doing it with AudioInputStream:

import java.io.File;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.swing.JDialog;
import javax.swing.JFileChooser;

public class CoreJavaSound extends Object implements LineListener {
    File soundFile;

    JDialog playingDialog;

    Clip clip;

    public static void main(String[] args) throws Exception {
        CoreJavaSound s = new CoreJavaSound();
    }

    public CoreJavaSound() throws Exception {
        JFileChooser chooser = new JFileChooser();
        chooser.showOpenDialog(null);
        soundFile = chooser.getSelectedFile();

        System.out.println("Playing " + soundFile.getName());

        Line.Info linfo = new Line.Info(Clip.class);
        Line line = AudioSystem.getLine(linfo);
        clip = (Clip) line;
        clip.addLineListener(this);
        AudioInputStream ais = AudioSystem.getAudioInputStream(soundFile);
        clip.open(ais);
        clip.start();
    }

    public void update(LineEvent le) {
        LineEvent.Type type = le.getType();
        if (type == LineEvent.Type.OPEN) {
            System.out.println("OPEN");
        } else if (type == LineEvent.Type.CLOSE) {
            System.out.println("CLOSE");
            System.exit(0);
        } else if (type == LineEvent.Type.START) {
            System.out.println("START");
            playingDialog.setVisible(true);
        } else if (type == LineEvent.Type.STOP) {
            System.out.println("STOP");
            playingDialog.setVisible(false);
            clip.close();
        }
    }
}
God
  • 1,238
  • 2
  • 18
  • 45
1

A solution without java reflection DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat)

Java reflection decrease performance. to run: java playsound absoluteFilePathTo/file.wav

import javax.sound.sampled.*;
import java.io.*;
public class playsound {

    public static void main (String args[]) throws Exception {
        playSound (args[0]);
    }

    public static void playSound () throws Exception {
        AudioInputStream 
        audioStream = AudioSystem.getAudioInputStream(new File (filename));

        int BUFFER_SIZE = 128000;
        AudioFormat audioFormat = null;
        SourceDataLine sourceLine = null;

        audioFormat = audioStream.getFormat();

        sourceLine = AudioSystem.getSourceDataLine(audioFormat);
        sourceLine.open(audioFormat);
        sourceLine.start();

        int nBytesRead = 0;
        byte[] abData = new byte[BUFFER_SIZE];
        while (nBytesRead != -1) {
            try {
                nBytesRead = 
                audioStream.read(abData, 0, abData.length);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (nBytesRead >= 0) {
                int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
            }
        }

        sourceLine.drain();
        sourceLine.close();
    }

}
Community
  • 1
  • 1
guest123
  • 71
  • 1
  • 5
0

You can use AudioStream this way as well:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import sun.audio.AudioPlayer;
import sun.audio.AudioStream;

public class AudioWizz extends JPanel implements ActionListener {

    private static final long serialVersionUID = 1L; //you like your cereal and the program likes their "serial"

    static AudioWizz a;
    static JButton playBuddon;
    static JFrame frame;

    public static void main(String arguments[]){

        frame= new JFrame("AudioWizz");
        frame.setSize(300,300);
        frame.setVisible(true);
        a= new AudioWizz();
        playBuddon= new JButton("PUSH ME");
        playBuddon.setBounds(10,10,80,30);
        playBuddon.addActionListener(a);

        frame.add(playBuddon);
        frame.add(a);
    }

    public void actionPerformed(ActionEvent e){ //an eventListener
        if (e.getSource() == playBuddon) {
            try {
                InputStream in = new FileInputStream("*.wav");
                AudioStream sound = new AudioStream(in);
                AudioPlayer.player.start(sound);
            } catch(FileNotFoundException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

}
burb
  • 1
  • 1
0

I took @greenLizard's code and made it more robust.

  1. I closed the AudioInputStream.
  2. I used a BufferedInputStream. The AudioSystem getAudioInputStream was throwing an occasional IOException because the getAutoInputSytream method couldn't back up the input stream and start over.

Hopefully, there are no more exceptions to be found.

Here's the modified code. The ErrorDisplayDialog shows an exception as a JDialog in a Java Swing application. Just replace with e.printStackTrace();.

private void playWavFile(String fileName) {
    InputStream inputStream = getClass().getResourceAsStream(fileName);
    BufferedInputStream bufferedInputStream = new BufferedInputStream(
            inputStream);
    AudioInputStream audioStream = null;
    AudioFormat audioFormat = null;

    try {
        audioStream = AudioSystem.getAudioInputStream(bufferedInputStream);
        audioFormat = audioStream.getFormat();
    } catch (UnsupportedAudioFileException e) {
        new ErrorDisplayDialog(view.getFrame(),
                "UnsupportedAudioFileException", e);
        return;
    } catch (IOException e) {
        new ErrorDisplayDialog(view.getFrame(), "IOException", e);
        return;
    }

    DataLine.Info info = new DataLine.Info(SourceDataLine.class,
            audioFormat);
    SourceDataLine sourceLine;
    try {
        sourceLine = (SourceDataLine) AudioSystem.getLine(info);
        sourceLine.open(audioFormat);
    } catch (LineUnavailableException e) {
        new ErrorDisplayDialog(view.getFrame(), "LineUnavailableException",
                e);
        return;
    }

    sourceLine.start();

    int nBytesRead = 0;
    byte[] abData = new byte[128000];
    while (nBytesRead != -1) {
        try {
            nBytesRead = audioStream.read(abData, 0, abData.length);
        } catch (IOException e) {
            new ErrorDisplayDialog(view.getFrame(), "IOException", e);
            return;
        }

        if (nBytesRead >= 0) {
            sourceLine.write(abData, 0, nBytesRead);
        }
    }

    sourceLine.drain();
    sourceLine.close();

    try {
        audioStream.close();
    } catch (IOException e) {
        new ErrorDisplayDialog(view.getFrame(), "IOException", e);
    }
}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111