Como controlar a amplitude com o VolumeShaper

Você pode usar um VolumeShaper em um app de áudio para tocar fade-ins, fade-outs, cross fades, redução de áudio e outros volumes curtos automatizados transições. A classe VolumeShaper está disponível no Android 8.0 (API de nível 26). e mais tarde.

Crie um VolumeShaper chamando createVolumeShaper() em uma instância do AudioTrack ou MediaPlayer. A O VolumeShaper só atua no áudio produzido pela AudioTrack ou MediaPlayer. que o criou.

VolumeShaper.Configuration

O comportamento de uma VolumeShaper é definido pela VolumeShaper.Configuration. A configuração especifica um *curva de volume, tipo de interpolador e duração.*

Curva de volume

A curva de volume representa a mudança de amplitude ao longo do tempo. Ela é definida por um par de matrizes flutuantes, x[] e y[], que definem uma série de pontos de controle. Cada (x, y) representa tempo e volume, respectivamente. As matrizes precisam ter o mesmo comprimento e conter pelo menos 2 e não mais de 16 valores. (O comprimento máximo da curva é definido em getMaximumCurvePoints().

As coordenadas de tempo são fornecidas no intervalo [0.0, 1.0]. A primeira vez O ponto deve ser 0,0, o último deve ser 1,0 e os tempos devem ser monotonicamente está aumentando.

As coordenadas de volume são especificadas em escala linear no intervalo [0,0, 1,0].

Tipo de interpolador

A curva de volume sempre passa pelos pontos de controle especificados. Valores entre os pontos de controle são derivadas por uma spline de acordo com as tipo de interpolador da configuração. Há quatro constantes para a classe Tipos de interpolador VolumeShaper:

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

Duração

As coordenadas de tempo especificadas no intervalo [0,0, 1,0] são dimensionadas para um que você especificar em milissegundos. Isso determina o comprimento real em de tempo da curva de volume quando o shaper está em execução e aplicando a curva a saída de áudio.

Usar um VolumeShaper

Criar uma configuração

Antes de criar uma VolumeShaper, você precisa criar uma instância de VolumeShaper.Configuration. Faça isso usando uma 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})

Inicie a reprodução e o shaper ao mesmo tempo. Isso garante que a reprodução começa a partir do silêncio, e o volume aumenta para o volume máximo. Isso é explicado em na próxima seção.

Executar um VolumeShaper

Embora o nível de volume do primeiro ponto de controle seja aplicado ao caminho do áudio Assim que o shaper é criado, ele não avança ao longo da curva até chamar o método apply() com VolumeShaper.Operation.PLAY. Depois criar o shaper, a primeira invocação de apply() precisa especificar o PLAY; para iniciar o shaper. Isso executa a curva do primeiro últimos pontos de controle:

Kotlin

shaper.apply(VolumeShaper.Operation.PLAY)

Java

shaper.apply(VolumeShaper.Operation.PLAY);

Enquanto o shaper está em execução, você pode emitir chamadas apply() alternadas especificando REVERSE e PLAY. Isso muda a direção da leitura da pontos de controle cada vez.

O shaper ajusta o volume continuamente e passa por todos os pontos de controle até expirar. Isso acontece quando o shaper chega ao último (para PLAY) operação) ou primeiro (para operação REVERSE) ponto de controle na curva.

Quando o shaper expira, o volume permanece na última configuração, que pode ser primeiro ou último ponto de controle. Você pode chamar VolumeShaper.getVolume() para o nível de volume atual a qualquer momento.

Depois que o shaper expirar, você poderá emitir outra chamada apply() para executar a curva. na direção oposta. Por exemplo, se o shaper expirou durante a execução PLAY, o próximo apply() precisa ser REVERSE. Ligando para PLAY depois que PLAY tiver expirado ou REVERSE após REVERSE ter expirado não terá efeito.

Você precisa alternar as operações PLAY e REVERSE. Não é possível reproduzir curva do primeiro ao último ponto de controle e, em seguida, reinicia-a novamente do primeiro ponto de controle. Você pode usar o método replace(), descrito a seguir para substituir a curva por uma cópia dela mesma. Isso redefine o shaper, exigindo que a operação PLAY a reinicie.

Mudar a curva

Use o método replace() para mudar a curva de um VolumeShaper. Esse método leva configuração, operação e parâmetro de mesclagem. É possível chamar o método replace() a qualquer momento, enquanto o shaper está em execução ou depois que ele expira:

Kotlin

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

Java

VolumeShaper.Configuration newConfig =
  novo VolumeShaper.Configuration.Builder()
    .setDuration(1000)
    .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);

Quando você chama replace() enquanto o shaper está em execução, ele para de mudar o volume e permanece no valor atual. Em seguida, o shaper tenta iniciar o novo curva a partir do primeiro ponto de controle. Isso significa que o argumento da operação controla se o shaper é executado ou não após a chamada. Especifique PLAY para iniciar imediatamente a nova curva, especificar REVERSE para deixar o shaper pausado em o volume do primeiro ponto de controle na nova curva. Você pode iniciar o shaper depois com apply(VolumeShaper.Operation.PLAY).

Quando você chama replace() com join = false, o shaper começa a curva em o nível especificado pelo primeiro ponto de controle. Isso pode causar uma descontinuidade no volume. Você pode evitar isso chamando replace() com join = true. Define o primeiro ponto de controle da nova curva como o nível atual da e dimensiona o volume de todos os pontos de controle entre os primeiros e último a manter a forma relativa da nova curva (o último ponto de controle é inalterado). A operação de escalonamento altera permanentemente os pontos de controle na a nova curva do shaper.

Remover um VolumeShaper

O sistema fecha e coleta um VolumeShaper quando o AudioTrack ou MediaPlayer foi lançado ou não está mais em uso. Você pode chamar o método close(). em um shaper para destruí-la imediatamente. O sistema remove o shaper em cerca de 20 ms. Cuidado ao fechar um VolumeShaper enquanto o áudio está tocando. Se o shaper tiver um volume inferior a 1,0 quando você chamar close(), a escala de volume do shaper muda para 1.0. Isso pode causar uma queda repentina de aumento de volume.