使用 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] 之間的指定時間座標會縮放至您指定的時間長度 (以毫秒為單位)。這會決定形狀器運作時的音量曲線實際長度,並將曲線套用至音訊輸出。

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

同時開始播放和形狀器。這可確保播放作業從無聲開始,並將音量提高到最大。我們將在下一節中說明。

執行 VolumeShaper

雖然建立形狀工具後,音訊路徑的音量等級就會立即套用至音訊路徑,但您必須先使用 VolumeShaper.Operation.PLAY 呼叫 apply() 方法,形狀器才會沿著曲線移動。建立形狀器後,首次叫用 apply() 時必須指定 PLAY 作業,才能啟動形狀器。這會執行曲線從第一個到最後一個控制點執行:

Kotlin

Shaper.apply(VolumeShaper.Operation.PLAY)

Java

Shaper.apply(VolumeShaper.Operation.PLAY);

在圖形器執行期間,您可以發出交替指定 REVERSE 和 PLAY 作業的 apply() 呼叫。這會變更每次的控制點讀取方向。

形狀器會持續調整音量並傳遞所有控制點,直到到期為止。當形狀器達到曲線中的最後一個 (針對 PLAY 作業) 或第一個 (針對 REVERSE 作業) 控制點時,就會發生此情況。

形狀器到期後,音量會保持在最後的設定,可能是第一個或最後一個控制點。您隨時可以針對目前的音量呼叫 VolumeShaper.getVolume()

在形狀器到期後,您可以發出另一個 apply() 呼叫,往反方向執行曲線。舉例來說,如果形狀工具在執行 PLAY 時已過期,則下一個 apply() 必須為 REVERSE。在 PLAY 過期之後呼叫 PLAY,或在 REVERSE 過期後呼叫 REVERSE 不會有任何作用。

您必須替代 PLAYREVERSE 作業。您無法從第一個到最後一個控制點播放曲線,並從第一個控制點重新開始。您可以使用下一節所述的 replace() 方法,將曲線替換為自己的副本。這樣會重設形狀器,但必須先執行 PLAY 作業才能再次啟動。

改變曲線

使用 replace() 方法即可變更 VolumeShaper 的曲線。這個方法可使用設定、作業和彙整參數。在形狀工具執行期間或到期後,您隨時可以呼叫 replace() 方法:

Kotlin

val newConfig = VolumeShaper.Configuration.Builder()
 .setDuration(1000)
 .setCurve(floatArrayOf(0f, 0.5f), floatArrayOf(0f, 1f))
 .setInterpoatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINE
)

Java

VolumeShaper.Configuration newConfig =
 new VolumeShaper.Configuration.Builder()
 .setDuration(1000)
 .setCurve(new float[] {0.f, 0.5f}, new float[] {0.f, 1.f}
 .setInterpoatorType(VolumeShaper.Configuration.INTERPOER_TYPE_

如果在形狀器執行期間呼叫 replace(),系統會停止變更音量,並保持目前的值。接著,形狀器會嘗試從第一個控制點啟動新的曲線。這表示作業引數可控制形狀器在呼叫後是否要執行。指定 PLAY 可立即啟動新曲線。指定 REVERSE,即可在新曲線中第一個控制點的音量下暫停形狀器。您之後可以使用 apply(VolumeShaper.Operation.PLAY) 啟動形狀器。

當您使用 join = false 呼叫 replace() 時,形狀器會在第一個控制點指定的層級開始曲線。這可能會導致磁碟區中斷。如要避免這種情況,請使用 join = true 呼叫 replace()。這會將新曲線的第一個控制點設為形狀的目前等級,並縮放第一個和最後一個控制點之間的所有控制點音量,以維持新曲線的相對形狀 (最後一個控制點未變更)。縮放作業會永久變更形狀新曲線中的控制點。

移除 VolumeShaper

VolumeShaperAudioTrackMediaPlayer 釋放或不再使用時,系統會關閉並垃圾收集。您可以對形狀器呼叫 close() 方法,立即將其刪除。系統會在約 20 毫秒內將形狀器從音訊管道中移除。播放音訊時關閉 VolumeShaper 時請務必小心。如果您呼叫 close() 時,形狀器的音量小於 1.0,形狀器的音量縮放會變更為 1.0。這可能會導致流量突然增加。