Contrôler l'amplitude avec VolumeShaper

Vous pouvez utiliser un VolumeShaper dans une application audio pour effectuer des fondus et des fondus, des fondus enchaînés, des atténuations et d'autres transitions de volume automatisées courtes. La classe VolumeShaper est disponible sur Android 8.0 (niveau d'API 26) et versions ultérieures.

Pour créer un VolumeShaper, appelez createVolumeShaper() sur une instance de AudioTrack ou MediaPlayer. VolumeShaper agit uniquement sur le contenu audio produit par l'élément AudioTrack ou MediaPlayer qui l'a créé.

VolumeShaper.Configuration

Le comportement d'une VolumeShaper est défini par son VolumeShaper.Configuration. La configuration spécifie une *courbe de volume, un type d'interpolateur et une durée*.

Courbe de volume

La courbe de volume représente les changements d'amplitude au fil du temps. Elle est définie par une paire de tableaux à virgule flottante x[] et y[], qui définissent une série de points de contrôle. Chaque paire (x, y) représente respectivement le temps et le volume. Les tableaux doivent être de longueur égale, et contenir entre 2 et 16 valeurs. (La longueur maximale de la courbe est définie dans getMaximumCurvePoints().)

Les coordonnées temporelles sont indiquées sur l'intervalle [0,0, 1,0]. Le premier point temporel doit être 0,0, le dernier doit être 1,0, et les heures doivent augmenter de manière monotone.

Les coordonnées du volume sont spécifiées à l'échelle linéaire sur l'intervalle [0,0, 1,0].

Type d'interpolateur

La courbe de volume passe toujours par les points de contrôle spécifiés. Les valeurs entre les points de contrôle sont dérivées d'une spline en fonction du type d'interpolateur de la configuration. Il existe quatre constantes pour les types d'interpolateurs VolumeShaper disponibles:

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

Durée

Les coordonnées temporelles spécifiées dans l'intervalle [0,0, 1,0] sont mises à l'échelle selon une durée que vous spécifiez en millisecondes. Ce paramètre détermine la durée réelle de la courbe de volume lorsque le Shaper est en cours d'exécution et applique la courbe à la sortie audio.

Utiliser un VolumeShaper

Créer une configuration

Avant de compiler un VolumeShaper, vous devez créer une instance de VolumeShaper.Configuration. Pour ce faire, utilisez 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})

Lancer la lecture et le tracé en même temps. Ainsi, la lecture commence par le silence et le volume augmente au maximum. Cela est expliqué dans la section suivante.

Exécuter un VolumeShaper

Bien que le niveau de volume du premier point de contrôle soit appliqué à la piste audio dès que le Shaper est créé, il ne progresse pas le long de la courbe tant que vous n'avez pas appelé la méthode apply() avec VolumeShaper.Operation.PLAY. Après avoir créé le Shaper, le premier appel de apply() doit spécifier l'opération PLAY afin de démarrer le Shaper. La courbe est exécutée du premier au dernier point de contrôle:

Kotlin

shaper.apply(VolumeShaper.Operation.PLAY)

Java

shaper.apply(VolumeShaper.Operation.PLAY);

Pendant l'exécution du shaper, vous pouvez émettre des appels apply() alternés spécifiant les opérations REVERSE et PLAY. La direction de la lecture des points de contrôle change à chaque fois.

Le sculpteur ajuste en permanence le volume et passe par tous les points de contrôle jusqu'à ce qu'il expire. Cela se produit lorsque le shaper atteint le dernier point de contrôle de la courbe (pour l'opération de lecture) ou le premier point de contrôle (pour l'opération inverse).

Lorsque le paramètre de forme expire, le volume reste sur le dernier paramètre, qui peut être le premier ou le dernier point de contrôle. Vous pouvez appeler VolumeShaper.getVolume() pour obtenir le niveau de volume actuel à tout moment.

Une fois que le shaper a expiré, vous pouvez émettre un autre appel apply() pour exécuter la courbe dans la direction opposée. Par exemple, si le tracé a expiré lors de l'exécution de PLAY, le apply() suivant doit être REVERSE. L'appel de PLAY après l'expiration de PLAY ou de REVERSE après l'expiration de REVERSE n'a aucun effet.

Vous devez alterner les opérations PLAY et REVERSE. Il n'y a aucun moyen de lire une courbe de son premier au dernier point de contrôle, puis de la redémarrer à nouveau à partir du premier point de contrôle. Vous pouvez utiliser la méthode replace(), décrite dans la section suivante, pour remplacer la courbe par une copie d'elle-même. Cette opération réinitialise le Shaper, nécessitant l'opération PLAY pour le redémarrer.

Changer la courbe

Utilisez la méthode replace() pour modifier la courbe d'une VolumeShaper. Cette méthode utilise une configuration, une opération et un paramètre de jointure. Vous pouvez appeler la méthode replace() à tout moment, pendant ou après son expiration:

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 .Shaper)shaper

Java

VolumeShaper.Configuration newConfig =
 new VolumeShaper.Configuration.Builder()
 .setDuration(1000)
 .setCurve(new float[] {0.f, 0.5f}, new float[] {0.f, 1.f})
 .setInterpolatorType(VolumeInterpolatorType(VolumeShaper.Operation.INTERPOLATOR float .ShaperLINEAR)

Lorsque vous appelez replace() alors que le Shaper est en cours d'exécution, il cesse de modifier le volume et conserve sa valeur actuelle. Ensuite, le Shaper tente de démarrer la nouvelle courbe à partir du premier point de contrôle. Cela signifie que l'argument "operation" contrôle si le Shaper s'exécute ou non après l'appel. Spécifiez PLAY pour démarrer immédiatement la nouvelle courbe et REVERSE pour laisser le tracé en pause au volume du premier point de contrôle de la nouvelle courbe. Vous pourrez démarrer le Shaper ultérieurement avec apply(VolumeShaper.Operation.PLAY).

Lorsque vous appelez replace() avec join = false, le Shaper commence sa courbe au niveau spécifié par son premier point de contrôle. Cela peut entraîner une discontinuité dans le volume. Pour éviter cela, appelez replace() avec join = true. Le premier point de contrôle de la nouvelle courbe est défini sur le niveau actuel du Shaper, et le volume de tous les points de contrôle entre le premier et le dernier est ajusté afin de conserver la forme relative de la nouvelle courbe (le dernier point de contrôle est inchangé). L'opération de scaling modifie définitivement les points de contrôle dans la nouvelle courbe du Shaper.

Supprimer un VolumeShaper

Le système se ferme et une VolumeShaper est récupérée lorsque son AudioTrack ou son MediaPlayer est libéré ou qu'il n'est plus utilisé. Vous pouvez appeler la méthode close() sur un Shaper pour le détruire immédiatement. Le système supprime le Shaper du pipeline audio en 20 ms environ. Soyez prudent lorsque vous fermez une VolumeShaper pendant la lecture d'un contenu audio. Si le volume du Shaper est inférieur à 1.0 lorsque vous appelez close(), l'échelle de volume du Shaper passe à 1.0. Cela peut entraîner une augmentation soudaine du volume.