Build with this node

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

Ask Studio

@maruaudio/dsp/oscillators/band-limited-table plays a stack of single-cycle frames without the upper harmonics folding past Nyquist. Each 2048-sample source frame is built once into sixteen half-octave levels: one forward FFT, then for level L an inverse FFT that keeps harmonics 1..round(256 / 2^(L/2)) (256, 181, 128, 91 … 1) in a power-of-two cycle of at least four samples per top harmonic. DC is dropped, as in Web Audio's PeriodicWave. Playback picks the brightest level whose top harmonic is below Nyquist and crossfades toward the next one once that harmonic passes 0.42 of the rate; each level is read with a 4-point Catmull-Rom cubic, and position morphs linearly between neighbouring frames.

Parameters

PathSetterRange as codedDefaultUnit
frameCountsetBandLimitedTableFrameCountFloored, then 0 to maxFrames0 (silent)frames
levelbandLimitedTableLevel(state, phaseIncrement)0 to 15, fractional inside a crossfade; uses \increment\; 0 for a zero or NaN increment
positionargument of bandLimitedTableSample or prepareBandLimitedTablePositionClamped to 0..1 across the frame stackfraction
phaseargument of the sample callsWrapped to 0..1cycles

Lifecycle

initBandLimitedTable(maxFrames) allocates every table, twiddle and work array (maxFrames floored, at least 1). bandLimitedTableBuildFrame(state, index, source, offset) builds one frame, so a caller can spread a table across audio blocks; out-of-range source samples read as 0 and an out-of-range index is ignored. setBandLimitedTableFrameCount then publishes how many frames playback may read. Per block compute bandLimitedTableLevel; per sample call bandLimitedTableSample. Voices sharing one position can prepare a BandLimitedTablePosition (initBandLimitedTablePosition, prepareBandLimitedTablePosition) and call bandLimitedTableSamplePrepared; refresh it whenever the position or the published frame count changes.

When to use it

Wavetable synthesis where frames are drawn or imported and then played across the keyboard and swept by position. The Wavetable and Evolving Environment modules use it.

Limits

  • Mono sample read of up to four cubic lookups (two frames, two levels). No allocation after init; f32 tables.
  • Silent until a frame count is published; a single frame ignores position.
  • Its FFT is private and f32. It does not use @maru/spectral-real-fft, an f64 owner, because migrating would move the built tables in the last bits (spectral and rooms).
  • Live and spare tables with different frame counts need separate prepared selections.

Algorithm properties and proofs

No Lean 4 proof is mapped to this node.

Explore proofs alongside performance

Parameters

ParameterTypeSetter
Frame count frameCount

Publish how many built frames playback may read.

floatsetBandLimitedTableFrameCount

Dependencies

None: this node imports no other node.

Dependents

No other node imports this one.

Used by