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 メディア形式がサポートされています。

ステレオ音声は 2 チャンネルの音声形式を指し、サラウンド音声は 5.1 サラウンド音声7.1 サラウンド音声などの 3 チャンネル以上の音声形式を指します。各チャンネルの音声データは 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: 音声データの読み込み方法を最も細かく制御できます。音声のバッファを直接書き込む場合や、独自の音声ファイルを合成またはデコードする場合に使用します。

アプリにポジショナル オーディオを追加する

位置音源は、PointSourceParams と関連する Entity によって定義されます。Entity の位置と向きによって、3D 空間で PointSourceParams がレンダリングされる場所が決まります。

ポジショナル オーディオの例

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

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities
    .hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_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(entity)

    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,
                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.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val pointSourceAttributes = PointSourceParams(session.scene.mainPanelEntity)

    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
    )

    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.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val soundFieldAttributes =
        SoundFieldAttributes(SpatializerConstants.AMBISONICS_ORDER_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
}

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

  • 前のスニペットと同様に、最初の手順は hasCapability() を使用して空間オーディオ機能が利用可能かどうかを確認することです。
  • contentType と使用状況は参考情報です。
  • AMBISONICS_ORDER_FIRST_ORDER は、サウンド フィールド ファイルが 4 つのチャンネルを定義していることを SceneCore に通知します。