simvx.core.audio_protocol

Backend-agnostic audio interface.

The audio system talks to three thin structural :class:Protocol types:

  • class:

    AudioPlaybackBackend: start / stop / pause / live-update sounds.

  • class:

    AudioStreamingBackend: chunk-fed PCM streaming (for procedural synthesis, AudioWorklet, etc.).

  • class:

    AudioBusBackend: bus-layout reconciliation and capability advertisement.

A concrete backend implements whichever facets it can. The union

class:

AudioBackend keeps the legacy “everything in one Protocol” surface for callers that genuinely need all three (e.g. MiniaudioBackend, WebAudioBackend); narrower callers should depend on the smallest Protocol they actually use and reach the backend via

attr:

SceneTree.audio_playback / :attr:audio_streaming /

attr:

audio_buses so the type checker enforces the facet boundary.

Capabilities are a :class:enum.StrEnum so typos are caught at import. Existing string callers keep working: Capability.PLAY_BASIC compares equal to "play.basic" and round-trips through frozenset literally.

Channels are opaque integer handles allocated by the backend. The backend owns the mapping from handle to native voice; the Python layer treats them as bookmarks.

Module Contents

Classes

Capability

Capabilities a backend can advertise via :meth:AudioBusBackend.list_capabilities.

AudioPlaybackBackend

Backend facet for starting and controlling individual sounds.

AudioStreamingBackend

Backend facet for chunk-fed PCM streaming.

AudioBusBackend

Backend facet for bus-layout reconciliation and capability discovery.

AudioBackend

Union Protocol: a backend that implements all three facets.

Data

__all__

CAPABILITIES_CORE

Capabilities every backend that participates in playback + streaming advertises.

PlayMode

Mode kwarg for :meth:AudioPlaybackBackend.play_audio.

API

simvx.core.audio_protocol.__all__

[‘AudioBackend’, ‘AudioBusBackend’, ‘AudioPlaybackBackend’, ‘AudioStreamingBackend’, ‘CAPABILITIES_C…

class simvx.core.audio_protocol.Capability[source]

Bases: enum.StrEnum

Capabilities a backend can advertise via :meth:AudioBusBackend.list_capabilities.

Members are strings so Capability.PLAY_BASIC in caps works against either a frozenset[Capability] or a legacy frozenset[str]. New capability flags must be declared here: string literals in backend code bypass the typo check and are banned.

Initialization

Initialize self. See help(type(self)) for accurate signature.

PLAY_BASIC

‘play.basic’

PLAY_2D

‘play.2d’

PLAY_3D

‘play.3d’

SPATIAL_HRTF

‘spatial.hrtf’

SPATIAL_DOPPLER

‘spatial.doppler’

STREAMING

‘streaming’

STREAMING_WAV

‘streaming.wav’

STREAMING_OGG

‘streaming.ogg’

STREAMING_MP3

‘streaming.mp3’

STREAMING_FLAC

‘streaming.flac’

EFFECT_GAIN

‘effect.gain’

EFFECT_FILTER_BIQUAD

‘effect.filter_biquad’

EFFECT_PARAMETRIC_EQ

‘effect.parametric_eq’

EFFECT_DELAY

‘effect.delay’

EFFECT_REVERB

‘effect.reverb’

EFFECT_COMPRESSOR

‘effect.compressor’

EFFECT_SOFTCLIP

‘effect.softclip’

__new__(*values)
__add__()
__contains__()
__delattr__()
__dir__()
__eq__()
__format__()
__ge__()
__getattribute__()
__getitem__()
__getnewargs__()
__getstate__()
__gt__()
__hash__()
__iter__()
__le__()
__len__()
__lt__()
__mod__()
__mul__()
__ne__()
__reduce__()
__reduce_ex__()
__repr__()
__rmod__()
__rmul__()
__setattr__()
__sizeof__()
__str__()
__subclasshook__()
capitalize()
casefold()
center()
count()
encode()
endswith()
expandtabs()
find()
format()
format_map()
index()
isalnum()
isalpha()
isascii()
isdecimal()
isdigit()
isidentifier()
islower()
isnumeric()
isprintable()
isspace()
istitle()
isupper()
join()
ljust()
lower()
lstrip()
partition()
removeprefix()
removesuffix()
replace()
rfind()
rindex()
rjust()
rpartition()
rsplit()
rstrip()
split()
splitlines()
startswith()
strip()
swapcase()
title()
translate()
upper()
zfill()
__deepcopy__(memo)
__copy__()
name()
value()
simvx.core.audio_protocol.CAPABILITIES_CORE: frozenset[simvx.core.audio_protocol.Capability]

‘frozenset(…)’

Capabilities every backend that participates in playback + streaming advertises.

The Null backend deliberately omits the streaming members because it does not implement :class:AudioStreamingBackend; see NullAudioBackend for its narrowed capability set.

simvx.core.audio_protocol.PlayMode

None

Mode kwarg for :meth:AudioPlaybackBackend.play_audio.

The Node-side dispatcher (_AudioPlaybackMixin._play_common) selects the mode from the player class; backends branch on it internally so the spatial / non-spatial code paths share one entry point.

class simvx.core.audio_protocol.AudioPlaybackBackend[source]

Bases: typing.Protocol

Backend facet for starting and controlling individual sounds.

The unified :meth:play_audio collapses the historical play_audio / play_audio_2d / play_audio_3d trio into one entry point parameterised by mode. Backends branch on mode internally; spatial kwargs (position, max_distance) are ignored when mode == "non_positional".

play_audio(stream: simvx.core.audio.AudioStream, *, mode: simvx.core.audio_protocol.PlayMode = 'non_positional', position: Any = None, volume_db: float = 0.0, pitch: float = 1.0, loop: bool = False, bus: str = 'Master', max_distance: float = 100.0, from_position: float = 0.0, pan: float = 0.0, gain_db: float = 0.0) int | None[source]

Play stream. Returns the channel id or None on failure.

mode selects the spatial path:

  • "non_positional": background music / UI sounds. position

    • max_distance are ignored; bus defaults to "Master".

  • "2d": Node-side spatialization computes pan + volume_db from the listener; the backend just applies them before the first audio buffer is rendered. bus defaults to "SFX".

  • "3d": same as 2D, plus :meth:update_audio_3d per frame for Doppler. The Node pre-computes initial pitch and forwards it.

from_position seeks the playback cursor (in seconds) before the first sample is rendered. pan ([-1, 1], 0 = centre) is applied before sound.start() so spatial players’ first audio buffer is correctly panned.

stop_audio(channel_id: int) None[source]
pause_audio(channel_id: int) None[source]
resume_audio(channel_id: int) None[source]
update_audio_2d(channel_id: int, volume_db: float, pan: float) None[source]
update_audio_3d(channel_id: int, volume_db: float, pan: float, pitch: float) None[source]
set_pitch(channel_id: int, pitch: float) None[source]
set_listener_position(x: float, y: float, z: float) None[source]
set_listener_velocity(x: float, y: float, z: float) None[source]
set_listener_direction(x: float, y: float, z: float) None[source]
set_listener_world_up(x: float, y: float, z: float) None[source]
get_playback_position(channel_id: int) float[source]
is_channel_active(channel_id: int) bool[source]
shutdown() None[source]
__slots__

()

classmethod __init_subclass__(*args, **kwargs)
classmethod __class_getitem__(item)
class simvx.core.audio_protocol.AudioStreamingBackend[source]

Bases: typing.Protocol

Backend facet for chunk-fed PCM streaming.

Procedural synthesis (AudioSynth.attach_to), AudioWorklet feeds, and compressed-container streaming via native decoders all flow through these two methods. Backends that can’t stream (the Null backend, any no-device test stub) deliberately do NOT implement this Protocol: callers must isinstance(backend, AudioStreamingBackend) and raise

Class:

AudioCapabilityError (or warn-once and skip) when the facet is absent.

open_stream(*, volume_db: float = 0.0, bus: str = 'Master', buffer_seconds: float = 0.5, stream: simvx.core.audio.AudioStream | None = None) int[source]

Open a streaming channel for chunk-fed PCM playback.

If stream is provided and its container is a compressed format ("ogg"/"mp3"/"flac"), backends with a native streaming decoder open the file directly and ignore subsequent

Meth:

feed_audio_chunk calls. For "wav" or synthetic "pcm" streams, the caller is expected to feed raw int16 stereo bytes via :meth:feed_audio_chunk. Backends that cannot decode the requested container raise :class:AudioCapabilityError.

feed_audio_chunk(channel_id: int, chunk: bytes) None[source]
__slots__

()

classmethod __init_subclass__(*args, **kwargs)
classmethod __class_getitem__(item)
class simvx.core.audio_protocol.AudioBusBackend[source]

Bases: typing.Protocol

Backend facet for bus-layout reconciliation and capability discovery.

sync_bus_layout(layout: simvx.core.audio_bus.AudioBusLayout) None[source]

Reconcile the backend’s native bus / effect graph against layout.

Cheap and idempotent: backends keep their own dict[bus_name, native_handle] and add/remove/update only what changed since the last call. Called automatically by the audio server when :class:AudioBusLayout or any bus’s effects list changes; manual call is safe.

list_capabilities() frozenset[simvx.core.audio_protocol.Capability][source]

Capability flags this backend supports.

Effect modules and Nodes call this before attempting to materialise a native feature; absent capabilities raise

Class:

AudioCapabilityError (strict) or warn-once (lenient).

__slots__

()

classmethod __init_subclass__(*args, **kwargs)
classmethod __class_getitem__(item)
class simvx.core.audio_protocol.AudioBackend[source]

Bases: simvx.core.audio_protocol.AudioPlaybackBackend, simvx.core.audio_protocol.AudioStreamingBackend, simvx.core.audio_protocol.AudioBusBackend, typing.Protocol

Union Protocol: a backend that implements all three facets.

MiniaudioBackend (and its legacy fallback) and WebAudioBackend satisfy this. NullAudioBackend does NOT (it doesn’t implement

Class:

AudioStreamingBackend): callers that need streaming should isinstance-check :class:AudioStreamingBackend directly via

Attr:

SceneTree.audio_streaming.

play_audio(stream: simvx.core.audio.AudioStream, *, mode: simvx.core.audio_protocol.PlayMode = 'non_positional', position: Any = None, volume_db: float = 0.0, pitch: float = 1.0, loop: bool = False, bus: str = 'Master', max_distance: float = 100.0, from_position: float = 0.0, pan: float = 0.0, gain_db: float = 0.0) int | None
stop_audio(channel_id: int) None
pause_audio(channel_id: int) None
resume_audio(channel_id: int) None
update_audio_2d(channel_id: int, volume_db: float, pan: float) None
update_audio_3d(channel_id: int, volume_db: float, pan: float, pitch: float) None
set_pitch(channel_id: int, pitch: float) None
set_listener_position(x: float, y: float, z: float) None
set_listener_velocity(x: float, y: float, z: float) None
set_listener_direction(x: float, y: float, z: float) None
set_listener_world_up(x: float, y: float, z: float) None
get_playback_position(channel_id: int) float
is_channel_active(channel_id: int) bool
shutdown() None
__slots__

()

classmethod __init_subclass__(*args, **kwargs)
classmethod __class_getitem__(item)
open_stream(*, volume_db: float = 0.0, bus: str = 'Master', buffer_seconds: float = 0.5, stream: simvx.core.audio.AudioStream | None = None) int
feed_audio_chunk(channel_id: int, chunk: bytes) None
sync_bus_layout(layout: simvx.core.audio_bus.AudioBusLayout) None
list_capabilities() frozenset[simvx.core.audio_protocol.Capability]