synth
A CPU DSP toolkit for building sound in pure Luau. Everything is flat arrays of f32 samples in `[-1, 1]` at `Synth.SR` (24 kHz), ready for `audio.encodePcm(buf, Synth.SR, 1, opts)`.
audio.synth
A CPU DSP toolkit for building sound in pure Luau. Everything is flat arrays
of f32 samples in [-1, 1] at Synth.SR (24 kHz), ready for
audio.encodePcm(buf, Synth.SR, 1, opts).
It runs headless, costs no credits and cannot fail for network reasons — which is why the whole SFX library of this game is built with it rather than generated.
local Synth = require("audio.synth")
local bell = Synth.bell({ dur = 4.0, root = 71, seed = 3 })
Synth.reverb(bell, { decay = 0.9, mix = 0.45, size = 2.2 })
Synth.normalize(bell, 1.0)
What is in it
Buffers — buf, mixInto, gain, peak, rms, normalize, fadeIn,
fadeOut, dcBlock.
Filters — lowpass, highpass, resonant bandpass, and sweepLowpass,
whose cutoff travels the length of the buffer. That sweep is the single most
useful gesture here: it is what makes a whoosh a whoosh and a steam burst
collapse into a hiss.
Space — reverb is a six-comb, two-allpass Schroeder network with
decay, mix, size and damp. This fight happens in a cathedral, so
almost everything gets some.
Loops — seamless(buf, crossfadeSeconds) folds the tail back over the
head with an equal-power crossfade and returns a shorter buffer whose last
sample joins its first. That is how a bed loops without loop markers and
without depending on a codec preserving the first millisecond.
Generators — metal (an inharmonic partial stack, the struck-bronze
engine), bell (the same with founder's ratios and a long tail), noise
(filtered and enveloped — steam, cloth, gravel, air) and tone (a pitched
voice with a glide, for weight and blips).
Synth.rng(seed) is a deterministic LCG, so a rebuild of the library is
byte-identical and a clip is diffable.
Scoped to this part · feeds back into the world's score.