# DSP fundamentals

> Understand audio I/O, samples, state, controls and the building blocks you can compose into a Maru module.

Canonical: https://maru.audio/docs/dsp-fundamentals
Documentation index: https://maru.audio/llms.txt

Maru’s DSP toolkit gives you the parts to build instruments, effects, samplers
and musical utilities: oscillators, filters, envelopes, dynamics, delay lines,
reverbs, meters, sample readers and complete reusable voices. Start with a
working module, choose the pieces for your sound, then audition and refine them.
You can also write your own processing alongside these shared components.

A **DSP leaf** is a focused processing unit with explicit inputs, state and
outputs. Some APIs call that unit a **node**. In a Processor, you connect leaves
by passing their results to the next operation. A **Graph** instead describes
connections between the Audio SDK’s registered nodes. The DSP library’s public
imports and the Graph node registry are related authoring tools with different
interfaces; a leaf import does not automatically create a Graph node.

## Find a building block

| What you want to build | Reference |
| --- | --- |
| Input/output trim, a mixer, pan or dry/wet control | [Maths, gains and mixing](https://maru.audio/docs/dsp-math-and-mixing.md) |
| Tone control, resonant filtering, EQ or IR filtering | [Filters and EQ](https://maru.audio/docs/dsp-filters.md) |
| Compression, gating, limiting, de-essing or low-band repair | [Dynamics and repair](https://maru.audio/docs/dsp-dynamics.md) |
| Echo, delay alignment or a reverberant space | [Delays and reverbs](https://maru.audio/docs/dsp-delays-and-reverbs.md) |
| LFO motion, chorus, pitch modulation, drive or lo-fi colour | [Modulation and distortion](https://maru.audio/docs/dsp-modulation-and-distortion.md) |
| Subtractive, FM, wavetable or physical-model instruments | [Oscillators, envelopes and voices](https://maru.audio/docs/dsp-synthesis.md) |
| Sample instruments, loops, pads, articulations or clip playback | [Sampling and playback](https://maru.audio/docs/dsp-sampling.md) |
| Pitch tracking, loudness, true peak, vocoding or spectral effects | [Metering and spectral processing](https://maru.audio/docs/dsp-metering-and-spectral.md) |
| Sequencers, note maps, expression, musical clocks or effect chains | [MIDI, clocks and composition](https://maru.audio/docs/dsp-midi-and-composition.md) |
| Room responses or prepared neural amp inference | [Room acoustics and neural models](https://maru.audio/docs/dsp-acoustics-and-models.md) |

Each reference lists the focused toolkit imports and explains the choices that
matter when connecting them. The [DSP library overview](https://maru.audio/docs/dsp.md) also
includes a biquad example, a seeded record-texture example and effect control ranges.

## Samples, frames and audio I/O

A sample is one channel’s amplitude at one instant. A frame contains the
channels at that instant; stereo has a left and right sample per frame.
The sample rate is frames per second: at 48,000 Hz, 480 frames last 10 ms.
A processing block groups frames into one call, reducing scheduling overhead.

Floating-point audio conventionally uses −1 to +1 as the nominal full-scale
range. Values outside it are possible inside a chain, so choose headroom and
output gain deliberately. Do not silently clamp every intermediate signal:
that introduces clipping and changes the sound.

The module declares its input/output widths and MIDI ports. The host connects
devices and other modules; it passes buffers and events to the Processor.
DSP does not open a microphone, select a MIDI device or connect browser audio
nodes. An instrument can have no audio input, an effect reads input, and an
event-only utility can have no audio bus.

`ProcessorBlock` uses **planar** audio: each channel occupies a contiguous
region of a shared array. Use `frameOffset`, `frameCount` and
`channelStride` when addressing it. These describe the current slice, which
may start partway through the buffer. Do not assume interleaved L/R samples or
that every call begins at zero. Address a channel’s sample as
`channel * channelStride + frameOffset + frame`. The
[Processor guide](https://maru.audio/docs/processor-module.md#implement-the-lifecycle)
connects this buffer contract to a complete module.

## Prepare state, then process

A filter remembers earlier samples; a delay retains a ring buffer; a voice
retains its phase and envelope. Keep that state per module instance and,
where required, per channel or note.

| Stage | What happens |
| --- | --- |
| Create | Allocate persistent state, voice pools, tables and capacity. |
| Prepare | Apply the host’s sample rate/layout and derive rate-dependent coefficients or active lengths. |
| Configure | Map parameters to the leaf’s setters; refresh coefficients at the documented point. |
| Process | Advance the prepared state and write audio/events for the current frames. |
| Reset | Restore the documented transient state, such as phase, histories, held notes or transport. |

A leaf may combine some of these stages or use different names. Stateless math
has no allocation/reset lifecycle. Some stereo leaves return a scalar gain;
others return audio or write `outLeft`/`outRight` on state. Read the selected
signature before connecting its output.

Keep allocations, file access, network requests, decoding, locks and UI calls
outside realtime processing. Prepare assets and candidate configurations
before installing them. For large rings or IR changes, use bounded work and
staged transitions where provided. A reset that clears a large buffer is a
lifecycle operation, not automatically a safe live control operation.

When sample rate changes, re-prepare the rate-dependent state using the leaf’s
supported lifecycle. An initializer called at an arbitrary hard-coded rate
does not make its pitch, timing or filter coefficients correct at another rate.

## Units and controls

Use the leaf’s declared units: Hz for a cutoff, dB for a threshold or trim,
seconds/milliseconds/frames for time, and ratios or normalized values only
where specified. For example, a normalized knob position of 0.5 is not 0.5 Hz
and is not a −6 dB gain.

The parameter schema owns the range, default, unit and taper. The module maps
that physical value into the DSP setter; the face and host automation use the
same contract. Smooth a parameter where a discontinuous jump would click or
produce an unintended pitch change. Use the toolkit’s smoothing or the leaf’s
own transition law rather than adding an unrelated UI-only curve.

A leaf may output wet audio only, include its own dry/wet control, or generate
sound with no input. Choose the product’s mix at the right point. Delay,
lookahead and partitioned processing may also require dry-path alignment and
a declared latency. Those choices determine both the sound and host behavior.

## Imports and API discovery

```ts
import { initBiquadNode, biquadNodeTick } from "maruaudio/dsp/filters/biquad"
```

Public projects use `maruaudio/dsp/...`. Repository examples may spell the same
focused API as `@maruaudio/dsp/...`. Prefer the narrow path your Processor uses;
category barrels such as `filters`, `mixing` and `voices`, and the root DSP
barrel, are discovery conveniences. `processor` and `processor-events` expose
the processing and event contracts rather than audible effects.

Use your editor’s completion and **Go to Definition** on an import to inspect
its exported types, exact setter arguments, constants and reset behavior in
the installed package. The category references distinguish algorithms,
prepared-data helpers and reference processors so you can select the right layer.

## Try a complete example

```bash
maru init my-effect --kind processor-effect
cd my-effect
npm install
maru dev --open
```

The effect starter already connects a declaration, drive/tone Processor,
parameters, presets, face and a test. The `processor-instrument` starter adds
note-driven voices. Follow [Define a Processor module](https://maru.audio/docs/processor-module.md)
for the file-by-file walkthrough and the checklist for `maru publish`.
Its [example discovery commands](https://maru.audio/docs/processor-module.md#find-more-examples)
help you inspect other available modules.

The small gain, oscillator and true-peak examples in this section isolate one
operation at a time; integrate them through the starter’s state and lifecycle.
In a repository checkout, `packages/dsp/examples/leaf-playground/` also contains
focused teaching examples such as `gain.ts`, `biquad.ts`, `oscillator.ts` and
`adsr.ts`. These demonstrate the leaf APIs; their preview helpers are not the
Processor module contract.

Audition the musical behavior and test state, silence, extreme settings,
control changes, tails and the intended sample rates. Then run the module’s
checks for the selected build targets. [Check, build and export](https://maru.audio/docs/export.md)
explains the next step; [parity and determinism](https://maru.audio/docs/parity-and-determinism.md)
explains repeatable comparisons.
