XR アプリに空間オーディオを追加する

対象となる XR デバイス
このガイダンスは、次のようなタイプの XR デバイス向けのエクスペリエンスを構築する際に役立ちます。
XR ヘッドセット
有線 XR グラス

Jetpack SceneCore の空間オーディオ機能を使用すると、Android XR アプリ内で臨場感あふれるオーディオ エクスペリエンスを作成できます。

空間オーディオは、3D 環境でユーザーが音をどのように認識するかをシミュレートします。ユーザーの上下を含むあらゆる方向から音が聞こえてくるような感覚を作り出します。システムは、3D 空間の特定の場所に 1 つ以上の「仮想スピーカー」をシミュレートすることで、これを実現します。

Android XR 向けに設計または変更されていない既存のアプリでは、Android XR でオーディオが自動的に空間化されます。ユーザーが空間内を移動すると、アプリの UI がレンダリングされるパネルからアプリのすべての音声が出力されます。たとえば、時計アプリのタイマーが鳴ると、アプリパネルの位置から音が聞こえるようになります。Android XR は、位置のリアルさを実現するために音声を自動的に変更します。たとえば、アプリパネルとユーザーの間の知覚距離がオーディオの音量に微妙に影響し、よりリアルな感覚が得られます。

既存のアプリで空間オーディオをレンダリングする方法について詳しくは、このページのアプリにステレオとサラウンド音声を追加するをご覧ください。

XR 向けにアプリを最適化する場合、Jetpack SceneCore には高度な空間オーディオのカスタマイズ ツールが用意されています。3D 環境で音声を正確に配置し、アンビソニック オーディオを使用してリアルな音場を実現し、組み込みのサラウンド音声統合を活用できます。

Android XR で利用できる空間オーディオの種類

Android XR は、位置オーディオ、ステレオ、サラウンド音声、アンビソニック オーディオをサポートしています。

位置オーディオ

位置オーディオは、3D 空間内の特定のポイントから再生されるように配置できます。たとえば、仮想環境の隅で吠える犬の 3D モデルを配置できます。複数のエンティティがそれぞれの位置から音を出すように設定できます。位置オーディオをレンダリングするには、ファイルがモノラルまたはステレオである必要があります。

空間ステレオとサラウンド音声

位置、ステレオ、サラウンド音声では、すべての Android メディア形式がサポートされています。これらの形式に加えて、Android XR デバイスは Dolby Atmos、Dolby Digital、Dolby Digital+ の音声形式をサポートしている場合があります。

ステレオ音声とは、2 つのチャンネルを持つ音声形式を指します。サラウンド音声とは、2 つ以上のチャンネルを持つ音声形式を指します。たとえば、5.1 サラウンド音声や 7.1 サラウンド音声の構成などです。各チャンネルの音声データは 1 人の話者に関連付けられます。たとえば、ステレオで音楽を再生する場合、左スピーカー チャンネルは右スピーカー チャンネルとは異なる楽器トラックを出力することがあります。

サラウンド音声は、映画やテレビ番組でよく使用され、複数のスピーカー チャンネルを使用して臨場感と没入感を高めます。たとえば、会話はセンター スピーカー チャンネルから再生されることが多く、ヘリコプターが飛ぶ音は、ヘリコプターが 3D 空間を飛び回っているような感覚を与えるために、異なるチャンネルを順番に使用することがあります。

アンビソニック音声

アンビソニック オーディオ(またはアンビソニックス)は、オーディオのスカイボックスのようなもので、ユーザーに没入感のあるサウンドスケープを提供します。アンビソニックは、バックグラウンドの環境音や、リスナーを囲む全天球音場を再現するその他のシナリオで使用します。Android XR は、1 次、2 次、3 次のアンビソニックで AmbiX アンビソニック音声形式をサポートしています。Opus(.ogg)と PCM/Wave(.wav)のファイル形式をおすすめします。

Jetpack SceneCore で空間オーディオを使用する

Jetpack SceneCore で空間オーディオを実装するには、空間機能をチェックし、空間オーディオを読み込む API を選択します。

空間機能を確認する

空間オーディオ機能を使用する前に、Session が空間オーディオをサポートしていることを確認します。以下のセクションのすべてのコード スニペットでは、空間オーディオの再生を試みる前に、機能がチェックされます。

空間オーディオを読み込む

次のいずれかの API を使用して、Jetpack SceneCore で使用する空間オーディオを読み込むことができます。

  • SoundPool: サイズが 1 MB 未満の短い効果音に最適です。事前に読み込まれ、繰り返し使用できます。これは、位置オーディオのオーディオを読み込むのに最適な方法です。
  • ExoPlayer: 音楽や動画などのステレオ音声やサラウンド音声のコンテンツを読み込む場合に最適です。バックグラウンドでのメディア再生も可能です。
  • MediaPlayer: アンビソニック音声を読み込む最も簡単な方法を提供します。
  • AudioTrack: 音声データの読み込み方法を最も細かく制御できます。音声のバッファを直接書き込むことができます。また、独自の音声ファイルを合成またはデコードすることもできます。

メディア形式のサポートを確認する

一部のメディア形式は Android プラットフォームでサポートされています。ただし、特定の Android XR デバイスでは、Dolby Atmos などの追加の形式がサポートされている場合があります。メディア形式のサポートをクエリするには、ExoPlayer の AudioCapabilities を使用します。

val audioCapabilities = AudioCapabilities.getCapabilities(
    context,
    androidx.media3.common.AudioAttributes.DEFAULT,
    null,
    emptyList()
)

if (audioCapabilities.supportsEncoding(C.ENCODING_AC3)) {
    // Device supports playback of the Dolby Digital media format.
}
if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3)) {
    // Device supports playback of the Dolby Digital Plus media format.
}
if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3_JOC)) {
    // Device supports playback of the Dolby Digital Plus with Dolby Atmos media format.
}

これらの機能をチェックすると、呼び出しがブロックされる可能性があるため、メインスレッドで呼び出さないでください。

アプリに位置情報オーディオを追加する

位置音源は、PointSourceParams と関連する Entity によって定義されます。Entity の位置と向きによって、3D 空間で PointSourceParams がレンダリングされる場所が決まります。SpatialMediaPlayer で setPointSourceParams を呼び出して、MediaPlayer インスタンスに PointSourceParams とそれに関連付けられた entity を設定します。

位置オーディオの例

次の例では、効果音の音声ファイルをサウンドプールに読み込み、Entity の位置で再生します。

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)
) { // The session has spatial audio capabilities
    val maxVolume = 1F
    val lowPriority = 0
    val infiniteLoop = -1
    val normalSpeed = 1F

    val soundPool = SoundPool.Builder()
        .setAudioAttributes(
            AudioAttributes.Builder()
                .setContentType(CONTENT_TYPE_SONIFICATION)
                .setUsage(USAGE_ASSISTANCE_SONIFICATION)
                .build()
        )
        .build()

    val pointSource = PointSourceParams()

    val soundEffect = appContext.assets.openFd("sounds/tiger_16db.mp3")
    val pointSoundId = soundPool.load(soundEffect, lowPriority)

    soundPool.setOnLoadCompleteListener { soundPool, sampleId, status ->
        // wait for the sound file to be loaded into the soundPool
        if (status == 0) {
            SpatialSoundPool.play(
                session = session,
                entity = entity,
                soundPool = soundPool,
                soundID = pointSoundId,
                params = pointSource,
                volume = maxVolume,
                priority = lowPriority,
                loop = infiniteLoop,
                rate = normalSpeed
            )
        }
    }
} else {
    // The session does not have spatial audio capabilities
}

コードに関する主なポイント

  • 最初のステップは、spatialCapabilities を使用して、空間オーディオ機能が利用可能かどうかを確認することです。
  • contentType を CONTENT_TYPE_SONIFICATION に設定し、usage を USAGE_ASSISTANCE_SONIFICATION に設定すると、システムはこの音声ファイルを効果音として扱います。
  • 上記の例では、コードを簡素化するために、使用する直前に音声ファイルをプールに読み込んでいます。理想的には、アプリの読み込み時にすべての効果音を非同期で読み込み、必要なときにすべての音声ファイルがプールで使用できるようにする必要があります。

アプリにステレオ音声とサラウンド音声を追加する

アプリにステレオ音声とサラウンド音声を追加するには、Exoplayer を使用することをおすすめします。Exoplayer で空間オーディオを使用する方法について詳しくは、空間オーディオ ガイドをご覧ください。

ステレオ スピーカーとサラウンド スピーカーの配置

サラウンド音声スピーカーの配置では、仮想サラウンド音声スピーカーは、標準の ITU 構成でユーザーの周囲のセンタースピーカーを基準に配置され、方向付けられます。

デフォルトでは、センター チャンネル スピーカーはアプリの mainPanelEntity に配置されます。これには、Android XR によってオーディオが自動的に空間化されるモバイルアプリも含まれます。

ステレオの場合、スピーカーの配置はサラウンド音声と同様ですが、左右のチャンネルのみがパネルの左右にそれぞれ配置されます。

複数のパネルがあり、音声を出力するパネルを選択する場合や、ステレオまたはサラウンド音声を別の Entity を基準にしてレンダリングする場合は、PointSourceAttributes を使用してセンター チャンネルの位置を定義できます。残りのチャンネルは、前述のように配置されます。このような場合は、MediaPlayer も使用する必要があります。

ユーザーが空間内を移動すると、ステレオとサラウンド音声の仮想スピーカーが移動して調整され、スピーカーが常に最適な位置に配置されます。

バックグラウンドでステレオまたはサラウンド音声の再生を続行するように MediaPlayer または ExoPlayer を構成している場合、アプリがバックグラウンドに移行すると、仮想スピーカーの位置が変更されます。音声を固定するパネルやその他の空間ポイントがないため、空間オーディオはユーザーと一緒に移動します(つまり、「ヘッドロック」されます)。

サラウンド音声の例

次の例では、MediaPlayer を使用して 5.1 音声ファイルを読み込み、ファイルのセンター チャンネルを Entity に設定します。

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val pointSourceAttributes = PointSourceParams()

    val mediaPlayer = MediaPlayer()

    val fivePointOneAudio = appContext.assets.openFd("sounds/aac_51.ogg")
    mediaPlayer.reset()
    mediaPlayer.setDataSource(fivePointOneAudio)

    val audioAttributes =
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()

    SpatialMediaPlayer.setPointSourceParams(
        session,
        mediaPlayer,
        pointSourceAttributes,
        entity = session.scene.mainPanelEntity,
    )

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()
} else {
    // The session does not have spatial audio capabilities
}

コードに関する主なポイント

アプリにアンビソニック サウンド フィールドを追加する

アンビソニック音場を再生する最も簡単な方法は、MediaPlayer を使用してファイルを読み込むことです。アンビソニック サウンドはサウンドスケープ全体に適用されるため、位置を指定するために Entity を指定する必要はありません。代わりに、チャンネル数を指定する適切なアンビソニック オーダーを使用して SoundFieldAttributes のインスタンスを作成します。

Ambionics の例

次の例では、MediaPlayer を使用してアンビソニック音場を再生しています。

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val soundFieldAttributes =
        SoundFieldAttributes(SpatializerConstants.AmbisonicsOrder.FIRST_ORDER)

    val mediaPlayer = MediaPlayer()

    val soundFieldAudio = appContext.assets.openFd("sounds/foa_basketball_16bit.wav")

    mediaPlayer.reset()
    mediaPlayer.setDataSource(soundFieldAudio)

    val audioAttributes =
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()

    SpatialMediaPlayer.setSoundFieldAttributes(
        session,
        mediaPlayer,
        soundFieldAttributes
    )

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()
} else {
    // The session does not have spatial audio capabilities
}

コードに関する主なポイント

  • 前のスニペットと同様に、最初のステップは、spatialCapabilities を使用して空間オーディオ機能が利用可能かどうかを確認することです。
  • contentType と使用量は、純粋に情報提供を目的としています。
  • SpatializerConstants.AmbisonicsOrder.FIRST_ORDER は、音場ファイルが 4 つのチャンネルを定義していることを SceneCore に通知します。