commit
ed777a4654
@ -1,93 +1,100 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>core-java-os</artifactId>
|
<artifactId>core-java-os</artifactId>
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
<version>0.1.0-SNAPSHOT</version>
|
||||||
<name>core-java-os</name>
|
<name>core-java-os</name>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung.core-java-modules</groupId>
|
<groupId>com.baeldung.core-java-modules</groupId>
|
||||||
<artifactId>core-java-modules</artifactId>
|
<artifactId>core-java-modules</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>commons-collections4</artifactId>
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
<version>${commons-collections4.version}</version>
|
<version>${junit-jupiter-engine.version}</version>
|
||||||
</dependency>
|
<scope>test</scope>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>commons-io</groupId>
|
<dependency>
|
||||||
<artifactId>commons-io</artifactId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<version>${commons-io.version}</version>
|
<artifactId>commons-collections4</artifactId>
|
||||||
</dependency>
|
<version>${commons-collections4.version}</version>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<dependency>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<groupId>commons-io</groupId>
|
||||||
<version>${commons-lang3.version}</version>
|
<artifactId>commons-io</artifactId>
|
||||||
</dependency>
|
<version>${commons-io.version}</version>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>log4j</groupId>
|
<dependency>
|
||||||
<artifactId>log4j</artifactId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<version>${log4j.version}</version>
|
<artifactId>commons-lang3</artifactId>
|
||||||
</dependency>
|
<version>${commons-lang3.version}</version>
|
||||||
<!-- test scoped -->
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>log4j</groupId>
|
||||||
<artifactId>assertj-core</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
<version>${assertj.version}</version>
|
<version>${log4j.version}</version>
|
||||||
<scope>test</scope>
|
</dependency>
|
||||||
</dependency>
|
<!-- test scoped -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.unix4j</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
<artifactId>unix4j-command</artifactId>
|
<artifactId>assertj-core</artifactId>
|
||||||
<version>${unix4j.version}</version>
|
<version>${assertj.version}</version>
|
||||||
</dependency>
|
<scope>test</scope>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>com.googlecode.grep4j</groupId>
|
<dependency>
|
||||||
<artifactId>grep4j</artifactId>
|
<groupId>org.unix4j</groupId>
|
||||||
<version>${grep4j.version}</version>
|
<artifactId>unix4j-command</artifactId>
|
||||||
</dependency>
|
<version>${unix4j.version}</version>
|
||||||
</dependencies>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.grep4j</groupId>
|
||||||
|
<artifactId>grep4j</artifactId>
|
||||||
|
<version>${grep4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>core-java-os</finalName>
|
<finalName>core-java-os</finalName>
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
<directory>src/main/resources</directory>
|
<directory>src/main/resources</directory>
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>${maven-compiler-plugin.version}</version>
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>${maven.compiler.source}</source>
|
<source>${maven.compiler.source}</source>
|
||||||
<target>${maven.compiler.target}</target>
|
<target>${maven.compiler.target}</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!-- util -->
|
<!-- util -->
|
||||||
<commons-collections4.version>4.1</commons-collections4.version>
|
<commons-collections4.version>4.1</commons-collections4.version>
|
||||||
<collections-generic.version>4.01</collections-generic.version>
|
<collections-generic.version>4.01</collections-generic.version>
|
||||||
<!-- testing -->
|
<!-- testing -->
|
||||||
<assertj.version>3.6.1</assertj.version>
|
<assertj.version>3.6.1</assertj.version>
|
||||||
<asspectj.version>1.8.9</asspectj.version>
|
<asspectj.version>1.8.9</asspectj.version>
|
||||||
<maven.compiler.source>1.9</maven.compiler.source>
|
<maven.compiler.source>1.9</maven.compiler.source>
|
||||||
<maven.compiler.target>1.9</maven.compiler.target>
|
<maven.compiler.target>1.9</maven.compiler.target>
|
||||||
<guava.version>25.1-jre</guava.version>
|
<guava.version>25.1-jre</guava.version>
|
||||||
<unix4j.version>0.4</unix4j.version>
|
<unix4j.version>0.4</unix4j.version>
|
||||||
<grep4j.version>1.8.7</grep4j.version>
|
<grep4j.version>1.8.7</grep4j.version>
|
||||||
</properties>
|
<junit-jupiter-engine.version>5.7.2</junit-jupiter-engine.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.baeldung.example.soundapi;
|
||||||
|
|
||||||
|
import javax.sound.sampled.AudioFileFormat;
|
||||||
|
import javax.sound.sampled.AudioFormat;
|
||||||
|
|
||||||
|
public class App {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
AudioFormat format = buildAudioFormatInstance();
|
||||||
|
|
||||||
|
SoundRecorder soundRecorder = new SoundRecorder();
|
||||||
|
soundRecorder.build(format);
|
||||||
|
|
||||||
|
System.out.println("Start recording ....");
|
||||||
|
soundRecorder.start();
|
||||||
|
Thread.sleep(20000);
|
||||||
|
soundRecorder.stop();
|
||||||
|
|
||||||
|
WaveDataUtil wd = new WaveDataUtil();
|
||||||
|
Thread.sleep(3000);
|
||||||
|
wd.saveToFile("/SoundClip", AudioFileFormat.Type.WAVE, soundRecorder.getAudioInputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AudioFormat buildAudioFormatInstance() {
|
||||||
|
ApplicationProperties aConstants = new ApplicationProperties();
|
||||||
|
AudioFormat.Encoding encoding = aConstants.ENCODING;
|
||||||
|
float rate = aConstants.RATE;
|
||||||
|
int channels = aConstants.CHANNELS;
|
||||||
|
int sampleSize = aConstants.SAMPLE_SIZE;
|
||||||
|
boolean bigEndian = aConstants.BIG_ENDIAN;
|
||||||
|
|
||||||
|
return new AudioFormat(encoding, rate, sampleSize, channels, (sampleSize / 8) * channels, rate, bigEndian);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.baeldung.example.soundapi;
|
||||||
|
import javax.sound.sampled.AudioFormat;
|
||||||
|
|
||||||
|
public class ApplicationProperties {
|
||||||
|
public final AudioFormat.Encoding ENCODING = AudioFormat.Encoding.PCM_SIGNED;
|
||||||
|
public final float RATE = 44100.0f;
|
||||||
|
public final int CHANNELS = 1;
|
||||||
|
public final int SAMPLE_SIZE = 16;
|
||||||
|
public final boolean BIG_ENDIAN = true;
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package com.baeldung.example.soundapi;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
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.TargetDataLine;
|
||||||
|
|
||||||
|
public class SoundRecorder implements Runnable {
|
||||||
|
private AudioInputStream audioInputStream;
|
||||||
|
private AudioFormat format;
|
||||||
|
public Thread thread;
|
||||||
|
private double duration;
|
||||||
|
|
||||||
|
public SoundRecorder() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoundRecorder(AudioFormat format) {
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoundRecorder build(AudioFormat format) {
|
||||||
|
this.format = format;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
thread = new Thread(this);
|
||||||
|
thread.setName("Capture Microphone");
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
thread = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
duration = 0;
|
||||||
|
|
||||||
|
try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); final TargetDataLine line = getTargetDataLineForRecord();) {
|
||||||
|
|
||||||
|
int frameSizeInBytes = format.getFrameSize();
|
||||||
|
int bufferLengthInFrames = line.getBufferSize() / 8;
|
||||||
|
final int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
|
||||||
|
buildByteOutputStream(out, line, frameSizeInBytes, bufferLengthInBytes);
|
||||||
|
this.audioInputStream = new AudioInputStream(line);
|
||||||
|
setAudioInputStream(convertToAudioIStream(out, frameSizeInBytes));
|
||||||
|
audioInputStream.reset();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildByteOutputStream(final ByteArrayOutputStream out, final TargetDataLine line, int frameSizeInBytes, final int bufferLengthInBytes) throws IOException {
|
||||||
|
final byte[] data = new byte[bufferLengthInBytes];
|
||||||
|
int numBytesRead;
|
||||||
|
|
||||||
|
line.start();
|
||||||
|
while (thread != null) {
|
||||||
|
if ((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.write(data, 0, numBytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAudioInputStream(AudioInputStream aStream) {
|
||||||
|
this.audioInputStream = aStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioInputStream convertToAudioIStream(final ByteArrayOutputStream out, int frameSizeInBytes) {
|
||||||
|
byte audioBytes[] = out.toByteArray();
|
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes);
|
||||||
|
AudioInputStream audioStream = new AudioInputStream(bais, format, audioBytes.length / frameSizeInBytes);
|
||||||
|
long milliseconds = (long) ((audioInputStream.getFrameLength() * 1000) / format.getFrameRate());
|
||||||
|
duration = milliseconds / 1000.0;
|
||||||
|
System.out.println("Recorded duration in seconds:" + duration);
|
||||||
|
return audioStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TargetDataLine getTargetDataLineForRecord() {
|
||||||
|
TargetDataLine line;
|
||||||
|
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
|
||||||
|
if (!AudioSystem.isLineSupported(info)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
line = (TargetDataLine) AudioSystem.getLine(info);
|
||||||
|
line.open(format, line.getBufferSize());
|
||||||
|
} catch (final Exception ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioInputStream getAudioInputStream() {
|
||||||
|
return audioInputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioFormat getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormat(AudioFormat format) {
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread getThread() {
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.baeldung.example.soundapi;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.sound.sampled.AudioFileFormat;
|
||||||
|
import javax.sound.sampled.AudioInputStream;
|
||||||
|
import javax.sound.sampled.AudioSystem;
|
||||||
|
|
||||||
|
public class WaveDataUtil {
|
||||||
|
public boolean saveToFile(String name, AudioFileFormat.Type fileType, AudioInputStream audioInputStream) {
|
||||||
|
System.out.println("Saving...");
|
||||||
|
if (null == name || null == fileType || audioInputStream == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
File myFile = new File(name + "." + fileType.getExtension());
|
||||||
|
try {
|
||||||
|
audioInputStream.reset();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
while (myFile.exists()) {
|
||||||
|
String temp = "" + i + myFile.getName();
|
||||||
|
myFile = new File(temp);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
AudioSystem.write(audioInputStream, fileType, myFile);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
System.out.println("Saved " + myFile.getAbsolutePath());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.baeldung.example.soundapi;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
import javax.sound.sampled.AudioFileFormat;
|
||||||
|
import javax.sound.sampled.AudioFormat;
|
||||||
|
import javax.sound.sampled.TargetDataLine;
|
||||||
|
|
||||||
|
public class AppTest {
|
||||||
|
|
||||||
|
AudioFormat af = App.buildAudioFormatInstance();
|
||||||
|
SoundRecorder soundRecorder = new SoundRecorder();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void Given_SoundRecorderObject_When_Run_Then_ThrowsNoException() {
|
||||||
|
|
||||||
|
soundRecorder.build(af);
|
||||||
|
try {
|
||||||
|
soundRecorder.start();
|
||||||
|
Thread.sleep(20000);
|
||||||
|
soundRecorder.stop();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
fail("Exception: " + ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void Given_AudioFormatObject_When_NotNull_Then_ReturnsTargetDataLine() {
|
||||||
|
soundRecorder.setFormat(af);
|
||||||
|
Assertions.assertDoesNotThrow(() -> soundRecorder.getTargetDataLineForRecord());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void Given_TargetLineDataObject_When_Run_Then_GeneratesOutputStream() {
|
||||||
|
|
||||||
|
soundRecorder.setFormat(af);
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
TargetDataLine tLine = soundRecorder.getTargetDataLineForRecord();
|
||||||
|
|
||||||
|
int frameSizeInBytes = af.getFrameSize();
|
||||||
|
int bufferLengthInFrames = tLine.getBufferSize() / 8;
|
||||||
|
final int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
|
||||||
|
|
||||||
|
Assertions.assertDoesNotThrow(
|
||||||
|
() -> soundRecorder.buildByteOutputStream(out, tLine, frameSizeInBytes, bufferLengthInBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void Given_AudioInputStream_When_NotNull_Then_SaveToWavFile() {
|
||||||
|
soundRecorder.setFormat(af);
|
||||||
|
soundRecorder.build(af);
|
||||||
|
try {
|
||||||
|
soundRecorder.start();
|
||||||
|
Thread.sleep(20000);
|
||||||
|
soundRecorder.stop();
|
||||||
|
WaveDataUtil wd = new WaveDataUtil();
|
||||||
|
Thread.sleep(3000);
|
||||||
|
boolean saveFile = wd.saveToFile("/SoundClip", AudioFileFormat.Type.WAVE,
|
||||||
|
soundRecorder.getAudioInputStream());
|
||||||
|
|
||||||
|
assertEquals(saveFile, true);
|
||||||
|
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
fail("Exception: " + ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user