AtlatestRepositorysigil-audio
1# sigil-audio
2
3Audio playback and streaming for [Sigil](https://codeberg.org/sigil/sigil).
4
5Provides audio playback capabilities via sokol_audio. Sound effects are loaded into memory, music is streamed via stb_vorbis.
6
7## Modules
8
9| Module | Purpose |
10|--------|---------|
11| `(sigil audio)` | Audio playback, sound effects, and music streaming |
13## System Prerequisites
15- ALSA development headers on Linux (`libasound2-dev` / `alsa-lib-devel`)
16- AudioToolbox framework on macOS (included with Xcode)
17- Windows: nothing extra — sokol_audio drives WASAPI through
18 `ole32` / `winmm` / `ksuser`, all bundled with the OS.
20OGG Vorbis encoding/decoding is **vendored** (libogg 1.3.6 +
21libvorbis 1.3.7, see `vendor/ogg/README.md` and
22`vendor/vorbis/README.md`). No system `libogg` / `libvorbis` /
23`libvorbisenc` packages need to be installed — sigil-audio links
24them statically into `libsigil-audio.a`. This adds ~1 MB to the
25final binary and unblocks Windows cross-compile.
27## Dependencies
29- sigil-stdlib
31## Build
33```sh
34sigil deps install
35sigil build # native (host platform)
36sigil build --config windows-amd64 # cross-compile for Windows (zig)
37```
39## Streaming audio sink
41Three playback paths coexist in `(sigil audio)`:
431. **`load-sound` + `play-sound`** — short SFX, decoded once into
44 memory, fired from Sigil, mixed on the audio thread.
452. **`play-music`** — long OGG, streamed from disk on the audio
46 thread via stb_vorbis.
473. **`open-audio-stream` + `push-audio-samples`** — caller-driven
48 streaming sink. The caller produces interleaved float32 PCM
49 (any thread) and pushes it into a lockless SPSC ring; the audio
50 thread drains the ring into its output buffer. Use this for
51 live / generative audio (motif streaming render, live-coded
52 synths, etc.).
54Example — play a 440 Hz sine wave for 1 second:
56```scheme
57(import (sigil audio) (sigil math))
59(audio-setup)
61(define stream (open-audio-stream channels: 2
62 buffer-frames: 8192))
64(define sr 44100)
65(define pi 3.14159265358979)
66(define frames (* sr 1))
68;; Build a stereo float32 bytevector with a 440 Hz sine.
69(define samples
70 (let ((v (make-vector (* frames 2) 0.0)))
71 (let loop ((i 0))
72 (when (< i frames)
73 (let ((s (sin (* 2.0 pi 440.0 (/ i sr)))))
74 (vector-set! v (* i 2) s)
75 (vector-set! v (+ (* i 2) 1) s))
76 (loop (+ i 1))))
77 v))
79(define pcm (make-float-buffer samples))
81;; Push in chunks of whatever the ring has room for.
82(let loop ((remaining frames) (offset-frames 0))
83 (when (> remaining 0)
84 (let ((room (audio-stream-room stream)))
85 (if (= room 0)
86 (begin (sleep 0.005) (loop remaining offset-frames))
87 (let ((n (min remaining room)))
88 (push-audio-samples stream pcm n)
89 (loop (- remaining n) (+ offset-frames n)))))))
91(close-audio-stream! stream)
92```
94Notes:
95- Sample rate is fixed at 44100 to match sokol_audio's
96 configured rate; callers MUST match (no resampling).
97- `push-audio-samples` is non-blocking and returns the frame
98 count actually accepted — the caller decides whether to
99 retry or drop.
100- Streaming sinks coexist with `play-sound` / `play-music` —
101 they're an additional mix source, not a replacement.
102- Up to 4 streams may be open simultaneously.
103- Default `buffer-frames: 16384` (~370 ms at 44.1 kHz) is
104 safety margin against under-run, not added latency. Live
105 producers who want tighter reactivity can open with
106 `buffer-frames: 2048` or smaller.
108See `folio topics/sigil-audio-streaming-sink-architecture`
109for the SPSC ring design, threading model, and under-run /
110over-run semantics.
112## License
114BSD-3-Clause.
116Vendored libogg (1.3.6) and libvorbis (1.3.7) are also distributed
117under BSD-3-Clause (see `vendor/ogg/COPYING` and
118`vendor/vorbis/COPYING`). Both licenses are compatible with this
119package's BSD-3-Clause terms.