设置Java Clip的音量
有没有办法在Java
设置Clip
的相应音量?
我有这个方法:
public static void play(Clip clip) { if (Settings.getSettings().isVolumeOn()) { FloatControl volume = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); volume.setValue(-1 * Settings.getSettings().getVolume()); clip.start(); } }
Settings.getSettings().getVolume()
返回0 - 100
范围内的Integer
卷:
- 0:没有声音
- 40:带耳机的最佳声音
- 60:最佳声音
- 100:完整的声音
所以基本上这应该像VLC
的规模(但是一半,因为VLC从0 to 200
)。
我发现我可以通过使用volume.setValue(-10f);
来减少剪辑的分贝volume.setValue(-10f);
但我更喜欢某种类型的卷volume.setValue(clip.getMaxVolume() * Settings.getSettings().getVolume()/100)
。
其中clip.getMaxVolume()
将返回剪辑的最大音量。
根据安德鲁戴维森的杀手游戏编程 ,您可以调整音量这么简单:
float range = gainControl.getMaximum() - gainControl.getMinimum(); float gain = (range * volume) + gainControl.getMinimum(); gainControl.setValue(gain);
volume
是float中所需的音量(0.0f表示无声音,1.0f表示完整音频) gainControl
是FloatControl
希望你能得到它的工作!
MASTER_GAIN FloatControl
值以分贝为单位,这意味着它是对数刻度,而不是线性刻度。
虽然分贝非常适合音频专业人士,但我们的程序员通常需要一个很好的线性标度,其中0.0
是静音, 0.5
是半音量, 1.0
是全音量; 我的意思是声音样本的正常音量。 播放声音效果时,我们通常不会放大声音片段,只是将它们衰减。
浮点值计算器的分贝(dB)解释了将分贝转换为线性刻度的数学,但这里是代码:
在Fantom :
using [java] javax.sound.sampled::Clip using [java] javax.sound.sampled::FloatControl using [java] javax.sound.sampled::FloatControl$Type as FType ... private Clip clip Float volume { get { gainControl := (FloatControl) clip.getControl(FType.MASTER_GAIN) return 10f.pow(gainControl.getValue / 20f) } set { if (it < 0f || it > 1f) throw ArgErr("Invalid volume: $it") gainControl := (FloatControl) clip.getControl(FType.MASTER_GAIN) gainControl.setValue(20f * it.log10) } }
并转换为Java:
import javax.sound.sampled.Clip; import javax.sound.sampled.FloatControl; ... private Clip clip public float getVolume() { FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); return (float) Math.pow(10f, gainControl.getValue() / 20f); } public void setVolume(float volume) { if (volume < 0f || volume > 1f) throw new IllegalArgumentException("Volume not valid: " + volume); FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); gainControl.setValue(20f * (float) Math.log10(volume)); }
注意,不需要涉及clip.getMaxVolume()
或clip.getMinVolume()
因为1.0
的体积对应于0 Db
(无变化),而体积0.1
对应于-20 Db
(非常非常安静)。
如果你确实想要放大声音片段,那么就没有什么可以阻止你通过2.0
来加倍正常音量,即a-la VLC。
经过一些试验和错误后,我想出了这个:
public static void play(Clip clip) { if (Settings.getSettings().isVolumeOn()) { FloatControl control = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); int volume = Settings.getSettings().getVolume(); float range = control.getMinimum(); float result = range * (1 - volume / 100.0f); control.setValue(result); clip.start(); } }
我相信你实际上在寻找FloatControl.Type.VOLUME控件,而不是MASTER_GAIN。 尝试这个:
public static void setVolume(Clip clip, int level) { Objects.requireNonNull(clip); FloatControl volume = (FloatControl) clip.getControl(FloatControl.Type.VOLUME); if (volume != null) { volume.setValue(level / 100.0); } }