Управление амплитудой с помощью VolumeShaper

Вы можете использовать VolumeShaper в аудиоприложении для выполнения постепенного появления, затухания, перекрестного затухания, приглушения и других коротких автоматических переходов громкости. Класс VolumeShaper доступен в Android 8.0 (уровень API 26) и более поздних версиях.

Вы создаете VolumeShaper , вызывая createVolumeShaper() в экземпляре AudioTrack или MediaPlayer . VolumeShaper воздействует только на звук, созданный AudioTrack или MediaPlayer, который его создал.

VolumeShaper.Конфигурация

Поведение VolumeShaper определяется его VolumeShaper.Configuration . В конфигурации указывается *кривая объема, тип интерполятора и продолжительность.*

Кривая объема

Кривая объема представляет изменение амплитуды с течением времени. Он определяется парой массивов с плавающей точкой x[] и y[], которые определяют серию контрольных точек. Каждая пара (x, y) представляет время и объем соответственно. Массивы должны быть одинаковой длины и содержать не менее 2 и не более 16 значений. (Максимальная длина кривой определяется в getMaximumCurvePoints() .)

Временные координаты заданы на интервале [0,0, 1,0]. Первый момент времени должен быть равен 0,0, последний — 1,0, а время должно монотонно возрастать.

Координаты объема указаны в линейном масштабе в интервале [0,0, 1,0].

Тип интерполятора

Кривая объема всегда проходит через указанные контрольные точки. Значения между контрольными точками выводятся с помощью сплайна в соответствии с типом интерполятора конфигурации. Существует четыре константы для доступных типов интерполяторов VolumeShaper :

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

Продолжительность

Указанные координаты времени в интервале [0,0, 1,0] масштабируются до продолжительности, указанной вами в миллисекундах. Это определяет фактическую длину во времени кривой громкости, когда формирователь работает и применяет кривую к аудиовыходу.

Использование VolumeShaper

Создание конфигурации

Перед созданием VolumeShaper необходимо создать экземпляр VolumeShaper.Configuration . Сделайте это с помощью VolumeShaper.Configuration.Builder() :

Котлин

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})

Запустите воспроизведение и формирователь одновременно. Это гарантирует, что воспроизведение начнется с тишины, а громкость увеличится до полной. Это объясняется в следующем разделе.

Запуск VolumeShaper

Хотя уровень громкости первой контрольной точки применяется к аудиотракту сразу после создания формирователя, формирователь не продвигается по кривой, пока вы не вызовете метод apply() с VolumeShaper.Operation.PLAY . После создания формирователя первый вызов apply() должен указать операцию PLAY , чтобы запустить формирователь. Это проведет кривую от первой до последней контрольной точки:

Котлин

shaper.apply(VolumeShaper.Operation.PLAY)

Java

shaper.apply(VolumeShaper.Operation.PLAY);

Во время работы формирователя вы можете поочередно выполнять вызовы apply() , определяющие операции REVERSE и PLAY. При этом каждый раз меняется направление считывания контрольных точек.

Шейпер непрерывно регулирует громкость и проходит через все контрольные точки, пока не истечет . Это происходит, когда формирователь достигает последней (для операции PLAY) или первой (для операции REVERSE) контрольной точки кривой.

По истечении срока действия шейпера громкость остается на последней настройке, которая может быть первой или последней контрольной точкой. Вы можете вызвать VolumeShaper.getVolume() для текущего уровня громкости в любое время.

После истечения срока действия формирователя вы можете выполнить еще один вызов apply() , чтобы запустить кривую в противоположном направлении. Например, если срок действия формирователя истек во время выполнения PLAY , следующий apply() должен быть REVERSE . Вызов PLAY после истечения срока действия PLAY или REVERSE после истечения срока действия REVERSE не имеет никакого эффекта.

Вы должны чередовать операции PLAY и REVERSE . Невозможно воспроизвести кривую от первой до последней контрольной точки, а затем перезапустить ее снова с первой контрольной точки. Вы можете использовать метод replace() , описанный в следующем разделе, чтобы заменить кривую ее копией. Это сбрасывает формирователь, требуя, чтобы операция PLAY запустила его снова.

Изменение кривой

Используйте метод replace() , чтобы изменить кривую VolumeShaper . Этот метод принимает конфигурацию, операцию и параметр соединения. Вы можете вызвать метод replace() в любое время во время работы формирователя или после его истечения:

Котлин

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 =
  new 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);

Когда вы вызываете replace() во время работы формирователя, он перестает изменять громкость и остается с текущим значением. Затем формирователь пытается начать новую кривую с первой контрольной точки. Это означает, что аргумент операции определяет, запускается ли формирователь после вызова. Укажите PLAY , чтобы немедленно начать новую кривую, укажите REVERSE , чтобы оставить формирователь на паузе на громкости первой контрольной точки новой кривой. Вы можете запустить формирователь позже с помощью apply(VolumeShaper.Operation.PLAY) .

Когда вы вызываете replace() с join = false , формирователь начинает свою кривую на уровне, указанном его первой контрольной точкой. Это может привести к нарушению непрерывности объема. Вы можете избежать этого, вызвав replace() с join = true . Это устанавливает первую контрольную точку новой кривой на текущий уровень формирователя и масштабирует громкость всех контрольных точек между первой и последней, чтобы сохранить относительную форму новой кривой (последняя контрольная точка остается неизменной). Операция масштабирования навсегда изменяет контрольные точки на новой кривой формирователя.

Удаление VolumeShaper

Система закрывается, и VolumeShaper собирает мусор, когда его AudioTrack или MediaPlayer освобождается или больше не используется. Вы можете вызвать метод close() для формирователя, чтобы немедленно его уничтожить. Система удаляет формирователь из аудиоконвейера примерно за 20 мс. Будьте осторожны при закрытии VolumeShaper во время воспроизведения звука. Если объем формирователя меньше 1,0 при вызове close() , масштаб объема формирователя изменится на 1,0. Это может вызвать внезапное увеличение громкости.