Domanda

Sto cercando di creare un analizzatore grafico di spettro in Python.

Attualmente sto leggendo 1024 byte di un flusso audio a frequenza di campionamento a 44,100 Hz a doppio canale a 16 bit e calcolando la media dell'ampiezza dei 2 canali insieme. Quindi ora ho una serie di 256 cortometraggi firmati. Ora voglio preformare un fft su quell'array, usando un modulo come numpy, e usare il risultato per creare l'analizzatore grafico di spettro, che, per iniziare, sarà solo di 32 bar.

Ho letto gli articoli di Wikipedia su Trasformata di Fourier veloce e Trasformata di Fourier discreta, ma non sono ancora chiaro cosa rappresenti l'array risultante. Questo è l'aspetto dell'array dopo che ho preformato un fft sul mio array usando numpy:

   [ -3.37260500e+05 +0.00000000e+00j   7.11787022e+05 +1.70667403e+04j
   4.10040193e+05 +3.28653370e+05j   9.90933073e+04 +1.60555003e+05j
   2.28787050e+05 +3.24141951e+05j   2.09781047e+04 +2.31063376e+05j
  -2.15941453e+05 +1.63773851e+05j  -7.07833051e+04 +1.52467334e+05j
  -1.37440802e+05 +6.28107674e+04j  -7.07536614e+03 +5.55634993e+03j
  -4.31009964e+04 -1.74891657e+05j   1.39384348e+05 +1.95956947e+04j
   1.73613033e+05 +1.16883207e+05j   1.15610357e+05 -2.62619884e+04j
  -2.05469722e+05 +1.71343186e+05j  -1.56779748e+04 +1.51258101e+05j
  -2.08639913e+05 +6.07372799e+04j  -2.90623668e+05 -2.79550838e+05j
  -1.68112214e+05 +4.47877871e+04j  -1.21289916e+03 +1.18397979e+05j
  -1.55779104e+05 +5.06852464e+04j   1.95309737e+05 +1.93876325e+04j
  -2.80400414e+05 +6.90079265e+04j   1.25892113e+04 -1.39293422e+05j
   3.10709174e+04 -1.35248953e+05j   1.31003438e+05 +1.90799303e+05j...

Mi chiedo cosa rappresentino esattamente questi numeri e come li convertirò in una percentuale di altezza per ciascuna delle 32 barre. Inoltre, dovrei calcolare la media dei 2 canali insieme?

È stato utile?

Soluzione

L'array che stai mostrando sono i coefficienti di trasformata di Fourier del segnale audio. Questi coefficienti possono essere utilizzati per ottenere il contenuto in frequenza dell'audio. La FFT è definita per funzioni di input complesse e valutate, quindi i coefficienti che ottieni saranno numeri immaginari anche se i tuoi input sono tutti valori reali. Al fine di ottenere la quantità di potenza in ciascuna frequenza, è necessario calcolare l'entità del coefficiente FFT per ciascuna frequenza. Questo non è solo il componente reale del coefficiente, è necessario calcolare la radice quadrata della somma del quadrato dei suoi componenti reali e immaginari. Cioè, se il tuo coefficiente è a + b * j, la sua magnitudine è sqrt (a ^ 2 + b ^ 2).

Dopo aver calcolato l'entità di ciascun coefficiente FFT, è necessario capire a quale frequenza audio appartiene ciascun coefficiente FFT. Un punto N FFT ti fornirà il contenuto in frequenza del tuo segnale a N frequenze equidistanti, a partire da 0. Perché la frequenza di campionamento è 44100 campioni / sec. e il numero di punti nella tua FFT è 256, la tua spaziatura di frequenza è 44100/256 = 172 Hz (circa)

Il primo coefficiente nell'array sarà il coefficiente di frequenza 0. Questo è fondamentalmente il livello di potenza medio per tutte le frequenze. Il resto dei tuoi coefficienti verrà conteggiato da 0 in multipli di 172 Hz fino a raggiungere 128. In una FFT, puoi misurare solo le frequenze fino a metà dei punti di campionamento. Leggi questi link su Nyquist Frequency e Teorema di campionamento di Nyquist-Shannon se sei un ghiottone per punizione e devi sapere perché, ma il risultato di base è che le tue frequenze più basse verranno replicate o alias nei bucket a frequenza più elevata. Quindi le frequenze inizieranno da 0, aumenteranno di 172 Hz per ciascun coefficiente fino al coefficiente N / 2, quindi diminuiranno di 172 Hz fino al coefficiente N - 1.

Dovrebbero essere sufficienti informazioni per iniziare. Se desideri un'introduzione molto più accessibile alle FFT rispetto a quella fornita su Wikipedia, puoi provare Comprensione dell'elaborazione del segnale digitale: seconda edizione. . È stato molto utile per me.

Questo è ciò che rappresentano quei numeri. La conversione in una percentuale di altezza potrebbe essere effettuata ridimensionando la grandezza di ciascun componente di frequenza in base alla somma di tutte le magnitudini del componente. Tuttavia, ciò ti darebbe solo una rappresentazione della relativa distribuzione di frequenza e non la potenza effettiva per ciascuna frequenza. Potresti provare il ridimensionamento della massima ampiezza possibile per un componente di frequenza, ma non sono sicuro che sarebbe visualizzato molto bene. Il modo più rapido per trovare un fattore di ridimensionamento praticabile sarebbe sperimentare segnali audio forti e morbidi per trovare la giusta impostazione.

Infine, dovresti calcolare la media dei due canali se vuoi mostrare il contenuto in frequenza dell'intero segnale audio nel suo insieme. Stai mescolando l'audio stereo in audio mono e mostrando le frequenze combinate. Se desideri due display separati per le frequenze destra e sinistra, dovrai eseguire la trasformata di Fourier su ciascun canale separatamente.

Altri suggerimenti

Anche se questa discussione ha anni, l'ho trovata molto utile. Volevo solo dare il mio contributo a chiunque lo trovasse e stia cercando di creare qualcosa di simile.

Per quanto riguarda la divisione in barre, ciò non dovrebbe essere fatto come suggerisce Antti, dividendo i dati equamente in base al numero di barre. Il più utile sarebbe quello di dividere i dati in parti di ottava, ogni ottava essendo il doppio della frequenza della precedente. (cioè 100 hz è un'ottava sopra 50 hz, che è un'ottava sopra 25 hz).

A seconda di quante barre vuoi, dividi l'intero intervallo in intervalli di ottava 1 / X. Sulla base di una data frequenza centrale di A sulla barra, ottieni i limiti superiore e inferiore della barra da:

upper limit = A * 2 ^ ( 1 / 2X )
lower limit = A / 2 ^ ( 1 / 2X )

Per calcolare la prossima frequenza centrale adiacente si utilizza un calcolo simile:

next lower =  A / 2 ^ ( 1 / X )
next higher = A * 2 ^ ( 1 / X )

Quindi si esegue la media dei dati che rientrano in questi intervalli per ottenere l'ampiezza per ogni barra.

Ad esempio: Vogliamo dividere in intervalli di 1/3 di ottava e iniziamo con una frequenza centrale di 1khz.

Upper limit = 1000 * 2 ^ ( 1 / ( 2 * 3 ) ) = 1122.5
Lower limit = 1000 / 2 ^ ( 1 / ( 2 * 3 ) ) =  890.9

Dati 44100hz e 1024 campioni (43hz tra ciascun punto dati) dovremmo calcolare la media dei valori da 21 a 26. (890.9 / 43 = 20.72 ~ 21 e 1122.5 / 43 = 26.10 ~ 26)

(1/3 ottave bar ti porterebbero circa 30 bar tra ~ 40hz e ~ 20khz). Come puoi capire ora, mentre andiamo più in alto, faremo una media di un più ampio intervallo di numeri. Le barre basse in genere includono solo 1 o un numero limitato di punti dati. Mentre le barre più alte possono essere la media di centinaia di punti. Il motivo è che 86hz è un'ottava sopra 43hz ... mentre 10086hz suona quasi uguale a 10043hz.

quello che hai è un campione la cui lunghezza nel tempo è 256/44100 = 0,00580499 secondi. Ciò significa che la risoluzione della frequenza è 1 / 0,00580499 = 172 Hz. I 256 valori che ottieni da Python corrispondono alle frequenze, in sostanza, da 86 Hz a 255 * 172 + 86 Hz = 43946 Hz. I numeri che ottieni sono numeri complessi (quindi il "j" alla fine di ogni secondo numero).

MODIFICATO: INFORMAZIONI ERRATE FISSE

Devi convertire i numeri complessi in ampiezza calcolando sqrt (i 2 + j 2 ) dove iej sono le parti reali e immaginarie, resp.

Se vuoi avere 32 barre, per quanto ho capito dovresti prendere la media di quattro ampiezze successive, ottenendo 256/4 = 32 barre come vuoi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top