Java 中的多个混音器输出
Multiple Mixer outputs in Java
我正在尝试 Java 在两个输出(前后音频插孔)中播放不同的立体声音频。
我的声卡配置为独立处理两个输出,在 Windows 混音器中我可以让它们分别发出测试声音,所以这不是卡问题。
我在 Change Mixer to output sound to in java 上尝试了使用不同输出的方法,方法是使用 AudioSystem.getClip(AudioSystem.getMixerInfo()[i]);
获得两个具有不同混音器的剪辑。但是,这行代码仅适用于 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 秒,然后结束。它打印 how do I get Mixer channels layout in java 上看到的 Mixer 信息。它当前输出到 "Java Sound Audio Engine" Mixer,尝试更改为任何其他 Mixer 会引发上述异常。
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 {
//
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 但没有任何改变,但我估计跟这个问题无关)。
换句话说,似乎无法从不同的 Mixer 输出到 Clips,因为 Java 只能输出到 "Java Sound Audio Engine",而 "Java Sound Audio Engine" 是 Windows 的默认音频设备。有什么方法可以让其他 Mixer 工作吗?是否有使用多个音频输出的替代方法?
更新:好像是this problem was already fixed,但我仍然无法让它工作。我禁用了 "Stereo Mix" 记录设备和 运行 link 中给出的示例代码,并得到了这个输出:
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 声音音频引擎可以输出声音,因为前后音频插孔的混音器都被视为输入线。通过 Windows' 默认播放设备中的 Clip 或 SourceDataLine 输出播放音频。
此外,看起来它们 solved the problem by using DirectAudio 但我仍然没有弄清楚如何使用它们。
在不同的计算机上进行测试时,我通过升级到 Java 1.6.0_17 解决了这个问题(我的环境限制仍然可以从 Matlab 调用 Java)所以将列出 DirectAudio 驱动程序(尽管它看起来应该从 Java 1.5 开始工作)。每个 DirectAudio 声音设备为每个设备提供一个 SourceDataLine 和一个 Clip。
我正在尝试 Java 在两个输出(前后音频插孔)中播放不同的立体声音频。
我的声卡配置为独立处理两个输出,在 Windows 混音器中我可以让它们分别发出测试声音,所以这不是卡问题。
我在 Change Mixer to output sound to in java 上尝试了使用不同输出的方法,方法是使用 AudioSystem.getClip(AudioSystem.getMixerInfo()[i]);
获得两个具有不同混音器的剪辑。但是,这行代码仅适用于 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 秒,然后结束。它打印 how do I get Mixer channels layout in java 上看到的 Mixer 信息。它当前输出到 "Java Sound Audio Engine" Mixer,尝试更改为任何其他 Mixer 会引发上述异常。
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 {
//
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 但没有任何改变,但我估计跟这个问题无关)。
换句话说,似乎无法从不同的 Mixer 输出到 Clips,因为 Java 只能输出到 "Java Sound Audio Engine",而 "Java Sound Audio Engine" 是 Windows 的默认音频设备。有什么方法可以让其他 Mixer 工作吗?是否有使用多个音频输出的替代方法?
更新:好像是this problem was already fixed,但我仍然无法让它工作。我禁用了 "Stereo Mix" 记录设备和 运行 link 中给出的示例代码,并得到了这个输出:
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 声音音频引擎可以输出声音,因为前后音频插孔的混音器都被视为输入线。通过 Windows' 默认播放设备中的 Clip 或 SourceDataLine 输出播放音频。
此外,看起来它们 solved the problem by using DirectAudio 但我仍然没有弄清楚如何使用它们。
在不同的计算机上进行测试时,我通过升级到 Java 1.6.0_17 解决了这个问题(我的环境限制仍然可以从 Matlab 调用 Java)所以将列出 DirectAudio 驱动程序(尽管它看起来应该从 Java 1.5 开始工作)。每个 DirectAudio 声音设备为每个设备提供一个 SourceDataLine 和一个 Clip。