Java Sound可以用来控制系统音量吗?
Posted
技术标签:
【中文标题】Java Sound可以用来控制系统音量吗?【英文标题】:Can Java Sound be used to control the system volume? 【发布时间】:2012-12-27 10:04:20 【问题描述】:Java Sound 为各种声音线路功能提供FloatControl
实例,以及MASTER_GAIN
和VOLUME
控制类型。
这些控件可以用来改变系统音量吗?
【问题讨论】:
【参考方案1】:不,它不能。这是改编自 coderanch 上Adjusting master volume 的答案的源代码。源代码迭代可用的行,检查它们是否具有正确类型的控件,如果是,则将它们放在附加到 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 声音音频引擎”。两者都对当前系统音量没有任何影响。
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.MASTER_GAIN
换成FloatControl.Type.VOLUME
以查看.. 没有控件。
【讨论】:
所以你在这里说的是它不可能。这是一个 JDK 错误吗? @rogerdpack JSE 没有声称要控制系统音量,所以我想,没有。但请随时向 Oracle 打开错误报告并“直接从制造商处”获得答案。 我在 linux jre 1.8.0_60 上尝试了该示例,但它不起作用;所有混音器名称都有“不支持的控制类型:音量”;你能给我小费吗? @user390525 “你能给我小费吗?”对你妈妈好点。 问题中的平台没有指定,我可以得到它;我使用的是 linux,所以这可能是音量控制不起作用的原因吗?【参考方案2】:在 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;
【讨论】:
不错的一个。但是,虽然这里显示了另外两行FloatControl.Type.MASTER_GAIN
* 行,但它们都对系统音量没有任何影响。 * FloatControl.Type.VOLUME
仍为 0 【参考方案3】:
试试这个它不会让你失望....我们可以相应地修改上面的例子。
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<mixers.length;i++)
Mixer.Info mixerInfo = mixers[i];
System.out.println("Mixer Name:"+mixerInfo.getName());
Mixer mixer = AudioSystem.getMixer(mixerInfo);
Line.Info[] lineinfos = mixer.getTargetLineInfo();
for(Line.Info lineinfo : lineinfos)
System.out.println("line:" + lineinfo);
try
Line line = mixer.getLine(lineinfo);
line.open();
if(line.isControlSupported(FloatControl.Type.VOLUME))
FloatControl control = (FloatControl) line.getControl(FloatControl.Type.VOLUME);
System.out.println("Volume:"+control.getValue());
JProgressBar pb = new JProgressBar();
// if you want to set the value for the volume 0.5 will be 50%
// 0.0 being 0%
// 1.0 being 100%
control.setValue((float) 0.5);
int value = (int) (control.getValue()*100);
pb.setValue(value);
j.add(new JLabel(lineinfo.toString()));
j.add(pb);
j.pack();
catch (LineUnavailableException e)
e.printStackTrace();
public static void main(String[] args)
new SoundMeter();
【讨论】:
此代码将使系统体积达到 50%,由代码控制:control.setValue((float) 0.5); 这似乎没有为我调整主音量(win 7)【参考方案4】:我正在使用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);
【讨论】:
以上代码不会改变 Windows 7 上的主卷。【参考方案5】:我最近也在关注同样的问题。最后,我决定用 C++ 编写一个名为 VolumeChanger.exe 的小程序,并从 java 中调用它。效果很好。您可以使用
从 java 调用 exeProcess process = new ProcessBuilder(vcpath,"-u").start();
wehre vcpath 是您的 exe 文件的路径(当然也可以是真实的)。
如果您对我如何使用此工具感兴趣,请访问muteFritz@
如果您对整个源代码感兴趣,请随时 PM 我...
【讨论】:
【参考方案6】:这是一个仅适用于 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);
这会将音量设置为 50%,因为范围是 0.1 到 7.0
【讨论】:
鉴于它不使用 Java Sound,我看不出这是对所提问题的回答(关于“使用 Java Sound”非常具体)。 该代码是否会更改整个系统的声音值或音频播放器帧中的某些特定媒体应用?以上是关于Java Sound可以用来控制系统音量吗?的主要内容,如果未能解决你的问题,请参考以下文章