空間オーディオとは、コンテンツのサウンドをよりリアルにし、その場にいるかのような臨場感のあるオーディオ体験を楽しめる機能です。サウンドが「空間化」され、サラウンド環境のようなマルチスピーカー効果が得られます。ただし、ヘッドフォンが必要です。
たとえば、映画の中で、ユーザーの後ろから車の音が聞こえ、前方に移動して消えていくような効果を出すことができます。ビデオチャットでは、各発言者の声を異なる方向から聞こえるように分離することで、発言者を特定しやすくなります。
サポートされている音声形式のコンテンツは、アプリでの空間オーディオ再生が可能です(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() を呼び出すときは、
AudioAttributes に設定されているものと同じ Player インスタンスを使用します。たとえば、Jetpack Media3 ライブラリを使用していて、
AudioAttributes をカスタマイズしていない場合は、AudioAttributes.DEFAULT を使用します。
空間オーディオを無効にする
コンテンツがすでに空間化されていることを示すには、setIsContentSpatialized(true) を呼び出して、音声が二重に処理されないようにします。または、setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER) を呼び出して、空間化処理を調整して、空間化を完全に無効にすることもできます。
AudioFormat
AudioFormat オブジェクトは、音声トラックの形式とチャンネル構成の詳細を
示します。
AudioFormat をインスタンス化して canBeSpatialized() に渡す場合は、エンコーディングをデコーダから想定される出力形式に合わせて設定します。コンテンツのチャンネル構成と一致するチャンネル マスクも設定する必要があります。使用する特定の値については、デフォルトの空間化処理のセクションをご覧ください。
Spatializer の変更をリッスンする
Spatializer の状態の変化をリッスンするには、Spatializer.addOnSpatializerStateChangedListener() を使用してリスナーを追加します。同様に、ヘッド トラッキングの可用性の変化をリッスンするには、Spatializer.addOnHeadTrackerAvailableListener() を呼び出します。
これは、リスナーのコールバックを使用して再生中にトラックの選択を調整する場合に便利です。たとえば、ユーザーがヘッドセットをデバイスに接続または接続解除すると、onSpatializerAvailableChanged コールバックは、新しい音声出力ルーティングでスペーシャライザー効果が利用可能かどうかを示します。この時点で、デバイスの新しい機能に合わせてプレーヤーのトラック選択ロジックを更新することを検討してください。ExoPlayer のトラック選択の処理について詳しくは、ExoPlayer と空間オーディオのセクションをご覧ください。
ExoPlayer と空間オーディオ
ExoPlayer の最近のリリースでは、空間音声の導入が容易になっています。スタンドアロンの ExoPlayer ライブラリ(パッケージ名 com.google.android.exoplayer2)を使用している場合、バージョン 2.17 では空間オーディオを出力するようにプラットフォームが構成され、バージョン 2.18 ではオーディオ チャンネル数のルールが導入されます。Media3 ライブラリの ExoPlayer モジュール(パッケージ名 androidx.media3)を使用している場合、バージョン 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チャンネル(フロント左、フロント右、リア左、リア右)を含むチャンネル マスクを使用します。次の例では、AudioFormat.CHANNEL_OUT_5POINT15.1 音声トラックに使用しています。ステレオ オーディオ トラックの場合は、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)