Définir le volume du clip Java


Existe-t-il un moyen de définir le volume respectif d'un Clip dans Java?

, j'ai cette méthode:

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

Le Settings.getSettings().getVolume() renvoie un Integer dans la gamme de 0 - 100

Volumes:

  1. 0: Pas de son
  2. 40: Son optimal avec un casque
  3. 60: Son optimal
  4. 100: Son complet

Donc essentiellement cela devrait être comme l'échelle de VLC (mais la moitié puisque VLC est de 0 to 200).

J'ai trouvé que je peux réduire le décibel du clip en utilisant volume.setValue(-10f);

Mais je préférerais quelque chose du type volume.setValue(clip.getMaxVolume() * Settings.getSettings().getVolume()/100).

clip.getMaxVolume() renverrait le volume maximum du clip.

Author: nick zoum, 2016-11-09

4 answers

Selon Killer Game Programming par Andrew Davison, vous pouvez régler le volume aussi simple:

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

volume étant le volume souhaité en float (0.0 f signifie pas de son, 1.0 f signifie audio complet) gainControl est le FloatControl

J'espère que vous pouvez le faire fonctionner!

 1
Author: Squiddie, 2016-11-09 20:18:11

Le MASTER_GAIN FloatControl la valeur est en décibels, ce qui signifie que c'est une échelle logarithmique, pas linéaire.

Alors que décibels est idéal pour les professionnels de l'audio, les programmeurs américains veulent généralement une belle échelle linéaire où 0.0 est silencieux, 0.5 est demi-volume, et 1.0 est plein volume; par ce que je veux dire le volume normal pour l'échantillon sonore. Lors de la lecture d'effets sonores, nous n'amplifions généralement pas les clips sonores, nous les atténuons simplement.

Décibel (dB) à Valeur Flottante Calculator explique les mathématiques derrière la conversion des décibels à une échelle linéaire, mais voici le code:

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

Et converti en 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));
}

Remarque il n'est pas nécessaire d'impliquer clip.getMaxVolume() ou clip.getMinVolume(), car un volume de 1.0 correspond 0 Db (pas de changement) et un volume de 0.1 correspond -20 Db (très, très calme).

Si vous vouliez amplifier le clip sonore, rien ne vous empêche de passer 2.0 à double le volume normal, a-la VLC.

 5
Author: Steve Eynon, 2016-11-22 16:40:08

Donc, après un peu d'essais et d'erreurs, j'ai trouvé ceci:

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();
    }
}
 1
Author: nick zoum, 2016-11-09 20:27:08

Je crois que vous cherchez réellement le FloatControl.Type.Contrôle du VOLUME, plutôt que MASTER_GAIN. Essayez ceci:

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);     
    }
}
 0
Author: joshuaneigh, 2016-11-09 20:22:20