您可以在音频应用中使用 VolumeShaper
来执行淡入、淡出、淡入淡出、降低音量以及其他简短的自动音量过渡。VolumeShaper
类适用于 Android 8.0(API 级别 26)及更高版本。
您可以通过对 AudioTrack
或 MediaPlayer
的实例调用 createVolumeShaper()
来创建 VolumeShaper
。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] 中的指定时间坐标会调整为您指定的持续时间(以毫秒为单位)。这决定了在 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();
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 后立即应用于音频路径,但在您使用 VolumeShaper.Operation.PLAY
调用 apply()
方法之前,Shaper 不会沿着曲线前进。创建 Shaper 后,对 apply()
的第一次调用必须指定 PLAY
操作才能启动 Shaper。这会运行曲线从其第一个控制点到最后一个控制点:
Kotlin
formr.apply(VolumeShaper.Operation.PLAY)
Java
Shaper.apply(VolumeShaper.Operation.PLAY);
当 Shaper 正在运行时,您可以发出交替的 apply()
调用来指定 REVERSE 和 PLAY 操作。这会每次都会更改控制点的读出方向。
Shaper 会不断调整音量并通过所有控制点,直到过期为止。当 Shaper 到达曲线中的最后一个(对于 PLAY 操作)或第一个(对于 REVERSE 操作)控制点时,就会发生这种情况。
formr 到期后,音量会保留在最后一个设置,这可能是第一个或最后一个控制点。您可以随时调用 VolumeShaper.getVolume()
获取当前音量。
Shaper 过期后,您可以发出另一个 apply()
调用以相反的方向运行曲线。例如,如果 Shaper 在运行 PLAY
时过期,则下一个 apply()
必须为 REVERSE
。在 PLAY
过期后调用 PLAY
或在 REVERSE
过期后调用 REVERSE
不会产生任何影响。
您必须交替执行 PLAY
操作和 REVERSE
操作。您无法在播放从第一个控制点到最后一个控制点的曲线,然后从第一个控制点再次重新播放曲线。您可以使用下一部分中介绍的 replace()
方法将曲线替换为其自身的副本。这会重置 Shaper,需要执行 PLAY
操作才能重新启动。
更改曲线
使用 replace()
方法可以更改 VolumeShaper
的曲线。此方法接受配置、操作和联接参数。您可以在 Shaper 运行时或到期后随时调用 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 参数联接.shar.shar.
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_CANNOT TRANSLATE
当您在 shaper 运行时调用 replace()
时,它会停止更改音量并保持其当前值。然后,Shaper 会尝试从第一个控制点开始新曲线。这意味着,操作参数用于控制 Shaper 是否在调用后运行。指定 PLAY
可立即启动新曲线,指定 REVERSE
可让 Shaper 在新曲线中第一个控制点的音量下暂停。您稍后可以使用 apply(VolumeShaper.Operation.PLAY)
启动 transformr。
当您使用 join = false
调用 replace()
时,Shaper 会在其第一个控制点指定的级别开始运行曲线。这可能会导致音量不连贯。您可以通过使用 join = true
调用 replace()
来避免此问题。这会将新曲线的第一个控制点设为形状的当前水平,并缩放第一个和最后一个控制点之间所有控制点的音量,以保持新曲线的相对形状(最后一个控制点保持不变)。缩放操作会永久更改形状工具新曲线中的控制点。
移除 VolumeShaper
当 VolumeShaper
的 AudioTrack
或 MediaPlayer
被释放或不再使用时,系统会关闭并对其进行垃圾回收。您可以对 formr 调用 close()
方法以立即销毁它。系统会在大约 20 毫秒内从音频管道中移除 formr。在音频播放期间关闭 VolumeShaper
时要小心。如果您调用 close()
时,Shaper 的音量小于 1.0,则 Shaper 的音量比例会更改为 1.0。这可能会导致音量突然增加。