java - java捕获声音并听到并同时将其录制到WAV

标签 java audio

我正在制作一个程序,可捕获麦克风中的声音,并在扬声器上收听(完成)并同时将其保存到wav文件中。我在这个问题上搜索了三到四天。我相信,Stackoverflow可以帮助我。

我需要做的就是在用户实时收听的同时,将来自麦克风的声音写入到wav文件中。请帮助或指出正确的方向。我认为我可以以某种方式直接将字节写入文件,但是由于缺少 header ,这会很麻烦。

这是我的课:

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);
        }
    }
}
}}

谢谢!

最佳答案

好吧,我来了下面的工作代码。

我创建了新的“空” wav文件,

ais = new AudioInputStream(mTargetLine);
AudioSystem.write(ais, fileType, wavFile);

我得到了44个字节的wav文件,文件头存储在其中。

当我需要记录一个wav文件时,当我实时对其进行liSTListing时,我需要执行以下操作:创建一个空的wav文件,写入该 header (存储在jar中),在链接线程中附加字节。 (在我的情况下是Communicator类)它是将字节从SourceLine定向到TargetLine(基本上是从麦克风到扬声器)。这是我的问题中更新后的类(class)的代码。

P.S .: header 仅用于指定的AudioFormat。如果您需要另一个,则可以分别“生成”它们。
P.S.S:对不起,我的英语不好:)

编码:
public class RadioListener {
private Runnable mRunnable, mFounderR;
private Thread mThread = null, mFounderT = null;

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;

private static final String mHeader = "header.wav";
//private File wavFile = null;
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
AudioInputStream ais;
private FileOutputStream fos;
private boolean isRecording = false;

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 disposeListener() {
    if (isRecording) stopRecording();

    Stop();

    if (mFounderT != null)
        if (mFounderT.isAlive())
            mFounderT.interrupt();

    if (mThread != null)
        if (mThread.isAlive())
            mThread.interrupt();
}

public void Mute() {
    isRetranslating = false;
}

public void enableRecording (boolean f) {
    if (f) startRecording();
    else stopRecording();
}

public boolean isRecording() {
    return isRecording;
}

private void startRecording() {
    final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
    Date date = new Date(System.currentTimeMillis());
    String dt = formatter.format(date);
    final InputStream stream = this.getClass().getResourceAsStream("/" + mHeader);
    byte b[] = new byte[44];
    try {
        fos = new FileOutputStream(Defines.getCurrentFolder() + File.separator + dt + ".wav", true);
        try {
            stream.read(b, 0, 44);
            fos.write(b);
        } catch (IOException e) {
            try {fos.close();}
            catch (IOException e1) {;}
            isRecording = false;
            return;
        }

    } catch (FileNotFoundException e) {
        isRecording = false;
    }
    isRecording = true;
}

private void stopRecording() {
    isRecording = false;

    try {fos.close();}
    catch (IOException e) {;}
    isRecording = 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;

        //ais = new AudioInputStream(mTargetLine); //ok
        //AudioSystem.write(ais, fileType, wavFile); //ok
    } 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);

            if (numBytesRead == -1) break;

            if (isRetranslating)
                mSourceLine.write(targetData, 0, numBytesRead);

            if (isRecording) {
                try {fos.write(targetData);}
                catch (IOException e) {stopRecording();}
            }
        }
    }
}

}

关于java - java捕获声音并听到并同时将其录制到WAV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47268870/

相关文章:

java - 为什么库没有正确处理 HashMap 初始容量?

node.js - 我的node.js流代码有什么问题?

java - 如何将 org.apache.http.legacy 添加到 sbt 中

java - 即时重绘和验证

qt - 用QAudioOutput播放ulaw文件

audio - 音调识别智能手机上的音符,pt。 2

audio - FFMPEG 1 音频 + 1 静止图像 + 多次图像帧

facebook - 将音频文件上传到Facebook和Twitter

java - 在 Android 上使用 Redux 显示 Flash 消息

java - 如何检索weblogic域名主页?