SciDart
Fourier transform
FFT, inverse FFT, real FFT, frequency bins and spectra in dB.
Like scipy.fft
| Function | Does | NumPy / SciPy |
|---|---|---|
fft |
complex FFT | numpy.fft.fft |
ifft |
inverse complex FFT | numpy.fft.ifft |
rfft |
FFT of a real signal, positive frequencies only | numpy.fft.rfft |
rifft |
inverse of rfft |
numpy.fft.irfft |
fftFreq |
frequency of each bin | numpy.fft.fftfreq |
dbfft |
spectrum in dB with a window |
Lengths that are a power of two use the Cooley-Tukey algorithm. Other lengths use a direct DFT, which is much slower for long signals.
Spectrum of a signal
import 'dart:math' as math;
import 'package:scidart/numdart.dart';
import 'package:scidart/scidart.dart';
void main() {
var fs = 64.0; // sampling rate in Hz
var t = linspace(0, 1, num: 64, endpoint: false);
var signal = arraySin(arrayMultiplyToScalar(t, 2 * math.pi * 5)) +
arrayMultiplyToScalar(
arraySin(arrayMultiplyToScalar(t, 2 * math.pi * 12)), 0.5);
var spectrum = arrayComplexAbs(rfft(signal));
var freqs = fftFreq(signal.length, d: 1 / fs, realFrequenciesOnly: true);
for (var i = 0; i < spectrum.length; i++) {
if (spectrum[i] > 1) {
print('${freqs[i]} Hz: magnitude ${spectrum[i].toStringAsFixed(3)}');
}
}
}
Output
5.0 Hz: magnitude 32.000 12.0 Hz: magnitude 16.000
Precise frequency estimation
A tone between two bins spreads over several of them. A window reduces the leakage and parabolic interpolation on the log magnitude finds the true peak.
import 'dart:math' as math;
import 'package:scidart/numdart.dart';
import 'package:scidart/scidart.dart';
void main() {
var fs = 128.0;
var f0 = 3.7; // between two FFT bins
var n = linspace(0, 4, num: (4 * fs).toInt(), endpoint: false);
var signal = arraySin(arrayMultiplyToScalar(n, 2 * math.pi * f0));
var windowed = signal * blackmanharris(signal.length);
var spectrum = arrayComplexAbs(rfft(windowed));
var i = arrayArgMax(spectrum);
var refined = parabolic(arrayLog(spectrum), i)[0];
print('naive estimate: ${fs * i / windowed.length} Hz');
print(
'refined estimate: ${(fs * refined / windowed.length).toStringAsFixed(4)} Hz');
}
Output
naive estimate: 3.75 Hz refined estimate: 3.6993 Hz
Change the tones, the window and the number of samples:
Loading the interactive demo…