选择八声道声卡的java输出线
编辑:我现在正在使用插孔(插孔音频连接套件)。见下面的答案 我的Raspberry Pi上有一个声卡,有8个输出通道(4个立体声通道),一个八进制声卡。我要做的是选择一个频道,将声音传送到其中一个频道。 使用此代码,我打印声卡的信息:选择八声道声卡的java输出线,java,audio,raspberry-pi,jack,Java,Audio,Raspberry Pi,Jack,编辑:我现在正在使用插孔(插孔音频连接套件)。见下面的答案 我的Raspberry Pi上有一个声卡,有8个输出通道(4个立体声通道),一个八进制声卡。我要做的是选择一个频道,将声音传送到其中一个频道。 使用此代码,我打印声卡的信息: mixers = AudioSystem.getMixerInfo(); for (Mixer.Info mixerInfo : mixers) { logger.debug("\n"); logger.debug("Fou
mixers = AudioSystem.getMixerInfo();
for (Mixer.Info mixerInfo : mixers) {
logger.debug("\n");
logger.debug("Found Mixer: " + mixerInfo);
Mixer m = AudioSystem.getMixer(mixerInfo);
Line.Info[] sourceLines = m.getSourceLineInfo();
for (Line.Info li : sourceLines) {
logger.debug("Found source line: " + li + " " + li.getClass());
if (li instanceof Port.Info) {
Port.Info portInfo = (Port.Info) li;
logger.debug("port found " + portInfo.getName() + " is source " + portInfo.isSource());
sourceDataLines.add(portInfo);
}
}
Line.Info[] targetLines = m.getTargetLineInfo();
for (Line.Info li : targetLines) {
logger.debug("Found target line: " + li + " " + li.getClass());
outputLines.add(li);
if (li instanceof Port.Info) {
Port.Info portInfo = (Port.Info) li;
logger.debug("port found " + portInfo.getName() + " is source " + portInfo.isSource());
outputPorts.add(portInfo);
}
}
}
private void lineClose(int soundPort) throws LineUnavailableException {
Port.Info lineInfo = outputPorts.get(soundPort);
Line line = (Port) AudioSystem.getLine(lineInfo);
line.close();
}
private void lineOpen(int l) throws LineUnavailableException {
for (int i = 0; i < outputPorts.size(); i++) {
Port.Info lineInfo = outputPorts.get(i);
Line line = (Port) AudioSystem.getLine(lineInfo);
if (l == i) {
line.open();
} else {
line.close();
}
}
}
下面是我用来从wav文件输出声音的代码:
String path = soundDirectory + soundUrl;
InputStream is = new FileInputStream(path);
BufferedInputStream bis = new BufferedInputStream(is);
AudioInputStream inputStream = AudioSystem.getAudioInputStream(bis);
AudioFormat format = inputStream.getFormat();
Mixer.Info mi = mixers[0];
SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getSourceDataLine(format,mi);
sourceDataLine.open(format);
sourceDataLine.start();
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buf)) != -1){
sourceDataLine.write(buf, 0, bytesRead);
}
inputStream.close();
sourceDataLine.drain();
sourceDataLine.stop();
sourceDataLine.close();
lineClose(soundPort);
我试过很多方法,但在所有情况下,声音都是从所有输出中发出的 我自己找到了解决办法。我现在使用插孔(插孔音频连接套件,请参阅)。 让杰克用覆盆子圆周率真是有点麻烦。有很好的信息 我使用with提供了Java和Jack之间的接口 你不能在Raspbian开箱即用的情况下运行Jack。Debian Wheezy有一个补丁,但Raspbian Jessie似乎没有。因此你需要创建一个不使用DBus的Jackd2版本。它解释了如何在没有DBus的情况下构建Jackd2。有一个障碍:你所要做的就是删除引用DBus的两行。它们告诉你的其他一切默认情况下,您要修补的代码已在Raspbian中修补,或者看起来是这样。您需要替换以下代码行: 下载源代码后,在debian/rules中进行更改
waf-configure-options += $(if $(filter linux,$(DEB_HOST_ARCH_OS)),--alsa --dbus)
became
waf-configure-options += $(if $(filter linux,$(DEB_HOST_ARCH_OS)),--alsa)
dh_install -pjackd2 debian/tmp/usr/share/dbus-1/*
became
#dh_install -pjackd2 debian/tmp/usr/share/dbus-1/*
我修改了JnaJack源代码中的SimpleAudioClient示例:
public class SimpleAudioClient {
private boolean autoconnect = true;
private JackClient client;
private Processor processor;
private Callback callback;
private ShutDownHook shutDownHook;
private JackPort[] inputPorts;
private JackPort[] outputPorts;
private FloatBuffer[] inputBuffers;
private FloatBuffer[] outputBuffers;
private float samplerate;
private int buffersize;
private volatile boolean active;
private Logger logger = Logger.getLogger(getClass().getSimpleName());
private int channelNumber = 0;
public SimpleAudioClient() throws JackException {
Jack jack = Jack.getInstance();
logger.debug("Jack instance " + jack.toString());
EnumSet<JackOptions> options = EnumSet.of(JackOptions.JackNoStartServer);
EnumSet<JackStatus> status = EnumSet.noneOf(JackStatus.class);
try {
client = jack.openClient("jna_jack", options, status);
} catch (JackException ex) {
System.out.println("ERROR : Status : " + status);
throw ex;
}
String[] inputs = new String[0];
inputPorts = new JackPort[inputs.length];
EnumSet<JackPortFlags> flags = EnumSet.of(JackPortFlags.JackPortIsInput);
for (int i = 0; i < inputs.length; i++) {
//inputPorts[i] = client.registerPort(inputs[i], JackPortType.AUDIO, flags);
}
String[] outputs = new String[]{"playback_1", "playback_2", "playback_3", "playback_4", "playback_5", "playback_6", "playback_7", "playback_8"};
outputPorts = new JackPort[outputs.length];
flags = EnumSet.of(JackPortFlags.JackPortIsOutput);
for (int i = 0; i < outputs.length; i++) {
outputPorts[i] = client.registerPort(outputs[i], JackPortType.AUDIO, flags);
}
processor = new SineAudioSource();
this.inputBuffers = new FloatBuffer[inputPorts.length];
this.outputBuffers = new FloatBuffer[outputPorts.length];
this.callback = new Callback();
this.shutDownHook = new ShutDownHook();
client.onShutdown(shutDownHook);
for (JackPort port : inputPorts) {
logger.debug("input port " + port.getType() + " " + port.getName());
}
for (JackPort port : outputPorts) {
logger.debug("output port " + port.getType() + " " + port.getName());
}
}
public void activate(int channelNr) throws JackException {
this.channelNumber = channelNr;
try {
samplerate = client.getSampleRate();
System.out.println("Sample rate = " + samplerate);
buffersize = client.getBufferSize();
System.out.println("Buffersize = " + buffersize);
processor.setup(samplerate, buffersize);
active = true;
client.setProcessCallback(callback);
client.activate();
if (autoconnect) {
doAutoconnect();
}
} catch (Exception ex) {
active = false;
throw new JackException("Could not activate Jack client");
}
}
private void doAutoconnect() throws JackException {
Jack jack = Jack.getInstance();
String[] physical = jack.getPorts(client, null, JackPortType.AUDIO,
EnumSet.of(JackPortFlags.JackPortIsInput, JackPortFlags.JackPortIsPhysical));
int count = Math.min(outputPorts.length, physical.length);
for (int i = 0; i < count; i++) {
logger.debug("output port " + outputPorts[i].getName());
jack.connect(client, outputPorts[i].getName(), physical[i]);
}
physical = jack.getPorts(client, null, JackPortType.AUDIO,
EnumSet.of(JackPortFlags.JackPortIsOutput, JackPortFlags.JackPortIsPhysical));
count = Math.min(inputPorts.length, physical.length);
for (int i = 0; i < count; i++) {
logger.debug("input port " + inputPorts[i].getName());
//jack.connect(client, physical[i], inputPorts[i].getName());
}
}
public void shutdown() {
active = false;
client.deactivate();
client.close();
}
private void processBuffers(int nframes) {
for (int i = 0; i < inputPorts.length; i++) {
inputBuffers[i] = inputPorts[i].getFloatBuffer();
}
for (int i = 0; i < outputPorts.length; i++) {
outputBuffers[i] = outputPorts[i].getFloatBuffer();
}
processor.process(channelNumber, inputBuffers, outputBuffers);
}
private class Callback implements JackProcessCallback {
public boolean process(JackClient client,final int nframes) {
if (!active) {
return false;
} else {
try {
processBuffers(nframes);
return true;
} catch (Exception ex) {
System.out.println("ERROR : " + ex);
active = false;
return false;
}
}
}
}
private class ShutDownHook implements JackShutdownCallback {
public void clientShutdown(JackClient client) {
active = false;
processor.shutdown();
}
}
public static interface Processor {
public void setup(float samplerate, int buffersize);
public void process(int channelNumber, FloatBuffer[] inputs, FloatBuffer[] outputs);
public void shutdown();
}
/**
* Create a SimpleAudioClient.
*
* @return client
* @throws org.jaudiolibs.jnajack.JackException
*/
public static SimpleAudioClient create(
) throws JackException {
return new SimpleAudioClient();
}
}
当你启动杰克时,日志应该显示出来
creating alsa driver ... hw:audioinjectoroc|-|1024|2|48000|0|0|nomon|swmeter|-|32bit
其中“audioinjector”是声卡的名称。如果显示
...hw:audioinjectoroc|hw:audioinjectoroc|1024 ...
那么,连接到它时就会出现问题
您可以使用QJackCtl查看Jack设置,您可以在Raspberry Pi上运行QJackCtl,并从另一台计算机使用X服务器进行访问。我没有在Pi上运行X Windows
如果您想通过Jack播放wav文件,这是一个很好的示例,说明如何读取wav文件并将其提供给Jack
编辑:这个示例是一个很好的起点,但您需要做一些更改。最好打开您计划使用的所有端口,调用
client.activate()
,并在JackCallback中将音频文件中的频道路由到声卡中的相应频道。您可以使用qjackctl
查看Jack中发生的情况。那么您尝试过什么呢?除了我发布的代码和它的许多变体之外,我目前正在尝试使用Jack进行JnaJack。
/usr/bin/jackd -dalsa -dhw:audioinjectoroc -r48000 -p1024 -n2 -P &
creating alsa driver ... hw:audioinjectoroc|-|1024|2|48000|0|0|nomon|swmeter|-|32bit
...hw:audioinjectoroc|hw:audioinjectoroc|1024 ...