AtlatestRenderedmarkdown
Readme

sigil-audio

Audio playback and streaming for Sigil.

Provides audio playback capabilities via sokolaudio. Sound effects are loaded into memory, music is streamed via stbvorbis.

Modules

ModulePurpose
(sigil audio)Audio playback, sound effects, and music streaming

System Prerequisites

  • ALSA development headers on Linux (libasound2-dev / alsa-lib-devel)
  • AudioToolbox framework on macOS (included with Xcode)
  • Windows: nothing extra — sokol_audio drives WASAPI through ole32 / winmm / ksuser, all bundled with the OS.

OGG Vorbis encoding/decoding is vendored (libogg 1.3.6 + libvorbis 1.3.7, see vendor/ogg/README.md and vendor/vorbis/README.md). No system libogg / libvorbis / libvorbisenc packages need to be installed — sigil-audio links them statically into libsigil-audio.a. This adds ~1 MB to the final binary and unblocks Windows cross-compile.

Dependencies

  • sigil-stdlib

Build

sigil deps install
sigil build                       # native (host platform)
sigil build --config windows-amd64  # cross-compile for Windows (zig)

Streaming audio sink

Three playback paths coexist in (sigil audio):

  1. load-sound + play-sound — short SFX, decoded once into memory, fired from Sigil, mixed on the audio thread.
  2. play-music — long OGG, streamed from disk on the audio thread via stb_vorbis.
  3. open-audio-stream + push-audio-samples — caller-driven streaming sink. The caller produces interleaved float32 PCM (any thread) and pushes it into a lockless SPSC ring; the audio thread drains the ring into its output buffer. Use this for live / generative audio (motif streaming render, live-coded synths, etc.).

Example — play a 440 Hz sine wave for 1 second:

(import (sigil audio) (sigil math))

(audio-setup)

(define stream (open-audio-stream channels: 2
                                  buffer-frames: 8192))

(define sr 44100)
(define pi 3.14159265358979)
(define frames (* sr 1))

;; Build a stereo float32 bytevector with a 440 Hz sine.
(define samples
  (let ((v (make-vector (* frames 2) 0.0)))
    (let loop ((i 0))
      (when (< i frames)
        (let ((s (sin (* 2.0 pi 440.0 (/ i sr)))))
          (vector-set! v (* i 2) s)
          (vector-set! v (+ (* i 2) 1) s))
        (loop (+ i 1))))
    v))

(define pcm (make-float-buffer samples))

;; Push in chunks of whatever the ring has room for.
(let loop ((remaining frames) (offset-frames 0))
  (when (> remaining 0)
    (let ((room (audio-stream-room stream)))
      (if (= room 0)
          (begin (sleep 0.005) (loop remaining offset-frames))
          (let ((n (min remaining room)))
            (push-audio-samples stream pcm n)
            (loop (- remaining n) (+ offset-frames n)))))))

(close-audio-stream! stream)

Notes:

  • Sample rate is fixed at 44100 to match sokol_audio's configured rate; callers MUST match (no resampling).
  • push-audio-samples is non-blocking and returns the frame count actually accepted — the caller decides whether to retry or drop.
  • Streaming sinks coexist with play-sound / play-music — they're an additional mix source, not a replacement.
  • Up to 4 streams may be open simultaneously.
  • Default buffer-frames: 16384 (~370 ms at 44.1 kHz) is safety margin against under-run, not added latency. Live producers who want tighter reactivity can open with buffer-frames: 2048 or smaller.

See folio topics/sigil-audio-streaming-sink-architecture for the SPSC ring design, threading model, and under-run / over-run semantics.

License

BSD-3-Clause.

Vendored libogg (1.3.6) and libvorbis (1.3.7) are also distributed under BSD-3-Clause (see vendor/ogg/COPYING and vendor/vorbis/COPYING). Both licenses are compatible with this package's BSD-3-Clause terms.