使用 JLayer 时在 Java 中更改音量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/648107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Changing volume in Java when using JLayer
提问by Penchant
I'm using JLayer to play an inputstream of mp3 data from the internet. How do i change the volume of the output?
我正在使用 JLayer 播放来自互联网的 mp3 数据输入流。如何改变输出的音量?
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();
回答by ChrisH
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.
你可能认为这是一个不可接受的黑客,但它在我写的 MP3 播放器中工作。它需要向 JLayer 类之一添加少量代码。
Add the following method to javazoom.jl.player.JavaSoundAudioDevice.
将以下方法添加到 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);
}
回答by onebeartoe
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.
另一种(非 JLayer)调整 PC 扬声器音量的方法是使用 Sun/Oracle 提供的 javax.sound.sampled 包中的类。
On my machine, SPEAKER was the only output target supported.
在我的机器上,SPEAKER 是唯一支持的输出目标。
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
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.
请注意,我只有在 MS Windows 操作系统机器上使用它的经验。
回答by Gikkman
I made my own version on ChrisH's answer, but instead of changing the source code of JLayer, I did it via reflection:
我根据 ChrisH 的回答制作了自己的版本,但我没有更改 JLayer 的源代码,而是通过反射来完成的:
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
有点粗糙,但它有效
回答by Bombe
Try adjusting all bands of the equalizer for the volume you're trying to get. Maybe you can also use an EQFunctionfor that?
尝试根据您想要获得的音量调整均衡器的所有频段。也许您也可以为此使用EQFunction?
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); }
}

