Expand description
Music that follows a game: transitions, cues and intensity layers. Requires music.
A Music controller uses a fixed Transport on the mixer’s output-frame
clock. Each operation is prepared on the control thread and sent as one command.
The audio thread resolves its timing when it receives the command, then applies
the whole operation at that frame. A full command queue changes no playing voice.
With no room for all new layers, a transition is rejected without stopping the
previous track. Poll MixerEvent::MusicApplied / MixerEvent::MusicRejected
to distinguish application from submission; application starts a fade, not ends it.
Every layer starts together, including silent ones. Intensity only changes gains, so a layer becomes audible at its current source position. Multilayer tracks use the same source sample rate and, where known, length. The caller supplies stems with matching musical timing and compatible loops; unknown-length streams and synthesizers must also maintain that timing. A cue is independent of transitions and is played once (supply a finite source).
Music uses ordinary mixer voices at priority 255, without stealing on admission.
Provision max_voices for the entire crossfade overlap and any cues/effects.
Other priority-255 sounds can still steal music under the mixer’s normal rules.
With this feature the mixer reserves return storage for up to 16 layer voices per
queued command, so its queue setting also controls this preparation-time memory.
Poll events regularly to reclaim request containers and finished voices off audio.
As with ordinary mixer voices, exhausting both return buffers without polling
can free retired data on audio; the reservation covers a full render’s worst case,
not an unlimited number of renders without a consumer.
The transport follows output frames, including while a bus is paused; it does not
infer tempo from audio or follow per-voice rate/pitch changes. A shared bus pause
freezes all its stems together but does not stop the beat grid. Limiter lookahead
delays the audible result by MixerHandle::latency frames. Submit ahead of the
desired boundary: a command delayed by a full pending queue is quantized when it
is finally received. Operations at the same boundary follow submission order.
use audiobox::music::{Music, TimeSignature, Timing, Track, Transport};
use audiobox::mixer::{BusId, Fade, Mixer, MixerConfig};
use audiobox::Audio;
use std::sync::Arc;
let (mut mixer, mut handle) = Mixer::new(MixerConfig::default())?;
let transport = Transport::new(48_000, 120.0, TimeSignature::default(), 0)?;
let music = Music::new(&mut handle, transport, BusId::MASTER)?;
let source = Arc::new(Audio::new(vec![vec![0.1; 48_000]], 48_000)?);
music.transition(&mut handle, Track::new(source), 0.0, Timing::NOW, Fade::NONE)?;
music.cue(&mut handle, Arc::new(Audio::new(vec![vec![0.1; 2400]], 48_000)?),
0.5, Timing::BEAT)?;Structs§
- Layer
- One stem of a track. It keeps playing even when its intensity gain is zero.
- Music
- A controller bound to one mixer and one fixed transport. It does not own sounds or mutate voices on the control thread; future operations target whichever track is active when they actually execute. Dropping it does not stop its track.
- MusicId
- Identifies a submitted operation in mixer events, not a voice or a controller.
- Time
Signature - A notated bar:
numeratorbeats of1 / denominatorwhole notes. The transport accepts 1..=32 beats and denominators 1, 2, 4, 8, 16 or 32. - Timing
- Resolve at audio-thread receipt, using
max(received_frame, not_before). Beat/Bar are strictly after that reference, even if it is already a boundary. - Track
- 1..=16 synchronized stems, with one loop policy. All source rates must match; all known frame lengths must match. Unknown lengths/timing remain the caller’s responsibility. Single-stem tracks may use any supported source rate.
- Transport
- A fixed-tempo grid in output frames. BPM counts quarter notes per minute. Tempo is rounded to 0.001 BPM on construction; every boundary is computed directly with integer arithmetic, rounded to the nearest frame (halves up).
Enums§
- Quantize
- Where an operation lands on a transport. Beat means the signature’s beat unit; in 6/8 it is an eighth note, while BPM always counts quarter notes.
Constants§
- MAX_
LAYERS - Most stems in one track. Silent layers count toward the voice limit too.