androidx.xr.compose.subspace.media

Classes

PointSourceExoplayerAudioOutput

Creates a SpatializedExoplayerAudioOutput with PointSourceParams.

SoundFieldExoplayerAudioOutput

Creates a SpatializedExoplayerAudioOutput from SoundFieldAttributes.

SpatializedAudioOutput

Signifies that a class is capable of configuring spatialized audio output.

SpatializedExoplayerAudioOutput

Allows spatializing Exoplayer audio output.

Composables

Extension functions summary

Extension functions

SoundEffectPoolComponent.asSpatializedAudioOutput

fun SoundEffectPoolComponent.asSpatializedAudioOutput(): SpatializedAudioOutput

Returns a SpatializedAudioOutput that wraps this SoundEffectPoolComponent. This allows the component's audio to be spatialized from the Composable it is attached to via spatializedAudioOutput.

SubspaceModifier.spatializedAudioOutput

fun SubspaceModifier.spatializedAudioOutput(
    spatializedAudioOutput: SpatializedAudioOutput
): SubspaceModifier

Adds spatialized audio output to this Composable. Use PointSourceExoplayerAudioOutput, SoundFieldExoplayerAudioOutput or SoundEffectPoolComponent.asSpatializedAudioOutput to create an object capable of spatializing audio.

import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.movable
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.media.rememberPointSourceExoplayerAudioOutput
import androidx.xr.compose.subspace.media.spatializedAudioOutput
import androidx.xr.scenecore.PointSourceParams

val context = LocalContext.current

// Create a PointSourceExoplayerAudioOutput.
val audioOutput = rememberPointSourceExoplayerAudioOutput(PointSourceParams())

// Create an ExoPlayer and set its AudioOutputProvider.
val exoPlayer = remember {
    ExoPlayer.Builder(context).setAudioOutputProvider(audioOutput.audioOutputProvider).build()
}

DisposableEffect(Unit) {
    exoPlayer.setMediaItem(MediaItem.fromUri("asset:///audio.mp3"))
    exoPlayer.prepare()
    exoPlayer.play()

    onDispose { exoPlayer.release() }
}

// Attach the SpatializedAudioOutput via SubspaceModifier.spatializedAudioOutput. The audio will
// be spatialized from the position of this SpatialPanel, and will follow the Panel as it moves.
SpatialPanel(
    modifier =
        SubspaceModifier.width(600.dp)
            .height(400.dp)
            .spatializedAudioOutput(audioOutput)
            .movable()
) {
    // Content of the panel
}
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
import androidx.xr.compose.platform.LocalSession
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.movable
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.media.SoundFieldExoplayerAudioOutput
import androidx.xr.compose.subspace.media.spatializedAudioOutput
import androidx.xr.scenecore.SoundFieldAttributes
import androidx.xr.scenecore.SpatializerConstants

val context = LocalContext.current
val session = LocalSession.current ?: return

// Create a SoundFieldExoplayerAudioOutput.
val audioOutput = remember {
    SoundFieldExoplayerAudioOutput(
        session,
        SoundFieldAttributes(SpatializerConstants.AmbisonicsOrder.FIRST_ORDER),
    )
}

// Create an ExoPlayer and set its AudioOutputProvider.
val exoPlayer = remember {
    ExoPlayer.Builder(context).setAudioOutputProvider(audioOutput.audioOutputProvider).build()
}

DisposableEffect(Unit) {
    exoPlayer.setMediaItem(MediaItem.fromUri("asset:///ambient.mp3"))
    exoPlayer.prepare()
    exoPlayer.play()

    onDispose { exoPlayer.release() }
}

// Attach the SpatializedAudioOutput via SubspaceModifier.spatializedAudioOutput.
SpatialPanel(
    modifier =
        SubspaceModifier.width(600.dp)
            .height(400.dp)
            .spatializedAudioOutput(audioOutput)
            .movable()
) {
    // Content of the panel
}
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.xr.compose.platform.LocalSession
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.movable
import androidx.xr.compose.subspace.layout.width
import androidx.xr.compose.subspace.media.asSpatializedAudioOutput
import androidx.xr.compose.subspace.media.spatializedAudioOutput
import androidx.xr.scenecore.PointSourceParams
import androidx.xr.scenecore.SoundEffectPool
import androidx.xr.scenecore.SoundEffectPoolComponent

val context = LocalContext.current
val session = LocalSession.current ?: return

// Create a SoundEffectPool.
val soundEffectPool = remember { SoundEffectPool.create(session, maxStreams = 10) }

// Remember a sound effect loaded via AssetFileDescriptor.
val soundEffect = remember {
    val assetFileDescriptor = context.assets.openFd("click.wav")
    soundEffectPool.load(assetFileDescriptor)
}

// Create a SoundEffectPoolComponent.
val soundEffectPoolComponent =
    remember(session, soundEffectPool) {
        SoundEffectPoolComponent.create(session, soundEffectPool, PointSourceParams())
    }

// Attach the SpatializedAudioOutput via SubspaceModifier.spatializedAudioOutput.
SpatialPanel(
    modifier =
        SubspaceModifier.width(600.dp)
            .height(400.dp)
            .spatializedAudioOutput(soundEffectPoolComponent.asSpatializedAudioOutput())
            .movable()
) {
    Button(
        onClick = {
            soundEffectPoolComponent.play(
                soundEffect,
                volume = 1f,
                priority = 0,
                isLooping = false,
            )
        }
    ) {
        Text("Play Sound Effect")
    }
}
Parameters
spatializedAudioOutput: SpatializedAudioOutput

A SpatializedAudioOutput to be added to this Composable. A SpatializedAudioOutput should only be attached to one Composable at a time. If it is attached multiple times, its associated audio output will become head locked.