【问题标题】:Set volume of Java Clip设置 Java Clip 的音量
【发布时间】:2016-11-09 19:53:40
【问题描述】:

有什么方法可以设置ClipJava中的对应音量吗?

我有这个方法:

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

卷:

  1. 0:没有声音
  2. 40 : 耳机的最佳音效
  3. 60:最佳声音
  4. 100:全声

所以基本上这应该像VLC 的规模(但一半,因为 VLC 来自0 to 200)。

我发现使用volume.setValue(-10f);可以降低剪辑的分贝

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

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

【问题讨论】:

    标签: java audio volume clip


    【解决方案1】:

    MASTER_GAINFloatControl 值以分贝为单位,这意味着它是对数刻度,而不是线性刻度。

    虽然分贝非常适合音频专业人士,但我们的程序员通常需要一个很好的线性刻度,其中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 - 玩得开心!

    【讨论】:

      【解决方案2】:

      根据 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

      希望你可以让它工作!

      【讨论】:

      • gainControl.getMinimum() 有必要吗?我的方法不行吗? (两个版本都可以)。
      • 我只用一个文件试过这个,这就是我问的原因,你认为其他文件可能不适用于我的方法吗?
      • 好的,我接受你的回答,如果你发现你的回答应该更新,请这样做。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        所以经过一番反复试验,我想出了这个:

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

        【讨论】:

        • 也许你想回顾一下史蒂夫的回答;正如他所说,分贝不是线性的,因此您的转换可能不会是用户所期望的,例如将音量设置为 0.5 不会是剪辑音量的一半。
        猜你喜欢
        • 1970-01-01
        • 2011-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多