Saturday, 28 September 2019

Java sound record utility code example

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:
 SoundRecordingUtil class diagram
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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.

No comments:

Post a Comment