Can Java Sound be used to control the system volume?
Solution 1
No, it cannot. Here is source adapted from an answer to Adjusting master volume on coderanch. The source iterates the available lines, checks if they have a control of the right type, and if so, puts them in a GUI attached to a 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;
}
}
On this Windows 7 machine I get two controls, both from the "Java Sound Audio Engine". Neither has any effect on the current system volume.
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
...
Swap FloatControl.Type.MASTER_GAIN
for FloatControl.Type.VOLUME
to see.. no controls.
Solution 2
add following line just after Line is initialized. this is required to open the 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;
}
Solution 3
try this it wont disappoint you.... we can modify upper example accordingly.
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();
}
}
![Andrew Thompson](https://i.stack.imgur.com/yOfDr.png?s=256&g=1)
Andrew Thompson
Java desktop app. enthusiast (for the x-platform, rich client experience). No strong opinions on technologies, platforms etc. beyond that. Author of the SSCCE and wrote the initial draft of the MCVE at SO. Also seen at DrewTubeish. Some of the tools formerly available at my pscode.org domain can be downloaded from my Google Share Drive. At StackExchange: Completed the Java Web Start, JNLP, Applet & Java Sound tag information pages. Top user in same tags. Asked the How to create screenshots? FAQ & wrote the Why CS teachers should stop teaching Java applets blog post. One of the most prolific editors of questions & answers. Most active on StackOverflow but also seen at other places around StackExchange such as Space Exploration, Sci-Fi & Fantasy & Movies & TV.
Updated on July 16, 2022Comments
-
Andrew Thompson almost 2 years
Java Sound offers
FloatControl
instances for various sound line functionality, and both aMASTER_GAIN
&VOLUME
control type.Can these controls be used to change the system volume?
-
Andrew Thompson about 11 yearsNice one. But while that shows two more
FloatControl.Type.MASTER_GAIN
* lines here, none of them have any affect on system volume. * Still 0 forFloatControl.Type.VOLUME
-
Kislay Sinha about 11 yearsthis code will make system volume to 50% which governed by code :control.setValue((float) 0.5);
-
Torque about 11 yearsThe above code does not change the master volume on Windows 7.
-
rogerdpack almost 11 yearsThis does not seem to adjust the master volume for me (win 7)
-
rogerdpack almost 11 yearsSo what you're saying here is that it's not possible. Is this a JDK bug?
-
Andrew Thompson almost 11 years@rogerdpack The JSE makes no claims to controlling system volume so I imagine, no. But feel free to open a bug report with Oracle and get an answer 'direct from the manufacturer'.
-
Andrew Thompson over 9 yearsGiven it does not use Java Sound, I cannot see how this is an answer to the question asked (which was quite specific about 'using Java Sound').
-
user390525 about 8 yearsDoes the code changes the whole system sound value or for some specific media app in frames of audio player for example?
-
user390525 about 8 yearsI tried the sample on linux jre 1.8.0_60 but it doesn't work; all mixer names have "Unsupported control type: Volume"; Could you give me a tip?
-
Andrew Thompson about 8 years@user390525 "Could you give me a tip?" Be good to your mum.
-
user390525 about 8 yearsThe platform in the question is not specified, as I can get it; I am using linux so may that be the reason volume control doesn't work?
-
Andrew Thompson about 8 years@user390525 ".. I am using linux so may that be the reason volume control doesn't work?" Yep, looks like. Java Sound on Mac was always patchy, and while an audio 'loop back' was available on Windows, it did not seem to be available on Mac. Not sure with the case on Linux but always noted that Java Sound support was inconsistent across Java implementations (JREs).
-
user390525 about 8 years@AndrewThompson Ok thanks seems like the issue for linux is much deeper than I expected first :) So the Java Sound API is a bit platform dependent stuff my bad :P But is it always like that in linux or the volume control issue has started since some let say jre/linux version?
-
Andrew Thompson about 8 years@user390525 "But is it always like that in linux or the volume control issue has started since some let say jre/linux version?" Not sure, sorry.