简体   繁体   English

使用Java混音器混合两个音频流

[英]Mixing two streams of audio using Java mixer

I want to mix two streams of audio using a java mixer, and write the output into a file. 我想使用Java混音器混合两个音频流,然后将输出写入文件。

To do so, I capture the input of my two microphones by reading from the TargetDataLines of my microphone mixers: 为此,我通过读取麦克风混音器的TargetDataLines来捕获两个麦克风的输入:

    //microphone TargetDataLines
    TargetDataLine finalIn = null;
    TargetDataLine finalIn2 = null;

    Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
    for (Mixer.Info info: mixerInfos){

        Mixer m = AudioSystem.getMixer(info);
        Line.Info[] lineInfos = m.getSourceLineInfo();
        System.out.println("****mixer name:" + info.getName());
        if(info.getName().equals("C920 [plughw:1,0]"))
            finalIn=(TargetDataLine) m.getLine(m.getTargetLineInfo()[0]);
        if(info.getName().equals("C920_1 [plughw:3,0]"))
            finalIn2=(TargetDataLine) m.getLine(m.getTargetLineInfo()[0]);

        for (Line.Info lineInfo:lineInfos){
            System.out.println ("\n source line info: "+lineInfo);
        }
        lineInfos = m.getTargetLineInfo();
        for (Line.Info lineInfo:lineInfos){
            System.out.println ("target line info: "+lineInfo);
        }

    }

    AudioFormat format = new AudioFormat(8000,16, 1, true,false);

    finalIn.open(format,2000);
    finalIn.start();
    finalIn2.open(format,2000);
    finalIn2.start();

    int numBytesRead;
    byte[] targetData = new byte[finalIn.getBufferSize() / 5];

    int numBytesRead2;
    byte[] targetData2 = new byte[finalIn2.getBufferSize() / 5];

    while (true) {
            numBytesRead = finalIn.read(targetData,0,targetData.length);
            numBytesRead2 = finalIn2.read(targetData2, 0, targetData2.length);

The resulting data captured from the microphones will be in targetData , targetData2 . 从麦克风捕获的结果数据将位于targetDatatargetData2 Now I want to mix these two byte arrays containing my sound samples received from the microphone into a new byte array and I want to use another Java mixer for that . 现在,我要将包含从麦克风接收到的声音样本的这两个字节数组混合到一个新的字节数组中, 并且我想为此使用另一个Java混合器

To do so, I create two SourceDataLine and one TargetDataLine using the following code: 为此,我使用以下代码创建两个SourceDataLine和一个TargetDataLine:

        DataLine.Info targetInfo = new DataLine.Info(TargetDataLine.class, format);
        DataLine.Info sourceInfo = new DataLine.Info(SourceDataLine.class, format);
        SourceDataLine sourceLine = (SourceDataLine) AudioSystem.getLine(sourceInfo);
        SourceDataLine sourceLine2 = (SourceDataLine) AudioSystem.getLine(sourceInfo);

        sourceLine.open(format,2000);
        sourceLine.start();

        sourceLine2.open(format,2000);
        sourceLine2.start();

        TargetDataLine targetLine = (TargetDataLine)        AudioSystem.getLine(targetInfo);
        targetLine.open(format,2000);
        targetLine.start();

and then inside the "while" I will add: 然后在“ while”中添加:

    byte[] result = new byte[finalIn.getBufferSize() / 5];

    while (true) {
            numBytesRead = finalIn.read(targetData,0,targetData.length);
            numBytesRead2 = finalIn2.read(targetData2, 0, targetData2.length);

            sourceLine.write(targetData, 0, numBytesRead);
            sourceLine.write(targetData2, 0, numBytesRead2);
            targetLine.read(result, 0, numBytesRead2);
    }

however, while the sound is actually played properly through my headphones, the result array stays empty. 但是,尽管实际上可以通过耳机正确播放声音,但结果数组仍为空。 How can I solve this problem? 我怎么解决这个问题? What am I doing wrong? 我究竟做错了什么?

I wonder if you have a misconception about what a Java Mixer does. 我想知道您是否对Java Mixer的功能有误解。 I think this class was poorly named, because of my background experience as an audio engineer. 由于我作为音频工程师的背景经验,我认为这门课的名字不好。 In my mind, a mixer is where you combine various audio tracks. 在我看来,混音器是您组合各种音轨的地方。 This is not what a Java Mixer does. 不是 Java Mixer所做的。

I think to do what you want to do, you need to read your two lines in parallel. 我想做您想做的事,您需要并行阅读两行。 For each, you will read a buffer of bytes, and will have to convert the bytes to PCM data. 对于每个,您将读取一个字节缓冲区,并且必须将字节转换为PCM数据。 Then, you can add the PCM data together and convert that back to bytes and output it. 然后,您可以将PCM数据加在一起,然后将其转换回字节并输出。

There is a good tutorial that shows how to get at the individual bytes/frames here . 这是一个很好的教程,演示如何在单个字节/帧拿到这里 A short way down the page, there is a code example. 在页面的很短距离内,有一个代码示例。 Pay attention to the location of the comment: 注意注释的位置:

// Here, do something useful with the audio data that's 
// now in the audioBytes array...

This example reads from an AudioInputStream, but the technique for getting at the individual bytes from TargetDataLines is not that different. 此示例从AudioInputStream读取,但是从TargetDataLines获取单个字节的技术没有太大不同。 Of course, you would be reading from both lines instead of from the single AIS. 当然,您将从两条线而不是从单个AIS读取。 And the "useful thing" you would be doing is simply adding the PCM data on a per-frame basis, in parallel. 而您要做的“有用的事情”就是简单地每帧并行添加PCM数据。

Once you have the summed the audio data, you could maybe use some code I wrote and posted at another site, that takes a PCM stream and writes it out as a wav file. 对音频数据求和后,就可以使用在另一个站点上编写和发布的代码 ,该代码将PCM流作为wav文件写出。 Hopefully the discussion on that page is clear enough for you to follow. 希望该页面上的讨论足够清晰,您可以关注。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM