设置Java Clip

时间:2016-11-09 19:53:40

标签: java audio volume clip

有没有办法在Clip中设置Java的相应音量?

我有这个方法:

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()返回Integer

范围内的0 - 100
  

卷:

     
      
  1. 0:没有声音
  2.   
  3. 40:带耳机的最佳声音
  4.   
  5. 60:最佳声音
  6.   
  7. 100:Full Sound
  8.   

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

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

来减少剪辑的分贝

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

clip.getMaxVolume()将返回剪辑的最大音量。

4 个答案:

答案 0 :(得分:6)

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。

答案 1 :(得分:2)

根据安德鲁戴维森的Killer Game Programming,你可以调整音量这么简单:

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

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

希望你能让它发挥作用!

答案 2 :(得分:1)

经过一番反复尝试后,我想出了这个:

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

答案 3 :(得分:0)

我相信你实际上在寻找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);     
    }
}