【发布时间】:2017-11-17 01:11:37
【问题描述】:
我正在制作一个从麦克风捕获声音的程序,在扬声器上听到它(已经完成)并将其同时保存到 wav 文件。我正在寻找这个问题三四天。我相信,Stackoverflow 可以帮助我。
我需要做的就是将来自麦克风的声音写入一个 wav 文件,同时用户正在现场收听它。请帮助或指出正确的方向。我认为我可以以某种方式直接将字节写入文件,但由于缺少标头,这将是一团糟。
这是我的课:
public class RadioListener {
private Runnable mRunnable, mFounderR;
private Thread mThread, mFounderT;
private SourceDataLine mSourceLine;
private TargetDataLine mTargetLine;
private DataLine.Info mTargetInfo;
private DataLine.Info mSourceInfo;
private static final AudioFormat mFormat = new AudioFormat(44100, 16, 2, true, false);
private Mixer.Info[] mixers;
private Mixer mFoundMixer = null;
private Config mConfig;
private boolean isCommunicating = false;
private boolean isRetranslating = false;
File wavFile = null;
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
AudioInputStream ais;
public RadioListener (Config cfg) {
mConfig = cfg;
mixers = AudioSystem.getMixerInfo();
mSourceInfo = new DataLine.Info(SourceDataLine.class, mFormat);
mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
try {mSourceLine = (SourceDataLine) AudioSystem.getLine(mSourceInfo);}
catch (LineUnavailableException e) {System.out.println("RadioListener output error");}
wavFile = new File("E:/RecordAudio.wav");
}
public void Start() {
if (Defines.strToIntDef(mConfig.getProperty("debugOut"), 0) == 1)
showMixers();
if (mFoundMixer == null) searchDevice();
else startCommunication();
}
public void Stop() {
if (mFoundMixer == null) return;
try {
mSourceLine.stop();
mSourceLine.close();
mTargetLine.stop();
mTargetLine.close();
} catch (Exception e) {}
finally {
isCommunicating = false;
}
}
public void Mute() {
isRetranslating = false;
}
private void searchDevice() {
mFounderR = new RadioFinder();
mFounderT = new Thread(mFounderR);
mFounderT.start();
}
private void startThread() {
startCommunication();
mRunnable = new Communicator();
mThread = new Thread(mRunnable);
mThread.start();
}
private void startCommunication() {
if (isCommunicating) {
isRetranslating = true;
return;
}
try {
mTargetLine.open(mFormat);
mTargetLine.start();
mSourceLine.open(mFormat);
mSourceLine.start();
//Line line = mFoundMixer.getLine(mSourceInfo);
//FloatControl control = (FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN);
//control.setValue(limit(control,10000));
//control.setValue(-10);
isCommunicating = true;
isRetranslating = true;
//When I'm uncommenting this two lines sound is writing to file, but I don't hear it.
//ais = new AudioInputStream(mTargetLine);
//AudioSystem.write(ais, fileType, wavFile);
} catch (Exception e) {
isCommunicating = false;
isRetranslating = false;
}
}
private class RadioFinder implements Runnable {
@Override
public void run() {
Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
for (Mixer.Info info : mixers) {
Mixer tmp = AudioSystem.getMixer(info);
//if (myMixer.isLineSupported(Port.Info.LINE_IN) || myMixer.isLineSupported(Port.Info.MICROPHONE)) {
if (tmp.isLineSupported(targetDLInfo)) {
String s = tmp.getMixerInfo().getName();
if (s.toLowerCase().contains(mConfig.getProperty("radioName").toLowerCase())) {
mFoundMixer = tmp;
try {
mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
mTargetLine = (TargetDataLine) mFoundMixer.getLine(mTargetInfo);
System.out.println("Found radio device: " + mFoundMixer.getMixerInfo().getName());
startThread();
} catch (Exception e) {
System.out.println("RadioListener input error");
mFoundMixer = null;
}
break;
}
}
}
}
}
private static void showMixers() {
ArrayList<Mixer.Info> mixInfos = new ArrayList<Mixer.Info>(Arrays.asList(AudioSystem.getMixerInfo()));
Line.Info sourceDLInfo = new Line.Info(SourceDataLine.class);
Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
Line.Info clipInfo = new Line.Info(Clip.class);
Line.Info portInfo = new Line.Info(Port.class);
String support;
for (Mixer.Info mixInfo: mixInfos) {
Mixer mixer = AudioSystem.getMixer(mixInfo);
support = ", supports ";
if (mixer.isLineSupported(sourceDLInfo))
support += "SourceDataLine ";
if (mixer.isLineSupported(clipInfo))
support += "Clip ";
if (mixer.isLineSupported(targetDLInfo))
support += "TargetDataLine ";
if (mixer.isLineSupported(portInfo))
support += "Port ";
System.out.println("Mixer: " + mixInfo.getName() + support + ", " + mixInfo.getDescription());
}
}
private class Communicator implements Runnable {
@Override
public void run() {
int numBytesRead;
byte[] targetData = new byte[mTargetLine.getBufferSize() / 5];
while (isCommunicating) {
numBytesRead = mTargetLine.read(targetData, 0, targetData.length);
System.out.println(numBytesRead);
if (numBytesRead == -1) break;
if (isRetranslating)
mSourceLine.write(targetData, 0, numBytesRead);
}
}
}
}}
谢谢!
【问题讨论】: