Java sound record utility code example
- Details
- Written by Nam Ha Minh
- Last Updated on 01 July 2019   |   Print Email
In order to make recording sound in Java easier for developers, we created a generic and reusable utility class which is described below. Code is based on the Java Sound API.
The following class diagram depicts how the utility class is designed:
As we can see, this class has three public methods start(), stop() and save() which should be invoked sequentially. The start()method will run an infinite loop to store captured audio data into a byte array, until the method stop() is called; and the save()method stores recorded audio to the specified file in .wav format.
Here’s full source code of the utility class:
package net.codejava.sound; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import javax.sound.sampled.AudioFileFormat; 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.TargetDataLine; /** * A utility class provides general functions for recording sound. * @author www.codejava.net * */ public class SoundRecordingUtil { private static final int BUFFER_SIZE = 4096; private ByteArrayOutputStream recordBytes; private TargetDataLine audioLine; private AudioFormat format; private boolean isRunning; /** * Defines a default audio format used to record */ AudioFormat getAudioFormat() { float sampleRate = 16000; int sampleSizeInBits = 8; int channels = 2; boolean signed = true; boolean bigEndian = true; return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian); } /** * Start recording sound. * @throws LineUnavailableException if the system does not support the specified * audio format nor open the audio data line. */ public void start() throws LineUnavailableException { format = getAudioFormat(); DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); // checks if system supports the data line if (!AudioSystem.isLineSupported(info)) { throw new LineUnavailableException( "The system does not support the specified format."); } audioLine = AudioSystem.getTargetDataLine(format); audioLine.open(format); audioLine.start(); byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = 0; recordBytes = new ByteArrayOutputStream(); isRunning = true; while (isRunning) { bytesRead = audioLine.read(buffer, 0, buffer.length); recordBytes.write(buffer, 0, bytesRead); } } /** * Stop recording sound. * @throws IOException if any I/O error occurs. */ public void stop() throws IOException { isRunning = false; if (audioLine != null) { audioLine.drain(); audioLine.close(); } } /** * Save recorded sound data into a .wav file format. * @param wavFile The file to be saved. * @throws IOException if any I/O error occurs. */ public void save(File wavFile) throws IOException { byte[] audioData = recordBytes.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(audioData); AudioInputStream audioInputStream = new AudioInputStream(bais, format, audioData.length / format.getFrameSize()); AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, wavFile); audioInputStream.close(); recordBytes.close(); } }
To use this utility class, follow these steps:
- Create a new instance of the SoundRecordingUtilclass.
- Run the start() method in a separate thread because it will block the currently executing thread.
- In another thread (either main thread or a new one):
- Call the stop() method after a specified duration.
- Call the save() method to store the recorded sound to a WAV file.
Here’s an example program that tests the above utility class:
package net.codejava.sound; import java.io.File; import java.io.IOException; import javax.sound.sampled.LineUnavailableException; /** * A sample program that tests the SoundRecordingUtil utility class. * @author www.codejava.net * */ public class TestSoundRecordingUtil { private static final int RECORD_TIME = 60000; // 60 seconds public static void main(String[] args) { File wavFile = new File("E:/Test/Record.wav"); final SoundRecordingUtil recorder = new SoundRecordingUtil(); // create a separate thread for recording Thread recordThread = new Thread(new Runnable() { @Override public void run() { try { System.out.println("Start recording..."); recorder.start(); } catch (LineUnavailableException ex) { ex.printStackTrace(); System.exit(-1); } } }); recordThread.start(); try { Thread.sleep(RECORD_TIME); } catch (InterruptedException ex) { ex.printStackTrace(); } try { recorder.stop(); recorder.save(wavFile); System.out.println("STOPPED"); } catch (IOException ex) { ex.printStackTrace(); } System.out.println("DONE"); } }
This program will record sound for 60 seconds and save the audio to a file under E:/Test/Record.wav. You may change the duration and file location to suite your need.
Related Java Sound Tutorials:
- How to capture and record sound using Java Sound API
- How to develop a sound recorder program in Java Swing
- How to play back audio in Java with examples
- Java audio player sample application in Swing
Other Java Tutorials:
- 10 Common Mistakes Every Beginner Java Programmer Makes
- 10 Java Core Best Practices Every Java Programmer Should Know
- How to become a good programmer? 13 tasks you should practice now
Comments
same as #1 Rich's comment below.
Thank you all.
Recording function did not work as you expected.
Thank you for sharing your information which others can find useful.
Have a nice day!
On my WIN7 machine audioLine.drain(); seems to cause a hang, so I substituted audioLine.flush(); and accept that the remaining data is discarded. My audio format is 16bit, 16,000 sampling, 1 channel.