How to play .wav files with java
Asked Answered
M

10

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?

Medorra answered 10/3, 2010 at 12:49 Comment(0)
M
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();
    }
}
Medorra answered 12/3, 2010 at 14:45 Comment(6)
This one doesn't work for me. I recommend a very simple one : http://alvinalexander.com/java/java-audio-example-java-au-play-soundFungicide
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.Legit
if you try this in a gameloop it freezes the gameCaryopsis
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.Haddad
@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 ...Removed
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.Removed
H
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
}
Hagler answered 14/6, 2012 at 0:52 Comment(4)
I could not hear any audio coming out using this sample codes. Is there anything i'm missing out?Bridgettbridgette
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.Hagler
To hear the output, you should delay the application termination for a playback duration. Try put Thread.sleep(1000) after the clip.start().Congreve
You probably need a 'clip.loop(0);' (or to play it twice a clip.loop(1);) before clip.start().Removed
M
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();
Midiron answered 17/7, 2012 at 1:20 Comment(0)
V
17

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);
    }
}
Vieva answered 24/6, 2013 at 14:29 Comment(1)
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.Hirza
S
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();     
}
Southwick answered 10/3, 2010 at 13:12 Comment(1)
If you still have issues with that try to change the sound device. See also the tool recommended here #2175818Southwick
S
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();
    }
}
Shealy answered 28/10, 2016 at 11:14 Comment(0)
G
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();
        }
    }
}
Gentoo answered 6/6, 2015 at 10:17 Comment(2)
Why the extends Object?Britannic
@Britannic I truly don't remember :)Gentoo
D
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();
    }

}
Dianemarie answered 30/8, 2017 at 17:7 Comment(0)
C
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();
            }
        }
    }

}
Cinema answered 20/12, 2016 at 20:58 Comment(0)
H
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);
    }
}
Haddad answered 30/12, 2022 at 21:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.