Controllare l'ampiezza con VolumeShaper

Puoi usare VolumeShaper in un'app audio per eseguire dissolvenze in entrata, dissolvenze in uscita, dissolvenze incrociate, attenuazione automatica e altri volumi automatici di breve durata transizioni. La classe VolumeShaper è disponibile in Android 8.0 (livello API 26) e successivi.

Puoi creare un VolumeShaper chiamando createVolumeShaper() su un'istanza di AudioTrack o MediaPlayer. La VolumeShaper interviene solo sull'audio prodotto da AudioTrack o MediaPlayer che l'ha creato.

VolumeShaper.Configurazione

Il comportamento di un VolumeShaper è definito dal suo VolumeShaper.Configuration. La configurazione specifica *curva del volume, tipo di interpolatore e durata.*

Curva di volume

La curva di volume rappresenta la variazione di ampiezza nel tempo. È definito da una coppia di array in virgola mobile, x[] e y[] che definiscono una serie di punti di controllo. Ciascuno (x, y) rappresenta rispettivamente ora e volume. Le matrici devono essere di uguale lunghezza e contenere da 2 a 16 valori. (La lunghezza massima della curva è definita in getMaximumCurvePoints().

Le coordinate temporali sono indicate sull'intervallo [0,0, 1,0]. La prima volta il punto deve essere 0,0, l'ultimo deve essere 1,0 e i tempi devono essere monotonici sono in costante aumento.

Le coordinate del volume sono specificate in scala lineare sull'intervallo [0,0, 1,0].

Tipo di interpolatore

La curva di volume passa sempre attraverso i punti di controllo specificati. Valori tra i punti di controllo sono ricavate da una spline secondo tipo di interpolatore della configurazione. Esistono quattro costanti per VolumeShaper tipi di interpolatore:

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

Durata

Le coordinate temporali specificate nell'intervallo [0,0, 1,0] vengono scalate a un specificata in millisecondi. Questo determina la lunghezza effettiva in tempo della curva di volume quando lo shaper è in esecuzione e applica la curva a l'uscita audio.

Utilizzo di VolumeShaper

Creazione di una configurazione

Prima di creare un VolumeShaper, devi creare un'istanza di VolumeShaper.Configuration. Per farlo, utilizza un 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})

Avvia la riproduzione e lo shaper contemporaneamente. Ciò garantisce che la riproduzione inizia dal silenzio e il volume aumenta al massimo. Questa procedura è spiegata nella prossima sezione.

Esecuzione di un VolumeShaper

Anche se il livello del volume del primo punto di controllo viene applicato al percorso audio appena creato, lo shaper non progredisce lungo la curva finché non chiami il metodo apply() con VolumeShaper.Operation.PLAY. Dopo il giorno crea lo shaper, la prima chiamata di apply() deve specificare il valore PLAY per avviare lo shaper. Esegue la curva dalla prima ultimi punti di controllo:

Kotlin

shaper.apply(VolumeShaper.Operation.PLAY)

Java

shaper.apply(VolumeShaper.Operation.PLAY);

Mentre lo shaper è in esecuzione, puoi emettere chiamate apply() alterne specificando Operazioni INDIETRO e RIPRODUZIONE. Questo cambia la direzione di lettura del punti di controllo ogni volta.

Il shaper regola continuamente il volume e passa attraverso tutti i punti di controllo fino alla scadenza. Questo accade quando lo shaper raggiunge l'ultimo formato (per PLAY (per il funzionamento INDIETRO) o il primo punto di controllo nella curva.

Alla scadenza dello shaper, il volume rimane all'ultima impostazione, che potrebbe essere il primo o l'ultimo punto di controllo. Puoi chiamare VolumeShaper.getVolume() per il livello di volume corrente in qualsiasi momento.

Dopo la scadenza dello shaper, puoi emettere un'altra chiamata apply() per eseguire la curva nella direzione opposta. Ad esempio, se il shaper è scaduto durante la corsa, PLAY, il prossimo apply() deve essere REVERSE. Chiamata a PLAY dopo che PLAY o REVERSE dopo la scadenza di REVERSE non ha alcun effetto.

Devi alternare le operazioni PLAY e REVERSE. Non c'è modo di riprodurre un dalla curva dal primo all'ultimo punto di controllo e poi riavviala il primo punto di controllo. Puoi utilizzare il metodo replace(), descritto nella prossima per sostituire la curva con una copia di se stessa. Questa operazione reimposta lo shaper, richiedere l'avvio dell'operazione PLAY.

Modificare la curva

Usa il metodo replace() per modificare la curva di VolumeShaper. Questo metodo richiede una configurazione, un'operazione e un parametro di join. Puoi chiamare il replace() in qualsiasi momento, mentre lo shaper è in esecuzione o dopo la scadenza:

Kotlin

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

Java

VolumeShaper.Configuration newConfig =
  nuovo VolumeShaper.Configuration.Builder()
    .setDuration(1000)
    .setCurve(nuovo numero in virgola mobile[] {0.f, 0.5f}, nuovo numero in virgola mobile[] {0.f, 1.f})
    .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
    .build;

boolean join = true;
shaper.replace(newConfig, VolumeShaper.Operation.PLAY, join);

Quando chiami replace() mentre lo shaper è in esecuzione, smette di modificare il valore e il valore impostato è quello attuale. Poi lo shaper prova ad avviare la nuova dal primo punto di controllo. Ciò significa che l'argomento dell'operazione determina se lo shaper deve essere eseguito dopo la chiamata. Specifica PLAY in iniziare immediatamente la nuova curva, specifica REVERSE per lasciare il shaper in pausa il volume del primo punto di controllo nella nuova curva. Puoi iniziare a creare in seguito con apply(VolumeShaper.Operation.PLAY).

Quando chiami replace() con join = false, il shaper inizia la curva in il livello specificato dal suo primo punto di controllo. Ciò può causare una discontinuità nel volume. Puoi evitarlo chiamando replace() con join = true. Imposta il primo punto di controllo della nuova curva sul livello corrente dell' shaper e scala il volume di tutti i punti di controllo tra il primo per mantenere la forma relativa della nuova curva (l'ultimo punto di controllo è non modificato). L'operazione di scalabilità modifica in modo permanente i punti di controllo la nuova curva di shaper.

Rimozione di un VolumeShaper

Il sistema si chiude e garbage raccoglie un VolumeShaper quando il suo AudioTrack o MediaPlayer è stato rilasciato o non più in uso. Puoi chiamare il metodo close() su un shaper per distruggerlo immediatamente. Il sistema rimuove lo shaper in circa 20 ms. Fai attenzione quando chiudi una VolumeShaper durante la riproduzione dell'audio. Se il shaper ha un volume inferiore a 1,0 quando chiami close(), la scala del volume del shaper passa a 1,0. Ciò può causare un attacco improvviso di aumento del volume.