Build with this node

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

Ask Studio

Before installing external buffers, use isRealFftComplexMemoryValid for the complex transform, or isRealFftIoMemoryValid for real forward/inverse calls. These preparation checks admit fixed, disjoint views outside private scratch and tables. For inverse calls, pass the output and the two input arrays to the same symmetric three-view check. Recheck after replacing a view. Calls borrow storage only until they return; serialize work on one FFT state.

The transforms reject short spectrum/complex arrays before mutation. Forward also rejects identical real/imaginary outputs. Integer offsets retain their existing zero-padding and bounds-limited write behavior. Keep partial backing overlap out of the processing calls through the preparation check.

@maruaudio/dsp/spectral/real-fft is the one FFT a Processor closure may import. It transforms real signals of any power-of-two size from 4 to the maxSize the state was built for (at most 2^19) by the two-for-one method: an N-point input is packed as N/2 complex points x[2n] + i·x[2n+1], transformed by an iterative radix-2 decimation-in-time FFT and split into X[k] = Fe[k] + W^k·Fo[k]. Spectra are split re/im arrays of N/2 + 1 bins with numpy rfft/irfft conventions: the forward transform is unnormalised and the inverse carries 1/N. Everything is f64.

Functions

NameInputsOutputDomain as coded
initRealFftmaxSizestate with f64 twiddles, bit reversal and work arraysRounded up to a power of two, clamped to 4..2^19
realFftForwardstate, size, input, inputOffset, outRe, outImtrue and bins 0..size/2false for an unsupported size; input past the end reads as 0
realFftInversestate, size, inRe, inIm, output, outputOffsettrue and size samplesNormalised by 1/size; imaginary parts of DC and Nyquist ignored; writes bounds-checked
realFftComplexInPlacestate, size, re, im, inversetrue, in placeSize 2..maxSize/2; unnormalised both ways; false leaves the arrays untouched
realFftSizeSupportedstate, sizebooleanPower of two from 4 to maxSize
realFftLog2sizelog2, or −1Powers of two 1..2^19

Lifecycle

initRealFft(maxSize) allocates everything once, outside realtime. The same state then serves every smaller power-of-two size by striding the same tables; there is no reset, because the transforms keep no state between calls.

When to use it

Spectral analysis, FFT convolution and room-acoustics preparation inside a Processor. @maru/filters-partitioned-convolution and @maru/acoustics-octave-bands build on it (spectral and rooms).

Limits

  • Inside a realtime callback keep one transform at or below REAL_FFT_REALTIME_MAX_SIZE (8192 points); larger sizes belong in budgeted preparation steps.
  • Output arrays are caller-owned; spectra need at least size/2 + 1 entries.
  • The transforms allocate nothing, and every loop has a literal bound with the runtime size as an inner guard.
  • @maru/oscillators-band-limited-table keeps its own private f32 transform.

Algorithm properties and proofs

No Lean 4 proof is mapped to this node.

Explore proofs alongside performance

Dependencies

None: this node imports no other node.

Dependents

Used by