Control de la amplitud con VolumeShaper

Puedes usar un VolumeShaper en una app de audio para realizar fundido de entrada, fundido de salida, fundido cruzado, autosilenciado y otro volumen automatizado corto las transiciones. La clase VolumeShaper está disponible en Android 8.0 (nivel de API 26) y posteriores.

Para crear un VolumeShaper, llama a createVolumeShaper() en una instancia de AudioTrack o MediaPlayer. El VolumeShaper solo actúa sobre el audio producido por AudioTrack o MediaPlayer que la creó.

VolumeShaper.Configuration

El comportamiento de un VolumeShaper se define por su VolumeShaper.Configuration La configuración especifica un *curva de volumen, tipo de interpolación y duración.*

Curva de volumen

La curva de volumen representa el cambio de amplitud en el tiempo. Se define mediante un par de arrays de números de punto flotante, x[] e y[], que definen una serie de puntos de control. Cada (x, y) que representa el tiempo y el volumen respectivamente. Los arrays deben tener la misma longitud y contener entre 2 y 16 valores como mínimo. (La longitud máxima de la curva es definido en getMaximumCurvePoints()).

Las coordenadas de tiempo se proporcionan durante el intervalo [0.0, 1.0]. La primera vez el punto debe ser 0.0, el último debe ser 1.0 y las horas deben ser monótonamente en aumento.

Las coordenadas de volumen se especifican en escala lineal durante el intervalo [0.0, 1.0].

Tipo de interpolación

La curva de volumen siempre pasa por los puntos de control especificados. Valores entre los puntos de control se obtiene a través de un spline de acuerdo con el tipo de interpolador de la configuración. Hay cuatro constantes para las variables Tipos de interpoladores VolumeShaper:

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

Duración

Las coordenadas de tiempo especificadas en el intervalo [0.0, 1.0] se escalan a un la duración especificada en milisegundos. Esto determina la longitud real en tiempo de la curva de volumen cuando el modelador está en funcionamiento y aplica la curva a la salida de audio.

Uso de un VolumeShaper

Cómo crear una configuración

Antes de desarrollar un VolumeShaper, tienes que crear una instancia de VolumeShaper.Configuration. Para ello, utiliza 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})

Comienza la reproducción y el modelador al mismo tiempo. Esto garantiza que la reproducción comienza con el silencio y el volumen se sube a todo volumen. Esto se explica en la siguiente sección.

Cómo ejecutar un VolumeShaper

Sin embargo, el nivel de volumen del primer punto de control se aplica a la ruta de acceso de audio. tan pronto como se crea el modelador, este no progresa a lo largo de la curva hasta que llames al método apply() con VolumeShaper.Operation.PLAY. Después del cuando creas el modelador, la primera invocación de apply() debe especificar el PLAY para iniciar el modelador. Esto ejecuta la curva desde el primer momento últimos puntos de control:

Kotlin

modelr.apply(VolumeShaper.Operation.PLAY)

Java

modelr.apply(VolumeShaper.Operation.PLAY);

Mientras el modelador está en ejecución, puedes emitir llamadas apply() alternativas que especifiquen las operaciones REVERTIR y REPRODUCIR. Esto cambia la dirección de lectura de la puntos de control en cada ocasión.

El modelador ajusta el volumen de forma continua y pasa por todos los puntos de control hasta que caduque. Esto sucede cuando el modelador alcanza el último valor (para PLAY o el primer punto de control (para la operación REVERTIR) de la curva.

Cuando expira el modelador, el volumen permanece en la última configuración, que puede ser el primer o el último punto de control. Puedes llamar a VolumeShaper.getVolume() por el nivel de volumen actual en cualquier momento.

Una vez que vence el modelador, puedes emitir otra llamada a apply() para ejecutar la curva. en la dirección opuesta. Por ejemplo, si el modelador expiró mientras se ejecutaba PLAY, el próximo apply() debe ser REVERSE. Se llamará a PLAY después de que PLAY haya venció o REVERSE después del vencimiento de REVERSE no tiene ningún efecto.

Tienes que alternar las operaciones de PLAY y REVERSE. No hay forma de reproducir un desde el primer punto de control hasta el último y, luego, reiniciarlo nuevamente desde el primer punto de control. Puedes usar el método replace(), que se describe en la siguiente sección para reemplazar la curva por una copia de sí misma. Esto restablece el modelador, lo que requiere que la operación PLAY la inicie de nuevo.

Cambiar la curva

Usa el método de replace() para cambiar una curva de VolumeShaper. Este método toma una configuración, una operación y un parámetro de unión. Puedes llamar al replace() en cualquier momento, mientras el modelador está en ejecución o después de su vencimiento:

Kotlin

val newConfig = VolumeShaper.Configuration.Builder()
        .setDuration(1,000)
        .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 =
  Nuevo VolumeShaper.Configuration.Builder().
    .setDuration(1,000)
    .setCurve(new float[] {0.f, 0.5f}, new float[] {0.f, 1.f})
    .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
    .build();
boolean join = true;
shaper.replace(newConfig, VolumeShaper.Operation.PLAY, join);

Cuando llamas a replace() mientras el modelador está en ejecución, este deja de cambiar volumen y se mantiene en su valor actual. Luego, el modelador intenta iniciar el nuevo desde el primer punto de control. Esto significa que el argumento de operación controla si el modelador se ejecuta o no después de la llamada. Especifica PLAY para iniciar inmediatamente la nueva curva, especifica REVERSE para dejar el modelador en pausa en el volumen del primer punto de control en la nueva curva. Puedes iniciar el modelador más adelante con apply(VolumeShaper.Operation.PLAY).

Cuando llamas a replace() con join = false, el modelador comienza su curva en el nivel especificado por su primer punto de control. Esto puede causar una discontinuidad en el volumen. Puedes evitarlo si llamas a replace() con join = true. Esto establece el primer punto de control de la nueva curva en el nivel actual de la modelador y ajusta el volumen de todos los puntos de control entre el primer y último para mantener la forma relativa de la nueva curva (el último punto de control es sin cambios). La operación de escalamiento cambia permanentemente los puntos de control en la nueva curva del modelador.

Quitar un VolumeShaper

El sistema se cierra y los elementos no utilizados recogen un VolumeShaper cuando su AudioTrack o Se lanzó MediaPlayer o ya no está en uso. Puedes llamar al método close(). en un modelador para destruirlo inmediatamente. El sistema quita el modelador de la de audio en unos 20 ms. Ten cuidado cuando cierres un VolumeShaper mientras se reproduce el audio. Si el modelador tiene un volumen inferior a 1.0 cuando llamas close(), la escala de volumen del modelador cambia a 1.0. Esto puede causar un error o aumentar el volumen.