Tryst::SDL::Track
One playback slot on a mixer: an object the caller holds, carrying a single audio input, its own gain, and its own play/pause/stop state. There is no limit on how many can exist at once.
A track is not usually constructed directly - Sound#play_track
and Music make them - but doing so is legal and is how a caller
would reuse one slot for a series of different sounds.
Constructors
Instance methods
Points the track at some audio. A track with no input assigned cannot be played; assigning while playing swaps what it plays.
@api private - Mixer#dispatch_stopped calls this on the main
thread. Returns how many stops it delivered, which is more than
one when the track stopped several times since the last call.
This track's gain, multiplied with the mixer's: 1.0 unchanged, 0.0 silent, above 1.0 amplifies.
Loops STILL TO COME, which is not what was asked for at #play:
it counts down as they are used up, reads 0 on the final pass or
when stopped, and -1 when looping forever.
Replaces however many loops were left. -1 for forever, 0 to let the current pass be the last - which is how a looping track is brought to a graceful end rather than cut off.
Runs block after this track finishes - either because it played
to the end, or because something stopped it. Pausing does not
count, and neither does destroying a playing track.
NOT called from the audio thread. SDL fires its own callback
there, where allocating or running arbitrary Crystal is not safe;
all that happens then is a counter being bumped. The block runs
later, on whichever thread calls Mixer#dispatch_stopped - so
an application has to call that periodically, typically from a
timer in its event loop:
track.on_stopped { |finished| play_next_after(finished) }
session.every(50) { mixer.dispatch_stopped }
Setting a second block replaces the first.
Starts, or restarts, playback.
loops counts EXTRA passes: 0 plays once, 2 plays three times, -1 repeats forever.
A track is in exactly one of three states: playing, paused or
stopped. They are mutually exclusive, so a PAUSED TRACK IS NOT
PLAYING. To ask "has this been started at all", which is the
usual intent, use !stopped?.
Where the track sits in space.
Answers the origin both for a track placed at the origin and for one that was never placed at all - SDL keeps no way to tell those apart, so this cannot be used to ask whether placement is on.
Places the track in space relative to the listener, who sits at the origin and cannot move. Further away is quieter, and the direction is rendered onto whatever speakers there are.
The track's input is converted to MONO to be placed, so a stereo source loses its own left/right in exchange for a position.
How far into its input the track has played, or nil when the input cannot say. A playing track's answer moves; a stopped or paused one reports where it halted.
This is the playback position, not a position in space - see
#position_3d for that.
Seeks. Legal on a stopped track, though #play resets the start
position anyway; a paused track resumes from the new spot.
Needs an input that can seek, so not one fed by an audio stream, and some decoders can only land near the requested spot rather than exactly on it.
How much input is left to mix, or nil when the duration is not known. Zero for a stopped track.
Counts the input only: a track looping forever still reports the remainder of its current pass, and a fade-out in progress does not shorten it.
Forces the track to stereo and mixes it only onto the front left and right speakers, with each side scaled by its own gain.
track.stereo(left: 1.0, right: 0.0) # hard left
track.stereo(left: 0.7, right: 0.7) # centred, quieter
Negative gains clamp to zero; there is no ceiling, so above 1.0
makes a side louder. Deliberately no single pan knob wrapping
this: turning one number into a pair means picking a pan law, and
the two reasonable choices disagree about how loud the centre is.
Resets the 3D position to the origin, since it replaces 3D mode.
Halts playback, fading to silence first when asked. Halting an already-stopped track is legal and does nothing.
Neither playing nor paused: never started, or finished, or halted. The third of the three states.
Adds a tag - an arbitrary label like "sfx", "ui" or "ambient" -
so this track can be played, stopped or re-gained along with
every other track wearing it. See Mixer#set_tag_gain, which is
what makes an independent effects volume possible.
A track may carry any number of tags, and adding one twice is legal and does nothing.
Turns off placement of every kind - forced stereo and 3D alike - and returns the track to mixing normally across all speakers.