Java Sound可以用来控制系统卷吗?

Java Sound为各种声音线function提供了FloatControl实例,并提供了MASTER_GAINVOLUME控件类型。

这些控件可以用来改变系统音量吗?

不,它不能。 以下是根据coderanch上的调整主音量的答案改编的来源。 源迭代可用行,检查它们是否具有正确类型的控件,如果是,则将它们放在连接到JSlider的GUI中

 import java.awt.*; import javax.swing.*; import javax.sound.sampled.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class SoundMixer { public Component getGui() { JPanel gui = new JPanel(new GridLayout(0,1)); Mixer.Info[] mixers = AudioSystem.getMixerInfo(); System.out.println( "There are " + mixers.length + " mixer info objects"); for (Mixer.Info mixerInfo : mixers) { System.out.println("mixer name: " + mixerInfo.getName()); Mixer mixer = AudioSystem.getMixer(mixerInfo); Line.Info[] lineInfos = mixer.getSourceLineInfo(); for (Line.Info lineInfo : lineInfos) { System.out.println(" Line.Info: " + lineInfo); try { Line line = mixer.getLine(lineInfo); FloatControl volCtrl = (FloatControl)line.getControl( FloatControl.Type.MASTER_GAIN); VolumeSlider vs = new VolumeSlider(volCtrl); gui.add( new JLabel(volCtrl.toString()) ); gui.add( vs.getVolume() ); System.out.println( " volCtrl.getValue() = " + volCtrl.getValue()); } catch (LineUnavailableException e) { e.printStackTrace(); } catch (IllegalArgumentException iaEx) { System.out.println(" " + iaEx); } } } return gui; } public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { SoundMixer sm = new SoundMixer(); Component c = sm.getGui(); JOptionPane.showMessageDialog(null, c); } }; // Swing GUIs should be created and updated on the EDT // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html SwingUtilities.invokeLater(r); } } class VolumeSlider { JSlider volume; VolumeSlider(final FloatControl volumeControl) { volume = new JSlider( (int) volumeControl.getMinimum() * 100, (int) volumeControl.getMaximum() * 100, (int) volumeControl.getValue() * 100); ChangeListener listener = new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { float val = volume.getValue() / 100f; volumeControl.setValue(val); System.out.println( "Setting volume of " + volumeControl.toString() + " to " + val); } }; volume.addChangeListener(listener); } public JSlider getVolume() { return volume; } } 

在这台Windows 7机器上,我得到了两个来自“Java Sound Audio Engine”的控件。 对当前的系统容量都没有任何影响。

 run: There are 4 mixer info objects mixer name: Primary Sound Driver Line.Info: interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes java.lang.IllegalArgumentException: Unsupported control type: Master Gain Line.Info: interface Clip supporting 8 audio formats, and buffers of at least 32 bytes java.lang.IllegalArgumentException: Unsupported control type: Master Gain mixer name: Speakers (VIA High Definition Audio) Line.Info: interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes java.lang.IllegalArgumentException: Unsupported control type: Master Gain Line.Info: interface Clip supporting 8 audio formats, and buffers of at least 32 bytes java.lang.IllegalArgumentException: Unsupported control type: Master Gain mixer name: Java Sound Audio Engine Line.Info: interface SourceDataLine supporting 8 audio formats volCtrl.getValue() = 0.0 Line.Info: interface Clip supporting 8 audio formats, and buffers of 0 to 4194304 bytes volCtrl.getValue() = 0.0 mixer name: Port Speakers (VIA High Definition A Setting volume of Master Gain with current value: 0.0 dB (range: -80.0 - 13.9794) to 0.0 Setting volume of Master Gain with current value: 0.0 dB (range: -80.0 - 13.9794) to -0.41 Setting volume of Master Gain with current value: 0.0 dB (range: -80.0 - 13.9794) to -0.68 ... 

FloatControl.Type.VOLUME交换FloatControl.Type.MASTER_GAIN以查看..没有控件。

在Line初始化之后添加以下行。 这是打开线路所必需的。

 boolean opened = line.isOpen() || line instanceof Clip; if(!opened){ System.out.println("Line is not open, trying to open it..."); line.open(); opened = true; } 

试试这个它不会让你失望….我们可以相应地修改上面的例子。

 import javax.sound.sampled.AudioSystem; import javax.sound.sampled.FloatControl; import javax.sound.sampled.Line; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JProgressBar; public class SoundMeter { JFrame j; public SoundMeter() { j = new JFrame("SoundMeter"); j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); j.setLayout(new BoxLayout(j.getContentPane(), BoxLayout.Y_AXIS)); printMixersDetails(); j.setVisible(true); } public void printMixersDetails(){ javax.sound.sampled.Mixer.Info[] mixers = AudioSystem.getMixerInfo(); System.out.println("There are " + mixers.length + " mixer info objects"); for(int i=0;i 

我正在使用VOLUME控件类型。 此代码适用于XP和WIN 7,但不适用于OSX。 看我的例子:

 import java.io.IOException; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.FloatControl; import javax.sound.sampled.Line; import javax.sound.sampled.Mixer; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class VolumeExample extends JPanel { /** * @return main sound control object * @throws Exception for any problem */ private FloatControl getVolumeControl() throws Exception { try { Mixer.Info mixers[] = AudioSystem.getMixerInfo(); for (Mixer.Info mixerInfo : mixers) { Mixer mixer = AudioSystem.getMixer(mixerInfo); mixer.open(); //we check only target type lines, because we are looking for "SPEAKER target port" for (Line.Info info : mixer.getTargetLineInfo()) { if (info.toString().contains("SPEAKER")) { Line line = mixer.getLine(info); try { line.open(); } catch (IllegalArgumentException iae) {} return (FloatControl) line.getControl(FloatControl.Type.VOLUME); } } } } catch (Exception ex) { System.out.println("problem creating volume control object:"+ex); throw ex; } throw new Exception("unknown problem creating volume control object"); } VolumeExample() { JSlider slider = new JSlider(); add(slider); //this is for setting the value slider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { JSlider src = (JSlider)e.getSource(); //if (src.getValueIsAdjusting()) return; //optional if (src.getValue() % 5 !=0) return; float value = src.getValue() / 100.0f; try { getVolumeControl().setValue(value); //you can put a click play code here to have nice feedback when moving slider } catch (Exception ex) { System.out.println(ex); } } }); //and this is for getting the value try { slider.setValue((int) (getVolumeControl().getValue()*100.0f)); } catch (Exception e) { System.out.println(e); } } } 

我最近关注同样的问题。 最后,我决定在C ++中编写一个名为VolumeChanger.exe的程序,并从java中调用它。 效果很好。 你可以用java调用exe

Process process = new ProcessBuilder(vcpath,"-u").start();

wehre vcpath是你的exe文件的路径(当然可以是实例)。

如果您对我使用此工具感兴趣,请访问muteFritz

如果您对整个源代码感兴趣,请随时PM我…

这是一个仅适用于OS X的解决方案(我正在运行10.10):

 import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; public class MasterVolume { public void setMasterVolume(float value) { String command = "set volume " + value; try { ProcessBuilder pb = new ProcessBuilder("osascript","-e",command); pb.directory(new File("/usr/bin")); System.out.println(command); StringBuffer output = new StringBuffer(); Process p = pb.start(); p.waitFor(); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; while ((line = reader.readLine())!= null) { output.append(line + "\n"); } System.out.println(output); } catch(Exception e) { System.out.println(e); } } } 

您可以像这样调用方法:

 MasterVolume.setMasterVolume(3.5f); 

由于范围为.1到7.0,因此将音量设置为50%