使用 VolumeShaper 控制振幅

您可以在音频应用中使用 VolumeShaper 来执行 淡入、淡出、淡入淡出、降低音量以及其他简短的自动音量 过渡效果。Android 8.0(API 级别 26)中提供了 VolumeShaper 类。 和后续版本。

您可以通过对以下对象的实例调用 createVolumeShaper() 来创建 VolumeShaperAudioTrackMediaPlayer。通过 VolumeShaper 仅对 AudioTrack 或 MediaPlayer 生成的音频起作用 创建它的过程。

VolumeShaper.Configuration

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():

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

同时启动播放和 shaper。这样可以确保 从静音开始,然后音量逐渐上升至最大音量。具体说明请参阅 下一部分。

运行 VolumeShaper

尽管第一个控制点的音量会应用于音频路径 创建 Shaper 后,Shaper 不会沿着曲线前进 直到您使用 VolumeShaper.Operation.PLAY 调用 apply() 方法为止。更新后 创建 Shaper,第一次调用apply()时必须指定PLAY 操作来启动 Shaper。这样该曲线会从第一个到 最后一个控制点:

Kotlin

Shaper.apply(VolumeShaper.Operation.PLAY)

Java

Shaper.apply(VolumeShaper.Operation.PLAY);

当 Shaper 运行时,您可以发出交替的apply()调用,指定 REVERSE 和 PLAY 操作。这会改变 控制点。

Shaper 会不断调节音量并通过所有控制点 直至过期。当 Shaper 到达最后一个(对于 PLAY)时,就会发生这种情况 操作)或曲线中的第一个(对于 REVERSE 操作)控制点。

Shaper 过期后,音量会保持为最后的设置,可能是 第一个或最后一个控制点您可以拨打 VolumeShaper.getVolume() 随时保持当前音量

在 Shaper 过期后,您可以发出另一个apply()调用来运行曲线 就会反过来例如,如果 Shaper 在运行过程中过期 PLAY,下一个 apply() 必须是 REVERSE。在 PLAY 之后呼叫 PLAY 已过期,或者在 REVERSE 过期后 REVERSE没有任何作用。

您必须交替执行 PLAY 操作和 REVERSE 操作。 从第一个控制点到最后一个控制点 然后重新打开它 第一个控制点您可以使用 replace() 方法,如下文所述 部分,将曲线替换为其自身的副本。这将重置 shaper, 需要 PLAY 操作重新启动它。

更改曲线

使用 replace() 方法可以更改 VolumeShaper 的曲线。此方法采用 一个配置、一个操作和一个联接参数。您可以调用 replace() 方法随时调用:

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, 联接)

Java

VolumeShaper.Configuration newConfig =
  新的 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();
布尔值 join = true;
Shaper.Replace(newConfig, VolumeShaper.Operation.PLAY, join);

当您在形状运行期间调用 replace() 时,它会停止更改 并且保持当前值不变然后,Shaper 尝试 从第一个控制点开始绘制。这意味着,操作参数 控制 Shaper 在调用之后是否运行。将 PLAY 指定为 立即启动新曲线,指定 REVERSE 以让 Shaper 暂停在 新曲线中第一个控制点的音量。您可以启动 Shaper 稍后与 apply(VolumeShaper.Operation.PLAY) 共享。

当您使用 join = false 调用 replace() 时,Shaper 会在 第一个控制点所指定的级别这样会导致不连续 您可以通过使用 join = true 调用 replace() 来避免此问题。 此操作会将新曲线的第一个控制点设为 并调整第一个和第一个控制点之间的所有控制点的音量, 最后,保持新曲线的相对形状(最后一个控制点为 未做更改)。扩缩操作会永久性地改变 和 Shaper 的新曲线

移除 VolumeShaper

系统会在 VolumeShaperAudioTrackMediaPlayer 已发布或不再使用。您可以调用 close() 方法 就能立即销毁它系统会从 在大约 20 毫秒内运行完成。关闭 VolumeShaper 时要小心 。在您调用 Shaper 时,音量小于 1.0 close() 时,Shaper 的音量缩放会更改为 1.0。这可能会导致