Skip to content
Plugins (183)

fft

stable

Fast Fourier Transform and spectral analysis utilities. Compute forward/inverse FFT, power spectra, windowing, STFT, convolution, and peak frequency detection on real-valued signal arrays.

use plugin fft::{fft, ifft, magnitude, …}
19 functions Math
Runs with the native Zolo host

Plugin snippets can be edited in the Playground, but native capabilities are executed locally with the Zolo CLI.

/ filter jk navigate Esc clear
Functions (19)
  1. fft Forward FFT of real+imaginary arrays
  2. ifft Inverse FFT back to time domain
  3. magnitude Per-bin magnitude from real+imag arrays
  4. phase Per-bin phase angle from real+imag arrays
  5. power_spectrum Power spectrum of a real signal
  6. next_power_of_2 Smallest power of 2 >= n
  7. windowed_fft FFT with a window function applied first
  8. stft Short-Time Fourier Transform (frame-based)
  9. peak_frequencies Find dominant frequency peaks
  10. bandpass Zero out bins outside a frequency range
  11. convolution Linear convolution via FFT
  12. cross_correlation Cross-correlation of two signals via FFT
  13. autocorrelation Autocorrelation of a signal via FFT
  14. spectral_centroid Frequency-weighted centre of the spectrum
  15. spectral_rolloff Frequency below which most energy lies
  16. frequency_bins Frequency value for each FFT bin
  17. apply_window Apply a window function to a signal
  18. generate_sine Generate a sine wave sample array
  19. db_scale Convert magnitude values to decibels

From import to result

  1. 01Import only what you use
  2. 02Copy the smallest example
  3. 03Run it with the Zolo CLI

Overview

fft is a dependency-free signal-processing toolkit built around a Cooley-Tukey radix-2 FFT. Signals are plain Zolo arrays of numbers — there is no opaque handle or stateful context — so a waveform is just a table you can build, slice, and pass around freely. Inputs whose length is not a power of 2 are zero-padded automatically, and the complex spectrum is always returned as a {real, imag} table you can feed into the magnitude, phase, and spectral helpers.

The mental model is a pipeline: produce or load a real signal (for example with generate_sine), optionally taper it with apply_window, transform it with fft, then analyse the result with magnitude, peak_frequencies, spectral_centroid, or db_scale — and ifft back to the time domain when you need to reconstruct a filtered signal. Higher-level helpers such as convolution, cross_correlation, and stft wrap that pipeline for common tasks. Use it whenever you need spectral analysis, frequency-domain filtering, or fast convolution without pulling in a numeric library.

Common patterns

Generate a tone, transform it, and read back its magnitude spectrum:

use plugin fft::{generate_sine, fft, magnitude}

let signal = generate_sine(440.0, 44100.0, 1024)
let zeros  = generate_sine(0.0, 44100.0, 1024)
let spec   = fft(signal, zeros)
let mags   = magnitude(spec["real"], spec["imag"])
print("bins: {mags}")

Find the dominant frequency of a noisy signal:

use plugin fft::{generate_sine, fft, peak_frequencies}

let sig   = generate_sine(1000.0, 8000.0, 1024)
let zeros = generate_sine(0.0, 8000.0, 1024)
let spec  = fft(sig, zeros)
let peaks = peak_frequencies(spec["real"], spec["imag"], 8000.0)
print("dominant: {peaks[1]["frequency"]} Hz")

Band-pass filter a signal in the frequency domain, then reconstruct it:

use plugin fft::{generate_sine, fft, bandpass, ifft}

let sig      = generate_sine(440.0, 44100.0, 1024)
let zeros    = generate_sine(0.0, 44100.0, 1024)
let spec     = fft(sig, zeros)
let filtered = bandpass(spec["real"], spec["imag"], 400.0, 500.0, 44100.0)
let restored = ifft(filtered["real"], filtered["imag"])
print(restored["real"])

Forward FFT of real+imaginary arrays

Performs a forward Cooley-Tukey radix-2 FFT. Both arrays must be the same length; zero-padding to the next power of 2 is applied automatically. Returns {real, imag}.

use plugin fft::{fft, magnitude, generate_sine}

let signal = generate_sine(440.0, 44100.0, 1024)
let zeros  = generate_sine(0.0, 44100.0, 1024)
let result = fft(signal, zeros)
let mags   = magnitude(result["real"], result["imag"])
print(mags)

Inverse FFT back to time domain

Inverse FFT: converts frequency-domain arrays back to the time domain. The output is normalised by 1/N. Returns {real, imag}.

use plugin fft::{fft, ifft, generate_sine}

let sig    = generate_sine(220.0, 44100.0, 512)
let zeros  = generate_sine(0.0, 44100.0, 512)
let freq   = fft(sig, zeros)
let back   = ifft(freq["real"], freq["imag"])
print(back["real"])

A forward then inverse transform reconstructs the original signal (up to padding):

use plugin fft::{fft, ifft}

let sig   = [1.0, 2.0, 3.0, 4.0]
let zeros = [0.0, 0.0, 0.0, 0.0]
let freq  = fft(sig, zeros)
let round = ifft(freq["real"], freq["imag"])
print(round["real"])  // ~[1, 2, 3, 4]

Per-bin magnitude from real+imag arrays

Computes sqrt(r^2 + i^2) for each bin. Use this after fft to get the amplitude spectrum.

use plugin fft::{fft, magnitude, generate_sine}

let sig  = generate_sine(1000.0, 8000.0, 256)
let im   = generate_sine(0.0, 8000.0, 256)
let spec = fft(sig, im)
let mags = magnitude(spec["real"], spec["imag"])
print(mags)

Per-bin phase angle from real+imag arrays

Computes atan2(imag, real) for each bin, returning phase angles in radians.

use plugin fft::{fft, phase, generate_sine}

let sig = generate_sine(100.0, 8000.0, 256)
let im  = generate_sine(0.0, 8000.0, 256)
let sp  = fft(sig, im)
let ph  = phase(sp["real"], sp["imag"])
print(ph)

Power spectrum of a real signal

Computes the power spectrum (r^2 + i^2) of a real-valued signal in one step. Takes only the real array; the imaginary part is assumed zero.

use plugin fft::{power_spectrum, generate_sine}

let sig   = generate_sine(440.0, 44100.0, 1024)
let power = power_spectrum(sig)
print(power)

Smallest power of 2 >= n

Returns the smallest power of 2 that is greater than or equal to n. Useful for sizing FFT buffers.

use plugin fft::{next_power_of_2}

print(next_power_of_2(100))   // 128
print(next_power_of_2(1024))  // 1024
print(next_power_of_2(1025))  // 2048

FFT with a window function applied first

Applies a window function to the signal before computing the FFT. Supported window types: "hann", "hamming", "blackman". Returns {real, imag}.

use plugin fft::{windowed_fft, magnitude, generate_sine}

let sig  = generate_sine(440.0, 44100.0, 1024)
let spec = windowed_fft(sig, "hann")
let mags = magnitude(spec["real"], spec["imag"])
print(mags)

Short-Time Fourier Transform (frame-based)

Computes the Short-Time Fourier Transform by sliding a Hann-windowed frame over the signal with the given hop size. Returns a table of frames, each containing {real, imag} for the positive-frequency bins.

use plugin fft::{stft, generate_sine}

let sig    = generate_sine(440.0, 44100.0, 4096)
let frames = stft(sig, 512, 256)
print("frame count: {frames}")

Each frame is a {real, imag} table, so you can transform a single frame further:

use plugin fft::{stft, magnitude, generate_sine}

let sig    = generate_sine(440.0, 44100.0, 4096)
let frames = stft(sig, 512, 256)
let first  = frames[1]
let mags   = magnitude(first["real"], first["imag"])
print(mags)

Find dominant frequency peaks

Finds local maxima in the magnitude spectrum and returns them sorted by magnitude descending. Each entry contains {frequency, magnitude}.

use plugin fft::{fft, peak_frequencies, generate_sine}

let sig    = generate_sine(440.0, 44100.0, 1024)
let zeros  = generate_sine(0.0, 44100.0, 1024)
let spec   = fft(sig, zeros)
let peaks  = peak_frequencies(spec["real"], spec["imag"], 44100.0)
print(peaks[1]["frequency"])  // ~440 Hz

Zero out bins outside a frequency range

Zeroes out all FFT bins outside the [low_freq, high_freq] range, effectively filtering the spectrum. Returns {real, imag}.

use plugin fft::{fft, bandpass, ifft, generate_sine}

let sig      = generate_sine(440.0, 44100.0, 1024)
let zeros    = generate_sine(0.0, 44100.0, 1024)
let spec     = fft(sig, zeros)
let filtered = bandpass(spec["real"], spec["imag"], 400.0, 500.0, 44100.0)
let out      = ifft(filtered["real"], filtered["imag"])
print(out["real"])

Linear convolution via FFT

Computes the linear convolution of two signals using FFT multiplication. Returns the result as a real-valued array of length len(s1) + len(s2) - 1.

use plugin fft::{convolution}

let a   = [1.0, 2.0, 3.0]
let b   = [1.0, 1.0]
let out = convolution(a, b)
print(out)  // [1.0, 3.0, 5.0, 3.0]

Convolving a signal with a smoothing kernel applies a moving average filter:

use plugin fft::{convolution}

let signal = [0.0, 4.0, 0.0, 4.0, 0.0]
let kernel = [0.5, 0.5]
let smooth = convolution(signal, kernel)
print(smooth)

Cross-correlation of two signals via FFT

Computes the cross-correlation between two signals via FFT. Useful for detecting time delays between related signals.

use plugin fft::{cross_correlation, generate_sine}

let a    = generate_sine(440.0, 44100.0, 512)
let b    = generate_sine(440.0, 44100.0, 512)
let corr = cross_correlation(a, b)
print(corr)

Autocorrelation of a signal via FFT

Computes the autocorrelation of a signal with itself, returning a real-valued array of length 2*N - 1. Useful for pitch detection.

use plugin fft::{autocorrelation, generate_sine}

let sig  = generate_sine(440.0, 44100.0, 512)
let auto = autocorrelation(sig)
print(auto)

Frequency-weighted centre of the spectrum

Returns the frequency-weighted mean of the magnitude spectrum — the "centre of mass" of the spectrum. Higher values indicate more high-frequency content.

use plugin fft::{fft, magnitude, spectral_centroid, generate_sine}

let sig  = generate_sine(1000.0, 44100.0, 1024)
let im   = generate_sine(0.0, 44100.0, 1024)
let spec = fft(sig, im)
let mags = magnitude(spec["real"], spec["imag"])
let sc   = spectral_centroid(mags, 44100.0)
print("centroid: {sc} Hz")

Frequency below which most energy lies

Returns the frequency below which threshold fraction (default 0.85) of total spectral energy is contained. Useful for characterising timbral brightness.

use plugin fft::{fft, magnitude, spectral_rolloff, generate_sine}

let sig  = generate_sine(2000.0, 44100.0, 1024)
let im   = generate_sine(0.0, 44100.0, 1024)
let spec = fft(sig, im)
let mags = magnitude(spec["real"], spec["imag"])
let ro   = spectral_rolloff(mags, 44100.0, 0.85)
print("rolloff: {ro} Hz")

Frequency value for each FFT bin

Returns a table of n frequency values (in Hz), one per FFT bin. Use this to label the output of magnitude or power_spectrum.

use plugin fft::{frequency_bins}

let bins = frequency_bins(8, 8000.0)
print(bins)  // [0, 1000, 2000, 3000, 4000, 5000, 6000, 7000]

Apply a window function to a signal

Applies a named window function ("hann", "hamming", or "blackman") to a sample array and returns the windowed signal. Use before FFT to reduce spectral leakage.

use plugin fft::{apply_window, generate_sine}

let sig      = generate_sine(440.0, 44100.0, 512)
let windowed = apply_window(sig, "hamming")
print(windowed)

Generate a sine wave sample array

Generates a table of num_samples sine wave samples at the given frequency and sample rate. Useful for testing FFT functions.

use plugin fft::{generate_sine}

let wave = generate_sine(440.0, 44100.0, 1024)
print(wave[1])  // first sample

Convert magnitude values to decibels

Converts magnitude values to decibels using 20 * log10(magnitude / reference). reference defaults to 1.0 when omitted. Values of 0 or below become -Infinity.

use plugin fft::{fft, magnitude, db_scale, generate_sine}

let sig  = generate_sine(440.0, 44100.0, 1024)
let im   = generate_sine(0.0, 44100.0, 1024)
let spec = fft(sig, im)
let mags = magnitude(spec["real"], spec["imag"])
let db   = db_scale(mags, 1.0)
print(db)

When reference is omitted it defaults to 1.0, so raw magnitudes convert directly to dB:

use plugin fft::{db_scale}

let mags = [1.0, 0.1, 0.01]
print(db_scale(mags))  // [0, -20, -40]

Global index

Find your way through Zolo

Try an idea

Start here

9 results

9 results

en