MASTER_GAIN FloatControl
的值以分贝为单位,意味着它是一个对数刻度,而不是线性的。
尽管分贝对于音频专业人员很有用,但我们程序员通常想要一个漂亮的线性比例尺,其中 0.0
表示无声, 0.5
表示一半音量, 1.0
表示最大音量;我指的是声音样本的正常音量。在播放音效时,我们通常不对声音剪辑进行放大,而只是减弱它们。
Decibel (dB) to Float Value Calculator 解释了将分贝转换为线性刻度背后的数学原理,但这里是代码:
在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
来将正常音量加倍,类似于VLC。
作为一个厚颜无耻的宣传,想看我如何运用这些知识,请查看逃离机房 - 一个在浏览器和桌面Java应用程序中运行的迷你跳跃游戏。使用Fantom编写 - 玩得开心!
gainControl.getMinimum()
是必要的吗?我的方法不行吗?(两个版本都可以工作)。 - nick zoum