6.14. FFT

Una trasformata di Fourier scompone un segnale nel dominio del tempo nelle sue frequenze costituenti. La trasformata di Fourier veloce (FFT) è l’algoritmo standard per calcolarla in modo efficiente – la ragione per cui esiste questo modulo, e il motivo per cui trasformate abbastanza lunghe da essere utili (1024 punti, 4096 punti) sono trattabili su un microcontrollore in primo luogo.

Su una camera, l’input è tipicamente un buffer di campioni equispaziati provenienti da un microfono, da un asse di un accelerometro, da un sensore di corrente o da una sonda di vibrazione; l’output è uno spettro che l’applicazione esamina poi alla ricerca di picchi, energia o caratteristiche per un classificatore.

numpy.fft fornisce la trasformata discreta di Fourier monodimensionale. Le due funzioni sono fft() (diretta) e ifft() (inversa, normalizzata per N).

La lunghezza della trasformata deve essere una potenza di due. Altre lunghezze sollevano ValueError. N = 256 e N = 1024 sono scelte comuni: abbastanza lunghe per una risoluzione in frequenza utilizzabile alla maggior parte delle frequenze di campionamento embedded, abbastanza corte da entrare in RAM e da terminare ben dentro un periodo di frame.

fft() accetta la parte reale dell’input come primo argomento posizionale e una parte immaginaria opzionale come secondo, e restituisce una 2-tupla (real, imag) di array reali.

6.14.1. Input reale, output di magnitudine

Quando l’applicazione fornisce solo input reale e necessita solo dello spettro di magnitudine:

real, imag = np.fft.fft(x)
magnitude  = np.sqrt(real * real + imag * imag)

Il risultato è un ndarray reale della stessa lunghezza dell’input. La funzione di supporto spectrogram() fa esattamente questo senza le allocazioni intermedie – la chiamata giusta all’interno di un loop in streaming.

6.14.2. Trasformata inversa

ifft() è normalizzata in modo che il giro completo restituisca l’input originale entro l’errore in virgola mobile. Entrambe le chiamate accettano e restituiscono una coppia di array reali:

real, imag       = np.fft.fft(y)
re_back, im_back = np.fft.ifft(real, imag)

6.14.3. Trovare la frequenza dominante

Uno schema comune è individuare il picco più grande in un buffer di campioni – audio, vibrazione, IR modulato. La ricetta:

  1. Acquisisci N campioni, con N una potenza di due.

  2. Calcola la FFT.

  3. Trova il bin con la magnitudine maggiore.

  4. Converti l’indice del bin in Hz usando la frequenza di campionamento.

from ulab import numpy as np

N  = 1024
fs = 8000.0                       # sample rate, Hz

# ... fill ``samples`` with N data points ...

real, imag = np.fft.fft(samples)
spectrum   = np.sqrt(real * real + imag * imag)

half      = spectrum[:N // 2]     # only first half is meaningful
peak_bin  = np.argmax(half)
peak_hz   = peak_bin * fs / N

print("peak at", peak_hz, "Hz")