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:
To use this utility class, follow these steps:
Here’s an example program that tests the above utility class:
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.
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(); } } |
- 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.
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" ); } } |
No comments:
Post a Comment