Softanza
StartFrançais
Softanza
I/O, formats, extensibility, media

Sound

Fully shipped: a lock-free callback, an owned graph, librosa-grade analysis, sonification.

5 Strong · 5 Solid · 1 Partial · 1 Emerging

Measured against: miniaudio · Web Audio · JUCE · Folders: base/sound(opens in a new tab) · For programmers: this area's reference

a note, as the engine hears it
a note, as the engine hears it. drawn on 2026-10-01 by the site's script tools/areas-figurative.ring, run inside the library at commit 0e72e2e2c · the source(opens in a new tab)

Rethought from first principles

What Softanza kept from what works, and what it rethought, as the library wrote it down in its design documents and narrations.

The Softanza wayA sound is described, not hand-built: you declare a graph or a meaning, the engine renders it, and a listener is the last judge.

Kept from the best practice

  • Device input and output and file decoding come from miniaudio: one public-domain file, no dependencies, all three operating systems, playback and capture. Only the missing half is borrowed. source(opens in a new tab)
  • The real-time rule of audio is kept strictly: the device callback never allocates memory, never locks and never calls the platform's language; it reads prepared buffers only. source(opens in a new tab)
  • Music keeps Euterpea's score algebra: notes and rests joined in sequence or together, repeated and transposed. A score is data that can be analysed before it is heard. source(opens in a new tab)

Rethought

  • One sound graph renders to the speaker or to a file through the same path, so what you hear and what you export can never drift apart. source(opens in a new tab)
  • An author fires a meaning such as 'danger' and gets a sound. Since an alert that can be talked over is no alert, lesser sounds are turned down or dropped. source(opens in a new tab)
  • A cultural universe is declared as data: tuning, movement rules, rhythmic cycle, ornaments and instruments, so one phrase can render in maqam, raga or gamelan. source(opens in a new tab)
  • The ear is the last gate: speech playing at double speed passed every counter and was caught by a listener. Each phase records who listened. source(opens in a new tab)

The survey's biggest surprise: memory said 'plan, SN0 next', the code says one of the most fully-realized planes in the library, SN0-SN6 and a sonification series shipped and closed. miniaudio is vendored and split into two DLLs, there is an owned Zig sound graph (Web-Audio-shaped), FFT-backed analysis, and a real lock-free real-time callback that does no allocation, no lock, and never re-enters the Haro VM. What it refuses on purpose: MIDI, spatial/HRTF, plugin hosting, notation; and reverb is absent even from the effect palette.

What a crafter does with it, and what stands out

  • A lock-free real-time callback: no alloc, no lock, no Haro re-entry, guarded down to worst-callback microseconds
  • An owned Zig sound graph, Web-Audio-shaped, not a wrapper
  • librosa-grade analysis: spectrogram, onsets, tempo and LUFS on the shared engine FFT
  • A sonification / earcon / voice layer no mainstream audio library offers

What is owed

  • Reverb and a fuller effect palette (compressor, chorus, distortion)
  • Richer synthesis (wavetable, FM, additive, granular)
  • MP3 / OGG encode to close the read-broad / write-narrow asymmetry
  • MIDI input, spatial/HRTF and plugin hosting (deliberate non-goals)

The Softanza way, run

What Softanza does differently in this area, shown by code taken from its narrations and guards, and run for this page.

While a danger alert sounds, a success cue and a warning are dropped; once it ends cues pass again, and a warning never silences danger.

Softanza
oP = new stzEarcons()
oP.RecordFireAt("Danger.Alert", 10.0)
Chk("a cue under a sounding alert is DROPPED", NOT oP.WouldFireAt(:Success, 10.05))
Chk("and so is a warning -- rank, not recency", NOT oP.WouldFireAt(:Warning, 10.05))
Chk("once the alert is over, a cue passes again", oP.WouldFireAt(:Success, 12.0))
oP2 = new stzEarcons()
oP2.RecordFireAt("Warning.Alert", 10.0)
Chk("a warning alert does NOT pre-empt danger", oP2.WouldFireAt(:Danger, 10.05))
Output
  [ok]   a cue under a sounding alert is DROPPED
  [ok]   and so is a warning -- rank, not recency
  [ok]   once the alert is over, a cue passes again
  [ok]   a warning alert does NOT pre-empt danger

run on 2026-10-01 21:18 inside the library at commit 0e72e2e2c; taken from base/test/sound/sound_semantics_narrated.ring(opens in a new tab)

A Hausa greeting becomes a drum phrase that follows the language's low and high tones, the way a talking drum does.

Softanza
oNig = StzSoundUniverseQ(:niger)
oKal = oNig.SentenceQ("sannu da zuwa")
aK = oNig.PlayedNotes()
cTones = ""
for k in aK  cTones += k[3] + " " next
? "   sannu da zuwa ('welcome'): " + trim(cTones) + "  -- Newman's tones, low-high-low-high-low"
Chk("the declared contour is L H L H L", trim(cTones) = "L H L H L")
Output
   sannu da zuwa ('welcome'): L H L H L  -- Newman's tones, low-high-low-high-low
  [ok]   the declared contour is L H L H L

run on 2026-10-01 21:18 inside the library at commit 0e72e2e2c; taken from base/test/sound/sound_mu4_narrated.ring(opens in a new tab)

The lanes, one by one

Lanes and their notes are quoted as they were read at the source, on Read from the source on 2026-09-16, from a read-only main worktree -- base/sound; engine sound.zig, soundgraph.zig, soundanalysis.zig, audiodev.zig, sounddsp.zig, soundring.zig, soundwasm.zig + vendored miniaudio 0.11.25; guards under test/sound (31 files + a web-audio harness).

Real-time callback discipline
Strong
sinkCallback does no allocation, no lock, never re-enters the Haro VM; SPSC lock-free circular buffer, underruns counted, worst-callback microseconds trackedengine audiodev.zig sinkCallback, soundring.zig
Device playback & transport
Strong
Vendored miniaudio backends per OS: open/start/stop/close, a stzSoundTransport face, an honest report when no device; split into decode and device DLLsstz_sound + stz_audiodev DLLs
Sound graph -- mixing & routing
Strong
An owned node graph (miniaudio's own graph disabled): OSC/SOURCE/GAIN/MIX/PAN/FILTER/DELAY/ENVELOPE over planar buses, topological and cycle-freeengine soundgraph.zig
Spectral analysis
Strong
soundanalysis.zig on the shared fft.zig: Hann spectrum, threaded spectrogram, onset detection, tempo estimation, LUFS loudness, dominant frequencyengine soundanalysis.zig, fft.zig
Sonification, earcons & voice
Strong
stzEarcons (66 methods), stzVoice/stzVoicePool, stzListener (closed grammar), and the SS1-SS5 sonification series; no mainstream audio library offers thistest/sound earcon_expect.json, voice_guard.html
File decode / encode
Solid
Decodes WAV/MP3/FLAC/OGG via miniaudio with resample and channel conversion; encode is WAV/FLAC only, MP3/OGG out return UNSUPPORTEDengine sound.zig
Synthesis
Solid
Band-limited oscillators (polyBLEP/polyBLAMP) for sine/square/saw/triangle plus ADSR, f64, unit-tested; no wavetable, FM, additive or granularengine sounddsp.zig
Capture / recording
Solid
Microphone capture through the same device layer and callback discipline; multi-device selection and format negotiation stay basicstzMicrophone; audiodev.zig capture side
Streaming
Solid
A producer thread feeds the lock-free circular buffer the callback drains, bounded at MAX_STREAMS=16, with StreamStart/Stop/Drain; no network streamingengine soundgraph.zig (the stream)
Audio <-> graphics convergence
Solid
stzSoundPlot and stzSoundGrid render waveforms and spectrograms through the library's own graphics plane as SVG/PNG, plus a browser guard harness
DSP effects palette
Partial
RBJ biquad filters (lowpass/highpass/bandpass), a feedback delay, gain and pan; no reverb (absent even as a named node), compressor, chorus or distortion
Pro-audio breadth (MIDI, spatial, plugins)
Emerging
None, stated in writing as deliberate non-goals: MIDI, notation, 3D/HRTF spatial, time-stretching and VST/CLAP hosting are OUT until askedSOFTANZA_SOUND_PLAN.md (non-goals)