Build with this node

Start with a prompt in Studio, or copy it into your own coding agent.

Ask Studio

processConvolutionBlock returns false before changing history or output when its integer [fromIndex, toIndex) range exceeds either buffer. It returns true after a valid block. Identical source/output spans support in-place use; other spans must be disjoint. During preparation, isConvolutionBlockMemoryValid checks that the borrowed views have fixed backing and do not overlap private history or impulse storage. Recheck whenever installing different views.

@maruaudio/dsp/filters/convolution is a zero-latency direct FIR convolver, y[n] = x[n]·(1 − mix) + outputGain·mix·Σ h[k]·x[n−k], capped at CONVOLUTION_MAX_TAPS (256) mono taps. History and impulse are fixed 256-word f32 arrays allocated at init; the sum runs in double. FIR taps are rate agnostic, so no sample rate enters the state.

const state = initConvolutionNode()
loadConvolutionImpulse(state, ir.length, ir.length, (tap) => ir[tap])
const y = convolutionNodeTick(state, x)

Parameters

SetterRange the setter enforcesDefault
loadConvolutionImpulse(state, available, requestedTaps, readTap)Length bounded to 0 to available and 256; taps rounded to f32, the rest zeroed; returns the accepted lengthEmpty (0 taps)
setConvolutionMix0 to 11 (fully wet)
setConvolutionOutputGain0 to 2 (linear, wet path)1

Lifecycle

initConvolutionNode → loadConvolutionImpulse (control thread, it calls the caller's readTap) → mix and gain setters → convolutionNodeTick per sample or processConvolutionBlock over a range → resetConvolutionNode, which clears the history and write position and keeps the impulse. The block entry rounds each output to f32 and accepts any block partition.

When to use it

Short cabinet, coloration or tone-shaping impulses that must add no latency. At 48 kHz, 256 taps is 5.33 ms; long impulses and reverbs belong to @maru/filters-partitioned-convolution.

Limits

  • Mono; one sample per tick, at most 256 multiply-adds.
  • The impulse is not resampled: the host resamples it before loading.
  • The loop has a literal 256 bound with the IR length as an inner guard. convolutionDirectSum is shared with the partitioned convolver's head.
  • Clamps are the kernel node's conditional clamp; a NaN mix passes through.
  • audio-kernels keeps the PCM16 impulse decoding and render entry.

Algorithm properties and proofs

Lean 4 checks specific properties of this algorithm’s mathematical model. Each model result applies within its stated domain and assumptions.

6 Lean 4 results: 5 proofs in their stated domains; 1 counterexample.

Proved in the stated domain.Every index processed inside an admitted FIR interval is valid for both source and target.Natural-number admitted block intervals and prepared history-ring addresses
Limits and assumptions
  • Hand-written source-reviewed Nat/Rat model, not formal refinement of TypeScript, Rust or compiled output. Whole-file source digests and finite canonical JavaScript vectors are checked. Capacities, clocks, delay and block addresses must be valid nonnegative exactly representable integers. The ring model uses a conditional backwards step; the canonical 256-slot bit-mask traversal is compared on executable vectors, not formally translated. The interval proof assumes prior fixed-buffer/disjoint-or-identical-span admission. It does not prove backing ownership, IEEE convolution sums, IR loading or all execution paths.
Theorem
MaruLean.LeafContracts.admitted_block_access_in_bounds
Recorded axioms
propext, Classical.choice, Quot.sound
Manifest reviewed
Proved in the stated domain.Each admitted FIR loop step strictly decreases the remaining frame count.Natural-number admitted block intervals and prepared history-ring addresses
Limits and assumptions
  • Hand-written source-reviewed Nat/Rat model, not formal refinement of TypeScript, Rust or compiled output. Whole-file source digests and finite canonical JavaScript vectors are checked. Capacities, clocks, delay and block addresses must be valid nonnegative exactly representable integers. The ring model uses a conditional backwards step; the canonical 256-slot bit-mask traversal is compared on executable vectors, not formally translated. The interval proof assumes prior fixed-buffer/disjoint-or-identical-span admission. It does not prove backing ownership, IEEE convolution sums, IR loading or all execution paths.
Theorem
MaruLean.LeafContracts.admitted_block_step_remaining
Recorded axioms
propext, Quot.sound
Manifest reviewed
Proved in the stated domain.A backwards history-ring step preserves the prepared ring bound.Natural-number admitted block intervals and prepared history-ring addresses
Limits and assumptions
  • Hand-written source-reviewed Nat/Rat model, not formal refinement of TypeScript, Rust or compiled output. Whole-file source digests and finite canonical JavaScript vectors are checked. Capacities, clocks, delay and block addresses must be valid nonnegative exactly representable integers. The ring model uses a conditional backwards step; the canonical 256-slot bit-mask traversal is compared on executable vectors, not formally translated. The interval proof assumes prior fixed-buffer/disjoint-or-identical-span admission. It does not prove backing ownership, IEEE convolution sums, IR loading or all execution paths.
Theorem
MaruLean.LeafContracts.fir_previous_in_bounds
Recorded axioms
propext, Quot.sound
Manifest reviewed
Show 3 more Lean 4 results
Proved in the stated domain.A backwards history step followed by a forward step returns the same admitted index.Natural-number admitted block intervals and prepared history-ring addresses
Limits and assumptions
  • Hand-written source-reviewed Nat/Rat model, not formal refinement of TypeScript, Rust or compiled output. Whole-file source digests and finite canonical JavaScript vectors are checked. Capacities, clocks, delay and block addresses must be valid nonnegative exactly representable integers. The ring model uses a conditional backwards step; the canonical 256-slot bit-mask traversal is compared on executable vectors, not formally translated. The interval proof assumes prior fixed-buffer/disjoint-or-identical-span admission. It does not prove backing ownership, IEEE convolution sums, IR loading or all execution paths.
Theorem
MaruLean.LeafContracts.fir_previous_reverses_step
Recorded axioms
propext, Quot.sound
Manifest reviewed
Proved in the stated domain.Every tap in a backwards FIR history walk stays inside the prepared ring.Natural-number admitted block intervals and prepared history-ring addresses
Limits and assumptions
  • Hand-written source-reviewed Nat/Rat model, not formal refinement of TypeScript, Rust or compiled output. Whole-file source digests and finite canonical JavaScript vectors are checked. Capacities, clocks, delay and block addresses must be valid nonnegative exactly representable integers. The ring model uses a conditional backwards step; the canonical 256-slot bit-mask traversal is compared on executable vectors, not formally translated. The interval proof assumes prior fixed-buffer/disjoint-or-identical-span admission. It does not prove backing ownership, IEEE convolution sums, IR loading or all execution paths.
Theorem
MaruLean.LeafContracts.fir_walk_in_bounds
Recorded axioms
propext, Quot.sound
Manifest reviewed
Counterexample.A block interval without the source-length guard can address past the source.Natural-number admitted block intervals and prepared history-ring addresses
Limits and assumptions
  • Hand-written source-reviewed Nat/Rat model, not formal refinement of TypeScript, Rust or compiled output. Whole-file source digests and finite canonical JavaScript vectors are checked. Capacities, clocks, delay and block addresses must be valid nonnegative exactly representable integers. The ring model uses a conditional backwards step; the canonical 256-slot bit-mask traversal is compared on executable vectors, not formally translated. The interval proof assumes prior fixed-buffer/disjoint-or-identical-span admission. It does not prove backing ownership, IEEE convolution sums, IR loading or all execution paths.
Theorem
MaruLean.LeafContracts.block_without_length_guard_refuses_bound
Manifest reviewed
Explore proofs alongside performance

Parameters

ParameterTypeSetter
Mix mixfloatsetConvolutionMix
Gain gainfloatsetConvolutionOutputGain

Ports

  • In ininput · audio · mono
  • Out outoutput · audio · mono

One sample per convolutionNodeTick call.

Dependencies

None: this node imports no other node.

Dependents

Used by