Webaudio guide
Modular Markdown-based audio skills for AI agents and developers, covering signal processing, synthesis, effects, analysis, and spatial audio.
npx -y skills add kunitoki/sonic-skills --skill webaudio-guideAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 14 stars14 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Step-by-step guide for building Web Audio processing pipelines — AudioWorklet processors, custom nodes, parameter automation, and WebMIDI integration. Use when the user asks how to build or wire up Web Audio code from scratch. Trigger on phrases like "build an AudioWorklet", "create a custom Web Audio effect", "how do I use WebMIDI", "how do I write an AudioWorkletProcessor", or "how do I connect AudioNodes".
SKILL.md
3.5 KB, as published. Nobody here has run it
Web Audio Processing Guide
Step 1 — Set up AudioContext and load worklet module
- Create
AudioContextinside a user gesture handler (click, keydown) to satisfy autoplay policy. - Call
await audioContext.audioWorklet.addModule('path/to/processor.js')before creating nodes. - The module path is resolved relative to the page; bundlers may require special config (e.g. Vite's
?worker&urlimport). - Check
audioContext.stateand callaudioContext.resume()if it is'suspended'.
Step 2 — Write the AudioWorkletProcessor
- Subclass
AudioWorkletProcessorin a separate file; callregisterProcessor('name', Class)at module scope. - Implement
process(inputs, outputs, parameters)—inputs[n][channel]andoutputs[n][channel]areFloat32Arrayviews for the current render quantum. Use.lengthin loops instead of hardcoding 128. - Pre-allocate all working buffers in
constructor(); never create objects or arrays insideprocess(). - Declare custom
AudioParams viastatic get parameterDescriptors()returning an array of{ name, defaultValue, minValue, maxValue, automationRate }descriptors. - Return
truefromprocess()to keep the processor alive;falseor no return shuts it down.
Step 3 — Wire up the node graph
- Instantiate the node on the main thread:
new AudioWorkletNode(ctx, 'name', options). - Use
node.connect(destination)andsource.connect(node)to build the signal path;AudioContext.destinationis the hardware output. - Access
AudioParams vianode.parameters.get('paramName')— set.valuefor immediate changes. - Schedule smooth automation with
.linearRampToValueAtTime(),.setTargetAtTime(), or.setValueCurveAtTime()on theAudioParam. - Tear down cleanly:
node.disconnect(), thensource.stop(), thenaudioContext.close().
Step 4 — Worklet ↔ main thread communication
- Use
this.port.postMessage()/node.port.onmessagefor low-frequency control (meters, state changes, error reporting). - Batch postMessage calls; avoid sending one per render quantum (currently ~344/sec at 44.1 kHz with 128-frame quanta).
- For high-frequency or low-latency control (e.g. live gain, pitch), share a
SharedArrayBufferand read/write integer views withAtomics.load()/Atomics.store(). Scale floats to integers or bit-cast through a private buffer;Atomicsdoes not operate onFloat32Array. - Cross-origin isolation (
COOP: same-origin+COEP: require-corpresponse headers) is required forSharedArrayBuffer.
Step 5 — WebMIDI integration
- Request access with
await navigator.requestMIDIAccess({ sysex: false }); handle theMIDIAccessobject on success. - Enumerate inputs via
midiAccess.inputs.forEach(input => ...)and attachinput.onmidimessage = handler. - Parse the
MIDIMessageEvent.databyte array:data[0] & 0xF0= status (0x90 = note on, 0xB0 = CC, 0xE0 = pitch bend),data[1]= note/CC number,data[2]= velocity/value. - Map MIDI values to
AudioParamtargets: normalize 7-bit CC (0–127) to your parameter range and write via.setTargetAtTime()or aSharedArrayBuffercell for real-time feel.