【发布时间】:2016-05-06 16:48:54
【问题描述】:
在我的 Music-Player 项目中,JLayer 有一个非常具体的问题。我想加入一些东西来调整音量,但似乎实现起来并不容易。
这是因为JLayer 本身并不支持它。我从我的项目中排除了Player 类并更改了一些方法,它可以正常播放mp3。为了调整音量,我在Player 类中添加了这个方法:
public boolean setGain(float newGain) {
if (audio instanceof JavaSoundAudioDevice) {
System.out.println("InstanceOf");
JavaSoundAudioDevice jsAudio = (JavaSoundAudioDevice) audio;
try {
jsAudio.write(null, 0, 0);
} catch (JavaLayerException ex) {
ex.printStackTrace();
}
return jsAudio.setLineGain(newGain);
}
return false;
}
然后我提取了JavaSoundAudioDevice,反编译并更改了它:
public boolean setLineGain(float gain)
{
System.out.println("Vor Source");
if (source != null)
{
System.out.println("Nach Source");
FloatControl volControl = (FloatControl) source.getControl(FloatControl.Type.MASTER_GAIN);
float newGain = Math.min(Math.max(gain, volControl.getMinimum()), volControl.getMaximum());
volControl.setValue(newGain);
return true;
}
return false;
}
还有:
public void createSource() throws JavaLayerException {
Throwable t = null;
try {
Line line = AudioSystem.getLine(getSourceLineInfo());
if (line instanceof SourceDataLine) {
source = (SourceDataLine) line;
//source.open(fmt, millisecondsToBytes(fmt, 2000));
source.open(fmt);
/*
if (source.isControlSupported(FloatControl.Type.MASTER_GAIN))
{
FloatControl c = (FloatControl)source.getControl(FloatControl.Type.MASTER_GAIN);
c.setValue(c.getMaximum());
}*/
source.start();
}
} catch (RuntimeException ex) {
t = ex;
} catch (LinkageError ex) {
t = ex;
} catch (LineUnavailableException ex) {
t = ex;
}
if (source == null) {
throw new JavaLayerException("cannot obtain source audio line", t);
}
}
但是已经实现的createSource 方法不起作用。在线上
Line line = AudioSystem.getLine(getSourceLineInfo());
我总是收到 IllegalArgumentException:
java.lang.IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_SIGNED 0.0 Hz, 16 bit, 0 channels, 0 bytes/frame, little-endian is supported.
at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:479)
at javazoom.jl.player.JavaSoundAudioDevice.createSource(JavaSoundAudioDevice.java:80)
at javazoom.jl.player.JavaSoundAudioDevice.writeImpl(JavaSoundAudioDevice.java:119)
at javazoom.jl.player.AudioDeviceBase.write(Unknown Source)
at MusikPlayer.Erweiterungen.Players.MyPlayer.setGain(MyPlayer.java:192)
at MusikPlayer.PlayerTest.main(PlayerTest.java:21)
Exception in thread "main" java.lang.IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_SIGNED 0.0 Hz, 16 bit, 0 channels, 0 bytes/frame, little-endian is supported.
at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:479)
at javazoom.jl.player.JavaSoundAudioDevice.createSource(JavaSoundAudioDevice.java:80)
at javazoom.jl.player.JavaSoundAudioDevice.writeImpl(JavaSoundAudioDevice.java:119)
at javazoom.jl.player.AudioDeviceBase.write(Unknown Source)
at MusikPlayer.Erweiterungen.Players.MyPlayer.decodeFrame(MyPlayer.java:161)
at MusikPlayer.Erweiterungen.Players.MyPlayer.play(MyPlayer.java:87)
at MusikPlayer.Erweiterungen.Players.MyPlayer.play(MyPlayer.java:66)
at MusikPlayer.PlayerTest.main(PlayerTest.java:22)
有人知道为什么会这样吗?有谁知道如何解决这个问题?
【问题讨论】:
-
你是从 GitHub 上的ccm.libs.javazoom.jl.player.JavaSoundAudioDevice 开始的吗?它似乎是开源的,所以我认为不需要反编译任何东西。
-
据我比较,两个类是相同的。我刚刚从我的 jlayer 库中反编译了这个类:javazoom.net/javalayer/sources.html
-
从 GitHub 下载项目并进行调试。这个问题需要对这个库有深入的了解。这就是它是开源的优势:您可以自己找到问题。
-
如果我将 getSourceDataInfo() 中使用的格式从
fmt = new AudioFormat(decoder.getOutputFrequency(), 16, decoder.getOutputChannels(), true, false);更改为new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);我不会收到异常,但我不会从 audioFile 中听到任何声音,只会听到令人讨厌的尖叫声。任何可以在这里工作的 AudioFormat 的猜测?
标签: java volume javasound jlayer