Skip to content

Audio Streaming Demo

App: apps/audio_streaming_demo/

Streams synthesized float PCM to the audio device over time (engine PLM-133 / ADR 0042) — the counterpart to a one-shot clip loaded from a file. Each frame the game renders ~1/60 s of a 220 Hz sine tone and tops up the source’s buffer queue; the engine recycles finished buffers and (re)starts playback automatically, so the tone plays continuously. This is the primitive a SoundFont/MIDI synth renders into.

Terminal window
% ./plume3d audio_streaming_demo

You should hear a steady 220 Hz sine tone; a small GUI window shows the frequency and the current queued-buffer count.

  • On init, creates a mono 48 kHz streaming source with Audio.newStreamingSource(48000, 1).
  • Each update, while fewer than 4 buffers are queued (_src.queuedBuffers < 4), synthesizes 800 float samples (~1/60 s at 48 kHz) of a 0.2-amplitude sine and queues them with _src.queueSamples(list) — interleaved floats in [-1, 1].
  • The engine recycles played-out buffers and restarts playback on the initial queue or after an underrun, so keeping a few buffers queued makes the tone gapless.
  • Draws a small Gui window showing the frequency and live queuedBuffers count.
import "engine" for Audio
// init: make a source you FEED over time (mono, 48 kHz).
_src = Audio.newStreamingSource(48000, 1)
// update: top the queue up each frame so playback never underruns.
while (_src.queuedBuffers < 4) {
var samples = []
for (i in 0...800) { // ~1/60 s of audio
_phase = _phase + 2.0 * Num.pi * 220.0 / 48000
if (_phase > 2.0 * Num.pi) _phase = _phase - 2.0 * Num.pi
samples.add(0.2 * _phase.sin) // float in [-1, 1]
}
_src.queueSamples(samples) // interleaved for stereo: L,R,L,R…
}

Uses the AL_EXT_FLOAT32 OpenAL path when available, with an int16 fallback. The queue is fed from the main thread, so a stalled frame can underrun — a few buffers of headroom (here 4) absorbs the jitter.

  • AudionewStreamingSource, queueSamples, queuedBuffers (the streaming section).
  • Source — the same foreign object as a file-backed source.
  • Gui — the status window.
  • Loggererror if the source can’t be created.