class

Tryst::SDL::AudioStream

Inherits Reference < Object

Push-based real-time PCM output, with no mixer involved: open a device, hand it raw samples as fast as you make them.

Where Sound and Music play audio that already exists, this is for audio that does not - a synthesiser, a decoder, an emulator's sound chip.

stream = Tryst::SDL::AudioStream.new(
  Tryst::SDL::AudioSpec.new(format: :S16LE, channels: 1, freq: 44_100))
stream.queue(samples)
stream.resume # starts paused; queue first, then start

It starts PAUSED deliberately, which is SDL's behaviour and the right one: resuming with an empty queue plays a gap.

Constructors

new(spec : AudioSpec = AudioSpec.new(format: AudioFormat::S16LE), allow_silent : Bool = false)

allow_silent: when the device fails to open, fall back to a silent no-op stream instead of raising. available?/ device_count cannot be trusted to predict this in advance on every platform (confirmed directly: some containers report a nonzero device count from a stale ALSA config entry with no real node behind it, so the count says yes while the open still fails) - actually attempting the open is the only reliable check, which is why this is a fallback on failure rather than a pre-check.

Source

Class methods

available?

Whether SDL can see any playback device at all. Brings up SDL's audio subsystem to find out, since there is no way to ask otherwise; that is reference counted and harmless to repeat.

Source
device_count
Source
driver_name

The audio backend SDL chose - "coreaudio", "pulseaudio", "dummy" and so on. Brings the audio subsystem up to answer, since SDL has not picked a driver before that and would just say nothing; nil only if it comes up without one.

Source

Instance methods

channels
Source
clear

Throws away everything queued but not yet played.

Source
destroy

Closes the stream and the device bound to it.

Source
destroyed?
Source
format
Source
freq
Source
gain

This stream's own volume: 1.0 unchanged, 0.0 silent, above 1.0 amplifies. SDL applies it during the format conversion it is already doing on the way to the device, so handing it a gain costs nothing over scaling every sample first - and it is the only volume control this API has, SDL3_mixer's Track/Mixer gain belonging to a mixer no AudioStream goes through.

Set it on a silent stream and it is remembered rather than applied, the same way #playing? answers from @silent_playing: there is no device to scale anything for, but a caller that sets a volume should still read that volume back.

Source
gain=(value : Float32 | Float64) : Float32
Source
pause

Stops the device pulling from the queue. Queued data is kept.

Source
playing?

Whether the device is running. An empty queue still counts as playing - it is playing silence.

Source
queue(data : Bytes) : Nil

Hands raw PCM to the device. The bytes must be in this stream's own format and channel count - SDL cannot tell that they are not, and will happily play the misinterpretation.

Source
queued_bytes

Bytes still waiting to be played, measured in the format they were pushed in. Always 0 while silent - nothing is ever really queued.

Source
queued_frames

Sample FRAMES still waiting - one frame being one sample per channel. The number to pace generation against: keep a few thousand frames buffered and the output never gaps.

Source
resume

Starts, or restarts, playback of whatever is queued.

Source
silent?

True when this stream opened no real device and is quietly discarding everything instead - see allow_silent below.

Source
spec
Source
to_unsafe

@api private

Source