fft.h
Frequency domain.
#include <sonore/fft.h>- 3types
- 3other declarations
- Guides: Getting started, MIDI and MPE
On this page
Design notes
A radix-2 Cooley-Tukey FFT, window functions, a spectrum helper, and partitioned convolution. Our own implementation of the standard algorithm; no external library, and nothing here allocates once it is prepared.
Why we need it: spectral analysers on a faceplate, convolution reverb and cabinet impulses, and the measurement side of the toolkit. The FFT is compile-time sized so the twiddle table and scratch buffers are inline: a plugin's process() must not be the first place memory is asked for.
Types 3
template <size_t Size> class Fft
In-place complex FFT over Size points.
Usage is deliberately plain arrays rather than a complex type: the DSP that feeds this is real audio, and forcing every caller through std::complex would cost a copy for no clarity.
template <size_t Size = 1024> class SpectrumAnalyser
A spectrum analyser for a faceplate.
Feeds samples in, produces a windowed magnitude spectrum in dB whenever a frame fills. Hop is half the window, so a moving display stays smooth without paying for a transform every sample.
template <size_t BlockSize = 256, size_t MaxPartitions = 64> class Convolver
Uniformly-partitioned convolution: cabinet impulses, convolution reverb.
Direct convolution costs O(N) per sample and is unusable past a few hundred taps; this transforms once per block instead. The impulse is split into BlockSize partitions, each pre-transformed at load time, and the running input spectrum is multiplied against all of them (frequency-domain delay line). Latency is exactly one block, reported through the plugin's latency extension.
Everything is sized at compile time: loading an impulse allocates nothing, so it can be done on the audio thread. Not from another thread while process() runs -- the spectra would be read half-written; load a second convolver and hand it over instead, as the reverb example's Room does.
Functions 2
- fn
constexpr bool isPowerOfTwo(size_t n)True for 1, 2, 4, 8, ... (the FFT's only structural requirement).fft.h:22 - fn
inline void fillWindow(float* out, size_t n, Window kind)Writesfft.h:207nsamples of the windowkindtoout, in the symmetric form: sample 0 and sample n-1 are the window's two ends. Every shape's peak value is 1 (a sample lands on it when n is odd) except FlatTop's, which is divided by its constant term so that its mean is about 1. One sample is 1; zero samples writes nothing. No allocation.
Enums 1
- enum
enum class WindowAnalysis windows. A rectangular window smears a tone across every bin; which window to use is a resolution-vs-leakage trade, so both classics are here rather than one baked-in choice.fft.h:185