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

时间:2017-11-13 16:18:28

标签: java audio

我正在制作一个程序,用于从麦克风中捕获声音,在声音扬声器上听到它(已完成)并同时将其保存到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);
        }
    }
}
}}

谢谢!

1 个答案:

答案 0 :(得分:0)

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

我使用

创建了新的“空”wav文件
  <catalog_category_default translate="label">
        <label>Catalog Category (Non-Anchor)</label>
        <reference name="left">
			<block type="catalog/navigation" name="catalog.leftnav" after="currency" template="catalog/navigation/left.phtml"/>
        </reference>
        <reference name="content">

我有44个字节的wav文件,其中标题存储。

当我需要录制一个wav文件时,当我正在实时监听它时,我需要执行以下操作:创建一个空的wav文件,编写该头文件(存储在jar中),在链接线程中追加字节。 (在我的例子中是Communicator类)它将SourceLine中的字节指向TargetLine(基本上是从麦克风到扬声器)。以下是我的问题中更新课程的代码。

P.S。:标题仅适用于指定的AudioFormat。如果你需要另一个,那么你可以单独“生成”它们。 P.S.S:抱歉我的英语不好:)

代码:

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