namespaceAudio7 functions, 5 propertiesUI apps only
datumhue.audio
Synthesis, sound effects, music, sample playback and buses, made as they play: a call costs time in proportion to its notes, not to how long the sound lasts, and every control can move while it plays.
Linear volume over everything the app plays, clamped to 0..4 (1.0 = unchanged); in the root app, the workstation's volume over every app. An assignment reads back at once and glides like Audio.volume; every app shares one limiter, so a loud app makes room for itself.
level
number
read-only
The RMS of what the app played over the last 1024 frames heard (about 21 ms at 48 kHz), linear, after its master_volume; in the root app, of the whole output. 0 before the app has made a sound.
peak
number
read-only
The largest absolute sample over the same span as level.
Where the app's ear stands, in the units of the at its sounds are played with: every one played without a listener of its own is heard from here. An assignment moves the ear, and their pans and distance gains glide to follow like Audio.volume.
Seconds from a sound being made to it being heard: step, slot, position, on_step and playing turning false report heard time, audio.now() - audio.latency.
Play a tone. A one-shot tone releases after duration; a looping one holds until release or stop. Sounds started in the same callback begin on the same sample.
Example
-- A pad that swells in over a second and holds until released.local pad = datumhue.audio.synth({
waveform = "triangle",
frequency = 110,
volume = 0.3,
looping = true,
envelope = { attack = 1, release = 2 },
})
-- pad:release() fades it out over its 2-second release.
Where the sound stands, in any 2D unit kept consistent with its ear. Pan comes from the horizontal offset (via pan_scale / pan_limit), loudness from the distance curve (falloff_*, max_distance); both follow the handle's at and the ear as they move. Every other positional field requires it.
Play a sequence of notes once (an array of note tables).
Example
-- A coin pickup: a thin pulse blip, then a higher note sliding up.local blip = {
waveform = "square",
frequency = 988,
duration = 0.05,
duty = 0.125,
}
local ring = { waveform = "square", frequency = 1319, slide = 1760 }
-- A little to the left, in a small room.datumhue.audio.sfx({ blip, ring }, { pan = -0.3, space = 0.2 })
Stereo pan, -1 (left) .. 1 (right), constant power with the centre at the sound's own level; live through the handle's pan. A non-zero pan with at raises.
space
number
0
Room size for the reverb tail, 0 (dry) .. 1 (a gymnasium); the tail rings until it has decayed to silence.
muffle
number
0
Low-pass amount, 0 (open) .. 1 (through a shut door). Applied before the reverb tail.
volume
number
1
Linear gain for this play as a whole, clamped to 0..4, on top of each note's own volume; adjust it live via the handle's volume.
pitch
number
1
Playback rate, clamped to 0.25..4: the handle's starting pitch.
bus
string
no bus; the audible volume is master x instance
Route through the app's named bus (created on first use); the audible volume is master x bus x instance.
Where the sound stands, in any 2D unit kept consistent with its ear. Pan comes from the horizontal offset (via pan_scale / pan_limit), loudness from the distance curve (falloff_*, max_distance); both follow the handle's at and the ear as they move. Every other positional field requires it.
Patterns; each is an array of one or more note tables.
sequence required
(integer | integer[])[]
–no default
1-based pattern indices played in order. An entry that is a list plays those patterns together as tracks; the first sets the entry's length. An index outside the patterns raises.
looping
boolean
false
Loop the sequence.
volume
number
1
Linear playback volume, clamped to 0..4: the instance gain the handle's volume reads and writes.
pan
number
0
Stereo position, -1 (left) .. 1 (right), clamped; each note's own pan adds to it. Live through the handle's pan.
Where the sound stands, in any 2D unit kept consistent with its ear. Pan comes from the horizontal offset (via pan_scale / pan_limit), loudness from the distance curve (falloff_*, max_distance); both follow the handle's at and the ear as they move. Every other positional field requires it.
Get or create the app's named bus — the same name always returns the same bus. Route sounds into it with the constructors' bus option field. Past 32 buses an app's new bus raises.
Make a wavetable from levels written in code, each -1..1 (clamped) and held for an equal share of the cycle; the mean is removed. 2..4096 levels; any other count raises.
Example
-- Eight levels, each held for an eighth of the cycle.local levels = { 0, 0.7, 1, 0.7, 0, -0.7, -1, -0.7 }
local wave = datumhue.audio.wavetable(levels)
-- A wavetable plays wherever a waveform name does.datumhue.audio.synth({ waveform = wave, frequency = 220 })
Seconds on the render clock every sound shares: the earliest time a sound started now can begin. Monotonic; stands still while a browser holds audio suspended.
Where the sound stands, in any 2D unit kept consistent with its ear. Pan comes from the horizontal offset (via pan_scale / pan_limit), loudness from the distance curve (falloff_*, max_distance); both follow the handle's at and the ear as they move. Every other positional field requires it.