列出Applet中的输入和输出音频设备

时间:2011-11-01 19:11:37

标签: java javasound

我正在运行一个签名小程序,需要为用户提供选择输入和输出音频设备的能力(类似于skype提供的)。

我从其他thread借用了以下代码:

import javax.sound.sampled.*;
public class SoundAudit {
  public static void main(String[] args) { try {
    System.out.println("OS: "+System.getProperty("os.name")+" "+
      System.getProperty("os.version")+"/"+
      System.getProperty("os.arch")+"\nJava: "+
      System.getProperty("java.version")+" ("+
      System.getProperty("java.vendor")+")\n");
      for (Mixer.Info thisMixerInfo : AudioSystem.getMixerInfo()) {
        System.out.println("Mixer: "+thisMixerInfo.getDescription()+
          " ["+thisMixerInfo.getName()+"]");
        Mixer thisMixer = AudioSystem.getMixer(thisMixerInfo);
        for (Line.Info thisLineInfo:thisMixer.getSourceLineInfo()) {
            if (thisLineInfo.getLineClass().getName().equals(
              "javax.sound.sampled.Port")) {
              Line thisLine = thisMixer.getLine(thisLineInfo);
              thisLine.open();
              System.out.println("  Source Port: "
                +thisLineInfo.toString());
              for (Control thisControl : thisLine.getControls()) {
                System.out.println(AnalyzeControl(thisControl));}
              thisLine.close();}}
        for (Line.Info thisLineInfo:thisMixer.getTargetLineInfo()) {
          if (thisLineInfo.getLineClass().getName().equals(
            "javax.sound.sampled.Port")) {
            Line thisLine = thisMixer.getLine(thisLineInfo);
            thisLine.open();
            System.out.println("  Target Port: "
              +thisLineInfo.toString());
            for (Control thisControl : thisLine.getControls()) {
              System.out.println(AnalyzeControl(thisControl));}
            thisLine.close();}}}
  } catch (Exception e) {e.printStackTrace();}}
  public static String AnalyzeControl(Control thisControl) {
    String type = thisControl.getType().toString();
    if (thisControl instanceof BooleanControl) {
      return "    Control: "+type+" (boolean)"; }
    if (thisControl instanceof CompoundControl) {
      System.out.println("    Control: "+type+
        " (compound - values below)");
      String toReturn = "";
      for (Control children:
        ((CompoundControl)thisControl).getMemberControls()) {
        toReturn+="  "+AnalyzeControl(children)+"\n";}
      return toReturn.substring(0, toReturn.length()-1);}
    if (thisControl instanceof EnumControl) {
      return "    Control:"+type+" (enum: "+thisControl.toString()+")";}
    if (thisControl instanceof FloatControl) {
      return "    Control: "+type+" (float: from "+
        ((FloatControl) thisControl).getMinimum()+" to "+
        ((FloatControl) thisControl).getMaximum()+")";}
    return "    Control: unknown type";}
}

但我得到的是:

Mixer: Software mixer and synthesizer [Java Sound Audio Engine]
Mixer: No details available [Microphone (Pink Front)]

我期待得到我的设备的真实列表(我的偏好面板显示3个输出设备和1个麦克风)。我在Mac OS X 10.6.7上运行。

还有其他方法可以从Java获取该信息吗?

3 个答案:

答案 0 :(得分:4)

多年来,对于OS X的Java实现来说,这是一个非常不幸的限制,特别是对于那个平台而言是BTW,“Java Sound Audio Engine”是唯一可编程输出的音频线。因此,无论您发送到此行,即从您创建的任何Java应用程序中发送的内容,都将始终路由到已在OS X中设置为默认输出的内容,通常是内置扬声器。所以JSAE只是“默认音频输出”的Java术语。根据我们的理解 - 遗憾的是 - 最新版本仍然如此。

为什么不幸?因为它有效地禁用了甚至不起眼的音频路由。我们每天都在处理这些问题,并要求增加各种复杂性。有解决方法,但通过SoundFlower和HiJack Pro等第三方应用程序。例如www.soundPimp.com。

答案 1 :(得分:2)

也许你可以修改并使用它。以下代码用于选择我的两个Applet上的音频输出设备。我只对输出线感兴趣,而不是端口或输入线。第一部分列出了菜单栏下拉列表中选项组中的选项。第二部分根据所选选项设置混音器变量。

private void createMenuBars(){
    JMenuBar menuBar = new JMenuBar();
    menuBar.setBounds(0, 0, 60, 20);

    JMenu optionMenu = new JMenu("Options");
    JMenuItem pickMixers = new JMenuItem("Select a Playback Path");
    optionMenu.add(pickMixers);
    optionMenu.addSeparator();

    ButtonGroup mixerSelections = new ButtonGroup();

    addMixerOption("default sound system", mixerSelections, optionMenu, true);

    AudioFormat audioFmt = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
        44100, 16, 2, 4, 44100, false);
    Mixer.Info[] mixers = AudioSystem.getMixerInfo();
    for (Mixer.Info info : mixers) 
    {
        Mixer mixer = AudioSystem.getMixer(info);

        try
        {
//          System.out.println(info);
            Info sdlLineInfo = new DataLine.Info(SourceDataLine.class, audioFmt);

            // test if line is assignable
            @SuppressWarnings("unused")
            SourceDataLine sdl = (SourceDataLine) mixer.getLine(sdlLineInfo);

            // if successful, add to list
            addMixerOption(info.getName() + " <> " + info.getDescription(),
                mixerSelections, optionMenu, false);
        }
        catch (LineUnavailableException e) 
        {
            //e.printStackTrace();
            System.out.println("Mixer rejected, Line Unavailable: " + info);
        }
        catch (IllegalArgumentException e)
        {
            //e.printStackTrace();
            System.out.println("Mixer rejected, Illegal Argument: " + info);
        }           
    }

    menuBar.add(optionMenu);
    add(menuBar,0);
}

private void addMixerOption(String optionName, ButtonGroup bg, 
    JMenu menu, boolean isSelected
{
    JRadioButtonMenuItem newOption = new JRadioButtonMenuItem(optionName);
    bg.add(newOption);
    newOption.setSelected(isSelected);
    menu.add(newOption);
    newOption.addActionListener(new OptionListener());
    newOption.setActionCommand(optionName); 
}

选择一个选项时,混合变量会被设置。

public class OptionListener implements ActionListener 
{
    @Override
    public void actionPerformed(ActionEvent arg0) 
    {
        String optionName = arg0.getActionCommand();
        Boolean defaultMixer = true;

        Mixer.Info[] mixers = AudioSystem.getMixerInfo();
        for (Mixer.Info info : mixers)
        {
            if (optionName.equals(info.getName()+" <> "+info.getDescription()))
            {
                System.out.println("Option selected >  " + info.getName());
                System.out.println("    description >  " + info.getDescription());
                System.out.println("          class >  " + info.getClass());

                appMixer = AudioSystem.getMixer(info);
                System.out.println(appMixer);
                defaultMixer = false;
            }
        }
        if (defaultMixer) 
        {
            System.out.println("Using default mixer, whatever that is...");
            appMixer = null;
        }
    }
}

控制台消息过多。 我在http://hexara.com/VSL/JTheremin.htm

中使用它

答案 2 :(得分:1)

这可能是JVM不支持在OS X上检索此信息,也可能不支持您的设备。我会做两件事:

  • 尝试使用不同的JVM
  • 尝试不同的操作系统

我在linux上运行代码并且我正确地获得了所有细节:

OS: Linux 2.6.38-12-generic/amd64
Java: 1.6.0_22 (Sun Microsystems Inc.)

Mixer: the ear-candy mixer [PulseAudio Mixer]
Mixer: Direct Audio Device: default, default, default [default [default]]
Mixer: Direct Audio Device: HDA Intel, ALC662 rev1 Analog, ALC662 rev1 Analog [Intel [plughw:0,0]]
Mixer: Direct Audio Device: Plantronics Headset, USB Audio, USB Audio [Headset [plughw:1,0]]
Mixer: Direct Audio Device: USB Device 0x46d:0x8b2, USB Audio, USB Audio [U0x46d0x8b2 [plughw:2,0]]
Mixer: HDA Intel, Realtek ALC662 rev1 [Port Intel [hw:0]]
  Source Port: Mic Boost source port
    Control: Mic Boost (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
  Source Port: Capture source port
    Control: Capture (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
      Control: Select (boolean)
  Source Port: Capture source port
    Control: Capture (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
      Control: Select (boolean)
  Target Port: Master target port
    Control: Master (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Mute (boolean)
  Target Port: Headphone target port
    Control: Headphone (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
      Control: Mute (boolean)
  Target Port: Speaker target port
    Control: Speaker (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
      Control: Mute (boolean)
  Target Port: PCM target port
    Control: PCM (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
      Control: Mute (boolean)
  Target Port: Line target port
    Control: Line (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
      Control: Mute (boolean)
  Target Port: Mic target port
    Control: Mic (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
      Control: Mute (boolean)
  Target Port: Mic Boost target port
    Control: Mic Boost (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
Mixer: Plantronics Headset, USB Mixer [Port Headset [hw:1]]
  Source Port: Bass source port
    Control: Bass (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
  Source Port: Treble source port
    Control: Treble (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
  Source Port: Mic source port
    Control: Mic (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Select (boolean)
  Target Port: Bass target port
    Control: Bass (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
  Target Port: Treble target port
    Control: Treble (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
  Target Port: PCM target port
    Control: PCM (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Balance (float: from -1.0 to 1.0)
      Control: Mute (boolean)
Mixer: USB Device 0x46d:0x8b2, USB Mixer [Port U0x46d0x8b2 [hw:2]]
  Source Port: Mic source port
    Control: Mic (compound - values below)
      Control: Volume (float: from 0.0 to 1.0)
      Control: Select (boolean)