Skip to main content

Module audio

Module audio 

Source
Expand description

Audio as data: screens ask for sounds and music through Ctx::audio; Game hands the requests, and the MusicState’s commands, to the platform in each FrameOutput. Nothing here plays anything, so screens stay testable without a sound card.

Voice clips are asked for by dialogue line id, through Ctx::play_voice, which knows which lines have a clip that may be played. V is the game’s ClipVariant: which of a line’s clips plays.

The engine’s widgets and screens play the same few sounds for the same things on every screen (MenuSound); which cues those are is the game’s (AudioConfig, from GameData::audio_config).

A sound that must be stopped (rain, a hum, a cue that loops) is started with a handle: AudioQueue::start_sound gives its SoundId, which stop_sound, with or without a fade, and set_sound_volume take. It belongs to the screen that started it: when that screen leaves the stack, its sounds stop, so a loop can’t outlive it. A loop meant to outlive a screen is started by the screen below it, or is music.

A game can make a sound at run time, from samples (Samples) rather than a file: AudioQueue::add_sound makes them a cue, played from then on as a cue of the manifest is, within ADDED_SECONDS_MAX and ADDED_BYTES_MAX, and AudioQueue::remove_sound frees it.

let mut audio = AudioQueue::<()>::default();
audio.play_sound("menu_beep");
audio.play_music("theme");
assert_eq!(audio.pending()[1], AudioRequest::play_music("theme", None));

Structs§

AudioConfig
Which of the game’s sound cues the engine’s widgets and screens play (MenuSound, and the cursor’s tick): the game’s (GameData::audio_config). The default names them after what they are (ui_move, ui_select, ui_cancel, ui_cursor), with Denied playing ui_cancel.
AudioQueue
The requests screens made this frame. Game empties it every frame. It knows which cues the MenuSounds are (AudioConfig), and the sounds started with a handle that haven’t stopped.
MusicClock
Where the music is in its track, for a screen that keeps time with it, read from Ctx::music_clock. The platform reports what really sounds (a track starts only once its file has loaded); Game::set_music_playing turns that into this.
MusicState
Which tracks play, and how one gives way to the next (ADR-0054): each switch is a MusicSwitch, the request’s own or the default one. The old track fades out; the new one starts once it has stopped, or as it begins to fade (a crossfade), and may fade in. A cue already playing doesn’t restart, and at most two tracks are loaded at once. A fade-in, and an old track’s fade in a crossfade, wait until the new track sounds (heard), or LOAD_WAIT_SECS. Pure: feed it requests, time and what sounds, read the commands.
MusicSwitch
How one music track gives way to the next (ADR-0054): the old one fades out over out_ms, and the new one fades in over in_ms, starting as the old one begins to fade (overlap, a crossfade) or once it has stopped. Build it with new, after_fade or crossfade (ADR-0039).
Samples
A sound made at run time: 16-bit samples, interleaved (left first in stereo), at a rate. Any rate from 1 to Self::MAX_RATE: a backend plays it at its own.
SoundId
A sound started with a handle (AudioQueue::start_sound): the queue’s count of them, from 1, so the same calls give the same ids on every run.

Enums§

AddSoundError
Why AudioQueue::add_sound refused a sound. The game’s log says it too.
AudioRequest
Something a screen wants heard. Cue ids are the ones in the game’s audio manifest (AudioManifest).
MenuSound
The sounds the engine’s widgets and screens play: the same cue means the same thing on every screen.
MusicCommand
What the platform must do to the music this frame. A track is loaded, started, has its volume changed and is stopped, which also unloads it.
SamplesError
Why Samples couldn’t be made.

Constants§

ADDED_BYTES_MAX
The most bytes of samples the sounds added hold at once, all together: 32 MiB, two bytes a sample.
ADDED_SECONDS_MAX
The longest a sound added may play, in seconds.

Functions§

pick_from_pool
The music cue pool pool yields for seed: the same seed always gives the same cue. None if the manifest has no such pool or it is empty. This is not a game’s simulation RNG, so a pick never changes a battle or its replay.
splitmix64
One step of splitmix64: spreads nearby seeds (e.g. a counter) over the whole range.

Type Aliases§

SharedSamples
Samples that the queue and whatever plays them share, never copied on their way.