Recipes
Define a reusable sound with bounded versioned JSON data.
AudioBits API · 0.2.0 · Available on npm.
A recipe is data, not a native graph or code.
defineSound() throws on invalid data and returns a deeply frozen snapshot.
validateRecipe() returns path-specific issues without throwing for invalid input.
Both work without browser globals. validateRecipe(unknown) returns
{ ok: true, recipe } or { ok: false, issues }. Each issue has code, path,
and message; paths use JSON bracket notation such as $["layers"][0]["id"].
Inputs must be plain JSON data. The snapshot is copied, so later input mutations
cannot change an existing definition.
import { defineSound, validateRecipe } from "audiobits";
const input: unknown = {
schemaVersion: 1,
kind: "one-shot",
duration: 0.15,
layers: [
{
id: "tone",
source: { type: "oscillator", waveform: "sine", frequency: 660 },
gainDb: -18,
envelope: { attack: 0.004, decay: 0.08, sustain: 0.1, release: 0.04 },
},
],
};
const result = validateRecipe(input);
if (result.ok) {
const recipe = defineSound(result.recipe);
console.log(recipe.kind);
} else {
for (const issue of result.issues) console.error(issue.path, issue.message);
}Catalog source you own
All eight existing sounds have canonical source in catalog/recipes/. Install
an individual recipe from the source registry,
import its local recipe.ts, create a sound, and play it after gesture activation.
You own that source. The npm package supplies only the engine and recipe language.
See Quick start for a complete local recipe using public engine APIs.
Interactive source
Reactive thruster is a developer-owned catalog
recipe, separate from the catalog’s simpler thruster recipe. Copy recipe.ts for its
sound definition, or take pointer.ts, host.ts, and index.html too for a
complete vanilla interaction. Include canonical Impact at
../../recipes/impact/recipe.ts relative to the host, or install the complete
registry item to preserve that layout. The showcase displays all canonical files.
Install audiobits as the runtime dependency; the copied files belong to your
application and have no website or framework imports.
Throttle is a live control in [0, 1]. The pointer integration maps velocity to
throttle; the host adds canonical Impact on the same engine. Release preserves
the sound tail, Stop all cuts voices, and the host suspends on hide. Call
host.dispose() when removing the view. See Lifecycle for
engine ownership in other integrations.
Supported subset
Schema version 1 supports one-shot gates up to 60 seconds or sustained playback
without duration, 1–16 layers with unique IDs, four oscillator waveforms, white
noise, fixed ADSR envelopes, frequency automation, and lowpass/highpass/bandpass
filters. Layer gains are -60–0 dB; frequencies are 20–20000 Hz and must be below
the context's Nyquist frequency at play time. Filters are limited to eight across
the recipe; frequency automation to 128 points. Gain automation, expression
strings, file fetches, and sequencing are unsupported.
One-shot duration ends the gate, excluding release and bounded filter tails.
Attack and decay must fit within the gate, including the minimum effective
attack; zero decay ramps directly to sustain. Frequency automation begins at
zero, uses increasing times, and ends by gate close. Sustained automation is an
onset sequence of at most 60 seconds, then holds its final value. All mapping
and variation extrema must satisfy target bounds and playback Nyquist checks.
Noise requires integer context sample rates from 8000 through 192000 Hz;
unsupported rates fail with noise-rate before voice allocation.
Validation rejects unknown fields and versions, non-finite numbers, accessors,
cycles, depth beyond 16, more than 10000 visited values, and invalid parameter
references. Diagnostics are capped at 100. See Parameters
for mappings and live controls. The exported recipeSchema and
audiobits/schema.json describe the published schema version 1 structure.
Workbench editor
Each catalog workbench (/catalog/[slug]) accepts at most 32 KiB of JSON and shows the first ten validation
issues. Apply explicitly; invalid input preserves the last valid playable
sound. Applying a valid definition stops current playback and disposes the old
sound. Play again to hear the new definition.
Keep the sound's playback kind and its primary parameter's range, default, and mode. Additional parameters use their declared defaults. Restore and Reset return to the catalog recipe, seed 42, and primary control defaults. Raw comparisons apply only to catalog definitions. Edited recipes still have a copyable AudioBits example containing the entire accepted JSON.
Typed authoring preserves recipe structure, parameter names and parameter modes. Runtime validation remains authoritative for exact schema validity.