it-swarm.com.de

Android: MediaPlayer setVolume-Funktion

über die Parameter Legen Sie fest, was den Player auf keinen Ton und keinen vollen Sound ausgeben soll

Vielen Dank

50
Qing

Diese Funktion ist wirklich wunderbar. Dank ihr können Sie eine Volumenskala mit beliebig vielen Schritten erstellen!

Nehmen wir an, Sie wollen 50 Schritte:

int maxVolume = 50;

Um setVolume auf einen beliebigen Wert in diesem Bereich (0-49) festzulegen, führen Sie folgende Schritte aus:

float log1=(float)(Math.log(maxVolume-currVolume)/Math.log(maxVolume));
yourMediaPlayer.setVolume(1-log1);

Schön und einfach! Verwenden Sie den AudioManager NICHT zum Einstellen der Lautstärke! Dies hat viele Nebeneffekte wie das Deaktivieren des Silent-Modus zur Folge, der die Benutzer verrückt machen wird!

108
ssuukk

Nach der user100858 solution poste ich einfach meinen genauen Code, der funktioniert:

private final static int MAX_VOLUME = 100;
...
...
final float volume = (float) (1 - (Math.log(MAX_VOLUME - soundVolume) / Math.log(MAX_VOLUME)));
mediaPlayer.setVolume(volume, volume);

soundVolume ist die Lautstärke, die Sie einstellen möchten, zwischen 0 und MAX_VOLUME . In diesem Beispiel also zwischen 0 und 100.

47
Tomasz

Bei der Suche nach Android MediaPlayer.setVolume , Scheint das Web 0.0f für keinen Ton zu zeigen, 1.0f für vollen Ton. 

40
typo.pl

Die anderen Antworten hier sind nicht richtig - oder zumindest nicht richtig konfiguriert.

Führen Sie den folgenden Test mit ihrem Code aus (z. B. Tomasz oder Ssuukk):

1) Stellen Sie 100 als "maximale Lautstärke"/Anzahl der Schritte ein und senden Sie die Lautstärke 50.

Es gibt zurück: 0.150514997831991

2) Stellen Sie 1000 als "Maximalvolumen"/Anzahl der Schritte ein und senden Sie das Volume 500.

Was gibt es zurück? Derselbe Wert, 0,150514997831991, richtig?

Nee. Es ist stattdessen: 0.100343331887994

Mit anderen Worten: Die vorhandenen Antworten ändern die Skalierung des Eingangsvolumenprozentsatzes (d. H. Der Transformationskurve) basierend auf der Anzahl der eingestellten Volumenschritte .

Ich habe die letzten Stunden damit verbracht, mich mit diesem Thema zu beschäftigen. genug, dass ich nicht zu sehr ins Detail gehen möchte, um das Problem zu erklären. Stattdessen werde ich einfach den großen Code/Kommentarblock in meinem Programm dazu posten. (es ist in C #, für Xamarin Android, aber die Funktionalität sollte für Java gleich sein)

public enum VolumeScaleType
{
    //Energy, // what MediaPlayer possibly treats passed values as
    Amplitude, // what MediaPlayer most likely treats passed values as
    Loudness // what people treat everyday volume values as (as in "that sounded 2 times as loud")
}

// MediaPlayer
/*public static void SetVolume_IncorrectSOApproach(this MediaPlayer s, double volume, VolumeScaleType volumeType = VolumeScaleType.Loudness)
{
    const int maxVolume = 100;
    var volume_toScale = volume * maxVolume;
    double volume_scalar = volumeType == VolumeScaleType.Amplitude ? volume : (1 - (Math.Log(maxVolume - volume_toScale) / Math.Log(maxVolume)));
    s.SetVolume((float)volume_scalar, (float)volume_scalar);
}*/

public static void SetVolume_MyPossiblyCorrectApproach(this MediaPlayer s, double volume, VolumeScaleType volumeType = VolumeScaleType.Loudness)
{
    // Links:
    // 1) http://en.wikipedia.org/wiki/Decibel
    // 2) http://trace.wisc.edu/docs/2004-About-dB
    // 3) http://hyperphysics.phy-astr.gsu.edu/hbase/sound/loud.html
    // 4) http://www.animations.physics.unsw.edu.au/jw/dB.htm
    // 5) http://www.soundmaskingblog.com/2012/06/saved_by_the_bell
    // 6) http://www.campanellaacoustics.com/faq.html
    // 7) http://physics.stackexchange.com/questions/9113/how-sound-intensity-db-and-sound-pressure-level-db-are-related
    // 8) http://www.sengpielaudio.com/calculator-loudness.htm (note: page uses terms 'power/intensity' and 'pressure' differently; power/intensity: for whole Shell at distance, pressure: field-quantity?)
    // basic idea: you can think of one decibel (of gain), + or -, as *translating into* the given changes-in/multipliers-for energy, amplitude, or loudness
    // (i.e. one decibel provides a specific amount to multiply energy, amplitude, and loudness values, such that they remain aligned realistically)
    // note: the 'one decibel' unit is set up to correspond roughly to a change in loudness just substantial enough to be noticeable
    // note: the 'quietest perceivable sound' example (standard) base has these absolute values: 'e' is 1 pico-watt per square-foot, 'a' is 20 micropascals, 'l' is the quietest-perceivable-loudness

    // references (for q.p.s. base)   | db (gain) | energy           | amplitude            | loudness
    // ===============================================================================================
    // actual silence                 | -inf      | 0                | 0                    | 0
    // (a seeming silence)            | -20       | e / 100          | a / 10               | 0 (would be l / 4, if 'l' weren't already for the quietest-perceivable-sound)
    // (a seeming silence)            | -10       | e / 10           | a / 3.16227/sqrt(10) | 0 (would be l / 2, if 'l' weren't already for the quietest-perceivable-sound)
    // quietest perceivable sound     | 0         | e                | a                    | l
    // ?                              | 1         | e * 1.258925     | a * 1.122018         | l * 1.071773
    // rustling leaves                | 10        | e * 10           | a * 3.16227/sqrt(10) | l * 2
    // whisper, or rural nighttime    | 20        | e * 100          | a * 10               | l * 4
    // watch ticking                  | 30        | e * 1000         | a * 31.622/sqrt(100) | l * 8
    // quiet speech, or rural daytime | 40        | e * 10000        | a * 100              | l * 16
    // dishwasher in next room        | 50        | e * 100000       | a * 316/sqrt(100000) | l * 32
    // ordinary conversation          | 60        | e * 1000000      | a * 1000             | l * 64
    // ===============================================================================================

    // assuming MediaPlayer.SetVolume treats passed values as Amplitude
    Func<double, double> convertLoudnessToAmplitude = loudness=>Math.Pow(10, Math.Log(loudness, 4));
    var volume_amplitude = volumeType == VolumeScaleType.Amplitude ? volume : convertLoudnessToAmplitude(volume);
    s.SetVolume((float)volume_amplitude, (float)volume_amplitude);
    // assuming MediaPlayer.SetVolume treats passed values as Energy
    //Func<double, double> convertLoudnessToEnergy = loudness=>Math.Pow(100, Math.Log(loudness, 4));
    //var volume_energy = volumeType == VolumeScaleType.Energy ? volume : convertLoudnessToEnergy(volume);
    //s.SetVolume((float)volume_energy, (float)volume_energy);
}

Fazit

Die Dokumentation ist spärlich, daher kann ich nicht genau wissen, ob ich das richtige Skalierungssystem/Gerätetyp für die SetVolume-Methode habe.

Vorausgesetzt, es erwartet einen Amplitude-Wert, kann der obige Code der korrekte Lautstärkeeinstellcode sein. (Eingabe der gewünschten linearen Lautstärke als Eingabe und Ausgabe/Einstellung des für die integrierte SetVolume-Methode erforderlichen Amplitudenwerts)

Ich bin nicht sicher, ob es richtig ist, und bin zu müde, um es zu bestätigen. Wenn jemand weitere Gedanken hat, können Sie diese gerne hinzufügen. (3 Stunden sind genug, um an einem Tag wie diesem an einem Tag zu arbeiten)

Bearbeiten

Nachdem Sie sorgfältig zugehört haben und den Lautheit-Fade-Effekt verglichen haben

  1. Senden Sie einfach die gewünschte Lautstärke an die SetVolume-Methode.
  2. Potenzieren Sie (im Prinzip) die gewünschte Lautstärke vor dem Senden, um sie zu einem Amplitudenwert (oder ähnlichem) zu machen, den die SetVolume-Methode erwartet.

Ich finde, Option 1 scheint näher an einer linearen Einblendung der Lautstärke zu sein! Mit anderen Worten: Durch das tatsächliche Zuhören und Vergleichen des grundlegenden Ansatzes mit den verschiedenen hier gezeigten Transformationsansätzen scheint die Dokumentation falsch zu sein und die SetVolume-Methode erwartet tatsächlich nur den Lautheitswert auf einer linearen Skala. (Vielleicht haben sie es aktualisiert, um in einer der letzten API-Versionen intuitiver zu arbeiten, haben aber die Dokumente nicht aktualisiert?)

Wenn ja, macht das sicher einfach. Das ist es, mit dem ich vorerst gehe. (Obwohl ich den Exponentiation/Scale-Fixing-Ansatz als Programmeinstellung beibehalten möchte, nehme ich an, nur um eine Entschuldigung zu haben, um ein Ergebnis dieser ganzen Zeit zu behalten!)

11
Venryx

Die empfohlene Antwort ist falsch, wie Venryx feststellt. Protokollmathematik funktioniert nicht auf diese Weise (Sie müssen die Protokolle subtrahieren und nicht aufteilen, damit sie nach Ihren Wünschen funktionieren).

Egal, es sieht so aus, als ob die Lautstärkeeinstellung für Android jetzt proportional zur Lautstärke ist ... 0,5 ist also 50% so laut wie 1,0 und 0,1 ist 10% usw. Es ist keine komplizierte Log-Mathematik erforderlich, um Dezibel in Lautstärke zu konvertieren. Setzen Sie es einfach linear, wie es für die meisten Menschen intuitiv ist.

6
najak

Ich habe Android MediaPlayer.setVolume ausprobiert, aber diese Funktion ist unbrauchbar.

Ich denke, wir sollten die Funktion unten verwenden

AudioManager mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, maxVolume * mLastProgress / 10, 0);
5
Allen Zhang

Dieser Code unterteilt das Volumen in 10 gleiche Abschnitte und erhöht oder verringert das Volumen.

Button decreaseVolButton = (Button) findViewById(R.id.decrease_volumn);
Button increaseVolButton = (Button) findViewById(R.id.increase_volumn);

final MediaPlayer mediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.sample);

decreaseVolButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        volume = (float) (volume - 0.1);
        mediaPlayer.setVolume(volume, volume);
    }
});
increaseVolButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        volume = (float) (volume + 0.1);
        mediaPlayer.setVolume(volume, volume);
    }
});

Wenn Sie die Lautstärke auf keinen Ton einstellen möchten, übergeben Sie (0f, 0f)

Wenn Sie die Lautstärke auf vollen Ton einstellen möchten, übergeben Sie (1f, 1f)

0
rakesh kumar

Warum es so kompliziert machen? Ich verwende diese einfache Formel:

public float getVolume() {
    float currVolume = (float) sp.getInt("volume", 10);
    float maxVolume = 15.0f;
    float result = currVolume / maxVolume;
    return result;
}

und diesen Wert in Media Player einstellen, wie:

player.setVolume(getVolume(), getVolume());
0
Jan

Alles, was ich hier gesehen habe, hat meine Erwartungen nicht erfüllt. Das Hauptproblem, das ich hatte, war, dass sich 25 auf einer Skala von 0 bis 50 nie in der Mitte befand, sondern eher am maximalen Klang. Die hier vorgeschlagenen Log-Funktionen haben für mich fast keinen Unterschied gemacht.

Um mehr über die Mathematik zu erfahren, siehe diese Antwort .

Variablen

Linear input value   = x      // User-specified input value
Linear scale min,max = x1,x2  // My pre-determined range of 0-50 on my UI
Log scale min,max    = y1,y2  // Normalizes the log result to between 0-1
Log value result     = z      // The output to pass to the setVolume() method

Formel, bei der sich der Wert verlangsamt, wenn der Wert steigt (einfachste Form)

Das Problem bei diesem Ansatz ist, dass dies das Gegenteil von dem ist, was wir mit Android wollen, da dies standardmäßig bereits getan wird. Es wird bereits zu schnell inkrementiert, wenn die Werte bei der Übergabe von linearen Werten noch niedrig sind. Dies unterstreicht dies Wirkung noch weiter.

x1 + (log(x) - log(x1)) / (log(x2) - log(x1)) * (y2 - y1) = z

Ergebnisse dieser Funktion

Formel, bei der sich der Wert mit steigendem Wert beschleunigt

Dies ist der Ansatz, der für mich funktioniert. Die Eingabe wird umgedreht, um die gleiche Änderungsrate beizubehalten, aber umgekehrt. Mit dieser Einstellung erreiche ich mit ungefähr 25 eine perfekte Mittenlautstärke) und es ist ein sehr sanftes Hörerlebnis von 0 den ganzen Weg bis 50.

y2 - (x1 + (log(x2 + x1 - x) - log(x1)) / (log(x2) - log(x1)) * (y2 - y1)) = z

Ergebnisse dieser Funktion

0
Jon B

Nun, ich habe den folgenden Code geschrieben und er funktioniert leicht:

public class MainActivity extends Activity {

    float volumeLevel = 0.5f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        volumeUp = findViewById(R.id.volUp);
        volumeDown = findViewById(R.id.volDown);

        song = MediaPlayer.create(this, R.raw.audioFile);    

        volumeUp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v){
                volumeLevel = volumeLevel + 0.1f;
                song.setVolume(volumeLevel,volumeLevel);
            }
        });

        volumeDown.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                volumeLevel = volumeLevel - 0.1f;
                song.setVolume(volumeLevel,volumeLevel);
            }
        });
    }
}
0
mQadry