Amplitude mit VolumeShaper steuern

Mit VolumeShaper können Sie in einer Audio-App Ein- und Ausblendungen, Überblendungen, Ducking und andere kurze automatische Lautstärkeübergänge vornehmen. Die Klasse VolumeShaper ist ab Android 8.0 (API-Level 26) verfügbar.

Sie erstellen eine VolumeShaper, indem Sie createVolumeShaper() für eine Instanz von AudioTrack oder MediaPlayer aufrufen. VolumeShaper wirkt sich nur auf die Audioinhalte aus, die von dem AudioTrack oder MediaPlayer produziert wurden.

VolumeShaper.Configuration

Das Verhalten einer VolumeShaper wird durch ihre VolumeShaper.Configuration definiert. Die Konfiguration gibt eine *Volumenkurve, den Interpolatortyp und die Dauer an.*

Lautstärkekurve

Die Volumenkurve steht für die Amplitudenänderung im Zeitverlauf. Sie wird durch ein Paar Gleitkomma-Arrays x[] und y[] definiert, die eine Reihe von Kontrollpunkten definieren. Jedes (x, y)-Paar steht für Zeit bzw. Volumen. Die Arrays müssen gleich lang sein und mindestens 2 bis 16 Werte enthalten. Die maximale Kurvenlänge ist in getMaximumCurvePoints() definiert.

Die Zeitkoordinaten sind über das Intervall [0.0, 1.0] angegeben. Der erste Zeitpunkt muss 0,0 sein, der letzte 1,0 und die Zeiten müssen monoton ansteigen.

Die Volumenkoordinaten werden in linearer Skalierung über das Intervall [0,0, 1,0] angegeben.

Interpolatortyp

Die Lautstärkekurve durchläuft immer die angegebenen Kontrollpunkte. Die Werte zwischen den Kontrollpunkten werden von einem Spline gemäß dem Interpolatortyp der Konfiguration abgeleitet. Es gibt vier Konstanten für die verfügbaren VolumeShaper-Interpolatortypen:

  • VolumeShaper.Configuration.INTERPOLATOR_TYPE_STEP
  • VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR
  • VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC
  • VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC_MONOTONIC

Dauer

Die angegebenen Zeitkoordinaten im Intervall [0,0, 1,0] werden auf eine Dauer skaliert, die Sie in Millisekunden angeben. Damit wird die tatsächliche Dauer der Lautstärkekurve bestimmt, wenn der Shaper läuft und die Kurve auf die Audioausgabe angewendet wird.

VolumeShaper verwenden

Konfiguration erstellen

Bevor Sie ein VolumeShaper erstellen, müssen Sie eine Instanz von VolumeShaper.Configuration erstellen. Tun Sie dies mit einem VolumeShaper.Configuration.Builder():

Kotlin

val config: VolumeShaper.Configuration = VolumeShaper.Configuration.Builder()
        .setDuration(3000)
        .setCurve(floatArrayOf(0f, 1f), floatArrayOf(0f, 1f))
        .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
        .build()

Java

VolumeShaper.Configuration config =
  new VolumeShaper.Configuration.Builder()
      .setDuration(3000)
      .setCurve(new float[] {0.f, 1.f}, new float[] {0.f, 1.f})
      .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
      .build();

With no arguments the VolumeShaper.Configuration.Builder constructor returns a builder that creates a configuration with default settings: INTERPOLATOR_TYPE_CUBIC, a one second duration, and no curve. You must add a curve to the builder before calling build().

The framework provides constants for configurations with pre-built curves, each with one second duration:

  • VolumeShaper.Configuration.LINEAR_RAMP
  • VolumeShaper.Configuration.CUBIC_RAMP
  • VolumeShaper.Configuration.SINE_RAMP
  • VolumeShaper.Configuration.SCURVE_RAMP

Creating a VolumeShaper

To create a VolumeShaper, call createVolumeShaper() on an instance of the appropriate class, passing in a VolumeShaper.Configuration:

Kotlin

volumeShaper = myMediaPlayer.createVolumeShaper(config)
volumeShaper = myAudioTrack.createVolumeShaper(config)

Java

volumeShaper = myMediaPlayer.createVolumeShaper(config);
volumeShaper = myAudioTrack.createVolumeShaper(config);

A single track or media player can have many shapers attached to it, and you can control each shaper separately. The outputs of all the shapers on a track or player are multiplied together. A VolumeShaper cannot be shared between AudioTracks or MediaPlayers, but you can use the same configuration in calls to createVolumeShaper to build identical shapers on multiple AudioTracks or MediaPlayers.

When you create the shaper, its first control point (at t = 0) is applied to the audio stream. If the initial volume is not 1.0 and your app is playing material at create time, your audio might have an abrupt change in volume. Best practice is to start playing audio from silence and use a VolumeShaper to implement a fade-in when playback starts. Create a VolumeShaper that starts at 0 volume and fades up. For example:

setCurve(new float[] {0.f, 1.f}, new float[] {0.f, 1.f})

Starte die Wiedergabe und den Shaper gleichzeitig. Dadurch wird sichergestellt, dass die Wiedergabe nach der Stummschaltung beginnt und die Lautstärke auf die volle Lautstärke ansteigt. Dies wird im nächsten Abschnitt erläutert.

VolumeShaper ausführen

Obwohl die Lautstärke des ersten Kontrollpunkts auf den Audiopfad angewendet wird, sobald der Shaper erstellt wurde, bewegt sich der Shaper erst dann entlang der Kurve, wenn Sie die Methode apply() mit VolumeShaper.Operation.PLAY aufrufen. Nach dem Erstellen des Shapers muss beim ersten Aufruf von apply() der Vorgang PLAY angegeben werden, damit der Shaper gestartet wird. Dadurch wird die Kurve vom ersten bis zum letzten Kontrollpunkt ausgeführt:

Kotlin

shaper.apply(VolumeShaper.Operation.PLAY)

Java

shaper.apply(VolumeShaper.Operation.PLAY);

Während der Shaper ausgeführt wird, können Sie abwechselnde apply()-Aufrufe ausführen, in denen REVERSE- und PLAY-Vorgänge angegeben werden. Dadurch wird die Leserichtung der Kontrollpunkte jedes Mal geändert.

Der Shaper passt die Lautstärke kontinuierlich an und durchläuft alle Kontrollpunkte, bis er abläuft. Dies geschieht, wenn der Shaper den letzten Kontrollpunkt (beim WIEDERGABE-Vorgang) oder ersten Kontrollpunkt (für den UMkehrvorgang) in der Kurve erreicht.

Wenn der Shaper abläuft, bleibt die Lautstärke auf der letzten Einstellung, d. h. der erste oder letzte Kontrollpunkt. Sie können jederzeit VolumeShaper.getVolume() für die aktuelle Lautstärke aufrufen.

Nachdem der Shaper abgelaufen ist, können Sie einen weiteren apply()-Aufruf ausführen, um die Kurve in die entgegengesetzte Richtung auszuführen. Wenn der Shaper beispielsweise beim Ausführen von PLAY abgelaufen ist, muss der nächste apply() REVERSE sein. Der Aufruf von PLAY, nachdem PLAY abgelaufen ist, oder REVERSE, nachdem REVERSE abgelaufen ist, hat keine Auswirkungen.

Sie müssen die Vorgänge PLAY und REVERSE abwechselnd ausführen. Es ist nicht möglich, eine Kurve vom ersten bis zum letzten Kontrollpunkt abzuspielen und sie dann vom ersten Kontrollpunkt aus neu zu starten. Mit der Methode replace(), die im nächsten Abschnitt beschrieben wird, können Sie die Kurve durch eine Kopie von sich selbst ersetzen. Dadurch wird der Shaper zurückgesetzt. Der Vorgang PLAY ist erforderlich, um ihn neu zu starten.

Kurve ändern

Verwenden Sie die Methode replace(), um die Kurve einer VolumeShaper zu ändern. Diese Methode verwendet eine Konfiguration, einen Vorgang und einen Join-Parameter. Sie können die Methode replace() jederzeit aufrufen, während der Shaper ausgeführt wird oder nachdem er abgelaufen ist:

Kotlin

val newConfig = VolumeShaper.Configuration.Builder()
        .setDuration(1000)
        .setCurve(floatArrayOf(0f, 0.5f), floatArrayOf(0f, 1f))
        .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
        Volume.build()
val join = true
shaper.PLAY

Java

VolumeShaper.Configuration newConfig =
 new VolumeShaper.Configuration.Builder()
 .setDuration(1000)
 .setCurve(new float[] {0.f, 0.5f}, new float[] {0.f, 1.f})
 .setInterpolatorType(VolumeShaper.shaper.newConfig.PLAY/ genutzt.SUBPOLATOR join TYPE_LINEAR)

Wenn Sie replace() aufrufen, während der Shaper ausgeführt wird, ändert sich das Volumen nicht mehr und es bleibt auf seinem aktuellen Wert. Dann versucht der Shaper, die Kurve vom ersten Kontrollpunkt aus zu starten. Das bedeutet, dass das Vorgangsargument steuert, ob der Shaper nach dem Aufruf ausgeführt wird. Geben Sie PLAY an, um mit der neuen Kurve sofort zu beginnen. Geben Sie REVERSE an, um den Shaper bei der Lautstärke des ersten Kontrollpunkts in der neuen Kurve pausiert zu lassen. Sie können den Shaper später mit apply(VolumeShaper.Operation.PLAY) starten.

Wenn Sie replace() mit join = false aufrufen, beginnt die Kurve des Shapers bei der Ebene, die durch seinen ersten Kontrollpunkt angegeben wird. Dies kann zu einer Diskontinuität im Volume führen. Du kannst das vermeiden, indem du replace() mit join = true anrufst. Dadurch wird der erste Kontrollpunkt der neuen Kurve auf den aktuellen Pegel des Shaders gesetzt und das Volumen aller Kontrollpunkte zwischen dem ersten und dem letzten Kontrollpunkt skaliert, um die relative Form der neuen Kurve beizubehalten (der letzte Kontrollpunkt bleibt unverändert). Durch den Skalierungsvorgang werden die Kontrollpunkte in der neuen Kurve des Creators dauerhaft geändert.

VolumeShaper entfernen

Das System wird geschlossen und ein VolumeShaper wird automatisch bereinigt, wenn sein AudioTrack oder MediaPlayer freigegeben wird oder nicht mehr verwendet wird. Sie können die Methode close() für einen Shaper aufrufen, um ihn sofort zu löschen. Das System entfernt den Shaper innerhalb von etwa 20 ms aus der Audiopipeline. Seien Sie vorsichtig, wenn Sie VolumeShaper während der Audiowiedergabe schließen. Hat der Shaper beim Aufrufen von close() ein Volumen unter 1,0, ändert sich die Volumenskala des Shapers in 1,0. Dies kann zu einem plötzlichen Anstieg des Volumens führen.