设置 Java 剪辑的音量

Set volume of Java Clip

有什么方法可以设置 JavaClip 的相应音量吗?

我有这个方法:

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()return是0 - 100

范围内的Integer

Volumes:

  1. 0 : No Sound
  2. 40 : Optimal Sound with headphones
  3. 60 : Optimal Sound
  4. 100: Full Sound

所以本质上这应该像 VLC 的比例(但是一半因为 VLC 来自 0 to 200)。

我发现使用 volume.setValue(-10f);

可以降低剪辑的分贝

但我更喜欢 volume.setValue(clip.getMaxVolume() * Settings.getSettings().getVolume()/100) 类型的内容。

其中 clip.getMaxVolume() 将 return 剪辑的最大音量。

根据 Andrew Davison 的 Killer Game Programming,您可以如此简单地调节音量:

float range = gainControl.getMaximum() - gainControl.getMinimum();
float gain = (range * volume) + gainControl.getMinimum();
gainControl.setValue(gain);

volume 是浮动的所需音量(0.0f 表示没有声音,1.0f 表示完整音频) gainControlFloatControl

希望你能成功!

经过反复试验,我想到了这个:

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);     
    }
}

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 传递给正常音量的两倍,a-la VLC。

作为一个无耻的插件,看看我用这些知识做了什么 - 参见 Escape the Mainframe - 一个在浏览器和桌面上运行的迷你跳跃游戏Java 申请。写在 Fantom - 玩得开心!