Skip to content

FFTConvolve

Convolution along the last axis via the FFT, built on rfft / irfft (or the complex pair when either input is complex). O(n log n) instead of O(n·m): the fast path for long kernels like room impulse responses.

specux.fftconvolve(a, b, mode="full", backend="auto")
x = np.random.randn(48000).astype(np.float32)
impulse_response = np.random.randn(8000).astype(np.float32)
wet = specux.fftconvolve(x, impulse_response, mode="same") # reverb, x's length
specux.fftconvolve(np.ones(4), np.ones(3))
# array([1., 2., 3., 3., 2., 1.])
  • mode="full": the whole n + m - 1 response.
  • mode="same": the central part, the size of a.
  • mode="valid": only samples with full overlap.

Leading dimensions broadcast; the transforms pad to an even 5-smooth length internally. Differentiable end to end on torch (gradients flow to both inputs), resident on the GPU for torch/cupy inputs: CUDA, and Metal on both mps transports (DLPack from torch 2.9, compile_shader on 2.7/2.8), forward and backward.

The configured form

x = np.random.randn(48000).astype(np.float32)
impulse_response = np.random.randn(8000).astype(np.float32)
reverb = specux.FFTConvolve(mode="same")
wet = reverb(x, impulse_response)