java - Java 中的多个 Mixer 输出

标签 java audio mixer javax.sound.sampled

我试图让 Java 在两个输出(正面和背面音频插孔)中播放不同的立体声音频。

我的声卡配置为独立处理两个输出,在 Windows 混音器中我可以让它们分别发出测试声音,所以这不是卡问题。

我在 Change Mixer to output sound to in java 上尝试了该方法通过使用 AudioSystem.getClip(AudioSystem.getMixerInfo()[i]); 获取具有不同混频器的两个 Clip 来使用不同的输出。但是,这行代码仅适用于 Java Sound 音频引擎 (AudioSystem.getMixerInfo()[0]),它以 Windows 的默认音频输出方式进行输出。其他任何东西都会抛出

java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian

以下示例代码生成一个 5 秒长的白噪声并播放 1 秒然后结束。它打印 Mixer 信息,如 how do I get Mixer channels layout in java 所示。 。它当前输出到“Java Sound Audio Engine”混音器,尝试更改为任何其他混音器会引发上述异常。

import java.io.ByteArrayInputStream;
import java.security.SecureRandom;
import java.util.Random;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;

public class Main {
    static int SAMPLE_RATE = 44100;
    static AudioFormat format = new AudioFormat(
            AudioFormat.Encoding.PCM_SIGNED, // Encoding
            SAMPLE_RATE,    // sample rate
            8,              // sample size in bits
            2,              // channels
            4,              // frame size
            SAMPLE_RATE,    // frame rate
            true);          // is big endian

    static int DURATION = 5;
    Thread soundThread;

    // Noise audio
    static AudioInputStream inputStream = new AudioInputStream(new ByteArrayInputStream(generateNoise(DURATION*2*SAMPLE_RATE)), format, DURATION*SAMPLE_RATE);

    public static void main(String[] args) {
        try {

            // https://stackoverflow.com/questions/12863081/how-do-i-get-mixer-channels-layout-in-java
            Mixer.Info[] mi = AudioSystem.getMixerInfo();
            for (Mixer.Info info : mi) {
                System.out.println("info: " + info);
                Mixer m = AudioSystem.getMixer(info);
                System.out.println("mixer " + m);
                Line.Info[] sl = m.getSourceLineInfo();
                for (Line.Info info2 : sl) {
                    System.out.println("    info: " + info2);
                    Line line = AudioSystem.getLine(info2);
                    if (line instanceof SourceDataLine) {
                        SourceDataLine source = (SourceDataLine) line;

                        DataLine.Info i = (DataLine.Info) source.getLineInfo();
                        for (AudioFormat format : i.getFormats()) {
                            System.out.println("    format: " + format);
                        }
                    }
                }
                System.out.println("");
            }


            // Code only works for AudioSystem.getMixerInfo()[0] 
            final Clip clip = AudioSystem.getClip(AudioSystem.getMixerInfo()[0]);
            clip.open(inputStream);

            Thread soundThread = new Thread(new Runnable() {                
                @Override
                public void run() {
                    try {
                        clip.loop(Clip.LOOP_CONTINUOUSLY);
                        Thread.sleep(1000);
                        clip.close();
                        System.exit(0);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            soundThread.start();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static byte[] generateNoise(int size) {
        byte[] out = new byte[size];
        Random r = new SecureRandom();
        r.nextBytes(out);
        return out;
    }
}

这是混合器信息。此代码在连接两个输出插孔的情况下运行,并且 Windows 将其识别为两个不同的输出设备(扬声器和耳机)。看来只有Java的音频引擎才能播放声音。

info: Java Sound Audio Engine, version 1.0
mixer com.sun.media.sound.HeadspaceMixer@22c84d9
    info: interface SourceDataLine supporting 8 audio formats
    format: PCM_SIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, 
    format: PCM_UNSIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, 
    format: PCM_SIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 
    format: PCM_UNSIGNED unknown sample rate, 8 bit, stereo, 2 bytes/frame, 
    format: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, big-endian
    format: PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, little-endian
    format: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian
    format: PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, little-endian
    info: interface Clip supporting 8 audio formats, and buffers of 0 to 4194304 bytes

info: Microsoft ?T?E???h, version Unknown Version
mixer com.sun.media.sound.SimpleInputDevice@7e0df503

info: Stereo Mixer (Realtek High Defi, version Unknown Version
mixer com.sun.media.sound.SimpleInputDevice@4650d89c

info: Port Realtek HD Audio 2nd output (Re, version 6.1
mixer com.sun.media.sound.PortMixer@65bd0dd4

info: Port Stereo Mixer (Realtek High Defi, version 6.1
mixer com.sun.media.sound.PortMixer@78b5f53a
    info: ?}?X? source port

info: Port Speakers (Realtek High Definiti, version 6.1
mixer com.sun.media.sound.PortMixer@b37c60d

由于其他限制,我使用 Java 6。另外,一些名称被破坏可能是因为我处于日语环境中,并且 Eclipse 不会以正确的编码获取名称(我尝试将所有内容更改为 UTF-8 和 Shift_JIS,但没有任何改变,但我想这与此问题无关)。

换句话说,它看起来无法从不同的混音器输出剪辑,因为 Java 只能输出到“Java Sound Audio Engine”,该引擎会转到 Windows 的默认音频设备。有什么办法让其他 Mixer 工作吗?有没有使用多个音频输出的替代方法?

更新:看起来像this problem was already fixed但我仍然无法让它工作。我禁用了“立体声混合”录音设备并运行了该链接中给出的示例代码,并得到了以下输出:

MIXER 0: Java Sound Audio Engine, version 1.0
OUTPUT LINE (SourceDataLine) 0: interface SourceDataLine supporting 8 audio formats
OUTPUT LINE (SourceDataLine) 1: interface Clip supporting 8 audio formats, and buffers of 0 to 4194304 bytes

MIXER 1: Port Realtek HD Audio 2nd output (Re, version 6.1
INPUT LINE (TargetDataLine) 0: HEADPHONE target port

MIXER 2: Port Speakers (Realtek High Definiti, version 6.1
INPUT LINE (TargetDataLine) 0: SPEAKER target port

因此,看起来只有 Java Sound Audio Engine 可以输出声音,因为前后音频插孔的混音器都被视为输入线。通过 Windows 默认播放设备中的 Clip 或 SourceDataLine 输出播放音频。

而且,看起来他们 solved问题by using DirectAudio但我还是不知道如何使用它们。

最佳答案

在不同的计算机上进行测试时,我通过升级到 Java 1.6.0_17 解决了这个问题(这仍然可以满足我从 Matlab 调用 Java 的环境限制),因此会列出 DirectAudio 驱动程序(尽管它看起来应该可以从 Java 1.5 运行)。每个 DirectAudio 声音设备都为每个设备提供一个 SourceDataLine 和一个 Clip。

关于java - Java 中的多个 Mixer 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34941893/

相关文章:

java - 好的java webmail应用程序

java - 定义一个数据输入检查方法并调用它没有帮助,android

c++ - 来自视频文件的简单帧抓取器

ios - 在 iOS 中以编程方式创建 AAC 文件?

javascript - 如何在 javascript 中播放超声波 WAV/PCM 文件而不丢失数据

python - Python,pygame.mixer:声音不起作用

java - 如何让定时器运行应用程序

java - 在Java中构造不带时区的日历

java - 使用混音器混合两个音频文件

java - 在java中获取当前音量输出