simvx.core.audio_bus

Audio bus system – named buses with volume, mute, and routing.

Provides a mixing hierarchy similar to Godot’s audio bus layout. Buses can route to parent buses (e.g., SFX -> Master, Music -> Master), and the final volume is computed by walking the chain.

Bus names are case-sensitive and use the Godot convention: "Master", "Music", "SFX", "Voice", "UI". Looking up a bus that isn’t in the layout raises :class:UnknownBusError with the available names listed: no lazy creation, no fallback to Master.

send_to routes signal, not just gain. A bus’s output, after its own effect chain, flows into its send_to target and through that bus’s gain and effects on the way to the listener, so a reverb on Master reverberates every bus routed into Master. Every backend that can build a graph holds to that; the pure-Python fallback mixer runs no effects at all, so it folds the chain into one gain per bus instead.

Public API: from simvx.core.audio_bus import AudioBusLayout, AudioBus

layout = AudioBusLayout.get_default()
layout.get_bus("Music").volume_db = -6.0
layout.get_bus("SFX").mute = True

# Effective volume considers the full chain:
effective = layout.get_bus("SFX").effective_volume

Module Contents

Classes

AudioBus

A single audio bus with volume, mute, and parent routing.

AudioBusLayout

Collection of audio buses with routing and volume computation.

Data

API

simvx.core.audio_bus.log

‘getLogger(…)’

simvx.core.audio_bus.__all__

[‘AudioBus’, ‘AudioBusLayout’]

class simvx.core.audio_bus.AudioBus(name: str, volume_db: float = 0.0, send_to: str = '')[source]

A single audio bus with volume, mute, and parent routing.

Attributes: name: Bus display name (e.g., “Master”, “SFX”). Case-sensitive. volume_db: Volume in decibels (-80 to 24). 0 = full volume. Clamped to the declared range on every write. mute: If True, this bus and everything routed into it produce no output. solo: If True, only this bus, everything routed into it and the buses carrying it onward to Master produce output. send_to: Name of the bus this one routes its signal into (empty for a bus that feeds the listener directly).

Initialization

volume_db

‘Property(…)’

mute

‘Property(…)’

solo

‘Property(…)’

property linear_volume: float[source]

volume_db converted to linear scale (0.0 to ~15.85).

property effective_volume: float[source]

Effective dB after walking the send_to chain to Master.

Sum of volume_db along the chain. If any bus in the chain is muted, returns -80 (silent). Returns own volume_db when not in a layout.

Solo gating: when any bus in the layout has solo=True, every bus that is not on a soloed bus’s routing path is forced to the silence floor (-80 dB): mirroring the standard mixing-console “solo” behaviour. On the path means the soloed bus itself, the buses routed into it (which are the signal it isolates) and its ancestors (which carry that signal onward). Master is always exempt so the listener still hears the surviving signal.

property effective_linear_volume: float[source]

effective_volume converted to linear multiplier (0.0 to ~15.85).

add_effect(effect: Any) None[source]

Add an audio effect to this bus’s processing chain.

remove_effect(effect: Any) None[source]

Remove an audio effect from this bus.

property effects: list[Any][source]

Read-only view of effects on this bus.

__repr__() str[source]
class simvx.core.audio_bus.AudioBusLayout[source]

Collection of audio buses with routing and volume computation.

Default layout creates four buses: Master (root) <- Music, SFX, Voice

Initialization

add_bus(name: str, volume_db: float = 0.0, send_to: str = '') simvx.core.audio_bus.AudioBus[source]

Add a new audio bus.

Args: name: Unique bus name (case-sensitive). volume_db: Initial volume in dB (clamped to [-80, 24]). send_to: Name of parent bus to route to. Must already exist in this layout (other than the empty string for root buses). "Master" is permitted regardless because it’s the conventional root and is always present in default layouts.

Returns: The created AudioBus.

Raises: UnknownBusError: send_to references a bus that does not exist in this layout (and isn’t "Master").

remove_bus(name: str) None[source]

Remove a bus by name, re-routing whatever fed it. Cannot remove Master.

Every bus whose send_to named the removed bus is re-routed onto the removed bus’s own target, falling back to "Master", so the layout never holds a bus pointing at a name that is not in it. An orphan is not a state the backends can agree on: one folds the chain into a gain and stops walking at the missing name, the other builds a graph and would leave the child wired to a dead node.

The removed bus is detached from the layout, so its own

Attr:

AudioBus.effective_volume reports its own volume_db from then on. Removing a name that is not present does nothing.

get_bus(name: str) simvx.core.audio_bus.AudioBus[source]

Return the bus named name.

Raises: UnknownBusError: name is not present in this layout. The error message lists the available names. Bus names are case-sensitive: "master" does not match "Master".

has_bus(name: str) bool[source]

Return True iff a bus named name exists. Cheap, no raise.

property buses: list[simvx.core.audio_bus.AudioBus][source]

All buses in the layout.

property bus_names: list[str][source]

Names of all buses.

classmethod get_default() simvx.core.audio_bus.AudioBusLayout[source]

Return the default bus layout (Master, Music, SFX, Voice, UI).

classmethod create_default() simvx.core.audio_bus.AudioBusLayout[source]

Create the standard five-bus layout (Godot convention).

Buses: Master (root), Music, SFX, Voice, UI, each child routed to Master. Names are case-sensitive; the engine and every shipped player Property default uses TitleCase.

classmethod reset()[source]

Reset the default layout singleton (for tests).

to_dict() list[dict][source]

Serialize to JSON-compatible format.

Each bus emits its effect chain via :meth:AudioEffect.to_dict;

Meth:

from_dict rebuilds the effects symmetrically.

classmethod from_dict(data: list[dict]) simvx.core.audio_bus.AudioBusLayout[source]

Deserialize from JSON format.

Buses are added in the order they appear, so children must follow their parent. Layouts produced by :meth:to_dict already obey this ordering. send_to validation in :meth:add_bus will raise

Class:

UnknownBusError if a child precedes its parent. Each bus’s effects list is rebuilt via :meth:AudioEffect.from_dict.