Próbuję stworzyć graficzny analizator widma w Pythonie.
Obecnie czytam 1024 bajty 16-bitowego dwukanałowego strumienia audio z częstotliwością próbkowania 44100 Hz i uśredniam amplitudę 2 kanałów razem. Więc teraz mam zestaw 256 podpisanych szortów. Chcę teraz wykonać fft na tej tablicy, używając modułu takiego jak numpy, i użyć wyniku do stworzenia graficznego analizatora widma, który na początku będzie miał tylko 32 słupki.
Przeczytałem artykuły na Wikipedii o szybkiej transformacji Fouriera i dyskretnej transformacji Fouriera, ale nadal nie jestem pewien, co reprezentuje otrzymana tablica. Tak wygląda tablica po wykonaniu operacji fft na mojej tablicy przy użyciu 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...
Zastanawiam się, co dokładnie reprezentują te liczby i jak przeliczyłbym te liczby na procent wysokości dla każdego z 32 słupków. Czy powinienem również uśredniać razem 2 kanały?
Chociaż ten wątek ma już lata, okazał się bardzo pomocny. Chciałem tylko przekazać swoje uwagi każdemu, kto to znajdzie i próbuje stworzyć coś podobnego.
Jeśli chodzi o podział na słupki, nie należy tego robić, jak sugeruje antti, dzieląc dane równo na podstawie liczby słupków. Najbardziej przydatne byłoby podzielenie danych na części oktawowe, przy czym każda oktawa jest dwukrotnie większa od częstotliwości poprzedniej. (tj. 100 Hz to jedna oktawa powyżej 50 Hz, czyli jedna oktawa powyżej 25 Hz).
W zależności od tego, ile chcesz taktów, cały zakres dzielisz na zakresy 1 / X oktawy. Bazując na zadanej częstotliwości środkowej A na słupku, otrzymujesz górną i dolną granicę słupka z:
Aby obliczyć następną sąsiednią częstotliwość środkową, użyj podobnego obliczenia:
Następnie uśredniasz dane, które mieszczą się w tych zakresach, aby uzyskać amplitudę dla każdego słupka.
Na przykład: Chcemy podzielić na zakresy 1/3 oktawy i zaczynamy od częstotliwości środkowej 1 kHz.
Biorąc pod uwagę 44100 Hz i 1024 próbki (43 Hz między każdym punktem danych) powinniśmy uśrednić wartości od 21 do 26. (890,9 / 43 = 20,72 ~ 21 i 1122,5 / 43 = 26,10 ~ 26)
(Paski 1/3 oktawy dają około 30 taktów między ~ 40 Hz a ~ 20 kHz). Jak już możesz się domyślić, gdy będziemy podążać wyżej, będziemy uśredniać większy zakres liczb. Niskie słupki zazwyczaj zawierają tylko 1 lub niewielką liczbę punktów danych. Podczas gdy wyższe słupki mogą być średnią z setek punktów. Powodem jest to, że 86 Hz to oktawa powyżej 43 Hz ... podczas gdy 10086 Hz brzmi prawie tak samo jak 10043 Hz.
źródło
masz próbkę, której długość w czasie wynosi 256/44100 = 0,00580499 sekund. Oznacza to, że twoja rozdzielczość częstotliwości wynosi 1 / 0,00580499 = 172 Hz. 256 wartości, które otrzymujesz z Pythona, odpowiada częstotliwościom, w zasadzie, od 86 Hz do 255 * 172 + 86 Hz = 43946 Hz. Liczby, które otrzymujesz, są liczbami zespolonymi (stąd „j” na końcu każdej drugiej liczby).
EDITED: POPRAWIONE BŁĘDNE INFORMACJE
Musisz zamienić liczby zespolone na amplitudę, obliczając sqrt (i 2 + j 2 ), gdzie i i j są częściami rzeczywistymi i urojonymi.
Jeśli chcesz mieć 32 słupki, powinieneś, o ile rozumiem, wziąć średnią z czterech kolejnych amplitud, uzyskując 256/4 = 32 słupki, jak chcesz.
źródło
FFT zwraca N wartości zespolonych, z których można obliczyć
module=sqrt(real_part^2+imaginary_part^2)
. Aby uzyskać wartość dla każdego pasma, należy zsumować moduły dotyczące wszystkich harmonicznych w paśmie. Poniżej możesz zobaczyć przykład dotyczący analizatora widma 10 barów. Kod C musi zostać opakowany, aby uzyskać moduł pyd python.Zaprojektowałem i wykonałem cały 10-ledowy analizator widma słupkowego firmy Python. Zamiast użyć biblioteki nunmpy (zbyt dużej i bezużytecznej, aby uzyskać tylko FFT), utworzono moduł Pythona pyd (tylko 27KB), aby uzyskać FFT i podzielić całe widmo audio na pasma.
Dodatkowo do odczytu wyjściowego dźwięku został stworzony moduł loopback WASapi portaudio pyd. Możesz zobaczyć projekt (schemat blokowy) na obrazku 10BarsSpectrumAnalyzerWithWASapi.jpg
Właśnie dodałem film instruktażowy na moim kanale YouTube: jak zaprojektować i wykonać bardzo inteligentny Python Spectrum Analyzer 10 Led Bar
źródło