空間オーディオは、ユーザーをアクションの中心に置く没入感のあるオーディオ エクスペリエンスであり、コンテンツの臨場感を高めます。サウンドは「空間化」され、サラウンド音声のセットアップと同様のマルチスピーカー効果を生み出しますが、代わりにヘッドフォンを使用します。
たとえば映画では、車の音がユーザーの後ろで始まり、前に進んだ後、遠くまで遡ります。ビデオチャットでは、声を分離してユーザーの周囲に配置できるため、発話者を識別しやすくなります。
サポートされているオーディオ形式をコンテンツで使用している場合、Android 13(API レベル 33)以降ではアプリに空間オーディオを追加できます。
機能をクエリする
Spatializer
クラスを使用して、デバイスの空間化機能と動作をクエリします。まず、AudioManager
から Spatializer
のインスタンスを取得します。
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
Spatializer
を取得したら、デバイスが空間化された音声を出力するために満たす必要がある次の 4 つの条件を確認します。
条件 | 確認 |
---|---|
デバイスは空間化に対応していますか? |
getImmersiveAudioLevel() が SPATIALIZER_IMMERSIVE_LEVEL_NONE でない
|
立体化は可能ですか? ご利用いただけるかどうかは、現在のオーディオ出力ルーティングとの互換性によって異なります。 |
isAvailable() は true です |
空間化は有効になっていますか? | isEnabled() は true です |
指定されたパラメータを持つ音声トラックを空間化できますか? | canBeSpatialized() は true です |
これらの条件が満たされないことがあります。たとえば、現在の音声トラックで空間化を使用できない場合や、音声出力デバイス全体で無効になっている場合などです。
ヘッド トラッキング
サポートされているヘッドセットを使用すると、プラットフォームはユーザーの頭の位置に基づいてオーディオの空間化を調整できます。現在のオーディオ出力ルーティングでヘッド トラッカーを使用できるかどうかを確認するには、isHeadTrackerAvailable()
を呼び出します。
互換性のあるコンテンツ
Spatializer.canBeSpatialized()
は、指定されたプロパティを持つ音声を、現在の出力デバイスのルーティングで空間化できるかどうかを示します。このメソッドは、AudioAttributes
と AudioFormat
を受け取ります。どちらも以下で詳しく説明します。
AudioAttributes
AudioAttributes
オブジェクトは、オーディオ ストリーム(ゲーム音声や標準メディアなど)の使用方法と、その再生動作やコンテンツ タイプを記述します。
canBeSpatialized()
を呼び出すときは、Player
に設定されたものと同じ AudioAttributes
インスタンスを使用します。たとえば、Jetpack Media3 ライブラリを使用していて、AudioAttributes
をカスタマイズしていない場合は、AudioAttributes.DEFAULT
を使用します。
空間オーディオを無効にする
コンテンツがすでに空間化されていることを示すには、setIsContentSpatialized(true)
を呼び出して、音声が二重処理されないようにします。または、setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
を呼び出して、空間化の動作を調整して空間化を完全に無効にします。
AudioFormat
AudioFormat
オブジェクトは、音声トラックの形式とチャンネル構成に関する詳細を記述します。
canBeSpatialized()
に渡す AudioFormat
をインスタンス化する場合は、エンコードをデコーダから期待される出力形式と同じ値に設定します。また、コンテンツのチャンネル構成と一致するチャンネル マスクを設定する必要があります。使用する特定の値については、デフォルトの空間化動作のセクションをご覧ください。
Spatializer
の変更をリッスンする
Spatializer
の状態の変化をリッスンするには、Spatializer.addOnSpatializerStateChangedListener()
を使用してリスナーを追加します。同様に、ヘッド トラッカーの可用性の変化をリッスンするには、Spatializer.addOnHeadTrackerAvailableListener()
を呼び出します。
これは、リスナーのコールバックを使用して、再生中にトラックの選択を調整する場合に便利です。たとえば、ユーザーがヘッドセットをデバイスに接続または接続解除すると、onSpatializerAvailableChanged
コールバックは、新しいオーディオ出力ルーティングでスペイシャライザー エフェクトを使用できるかどうかを示します。この時点で、デバイスの新機能に合わせてプレーヤーのトラック選択ロジックを更新することをご検討ください。ExoPlayer のトラック選択動作について詳しくは、ExoPlayer と空間オーディオのセクションをご覧ください。
ExoPlayer と空間オーディオ
ExoPlayer の最近のリリースで、空間オーディオの導入が簡単になりました。スタンドアロンの ExoPlayer ライブラリ(パッケージ名 com.google.android.exoplayer2
)を使用する場合、バージョン 2.17 では空間化された音声を出力するようにプラットフォームが構成され、バージョン 2.18 ではオーディオ チャンネル数の制約が導入されています。Media3 ライブラリ(パッケージ名 androidx.media3
)の ExoPlayer モジュールを使用する場合、バージョン 1.0.0-beta01
以降にも同じアップデートが含まれています。
ExoPlayer の依存関係を最新リリースに更新した後は、空間化できるコンテンツをアプリに含めるだけで済みます。
音声チャンネル数の制約
空間オーディオの 4 つの条件がすべて満たされた場合、ExoPlayer はマルチチャンネル オーディオ トラックを選択します。そうでない場合、ExoPlayer は代わりにステレオ トラックを選択します。Spatializer
プロパティが変更されると、ExoPlayer は新しいトラック選択をトリガーして、現在のプロパティに一致するオーディオ トラックを選択します。この新しいトラックを選択すると、再バッファリング期間が短くなる場合があります。
オーディオ チャンネル数の制約を無効にするには、プレーヤーでトラック選択パラメータを次のように設定します。
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
同様に、次のように既存のトラック セレクタのパラメータを更新して、オーディオ チャンネル数の制約を無効にできます。
Kotlin
val trackSelector = DefaultTrackSelector(context) ... trackSelector.parameters = trackSelector.buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); ... trackSelector.setParameters( trackSelector .buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
音声チャンネル数の制約を無効にして、コンテンツに複数の音声トラックがある場合、ExoPlayer は最初にチャンネル数が最も多く、デバイスから再生可能なトラックを選択します。たとえば、コンテンツにマルチチャンネル オーディオ トラックとステレオ オーディオ トラックが含まれ、デバイスが両方の再生をサポートしている場合、ExoPlayer はマルチチャンネル トラックを選択します。この動作をカスタマイズする方法については、オーディオ トラックの選択をご覧ください。
音声トラックの選択
ExoPlayer のオーディオ チャンネル数の制約動作が無効になっている場合、ExoPlayer はデバイスのスペイシャライザーのプロパティに一致するオーディオ トラックを自動的に選択しません。代わりに、再生前または再生中にトラック選択パラメータを設定することで、ExoPlayer のトラック選択ロジックをカスタマイズできます。デフォルトでは、ExoPlayer は MIME タイプ(エンコード)、チャンネル数、サンプルレートに関して最初のトラックと同じオーディオ トラックを選択します。
トラック選択パラメータの変更
ExoPlayer のトラック選択パラメータを変更するには、Player.setTrackSelectionParameters()
を使用します。同様に、ExoPlayer の現在のパラメータは Player.getTrackSelectionParameters()
で取得できます。たとえば、再生中にステレオ音声トラックを選択するには、次のようにします。
Kotlin
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
Java
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
再生中にトラック選択パラメータを変更すると、再生が中断される場合があります。プレーヤーのトラック選択パラメータの調整について詳しくは、ExoPlayer ドキュメントのトラックの選択のセクションをご覧ください。
デフォルトの空間化動作
Android のデフォルトの空間化動作には、OEM がカスタマイズできる次の動作が含まれています。
ステレオ コンテンツではなく、マルチチャンネル コンテンツのみが空間化されます。 ExoPlayer を使用しない場合は、マルチチャンネル オーディオ コンテンツの形式に応じて、オーディオ デコーダが多数のチャンネルに出力できる最大チャンネル数を構成する必要があります。これにより、オーディオ デコーダはプラットフォームでマルチチャンネル PCM を出力し、プラットフォームで空間化します。
Kotlin
val mediaFormat = MediaFormat() mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)
Java
MediaFormat mediaFormat = new MediaFormat(); mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);
実際の例については、ExoPlayer の
MediaCodecAudioRenderer.java
をご覧ください。OEM のカスタマイズにかかわらず、自分で空間化をオフにするには、空間オーディオを無効にするをご覧ください。AudioAttributes
:usage
がUSAGE_MEDIA
またはUSAGE_GAME
に設定されている場合、音声は空間化の対象になります。AudioFormat
: 音声を空間化の対象にするには、少なくともAudioFormat.CHANNEL_OUT_QUAD
チャンネル(左前、左、右、左、右後)を含むチャンネル マスクを使用します。次の例では、5.1 オーディオ トラックにAudioFormat.CHANNEL_OUT_5POINT1
を使用します。ステレオ音声トラックの場合は、AudioFormat.CHANNEL_OUT_STEREO
を使用します。Media3 を使用している場合は、
Util.getAudioTrackChannelConfig(int channelCount)
を使用してチャンネル数をチャンネル マスクに変換できます。また、マルチチャンネル PCM を出力するようにデコーダを構成している場合は、エンコードを
AudioFormat.ENCODING_PCM_16BIT
に設定します。Kotlin
val audioFormat = AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build()
Java
AudioFormat audioFormat = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build();
空間オーディオをテストする
テストデバイスで空間オーディオが有効になっていることを確認します。
- 有線ヘッドセットの場合は、[システム設定] > [音とバイブレーション] > [空間オーディオ] に移動します。
- ワイヤレス ヘッドセットの場合は、[システム設定] > [接続済みのデバイス] > ワイヤレス デバイスの歯車アイコン > [空間オーディオ] に移動します。
現在のルーティングで空間オーディオを利用できるかどうかを確認するには、デバイスで adb shell dumpsys audio
コマンドを実行します。再生がアクティブな間は、出力に次のパラメータが表示されます。
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)