A simple and fast no_std
library to get the frequency spectrum of a digital signal (e.g. audio) using FFT.
It follows the KISS principle and consists of simple building blocks/optional features. In short, this is
a convenient wrapper around the great rustfft
library.
I'm not an expert on digital signal processing. Code contributions are highly welcome! :)
Most tips and comments are located inside the code, so please check out the repository on Github! Anyway, the most basic usage looks like this:
use spectrum_analyzer::{samples_fft_to_spectrum, FrequencyLimit};
use spectrum_analyzer::windows::hann_window;
fn main() {
// This lib also works in `no_std` environments!
let samples: &[f32] = get_samples(); // TODO you need to implement the samples source
// apply hann window for smoothing; length must be a power of 2 for the FFT
let hann_window = hann_window(&samples[0..4096]);
// calc spectrum
let spectrum_hann_window = samples_fft_to_spectrum(
// (windowed) samples
&hann_window,
// sample rate
44100,
// optional frequency limit: e.g. only interested in frequencies 50 <= f <= 150?
FrequencyLimit::All,
// optional per element scaling function, e.g. `20 * log10(x)`; see doc comments
None,
// optional total scaling at the end; see doc comments
None,
);
for (fr, fr_val) in spectrum_hamming_window.raw_data().iter() {
println!("{}Hz => {}", fr, fr_val)
}
}
As already mentioned, there are lots of comments in the code. Short story is:
Type ComplexSpectrumScalingFunction
can do anything whereas BasicSpectrumScalingFunction
is easier to write, especially for Rust beginners.
Measurements taken on i7-8650U @ 3 Ghz (Single-Core) with optimized build
Operation | Time |
---|---|
Hann Window with 4096 samples | ≈70µs |
Hamming Window with 4096 samples | ≈10µs |
Hann Window with 16384 samples | ≈175µs |
Hamming Window with 16384 samples | ≈44µs |
FFT to spectrum with 4096 samples @ 44100Hz | ≈240µs |
FFT to spectrum with 16384 samples @ 44100Hz | ≈740µs |
In the following example you can see a basic visualization of frequencies 0 to 4000Hz
for
a layered signal of sine waves of 50
, 1000
, and 3777Hz
@ 41000Hz
sample rate. The peaks for the
given frequencies are clearly visible. Each calculation was done with 2048
samples, i.e. ≈46ms.
The noise (wrong peaks) also comes from clipping of the added sine waves!
Peaks (50, 1000, 3777 Hz) are clearly visible but also some noise.
Peaks (50, 1000, 3777 Hz) are clearly visible and Hann window reduces noise a little bit. Because this example has few noise, you don't see much difference.
Peaks (50, 1000, 3777 Hz) are clearly visible and Hamming window reduces noise a little bit. Because this example has few noise, you don't see much difference.
I tested f64 but the additional accuracy doesn't pay out the ~40% calculation overhead (on x86_64).
Apply a window function, like Hann window or Hamming window. But I'm not an expert on this.