simvx.core.audio_backend._miniaudio

The native (ma_engine) production audio backend.

MiniaudioBackend mixes, spatializes, and runs DSP entirely in native C via the simvx.core._native.miniaudio_engine CFFI wrapper. Python only pushes parameter updates. Falls back to the legacy / null backends via make_backend when the compiled extension is unavailable.

Module Contents

Classes

MiniaudioBackend

Native-mixed audio backend on top of ma_engine.

API

class simvx.core.audio_backend._miniaudio.MiniaudioBackend(sample_rate: int = _DEFAULT_SAMPLE_RATE, nchannels: int = _DEFAULT_CHANNELS)[source]

Native-mixed audio backend on top of ma_engine.

All mixing, spatialization, and DSP runs in native C: Python only pushes parameter updates. Target latency: buffersize_msec=20 (vs the legacy backend’s 100 ms).

The native extension must be built once after install:

simvx build-audio

If the extension is missing, the constructor raises MiniaudioEngineUnavailable. Use make_backend() for an automatic fallback to _LegacyMiniaudioBackend with a one-time warning.

Initialization

play_audio(stream: simvx.core.audio.AudioClip, *, mode: str = '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]
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]
get_playback_position(channel_id: int) float[source]
is_channel_active(channel_id: int) bool[source]
open_stream(*, volume_db: float = 0.0, bus: str = 'Master', buffer_seconds: float = 0.5, stream: simvx.core.audio.AudioClip | None = None) int[source]

Open a streaming channel.

buffer_seconds (default 0.5 s) trades latency for underrun tolerance. At 48 kHz stereo s16 = ~96 KB. Drop to 0.1 s for low-latency interactive synthesis; bump to 1-2 s for music streams under heavy CPU load. Producer pushes int16 stereo bytes via feed_audio_chunk; underrun produces silence (no glitch). Only applies to the chunk-fed PCM path: when stream is a compressed container, miniaudio’s ma_sound_init_from_file(..., MA_SOUND_FLAG_STREAM) owns the buffering internally.

Container routing (when stream is provided):

  • "wav" / "pcm" (synthetic) / None: open an ma_pcm_rb-backed sound. Caller feeds raw int16 stereo bytes.

  • "ogg" / "mp3" / "flac": open the file directly via Sound.from_file(stream=True). Subsequent

    meth:

    feed_audio_chunk calls are no-ops for this channel.

  • "unknown": raise :class:InvalidStreamError.

Pitch is intentionally not a parameter: streaming sounds are built with pitch_enabled=False so the resampler can’t read past what the producer has written. set_pitch against the returned channel raises :class:AudioCapabilityError.

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

Push raw int16 stereo bytes into the channel’s ring buffer.

Misaligned chunks (length not a multiple of bytes-per-frame) have the trailing partial frame trimmed. When the ring is full the excess is silently dropped: callers can poll entry.keeper.available_write_frames if they need to know.

set_listener_position(x: float, y: float, z: float) None[source]

Forward listener position to the native ma_engine spatializer.

set_listener_velocity(x: float, y: float, z: float) None[source]

Forward listener velocity (m/s) to the native engine for Doppler.

set_listener_direction(x: float, y: float, z: float) None[source]

Forward listener forward vector to the native engine.

set_listener_world_up(x: float, y: float, z: float) None[source]

Forward listener world-up vector to the native engine.

shutdown() None[source]
list_capabilities() frozenset[simvx.core.audio_protocol.Capability][source]
sync_bus_layout(layout: simvx.core.audio_bus.AudioBusLayout) None[source]

Reconcile native ma_sound_group volumes + effect chains against layout.

Cheap and idempotent: pushes only on change. Called by the audio server every frame; safe to call manually.