使用 VolumeShaper 控制幅度

您可以在音频应用中使用 VolumeShaper 来执行淡入、淡出、交叉淡入淡出、背景音降低和其他短时自动音量转换。VolumeShaper 类在 Android 8.0 (API 级别 26) 及更高版本中可用。

您可以通过在 AudioTrackMediaPlayer 实例上调用 createVolumeShaper() 来创建 VolumeShaperVolumeShaper 仅对其创建的 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] 中指定的时间坐标会按您以毫秒为单位指定的持续时间进行缩放。这决定了当 shaper 运行时,音量曲线应用于音频输出的实际时间长度。

使用 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();

在没有 参数的 VolumeShaper.Configuration.Builder 构造函数中 返回一个 构建器 ,它 创建具有 默认设置的 配置: INTERPOLATOR_TYPE_CUBIC 一秒的 持续时间 以及 没有 曲线的 配置 您必须 在调用 build() 之前 构建器 添加曲线

该框架 提供了 常量 用于 具有 预置-曲线的 配置 每个 配置的 持续时间 为一秒:

  • VolumeShaper.Configuration.LINEAR_RAMP
  • VolumeShaper.Configuration.CUBIC_RAMP
  • VolumeShaper.Configuration.SINE_RAMP
  • VolumeShaper.Configuration.SCURVE_RAMP

创建 VolumeShaper

创建 一个 VolumeShaper 请在 相应类的 实例上 调用 createVolumeShaper() ,并传入 一个 VolumeShaper.Configuration:

Kotlin

volumeShaper = myMediaPlayer.createVolumeShaper(config)
volumeShaper = myAudioTrack.createVolumeShaper(config)

Java

volumeShaper = myMediaPlayer.createVolumeShaper(config);
volumeShaper = myAudioTrack.createVolumeShaper(config);

单个 音轨 媒体播放器 可以 附加 多个 shaper 并且 您可以 单独 控制 每个 shaper 音轨 播放器上 所有 shaper 的输出 相乘 一个 VolumeShaper 不能在 AudioTracks MediaPlayers 之间 共享 但您可以 在调用 createVolumeShaper 时使用 相同的 配置 在多个 AudioTracks MediaPlayers 构建 相同的 shaper

创建 shaper 第一个 控制点 ( t = 0) 应用 音频 如果 初始 音量 1.0 ,并且您的 应用 在创建时正在 播放 内容 您的 音频 可能会出现 音量 骤变 最佳 实践 静音 开始 播放 音频 ,并 在播放 开始时使用 一个 VolumeShaper 实现 淡入 创建 一个 0 音量 开始并 淡入的 VolumeShaper 例如:

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 将无效。

您必须交替使用 PLAYREVERSE 操作。无法将曲线从第一个控制点播放到最后一个控制点,然后再次从第一个控制点重新开始。您可以使用下一节中描述的 replace() 方法,将曲线替换为其自身的副本。这将重置 shaper,需要 PLAY 操作才能再次启动它。

更改曲线

使用 replace() 方法更改 VolumeShaper 的曲线。此方法接受配置、操作和连接参数。您可以随时调用 replace() 方法,无论 shaper 正在运行还是已过期。

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, 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);

当您在 shaper 运行时调用 replace() 时,它会停止改变音量并保持在当前值。然后,shaper 会尝试从第一个控制点开始新曲线。这意味着操作参数控制调用后 shaper 是否运行。指定 PLAY 可立即启动新曲线,指定 REVERSE 可使 shaper 暂停在新曲线第一个控制点的音量处。您可以稍后使用 apply(VolumeShaper.Operation.PLAY) 启动 shaper。

当您调用 replace() 并将 join = false 时,shaper 会在其第一个控制点指定的级别开始其曲线。这可能会导致音量出现不连续性。您可以通过调用 replace() 并将 join = true 来避免这种情况。这将新曲线的第一个控制点设置为 shaper 的当前级别,并缩放第一个和最后一个控制点之间所有控制点的音量,以保持新曲线的相对形状(最后一个控制点不变)。缩放操作会永久改变 shaper 新曲线中的控制点。

移除 VolumeShaper

VolumeShaperAudioTrackMediaPlayer 被释放或不再使用时,系统会关闭并垃圾回收它。您可以调用 shaper 上的 close() 方法立即销毁它。系统会在大约 20 毫秒内将 shaper 从音频管道中移除。在音频播放时关闭 VolumeShaper 时要小心。如果 shaper 在您调用 close() 时音量小于 1.0,shaper 的音量缩放将变为 1.0。这可能会导致音量突然增大。