Skip to main content

Module music

Module music 

Source
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.
TimeSignature
A notated bar: numerator beats of 1 / denominator whole 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.