How to play back audio in Java with examples
In this tutorial we’re going to understand how Java supports for playing audio with some interesting example programs.
Currently the Java Sound API supports playing back the following audio file format: AIFC, AIFF, AU, SND and WAVE. That means we cannot play the popular audio format MP3 with Java Sound API, so the examples will play with the WAVE format (.wav).
Generally, the Java Sound API (package: javax.sound ) provides two ways for playing back audio: using a Clip and using a SourceDataLine . Each way has its own advantages and drawbacks. Let’s explore the details.
1. Playing back audio using a Clip
Use a Clip ( javax.sound.sampled.Clip ) when you want to play non-real-time sound data such as a short sound file. The whole file is pre-loaded into memory before playing back, therefore we have total control over the playback.
-
- It’s possible to start playing from any position in the sound (using either of the Clip ’s methods setMicrosecondPosition(long) or setFramePosition(int) ).
- It’s possible to repeatedly play (loop) all or a part of the sound (using the setLoopPoints(int, int) and loop(int) methods).
- It’s possible to know duration of the sound before playing (using the getFrameLength() or getMicrosecondLength() methods).
- It’s possible to stop playing back at the current position and resume playing later (using the stop() and start() methods).
-
- It’s not suitable and inefficient to play back lengthy sound data such as a big audio file because it consumes too much memory.
- The Clip ’s start() method does playing the sound but it does not block the current thread (it returns immediately), so it requires to implement the LineListener interface to know when the playing completes. We’ll see how to do that in the examples.
Following are the steps to implement code for playing back an audio file (typically in .wav format) using the Clip :
- Create an AudioInputStream from a given sound file:
File audioFile = new File(audioFilePath); AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat(); DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream); audioClip.start();
audioClip.close(); audioStream.close();
Java Audio Playback Example using Clip:
Here’s an example program that plays back a given audio file using the Clip :
package net.codejava.sound; 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.Clip; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; /** * This is an example program that demonstrates how to play back an audio file * using the Clip in Java Sound API. * @author www.codejava.net * */ public class AudioPlayerExample1 implements LineListener < /** * this flag indicates whether the playback completes or not. */ boolean playCompleted; /** * Play a given audio file. * @param audioFilePath Path of the audio file. */ void play(String audioFilePath) < File audioFile = new File(audioFilePath); try < AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile); AudioFormat format = audioStream.getFormat(); DataLine.Info info = new DataLine.Info(Clip.class, format); Clip audioClip = (Clip) AudioSystem.getLine(info); audioClip.addLineListener(this); audioClip.open(audioStream); audioClip.start(); while (!playCompleted) < // wait for the playback completes try < Thread.sleep(1000); >catch (InterruptedException ex) < ex.printStackTrace(); >> audioClip.close(); > catch (UnsupportedAudioFileException ex) < System.out.println("The specified audio file is not supported."); ex.printStackTrace(); >catch (LineUnavailableException ex) < System.out.println("Audio line for playing back is unavailable."); ex.printStackTrace(); >catch (IOException ex) < System.out.println("Error playing the audio file."); ex.printStackTrace(); >> /** * Listens to the START and STOP events of the audio line. */ @Override public void update(LineEvent event) < LineEvent.Type type = event.getType(); if (type == LineEvent.Type.START) < System.out.println("Playback started."); >else if (type == LineEvent.Type.STOP) < playCompleted = true; System.out.println("Playback completed."); >> public static void main(String[] args) < String audioFilePath = "E:/Test/Audio.wav"; AudioPlayerExample1 player = new AudioPlayerExample1(); player.play(audioFilePath); >>
In this program, the play() method implements all the above mentioned steps, and the current thread will wait till the playback completes. We make this class implements the LineListener interface in order to receive line events (OPEN, CLOSE, START and STOP) to know when the playback completes (a STOP event is fired). Specify a listener for the Clip as follows:
audioClip.addLineListener(this);
public class AudioPlayerExample1 implements LineListener
@Override public void update(LineEvent event) < LineEvent.Type type = event.getType(); if (type == LineEvent.Type.START) < System.out.println("Playback started."); >else if (type == LineEvent.Type.STOP) < playCompleted = true; System.out.println("Playback completed."); >>
If the line event type is STOP, we set the flag playCompleted to true, so the current thread stops waiting and the program exits.
In addition, we can do the following things with the Clip :
- To know length (duration) of the sound:
int frameLength = audioClip.getFrameLength(); // length in frames long duration = audioClip.getMicrosecondLength(); // length in microseconds
audioClip.setMicrosecondPosition(50_000_000); // start playing from the 50th second audioClip.setFramePosition(300_000); // start playing from the 300,000th frame
audioClip.loop(2); // loop 2 times (total play 3 times)
// loop from frame 10,000th to frame 500,000th audioClip.setLoopPoints(10_000, 500_000); audioClip.loop(1);
To resume playing, call start() method again.
And all the above statements (except the stop() ) should be called after audioClip.open() and before audioClip.start() , for example:
audioClip.open(audioStream); int frameLength = audioClip.getFrameLength(); System.out.println("Frame length = " + frameLength); long duration = audioClip.getMicrosecondLength(); System.out.println("Duration = " + (duration / 1_000_000) + " sec"); audioClip.setMicrosecondPosition(10_000_000); // start playing from the 10th second audioClip.loop(1); // loop 1 time audioClip.start();
2. Playing back using a SourceDataLine
Use a SourceDataLine ( javax.sound.sampled.SourceDataLine ) when you want to play a long sound file which cannot be pre-loaded into memory or to stream real-time sound data such as playing sound back as it’s being captured.
-
- It’s suitable and efficient to play back long sound file or to stream sound in real-time.
- It’s possible to control what sound data to be written to the audio line’s playback buffer.
- Unlike the Clip , we don’t have to implement the LineListener interface to know when the playback completes.
-
- Cannot start playing from an arbitration position in the sound.
- Cannot repeatedly play (loop) all or a part of the sound.
- Cannot stop and resume playing in the middle.
- Cannot know duration of the sound before playing.
Following are the steps to implement code for playing back a sound file using the SourceDataLine :
- Obtain a SourceDataLine is similar to obtain a Clip :
File audioFile = new File(audioFilePath); AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile); AudioFormat format = audioStream.getFormat(); DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info);
audioLine.open(format); audioLine.start();
int BUFFER_SIZE = 4096; byte[] bytesBuffer = new byte[BUFFER_SIZE]; int bytesRead = -1; while ((bytesRead = audioStream.read(bytesBuffer)) != -1)
audioLine.drain(); audioLine.close(); audioStream.close();
Java Playback Audio Example using DataSourceLine:
Here’s an example program that plays back a given audio file using the SourceDataLine :
package net.codejava.sound; 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; import javax.sound.sampled.UnsupportedAudioFileException; /** * This is an example program that demonstrates how to play back an audio file * using the SourceDataLine in Java Sound API. * @author www.codejava.net * */ public class AudioPlayerExample2 < // size of the byte buffer used to read/write the audio stream private static final int BUFFER_SIZE = 4096; /** * Play a given audio file. * @param audioFilePath Path of the audio file. */ void play(String audioFilePath) < File audioFile = new File(audioFilePath); try < AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile); AudioFormat format = audioStream.getFormat(); DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info); audioLine.open(format); audioLine.start(); System.out.println("Playback started."); byte[] bytesBuffer = new byte[BUFFER_SIZE]; int bytesRead = -1; while ((bytesRead = audioStream.read(bytesBuffer)) != -1) < audioLine.write(bytesBuffer, 0, bytesRead); >audioLine.drain(); audioLine.close(); audioStream.close(); System.out.println("Playback completed."); > catch (UnsupportedAudioFileException ex) < System.out.println("The specified audio file is not supported."); ex.printStackTrace(); >catch (LineUnavailableException ex) < System.out.println("Audio line for playing back is unavailable."); ex.printStackTrace(); >catch (IOException ex) < System.out.println("Error playing the audio file."); ex.printStackTrace(); >> public static void main(String[] args) < String audioFilePath = "E:/Test/Audio.wav"; AudioPlayerExample1 player = new AudioPlayerExample1(); player.play(audioFilePath); >>
As we can see, this program is simpler than the Clip -based version, without having to implement the LineListener interface.
Related Java Sound Tutorials:
Other Java Tutorials:
About the Author:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.