I'm using JLayer to play an inputstream of mp3 data from the internet. How do i change the volume of the output?
I'm using this code to play it:
URL u = new URL(s);
URLConnection conn = u.openConnection();
conn.setConnectTimeout(Searcher.timeoutms);
conn.setReadTimeout(Searcher.timeoutms);
bitstream = new Bitstream(conn.getInputStream()/*new FileInputStream(quick_file)*/);
System.out.println(bitstream);
decoder = new Decoder();
decoder.setEqualizer(equalizer);
audio = FactoryRegistry.systemRegistry().createAudioDevice();
audio.open(decoder);
for(int i = quick_positions[0]; i > 0; i--){
Header h = bitstream.readFrame();
if (h == null){
return;
}
bitstream.closeFrame();
You may consider this an unacceptable hack, but it worked in an MP3 player I wrote. It requires a small code addition to one of the JLayer classes.
Add the following method to javazoom.jl.player.JavaSoundAudioDevice.
public void setLineGain(float gain)
{
if (source != null)
{
FloatControl volControl = (FloatControl) source.getControl(FloatControl.Type.MASTER_GAIN);
float newGain = Math.min(Math.max(gain, volControl.getMinimum()), volControl.getMaximum());
volControl.setValue(newGain);
}
}
This new method then allows you to change the volume with code like this.
if (audio instanceof JavaSoundAudioDevice)
{
JavaSoundAudioDevice jsAudio = (JavaSoundAudioDevice) audio;
jsAudio.setLineGain(yourGainGoesHere);
}
Another (non-JLayer) way to adjust the PC's speaker volume is to use classes in the javax.sound.sampled package provided by Sun/Oracle.
On my machine, SPEAKER was the only output target supported.
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.Line.Info;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Port;
public class SoundVolumeDemo
{
public static void main(String[] args)
{
Info source = Port.Info.SPEAKER;
// source = Port.Info.LINE_OUT;
// source = Port.Info.HEADPHONE;
if (AudioSystem.isLineSupported(source))
{
try
{
Port outline = (Port) AudioSystem.getLine(source);
outline.open();
FloatControl volumeControl = (FloatControl) outline.getControl(FloatControl.Type.VOLUME);
System.out.println(" volume: " + volumeControl.getValue() );
float v = 0.33F;
volumeControl.setValue(v);
System.out.println(" new volume: " + volumeControl.getValue() );
v = 0.73F;
volumeControl.setValue(v);
System.out.println("newest volume: " + volumeControl.getValue() );
}
catch (LineUnavailableException ex)
{
System.err.println("source not supported");
ex.printStackTrace();
}
}
}
}
This is how I am achieving volume control in this app:
http://onebeartoe.com/media-players/randomjuke/filesystem/java-web-start/swing/index.jsp
Please note that I have only had experience with it working on MS Windows OS machines.
Try adjusting all bands of the equalizer for the volume you’re trying to get. Maybe you can also use an EQFunction for that?
public class ChangeVolumeFunction extends EQFunction {
public double volume = 1.0;
public void setVolume(double volume) { this.volume = volume; }
public float getBand(int band) { return (float) (Math.log(volume) / Math.log(2) * 6.0); }
}
I made my own version on ChrisH's answer, but instead of changing the source code of JLayer, I did it via reflection:
Class<JavaSoundAudioDevice> clazz = JavaSoundAudioDevice.class;
Field[] fields = clazz.getDeclaredFields();
try{
SourceDataLine source = null;
for(Field field : fields) {
if("source".equals(field.getName())) {
field.setAccessible(true);
source = (SourceDataLine) field.get(device);
field.setAccessible(false);
FloatControl volControl = (FloatControl) source.getControl(FloatControl.Type.MASTER_GAIN);
if (volControl != null) {
float newGain = Math.min(Math.max(gain, volControl.getMinimum()), volControl.getMaximum());
volControl.setValue(newGain);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Kinda crude, but it works
来源:https://stackoverflow.com/questions/648107/changing-volume-in-java-when-using-jlayer