Prove the ordinary behaviour

A custom DSP idea often begins with its most dramatic setting. Start somewhere less glamorous: a processor that copies its input to its output at a controlled gain. This establishes loading, channel handling and parameter delivery before a nonlinear algorithm makes unexpected behaviour harder to locate.

MDN documents AudioWorkletProcessor as the processing side of an AudioWorkletNode, running on the audio rendering thread. Its process callback receives blocks of inputs, outputs and parameter values. The documentation advises inspecting array lengths rather than assuming a fixed block size, and notes that parameter arrays can contain either one value or per-frame values.

Handle absent input deliberately. A processor may receive no channels on an input, and a generator or tail-producing effect may need different behaviour from a simple pass-through. Decide what your processor should output in each case. Silence should be an expected state, not an exception that leaves stale samples in a buffer.

Keep the first processor small enough that you can explain every stored value and every branch of its processing path.

Add one transformation and a useful control

Choose a simple transformation whose neutral setting is easy to understand. A gain stage, a bounded waveshaping amount or a short filter study is enough for a first project. Keep the original transparent version available so you can compare the infrastructure independently of the sound design.

Expose one parameter with a sensible range and an intentional initial value. Test its neutral point, both extremes and movement between them. A parameter that sounds good at fixed settings can still click or behave unpredictably when moved. Use the appropriate automation or smoothing strategy and listen to the transition itself.

Preserve state where the algorithm needs continuity across blocks. An oscillator phase, filter memory or delay position cannot be restarted on every callback without changing the sound. At the same time, define a deliberate reset operation so a performer can return to a known condition. Continuity and recovery need separate decisions.

Keep avoidable allocation and heavy communication out of the processing callback. Chrome’s AudioWorklet design guidance explains the tight rendering deadline and the costs of unnecessary garbage creation. Allocate reusable working storage during setup where practical. Send occasional status information to the interface rather than attempting to narrate every sample through messages.

Listen to the edges of the design

Use a short test set: silence, a quiet sustained tone, a brief impulse-like sound and a representative musical phrase. Silence reveals unwanted output; a tone reveals discontinuities; a transient exposes timing and ringing; the phrase tells you whether the effect is musically useful. These checks answer different questions and should not be collapsed into one loud demonstration.

Try stopping the source while the processor is active, changing parameters during a tail and reconnecting a source. Check the processor’s lifetime policy against current browser behaviour and documentation. Do not assume that a callback return value is merely ceremonial; it participates in whether processing continues.

Observe processor errors and report them clearly. MDN notes that an uncaught processing error can leave the node outputting silence for the rest of its lifetime. A page should distinguish that failure from a muted instrument and provide a deliberate recovery path.

Only then increase the algorithm’s complexity. Keep a recording and source revision for each useful stage. A distinctive processor is easier to develop when its ordinary behaviour is dependable: silence stays silent, channels remain understood, controls move predictably and the performer knows how to recover from an extreme state.

Take it into a session

Try this.

Build a transparent gain processor, handle one-value and per-frame parameter arrays, then add one transformation. Check silence, tone, transient and a musical phrase, including parameter movement and source disconnection.

Listen back

  • What state must survive between blocks?
  • What does absent input mean for this processor?
  • Can an error be distinguished from an intentional mute?
Open the studio →