audio
This package implements a real-time audio system. It manages voice pooling, resource loading, and spatial audio calculations.
Features:
- Automated asset pipeline: Similarly to sprites, it utilizes auto-generated audio enums
(
AudioNamefrombonsai:generatedpackage) for fast access to all sound files. - Spatial audio: Built-in support for 2D positional audio via
playSpatial. It automatically calculates volume and panning based on the distance and relative position between the source and the listener. - Voice management: Uses a fixed-size voice pool (
MIXER_VOICE_CAPACITY) to recycle audio channels. - Playback control: Control over active sounds using functions like
pause,resume,stop,rewindandseek. - Bus system: Grouping voices via
Busto control volumes for distinct categories.
Usage:
init :: proc() { audio.playGlobal(.musicTheme, volume = 0.5, isLooped = true)}
update :: proc() { if potWalking { handle := audio.playSpatial(.potWalkSfx, potPosition) }
if potDead { audio.stop(handle) }}Bus :: enum { Master, SFX, Music,}Audio bus allows to mix the audio and let users control the volume of each element of audio in the game.
DEFAULT_MAX_DISTANCE
Section titled “DEFAULT_MAX_DISTANCE”DEFAULT_MAX_DISTANCE :: 360Default distance at which the falloff for spatial audio reaches 0.0 (muted).
DEFAULT_MIN_DISTANCE
Section titled “DEFAULT_MIN_DISTANCE”DEFAULT_MIN_DISTANCE :: 40Default distance at which the falloff for spatial audio reaches 1.0 (max volume).
MIXER_VOICE_CAPACITY
Section titled “MIXER_VOICE_CAPACITY”MIXER_VOICE_CAPACITY :: 64Amount of voices. Describes how many audio clips can play at once.
Mixer :: struct { lock: sync.Mutex, voices: [MIXER_VOICE_CAPACITY]Voice, sounds: map[SoundHandle]Sound, nextId: SoundHandle, listenerPosition: gmath.Vector2, busVolumes: [Bus]f32,}Internal state container for the audio mixer.
Holds the thread lock, the pool of Voice, loaded Sound data, and listener configuration.
ParseResult
Section titled “ParseResult”ParseResult :: struct { samples: []f32, channels: int, sampleRate: int,}Container for decoded PCM audio data.
Contains the raw samples converted to f32 (ranging from -1.0 to +1.0) and format metadata.
The caller is responsible for freeing the samples slice.
Sound :: struct { samples: []f32, channels: int, sampleRate: int,}Structure definition for the “sound”, being an audio clip container.
Holds the raw sample data and format information.
SoundHandle
Section titled “SoundHandle”SoundHandle :: distinct u64ID for a Sound object.
Voice :: struct { id: SoundHandle, cursor: int, position: gmath.Vector2, volume: f32, panning: f32, // Values range from -1.0 to +1.0 minDistance: f32, maxDistance: f32, bus: Bus, isActive: bool, isLooped: bool, isSpatial: bool, isPaused: bool,}Structure definition for the “voice”, which is essentialy the entity equivalent of the audio system.
It defines all active state variables needed to output a specific instance of Sound.
VoiceHandle
Section titled “VoiceHandle”VoiceHandle :: distinct u64ID for a Voice object.
getListenerPosition
Section titled “getListenerPosition”getListenerPosition :: proc () -> gmath.Vector2Returns the current position of the audio listener.
getMixer
Section titled “getMixer”getMixer :: proc () -> ^MixerReturns a pointer to the mixer state.
Example:
onVolumeSet :: proc(bus: audio.Bus, volume: f32) { mixer := audio.getMixer() mixer.busVolumes[bus] = volume}isPlaying
Section titled “isPlaying”isPlaying :: proc (id: VoiceHandle) -> boolReturns true if the voice is currently valid and not paused.
load :: proc (name: generated.AudioName) -> SoundHandleLoads an audio asset from the disk based on the provided AudioName enum.
This function handles reading the file, parsing the audio data (WAV file format), and registering it with the mixer.
Returns 0 if loading or parsing fails.
parseFromBytes
Section titled “parseFromBytes”parseFromBytes :: proc (data: []byte) -> (result: ParseResult, success: bool)Decodes raw WAV file bytes into a usable audio buffer.
Supports 8-bit (unsigned), 16-bit (signed), and 32-bit (float) WAV formats.
Returns:
result: The parsed sample data and metadata.success: False if the header is invalid or the format is unsupported.
pause :: proc (id: VoiceHandle)Pauses the specific voice. The voice retains its cursor position.
play :: proc { playGlobal, playSpatial,}Main entry point for playing sounds.
Use playGlobal for UI/Music and playSpatial for in-world sound effects.
playGlobal
Section titled “playGlobal”playGlobal :: proc ( id: SoundHandle, volume: f32 = 1.0, bus: Bus = Bus.Master, isLooped: bool = false, panning: f32 = 0.0,) -> VoiceHandlePlays a sound in global mode (no spatial positioning).
Ideal for UI sounds, background music, or narration.
playSpatial
Section titled “playSpatial”playSpatial :: proc ( id: SoundHandle, volume: f32 = 1.0, position: gmath.Vector2, bus: Bus = Bus.Master, minDistance: f32 = DEFAULT_MIN_DISTANCE, maxDistance: f32 = DEFAULT_MAX_DISTANCE, isLooped: bool = false,) -> VoiceHandlePlays a sound at a specific position in the world.
Volume and panning are automatically calculated based on the listener’s position.
resume
Section titled “resume”resume :: proc (id: VoiceHandle)Resumes a paused voice.
rewind
Section titled “rewind”rewind :: proc (id: VoiceHandle)Resets the playback position of Voice to the beginning.
seek :: proc (id: VoiceHandle, timeSeconds: f32)Sets the playback position of Voice to a specific time in seconds.
If the time is out of bounds, it will be clamped.
setListenerPosition
Section titled “setListenerPosition”setListenerPosition :: proc (position: gmath.Vector2)Updates the position of the “listener” (usually the camera or player) for spatial audio calculations.
stop :: proc (id: VoiceHandle)Immediately stops a specific Voice from playing.