オーディオ アプリで VolumeShaper
を使用すると、フェードイン、フェードアウト、クロスフェード、ダッキングなどの短時間の自動音量切り替えを行うことができます。VolumeShaper
クラスは Android 8.0(API レベル 26)以降で使用できます。
VolumeShaper
を作成するには、AudioTrack
または MediaPlayer
のインスタンスに対して createVolumeShaper()
を呼び出します。VolumeShaper
は AudioTrack または MediaPlayer で作成された音声にのみ作用します。
VolumeShaper.Configuration
VolumeShaper
の動作はその VolumeShaper.Configuration
で定義します。この設定では、「音量カーブ、補間タイプ、および時間」を指定します。
音量カーブ
音量カーブは、振幅(音量)の経時的な変化を表します。一連のコントロール ポイントを定義する float 型配列 x[] と y[] のペアで音量カーブが定義されます。(x, y) の各ペアはそれぞれ時間と音量を表します。2 つの配列は同じ長さで、2~16 個の値を含める必要があります(カーブの最大長は getMaximumCurvePoints()
で規定されます)。
時間座標の区間は [0.0, 1.0] です。最初の時点が 0.0、最後の時点が 1.0 で、時間の値は単調増加します。
音量座標は、区間 [0.0, 1.0] にわたって等間隔で指定します。
補間タイプ
音量カーブは指定されたコントロール ポイントを必ず通ります。コントロール ポイント間の値は、設定されている補間タイプに応じたスプラインによって計算されます。VolumeShaper
補間タイプとして指定可能な 4 つの定数は以下のとおりです。
- 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();
引数がない場合、VolumeShaper.Configuration.Builder
コンストラクタは、デフォルト設定を使って設定を作成するビルダーを返します。デフォルト設定は、INTERPOLATOR_TYPE_CUBIC、長さは 1 秒、カーブはなしです。build()
を呼び出す前にビルダーにカーブを指定する必要があります。
このフレームワークには、あらかじめ作成されたカーブを使用する設定用に以下の定数があり、長さはそれぞれ 1 秒です。
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);
1 つのトラックまたはメディア プレーヤーに多数のシェイパーを指定でき、各シェイパーを個別にコントロールできます。1 つのトラックまたはプレーヤーのすべてのシェイパーの出力が多重化されます。VolumeShaper
を複数の AudioTracks
または MediaPlayers
で共有することはできませんが、createVolumeShaper
への呼び出しに同じ設定を使って、複数の AudioTracks
または MediaPlayers
上に同等のシェイパーを作成できます。
シェイパーを作成するには、始点のコントロール ポイント(t = 0)を音声ストリームに適用します。初期値が 1.0 ではなく、その作成時にアプリがコンテンツを再生中の場合、音量が急に変わることがあります。おすすめの方法としては、無音状態から音声の再生を開始し、VolumeShaper
を使って音声の開始時にフェードインを実装します。音量が 0 から開始してフェードアップする VolumeShaper
を作成します。たとえば次のように指定します。
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
を呼び出したりしても、効果はありません。
PLAY
オペレーションと REVERSE
オペレーションは交互に行う必要があります。始点のコントロール ポイントから終点のコントロール ポイントまでカーブを再生した後に、また始点のコントロール ポイントから再開する方法はありません。次のセクションで説明する replace()
メソッドを使って、カーブをそのコピーと置き換えることができます。これによりシェイパーがリセットされるので、もう一度開始するには、PLAY
オペレーションが必要です。
カーブを変更する
VolumeShaper
のカーブを変更するには、replace()
メソッドを使用します。このメソッドには、設定、オペレーション、join パラメータを指定します。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, 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)
によって開始できます。
join = false
を指定して replace()
を呼び出すと、シェイパーは始点のコントロール ポイントで指定された音量でカーブを開始します。これにより、音量が不連続になることがあります。これを避けるには、join = true
を指定して replace()
を呼び出します。これにより、新しいカーブの始点のコントロール ポイントはシェイパーの現在の音量に設定されます。さらに、始点から終点の間にあるすべてのコントロール ポイントの音量がスケーリングされ、新しいカーブの相対的な形は維持されます(終点のコントロール ポイントは変更されません)。このスケーリング オペレーションによって、シェイパーの新しいカーブのコントロール ポイントは永続的に変更されます。
VolumeShaper を削除する
AudioTrack
または MediaPlayer
が解放されるか、使用されなくなると、システムは VolumeShaper
を終了してガベージ コレクションを行います。シェイパーをすぐに破棄するには、close()
メソッドを呼び出します。システムは約 20 ms 以内にオーディオ パイプラインからシェイパーを削除します。音声の再生中に VolumeShaper
を終了する際には注意してください。シェイパーの音量が 1.0 より小さい場合、close()
を呼び出すとシェイパーの音量スケールは 1.0 に変わります。それによって、音量が急激に大きくなることがあります。