Java Sound爲各種聲音線路功能提供FloatControl
實例,並且這兩個控制類型均爲MASTER_GAIN
& VOLUME
控制類型。Java Sound可以用來控制系統音量嗎?
這些控件可以用來改變系統音量嗎?
Java Sound爲各種聲音線路功能提供FloatControl
實例,並且這兩個控制類型均爲MASTER_GAIN
& VOLUME
控制類型。Java Sound可以用來控制系統音量嗎?
這些控件可以用來改變系統音量嗎?
不,它不能。這裏的源代碼是根據代碼分支上的Adjusting master volume的答案改編的。該人士遍歷可用的線路,檢查他們是否有正確類型的控制,如果是的話,把他們連接到JSlider
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
看到..沒有控制。
在初始化行後添加以下行。這是打開線路所必需的。
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 *行,但它們都沒有影響系統音量。 *仍然爲0 FloatControl.Type.VOLUME –
請檢查以下代碼。 –
試試這個吧不會讓你失望....我們可以相應地修改上面的例子。
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); –
這似乎並沒有調整主音量對我來說(贏7) – rogerdpack
我正在使用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上的主音量。 – Torque
我最近集中了同樣的問題。最後,我決定用C++編寫一個名爲VolumeChanger.exe的小程序,並從java中調用它。很棒。 wehre vcpath是通向你的exe文件(可能是realtive當然的),你可以從Java調用一個exe與
Process process = new ProcessBuilder(vcpath,"-u").start();
。
如果你有興趣我是如何使用這個工具查看我的muteFritz
如果你有興趣在整個源代碼,隨時下午我......
這是隻有在有效的解決方案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%
鑑於它不使用Java聲音,我不明白這是如何回答這個問題問(這是非常具體的'使用Java聲音')。 –
代碼是否會更改整個系統聲音值或用於音頻播放器幀中的某些特定媒體應用程序? – user390525
+1很好的例子 –
所以你在這裏說的是它不是*可能的。這是一個JDK錯誤? – rogerdpack
@rogerdpack JSE沒有要求控制系統音量,所以我想,不。但隨時可以打開Oracle的錯誤報告,並直接從製造商處獲得答案。 –