Analyser l'audio à l'aide de la transformation de Fourier rapide

109

J'essaye de créer un analyseur de spectre graphique en python.

Je lis actuellement 1024 octets d'un flux audio de fréquence d'échantillonnage de 44,100 Hz à deux canaux 16 bits et je fais la moyenne de l'amplitude des 2 canaux ensemble. Alors maintenant, j'ai une gamme de 256 courts-métrages signés. Je veux maintenant préformer un fft sur ce tableau, en utilisant un module comme numpy, et utiliser le résultat pour créer l'analyseur de spectre graphique, qui, pour commencer, n'aura que 32 barres.

J'ai lu les articles de wikipedia sur la transformation de Fourier rapide et la transformation de Fourier discrète, mais je ne sais toujours pas ce que représente le tableau résultant. Voici à quoi ressemble le tableau après avoir préformé un fft sur mon tableau en utilisant 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...

Je me demande ce que représentent exactement ces nombres et comment je les convertirais en pourcentage d'une hauteur pour chacune des 32 barres. Aussi, dois-je faire la moyenne des 2 canaux ensemble?

user19745
la source

Réponses:

209

Le tableau que vous affichez correspond aux coefficients de transformée de Fourier du signal audio. Ces coefficients peuvent être utilisés pour obtenir le contenu fréquentiel de l'audio. La FFT est définie pour les fonctions d'entrée à valeurs complexes, de sorte que les coefficients que vous obtenez seront des nombres imaginaires même si votre entrée est toutes des valeurs réelles. Afin d'obtenir la quantité de puissance dans chaque fréquence, vous devez calculer l'amplitude du coefficient FFT pour chaque fréquence. Ce n'est pas seulement la composante réelle du coefficient, vous devez calculer la racine carrée de la somme du carré de ses composantes réelles et imaginaires. Autrement dit, si votre coefficient est a + b * j, alors sa grandeur est sqrt (a ^ 2 + b ^ 2).

Une fois que vous avez calculé la magnitude de chaque coefficient FFT, vous devez déterminer à quelle fréquence audio appartient chaque coefficient FFT. Une FFT à N points vous donnera le contenu fréquentiel de votre signal à N fréquences également espacées, en commençant à 0. Parce que votre fréquence d'échantillonnage est de 44100 échantillons / s. et le nombre de points dans votre FFT est de 256, votre espacement de fréquence est de 44100/256 = 172 Hz (environ)

Le premier coefficient de votre tableau sera le coefficient de fréquence 0. C'est fondamentalement le niveau de puissance moyen pour toutes les fréquences. Le reste de vos coefficients comptera de 0 par multiples de 172 Hz jusqu'à ce que vous arriviez à 128. Dans une FFT, vous ne pouvez mesurer des fréquences que jusqu'à la moitié de vos points d'échantillonnage. Lisez ces liens sur la fréquence de Nyquist et le théorème d'échantillonnage de Nyquist-Shannon si vous êtes un gourmand de punition et que vous avez besoin de savoir pourquoi, mais le résultat de base est que vos fréquences inférieures vont être répliquées ou aliasées dans les tranches de fréquences plus élevées. Ainsi les fréquences commenceront à partir de 0, augmenteront de 172 Hz pour chaque coefficient jusqu'au coefficient N / 2, puis diminueront de 172 Hz jusqu'au coefficient N - 1.

Cela devrait être suffisant pour vous aider à démarrer. Si vous souhaitez une introduction aux FFT beaucoup plus accessible que celle donnée sur Wikipedia, vous pouvez essayer Comprendre le traitement numérique du signal: 2e éd. . Cela a été très utile pour moi.

Voilà donc ce que représentent ces chiffres. La conversion en pourcentage de hauteur pourrait être effectuée en mettant à l'échelle chaque amplitude de composante de fréquence par la somme de toutes les amplitudes de composante. Cependant, cela ne vous donnerait qu'une représentation de la distribution de fréquence relative, et non de la puissance réelle pour chaque fréquence. Vous pouvez essayer de mettre à l'échelle par la magnitude maximale possible pour un composant de fréquence, mais je ne suis pas sûr que cela s'affiche très bien. Le moyen le plus rapide de trouver un facteur de mise à l'échelle viable serait d'expérimenter sur des signaux audio forts et faibles pour trouver le bon réglage.

Enfin, vous devez faire la moyenne des deux canaux ensemble si vous souhaitez afficher le contenu en fréquence de l'ensemble du signal audio dans son ensemble. Vous mixez l'audio stéréo en audio mono et affichez les fréquences combinées. Si vous voulez deux affichages séparés pour les fréquences droite et gauche, vous devrez alors effectuer la transformation de Fourier sur chaque canal séparément.

A. Levy
la source
1
La plupart du temps, je ne peux trouver que des explications trop compliquées de la FFT en ligne, c'était une bonne et simple explication de la façon dont le nombre de points échantillonnés affecte les résultats de la FFT. Merci pour ça!
écholocation le
26

Bien que ce fil soit vieux de plusieurs années, je l'ai trouvé très utile. Je voulais juste donner mon avis à quiconque trouve cela et essaie de créer quelque chose de similaire.

Quant à la division en barres, cela ne devrait pas être fait comme le suggère antti, en divisant les données également en fonction du nombre de barres. Le plus utile serait de diviser les données en parties d'octave, chaque octave étant le double de la fréquence de la précédente. (c'est-à-dire que 100 Hz est une octave au-dessus de 50 Hz, ce qui est une octave au-dessus de 25 Hz).

Selon le nombre de mesures souhaitées, vous divisez la plage entière en plages de 1 / X octave. Sur la base d'une fréquence centrale donnée de A sur la barre, vous obtenez les limites supérieure et inférieure de la barre à partir de:

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

Pour calculer la prochaine fréquence centrale adjacente, utilisez un calcul similaire:

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

Vous faites ensuite la moyenne des données qui correspondent à ces plages pour obtenir l'amplitude de chaque barre.

Par exemple: Nous voulons diviser en plages de 1/3 d'octaves et nous commençons avec une fréquence centrale de 1 kHz.

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

Étant donné 44100 Hz et 1024 échantillons (43 Hz entre chaque point de données), nous devrions faire la moyenne des valeurs 21 à 26. (890,9 / 43 = 20,72 ~ 21 et 1122,5 / 43 = 26,10 ~ 26)

(Des mesures de 1/3 d'octave vous donneraient environ 30 mesures entre ~ 40hz et ~ 20khz). Comme vous pouvez le comprendre maintenant, à mesure que nous allons plus haut, nous établirons la moyenne d'une plus grande gamme de nombres. Les barres basses n'incluent généralement qu'un ou un petit nombre de points de données. Alors que les barres les plus élevées peuvent être la moyenne de centaines de points. La raison en est que 86hz est une octave au-dessus de 43hz ... tandis que 10086hz sonne presque comme 10043hz.

Erik A.
la source
10

ce que vous avez est un échantillon dont la durée est de 256/44100 = 0,00580499 secondes. Cela signifie que votre résolution de fréquence est de 1 / 0,00580499 = 172 Hz. Les 256 valeurs que vous obtenez de Python correspondent aux fréquences, essentiellement, de 86 Hz à 255 * 172 + 86 Hz = 43946 Hz. Les nombres que vous sortez sont des nombres complexes (d'où le "j" à la fin de chaque deuxième nombre).

MODIFIÉ: FIXE FAUX INFORMATIONS

Vous devez convertir les nombres complexes en amplitude en calculant le sqrt (i 2 + j 2 ) où i et j sont les parties réelles et imaginaires, resp.

Si vous voulez avoir 32 barres, vous devez pour autant que je sache prendre la moyenne de quatre amplitudes successives, en obtenant 256/4 = 32 barres comme vous le souhaitez.

Antti Huima
la source
4
Veuillez noter que, si c est un nombre complexe, sqrt (c.real 2 + c.imag 2) == abs (c)
tzot
0

FFT renvoie N valeurs complexes dont vous pouvez calculer le module=sqrt(real_part^2+imaginary_part^2). Pour obtenir la valeur de chaque bande, vous devez additionner les modules sur toutes les harmoniques à l'intérieur de la bande. Ci-dessous, vous pouvez voir un exemple d'un analyseur de spectre à 10 bars. Le code c doit être encapsulé pour obtenir un module pyd python.

float *samples_vett;
float *out_filters_vett;
int Nsamples;
float band_power = 0.0;
float harmonic_amplitude=0.0;
int i, out_index;

out_index=0;


for (i = 0; i < Nsamples / 2 + 1; i++)       
        {
            if (i == 1 || i == 2 || i == 4 || i == 8 || i == 17 || i == 33 || i == 66 || i == 132 || i == 264 || i == 511)
            {
                out_filters_vett[out_index] = band_power; 
                band_power = 0; 
                out_index++;  
            }

            harmonic_amplitude = sqrt(pow(ttfr_out_vett[i].r, 2) + pow(ttfr_out_vett[i].i, 2));
            band_power += harmonic_amplitude;

        }

J'ai conçu et fabriqué un analyseur de spectre à 10 barres LED par Python. Au lieu d'utiliser la bibliothèque nunmpy (trop grande et inutile pour obtenir uniquement la FFT), un module python pyd (seulement 27 Ko) a été créé pour obtenir la FFT et diviser tout le spectre audio en bandes.

De plus, pour lire l'audio de sortie, un module pyd portaudio WASapi en boucle a été créé. Vous pouvez voir le projet (diagramme) dans l'image 10BarsSpectrumAnalyzerWithWASapi.jpg

Je viens d'ajouter un tutoriel vidéo sur ma chaîne YouTube: comment concevoir et créer une barre LED très intelligente pour l'analyseur de spectre Python 10


la source