如何 play/record 听起来 on/from 一个 javax.sound.sampled.Line
How to play/record sound on/from a javax.sound.sampled.Line
我有一个数组,其中填充了所有当前连接的麦克风的 javax.sound.sampled.Line.Info 对象
Info[] sourceInfos = AudioSystem.getSourceLineInfo(Port.Info.MICROPHONE);
使用它们我可以得到所有麦克风的线路
for (Info sourceInfo : sourceInfos) {
Line sourceLine = AudioSystem.getLine(sourceInfo);
// record sound from those lines
}
演讲者也是如此
Info[] sourceInfos = AudioSystem.getSourceLineInfo(Port.Info.SPEAKER);
for (Info sourceInfo : sourceInfos) {
Line sourceLine = AudioSystem.getLine(sourceInfo);
// play sound on those lines
}
现在我只需要弄清楚如何在一条线上播放声音以及如何从一条线上录制声音。这是我卡住的地方,找不到解决方案。
所以就这么说吧,问题是,我怎样才能 read/write 到一行?
谢谢
巴施迪
您可以试试这个例子来捕捉和播放音频。它基于 Java 声音 API 文档中提供的示例。
以下是您可以参考的资源:
- Accessing Audio System Resources
- Capturing audio.
-
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.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
public class Audio {
boolean stopCapture = false;
ByteArrayOutputStream byteArrayOutputStream;
AudioFormat audioFormat;
TargetDataLine targetDataLine;
AudioInputStream audioInputStream;
SourceDataLine sourceDataLine;
byte tempBuffer[] = new byte[500];
public static void main(String[] args) {
Audio audio = new Audio();
audio.captureAudio();
}
private AudioFormat getAudioFormat() {
float sampleRate = 8000.0F;
int sampleSizeInBits = 16;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
private void captureAudio() {
try {
/* ~~~~~ UPDATE THIS PART OF CODE ~~~~~*/
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); //get available mixers
System.out.println("Available mixers:");
for (int cnt = 0; cnt < mixerInfo.length; cnt++) {
System.out.println(mixerInfo[cnt].getName());
}
audioFormat = getAudioFormat(); //get the audio format
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
Mixer mixer = AudioSystem.getMixer(mixerInfo[3]); //getting the mixer for capture device
/* ~~~~~ UPDATE THIS PART OF CODE ~~~~~*/
targetDataLine = (TargetDataLine) mixer.getLine(dataLineInfo);
targetDataLine.open(audioFormat);
targetDataLine.start();
DataLine.Info dataLineInfo1 = new DataLine.Info(SourceDataLine.class, audioFormat);
sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo1);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
Thread captureAndPlayThread = new captureAndPlayThread(); //thread to capture and play audio
captureAndPlayThread.start();
} catch (LineUnavailableException e) {
System.out.println(e);
System.exit(0);
}
}
class captureAndPlayThread extends Thread {
@Override
public void run() {
byteArrayOutputStream = new ByteArrayOutputStream();
stopCapture = false;
try {
int readCount;
while (!stopCapture) {
readCount = targetDataLine.read(tempBuffer, 0, tempBuffer.length); //capture sound into tempBuffer
if (readCount > 0) {
byteArrayOutputStream.write(tempBuffer, 0, readCount);
sourceDataLine.write(tempBuffer, 0, 500); //playing audio available in tempBuffer
}
}
byteArrayOutputStream.close();
} catch (IOException e) {
System.out.println(e);
System.exit(0);
}
}
}
}
`
编辑:请用这段代码更新之前的代码。以下代码片段仅在支持麦克风时选择混音器,即 TargetDataLine。同样,您可以为扬声器做,即 SourceDataLine。
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); //get available mixers
System.out.println("Available mixers:");
Mixer mixer = null;
for (int cnt = 0; cnt < mixerInfo.length; cnt++) {
System.out.println(cnt + " " + mixerInfo[cnt].getName());
mixer = AudioSystem.getMixer(mixerInfo[cnt]);
Line.Info[] lineInfos = mixer.getTargetLineInfo();
if (lineInfos.length >= 1 && lineInfos[0].getLineClass().equals(TargetDataLine.class)) {
System.out.println(cnt + " Mic is supported!");
break;
}
}
audioFormat = getAudioFormat(); //get the audio format
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
我有一个数组,其中填充了所有当前连接的麦克风的 javax.sound.sampled.Line.Info 对象
Info[] sourceInfos = AudioSystem.getSourceLineInfo(Port.Info.MICROPHONE);
使用它们我可以得到所有麦克风的线路
for (Info sourceInfo : sourceInfos) {
Line sourceLine = AudioSystem.getLine(sourceInfo);
// record sound from those lines
}
演讲者也是如此
Info[] sourceInfos = AudioSystem.getSourceLineInfo(Port.Info.SPEAKER);
for (Info sourceInfo : sourceInfos) {
Line sourceLine = AudioSystem.getLine(sourceInfo);
// play sound on those lines
}
现在我只需要弄清楚如何在一条线上播放声音以及如何从一条线上录制声音。这是我卡住的地方,找不到解决方案。
所以就这么说吧,问题是,我怎样才能 read/write 到一行?
谢谢
巴施迪
您可以试试这个例子来捕捉和播放音频。它基于 Java 声音 API 文档中提供的示例。
以下是您可以参考的资源:
- Accessing Audio System Resources
- Capturing audio.
-
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.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.TargetDataLine; public class Audio { boolean stopCapture = false; ByteArrayOutputStream byteArrayOutputStream; AudioFormat audioFormat; TargetDataLine targetDataLine; AudioInputStream audioInputStream; SourceDataLine sourceDataLine; byte tempBuffer[] = new byte[500]; public static void main(String[] args) { Audio audio = new Audio(); audio.captureAudio(); } private AudioFormat getAudioFormat() { float sampleRate = 8000.0F; int sampleSizeInBits = 16; int channels = 1; boolean signed = true; boolean bigEndian = true; return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian); } private void captureAudio() { try { /* ~~~~~ UPDATE THIS PART OF CODE ~~~~~*/ Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); //get available mixers System.out.println("Available mixers:"); for (int cnt = 0; cnt < mixerInfo.length; cnt++) { System.out.println(mixerInfo[cnt].getName()); } audioFormat = getAudioFormat(); //get the audio format DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat); Mixer mixer = AudioSystem.getMixer(mixerInfo[3]); //getting the mixer for capture device /* ~~~~~ UPDATE THIS PART OF CODE ~~~~~*/ targetDataLine = (TargetDataLine) mixer.getLine(dataLineInfo); targetDataLine.open(audioFormat); targetDataLine.start(); DataLine.Info dataLineInfo1 = new DataLine.Info(SourceDataLine.class, audioFormat); sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo1); sourceDataLine.open(audioFormat); sourceDataLine.start(); Thread captureAndPlayThread = new captureAndPlayThread(); //thread to capture and play audio captureAndPlayThread.start(); } catch (LineUnavailableException e) { System.out.println(e); System.exit(0); } } class captureAndPlayThread extends Thread { @Override public void run() { byteArrayOutputStream = new ByteArrayOutputStream(); stopCapture = false; try { int readCount; while (!stopCapture) { readCount = targetDataLine.read(tempBuffer, 0, tempBuffer.length); //capture sound into tempBuffer if (readCount > 0) { byteArrayOutputStream.write(tempBuffer, 0, readCount); sourceDataLine.write(tempBuffer, 0, 500); //playing audio available in tempBuffer } } byteArrayOutputStream.close(); } catch (IOException e) { System.out.println(e); System.exit(0); } } } }
`
编辑:请用这段代码更新之前的代码。以下代码片段仅在支持麦克风时选择混音器,即 TargetDataLine。同样,您可以为扬声器做,即 SourceDataLine。
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); //get available mixers
System.out.println("Available mixers:");
Mixer mixer = null;
for (int cnt = 0; cnt < mixerInfo.length; cnt++) {
System.out.println(cnt + " " + mixerInfo[cnt].getName());
mixer = AudioSystem.getMixer(mixerInfo[cnt]);
Line.Info[] lineInfos = mixer.getTargetLineInfo();
if (lineInfos.length >= 1 && lineInfos[0].getLineClass().equals(TargetDataLine.class)) {
System.out.println(cnt + " Mic is supported!");
break;
}
}
audioFormat = getAudioFormat(); //get the audio format
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);