Skip to content

Commit b45a59c

Browse files
committed
commits for BAEL 4293
1 parent 9147ccd commit b45a59c

6 files changed

Lines changed: 282 additions & 0 deletions

File tree

core-java-modules/core-java-os/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
</parent>
1717

1818
<dependencies>
19+
<dependency>
20+
<groupId>org.junit.jupiter</groupId>
21+
<artifactId>junit-jupiter-engine</artifactId>
22+
<version>5.7.2</version>
23+
<scope>test</scope>
24+
</dependency>
1925
<dependency>
2026
<groupId>org.apache.commons</groupId>
2127
<artifactId>commons-collections4</artifactId>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.baeldung.example.soundapi;
2+
3+
import javax.sound.sampled.AudioFileFormat;
4+
import javax.sound.sampled.AudioFormat;
5+
6+
public class App {
7+
public static void main(String[] args) throws Exception {
8+
9+
AudioFormat format = buildAudioFormatInstance();
10+
11+
SoundRecorder soundRecorder = new SoundRecorder();
12+
soundRecorder.build(format);
13+
14+
System.out.println("Start recording ....");
15+
soundRecorder.start();
16+
Thread.sleep(20000);
17+
soundRecorder.stop();
18+
19+
WaveDataUtil wd = new WaveDataUtil();
20+
Thread.sleep(3000);
21+
wd.saveToFile("/SoundClip", AudioFileFormat.Type.WAVE, soundRecorder.getAudioInputStream());
22+
}
23+
24+
public static AudioFormat buildAudioFormatInstance() {
25+
ApplicationProperties aConstants = new ApplicationProperties();
26+
AudioFormat.Encoding encoding = aConstants.ENCODING;
27+
float rate = aConstants.RATE;
28+
int channels = aConstants.CHANNELS;
29+
int sampleSize = aConstants.SAMPLE_SIZE;
30+
boolean bigEndian = aConstants.BIG_ENDIAN;
31+
32+
return new AudioFormat(encoding, rate, sampleSize, channels, (sampleSize / 8) * channels, rate, bigEndian);
33+
}
34+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.baeldung.example.soundapi;
2+
import javax.sound.sampled.AudioFormat;
3+
4+
public class ApplicationProperties {
5+
public final AudioFormat.Encoding ENCODING = AudioFormat.Encoding.PCM_SIGNED;
6+
public final float RATE = 44100.0f;
7+
public final int CHANNELS = 1;
8+
public final int SAMPLE_SIZE = 16;
9+
public final boolean BIG_ENDIAN = true;
10+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package com.baeldung.example.soundapi;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
6+
import javax.sound.sampled.AudioFormat;
7+
import javax.sound.sampled.AudioInputStream;
8+
import javax.sound.sampled.AudioSystem;
9+
import javax.sound.sampled.DataLine;
10+
import javax.sound.sampled.TargetDataLine;
11+
12+
public class SoundRecorder implements Runnable {
13+
private AudioInputStream audioInputStream;
14+
private AudioFormat format;
15+
public Thread thread;
16+
private double duration;
17+
18+
public SoundRecorder() {
19+
super();
20+
}
21+
22+
public SoundRecorder(AudioFormat format) {
23+
this.format = format;
24+
}
25+
26+
public SoundRecorder build(AudioFormat format) {
27+
this.format = format;
28+
return this;
29+
}
30+
31+
public void start() {
32+
thread = new Thread(this);
33+
thread.setName("Capture Microphone");
34+
thread.start();
35+
}
36+
37+
public void stop() {
38+
thread = null;
39+
}
40+
41+
@Override
42+
public void run() {
43+
duration = 0;
44+
45+
try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); final TargetDataLine line = getTargetDataLineForRecord();) {
46+
47+
int frameSizeInBytes = format.getFrameSize();
48+
int bufferLengthInFrames = line.getBufferSize() / 8;
49+
final int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
50+
buildByteOutputStream(out, line, frameSizeInBytes, bufferLengthInBytes);
51+
this.audioInputStream = new AudioInputStream(line);
52+
setAudioInputStream(convertToAudioIStream(out, frameSizeInBytes));
53+
audioInputStream.reset();
54+
} catch (IOException ex) {
55+
ex.printStackTrace();
56+
} catch (Exception ex) {
57+
ex.printStackTrace();
58+
return;
59+
}
60+
}
61+
62+
public void buildByteOutputStream(final ByteArrayOutputStream out, final TargetDataLine line, int frameSizeInBytes, final int bufferLengthInBytes) throws IOException {
63+
final byte[] data = new byte[bufferLengthInBytes];
64+
int numBytesRead;
65+
66+
line.start();
67+
while (thread != null) {
68+
if ((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1) {
69+
break;
70+
}
71+
out.write(data, 0, numBytesRead);
72+
}
73+
}
74+
75+
private void setAudioInputStream(AudioInputStream aStream) {
76+
this.audioInputStream = aStream;
77+
}
78+
79+
public AudioInputStream convertToAudioIStream(final ByteArrayOutputStream out, int frameSizeInBytes) {
80+
byte audioBytes[] = out.toByteArray();
81+
ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes);
82+
AudioInputStream audioStream = new AudioInputStream(bais, format, audioBytes.length / frameSizeInBytes);
83+
long milliseconds = (long) ((audioInputStream.getFrameLength() * 1000) / format.getFrameRate());
84+
duration = milliseconds / 1000.0;
85+
System.out.println("Recorded duration in seconds:" + duration);
86+
return audioStream;
87+
}
88+
89+
public TargetDataLine getTargetDataLineForRecord() {
90+
TargetDataLine line;
91+
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
92+
if (!AudioSystem.isLineSupported(info)) {
93+
return null;
94+
}
95+
try {
96+
line = (TargetDataLine) AudioSystem.getLine(info);
97+
line.open(format, line.getBufferSize());
98+
} catch (final Exception ex) {
99+
return null;
100+
}
101+
return line;
102+
}
103+
104+
public AudioInputStream getAudioInputStream() {
105+
return audioInputStream;
106+
}
107+
108+
public AudioFormat getFormat() {
109+
return format;
110+
}
111+
112+
public void setFormat(AudioFormat format) {
113+
this.format = format;
114+
}
115+
116+
public Thread getThread() {
117+
return thread;
118+
}
119+
120+
public double getDuration() {
121+
return duration;
122+
}
123+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.baeldung.example.soundapi;
2+
3+
import java.io.File;
4+
5+
import javax.sound.sampled.AudioFileFormat;
6+
import javax.sound.sampled.AudioInputStream;
7+
import javax.sound.sampled.AudioSystem;
8+
9+
public class WaveDataUtil {
10+
public boolean saveToFile(String name, AudioFileFormat.Type fileType, AudioInputStream audioInputStream) {
11+
System.out.println("Saving...");
12+
if (null == name || null == fileType || audioInputStream == null) {
13+
return false;
14+
}
15+
File myFile = new File(name + "." + fileType.getExtension());
16+
try {
17+
audioInputStream.reset();
18+
} catch (Exception e) {
19+
return false;
20+
}
21+
int i = 0;
22+
while (myFile.exists()) {
23+
String temp = "" + i + myFile.getName();
24+
myFile = new File(temp);
25+
}
26+
try {
27+
AudioSystem.write(audioInputStream, fileType, myFile);
28+
} catch (Exception ex) {
29+
return false;
30+
}
31+
System.out.println("Saved " + myFile.getAbsolutePath());
32+
return true;
33+
}
34+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.baeldung.example.soundapi;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.junit.jupiter.api.Assertions;
5+
6+
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
import static org.junit.jupiter.api.Assertions.fail;
8+
import java.io.ByteArrayOutputStream;
9+
10+
import javax.sound.sampled.AudioFileFormat;
11+
import javax.sound.sampled.AudioFormat;
12+
import javax.sound.sampled.TargetDataLine;
13+
14+
public class AppTest {
15+
16+
AudioFormat af = App.buildAudioFormatInstance();
17+
SoundRecorder soundRecorder = new SoundRecorder();
18+
19+
@Test
20+
public void when_run_save_SoundClip() {
21+
22+
soundRecorder.build(af);
23+
try {
24+
soundRecorder.start();
25+
Thread.sleep(20000);
26+
soundRecorder.stop();
27+
} catch (InterruptedException ex) {
28+
fail("Exception: " + ex);
29+
}
30+
31+
}
32+
33+
@Test
34+
public void when_run_get_targetdataline() {
35+
soundRecorder.setFormat(af);
36+
Assertions.assertDoesNotThrow(() -> soundRecorder.getTargetDataLineForRecord());
37+
}
38+
39+
@Test
40+
public void when_run_build_byte_ouptstream() {
41+
42+
soundRecorder.setFormat(af);
43+
ByteArrayOutputStream out = new ByteArrayOutputStream();
44+
TargetDataLine tLine = soundRecorder.getTargetDataLineForRecord();
45+
46+
int frameSizeInBytes = af.getFrameSize();
47+
int bufferLengthInFrames = tLine.getBufferSize() / 8;
48+
final int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
49+
50+
Assertions.assertDoesNotThrow(
51+
() -> soundRecorder.buildByteOutputStream(out, tLine, frameSizeInBytes, bufferLengthInBytes));
52+
}
53+
54+
@Test
55+
public void when_run_then_save_file() {
56+
soundRecorder.setFormat(af);
57+
soundRecorder.build(af);
58+
try {
59+
soundRecorder.start();
60+
Thread.sleep(20000);
61+
soundRecorder.stop();
62+
WaveDataUtil wd = new WaveDataUtil();
63+
Thread.sleep(3000);
64+
boolean saveFile = wd.saveToFile("/SoundClip", AudioFileFormat.Type.WAVE,
65+
soundRecorder.getAudioInputStream());
66+
67+
assertEquals(saveFile, true);
68+
69+
} catch (InterruptedException ex) {
70+
fail("Exception: " + ex);
71+
}
72+
73+
}
74+
75+
}

0 commit comments

Comments
 (0)