Analisis audio menggunakan Fast Fourier Transform


109

Saya mencoba membuat penganalisis spektrum grafis dengan python.

Saat ini saya membaca 1024 byte aliran audio tingkat sampel 16 bit saluran ganda 44.100 Hz dan rata-rata amplitudo dari 2 saluran bersama-sama. Jadi sekarang saya memiliki serangkaian 256 celana pendek yang ditandatangani. Sekarang saya ingin membentuk fft pada array itu, menggunakan modul seperti numpy, dan menggunakan hasilnya untuk membuat penganalisis spektrum grafis, yang, untuk memulai, hanya akan menjadi 32 bar.

Saya telah membaca artikel wikipedia tentang Fast Fourier Transform dan Discrete Fourier Transform tetapi saya masih belum jelas tentang apa yang diwakili oleh array yang dihasilkan. Ini adalah tampilan array setelah saya membentuk fft pada array saya menggunakan 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...

Saya bertanya-tanya apa sebenarnya yang diwakili oleh angka-angka ini dan bagaimana saya akan mengubah angka-angka ini menjadi persentase ketinggian untuk masing-masing dari 32 batang. Selain itu, haruskah saya membuat rata-rata 2 saluran bersama-sama?

Jawaban:


209

Larik yang Anda tunjukkan adalah koefisien Transformasi Fourier dari sinyal audio. Koefisien ini dapat digunakan untuk mendapatkan konten frekuensi audio. FFT ditentukan untuk fungsi masukan bernilai kompleks, sehingga koefisien yang Anda keluarkan akan menjadi bilangan imajiner meskipun masukan Anda adalah semua nilai riil. Untuk mendapatkan besaran daya di setiap frekuensi, Anda perlu menghitung besarnya koefisien FFT untuk setiap frekuensi. Ini bukan hanya komponen nyata dari koefisien, Anda perlu menghitung akar kuadrat dari jumlah kuadrat komponen nyata dan imajinernya. Artinya, jika koefisien Anda adalah a + b * j, maka besarnya adalah akar kuadrat (a ^ 2 + b ^ 2).

Setelah Anda menghitung besarnya setiap koefisien FFT, Anda perlu mencari tahu frekuensi audio yang dimiliki setiap koefisien FFT. FFT titik N akan memberi Anda konten frekuensi sinyal Anda pada frekuensi N yang berjarak sama, mulai dari 0. Karena frekuensi sampling Anda adalah 44100 sampel / detik. dan jumlah titik di FFT Anda adalah 256, jarak frekuensi Anda adalah 44100/256 = 172 Hz (kurang-lebih)

Koefisien pertama dalam larik Anda adalah koefisien frekuensi 0. Itu pada dasarnya adalah tingkat daya rata-rata untuk semua frekuensi. Koefisien lainnya akan dihitung dari 0 dalam kelipatan 172 Hz hingga Anda mencapai 128. Dalam FFT, Anda hanya dapat mengukur frekuensi hingga setengah titik sampel Anda. Bacalah tautan ini pada Teorema Pengambilan Sampel Nyquist Frequency dan Nyquist-Shannon jika Anda rakus untuk hukuman dan perlu mengetahui alasannya, tetapi hasil dasarnya adalah bahwa frekuensi rendah Anda akan direplikasi atau dialiasi dalam kelompok frekuensi yang lebih tinggi. Maka frekuensi akan dimulai dari 0, naik 172 Hz untuk setiap koefisien sampai ke koefisien N / 2, kemudian turunkan 172 Hz sampai koefisien N - 1.

Itu seharusnya cukup informasi untuk Anda mulai. Jika Anda ingin pengenalan FFT yang lebih mudah didekati daripada yang diberikan di Wikipedia, Anda dapat mencoba Memahami Pemrosesan Sinyal Digital: 2nd Ed. . Hal itu sangat membantuku.

Jadi itulah yang diwakili oleh angka-angka itu. Mengubah persentase ketinggian dapat dilakukan dengan menskalakan setiap besaran komponen frekuensi dengan menjumlahkan semua besaran komponen. Meskipun, itu hanya akan memberi Anda representasi dari distribusi frekuensi relatif, dan bukan daya sebenarnya untuk setiap frekuensi. Anda dapat mencoba melakukan penskalaan dengan besaran maksimum yang mungkin untuk komponen frekuensi, tetapi saya tidak yakin itu akan ditampilkan dengan sangat baik. Cara tercepat untuk menemukan faktor penskalaan yang bisa diterapkan adalah dengan bereksperimen pada sinyal audio yang keras dan lembut untuk menemukan pengaturan yang tepat.

Terakhir, Anda harus menghitung rata-rata kedua saluran jika Anda ingin menampilkan konten frekuensi dari seluruh sinyal audio secara keseluruhan. Anda mencampur audio stereo menjadi audio mono dan menampilkan frekuensi gabungan. Jika Anda menginginkan dua tampilan terpisah untuk frekuensi kanan dan kiri, maka Anda perlu melakukan Transformasi Fourier pada setiap saluran secara terpisah.


1
Saya kebanyakan hanya dapat menemukan penjelasan FFT online yang terlalu rumit, ini adalah penjelasan yang bagus dan sederhana tentang bagaimana jumlah titik sampel mempengaruhi hasil FFT. Terima kasih untuk ini!
ekolokasi

26

Meskipun utas ini sudah bertahun-tahun, saya merasa sangat membantu. Saya hanya ingin memberikan masukan kepada siapa pun yang menemukan ini dan mencoba membuat sesuatu yang serupa.

Sedangkan pembagian batangan sebaiknya tidak dilakukan seperti yang disarankan, yaitu dengan membagi data secara merata berdasarkan jumlah batangan. Yang paling berguna adalah membagi data menjadi bagian-bagian oktaf, setiap oktaf menjadi dua kali lipat frekuensi sebelumnya. (mis. 100hz adalah satu oktaf di atas 50hz, yang mana satu oktaf di atas 25hz).

Bergantung pada berapa banyak batang yang Anda inginkan, Anda membagi seluruh rentang menjadi 1 / X rentang oktaf. Berdasarkan frekuensi pusat A tertentu pada bilah, Anda mendapatkan batas atas dan bawah bilah dari:

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

Untuk menghitung frekuensi pusat yang berdampingan berikutnya, Anda menggunakan perhitungan yang serupa:

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

Anda kemudian rata-rata data yang sesuai dengan rentang ini untuk mendapatkan amplitudo untuk setiap batang.

Misalnya: Kami ingin membagi rentang 1/3 oktaf dan kami mulai dengan frekuensi tengah 1khz.

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

Diberikan 44100hz dan 1024 sampel (43hz antara setiap titik data) kita harus rata-rata keluar nilai 21 sampai 26. (890.9 / 43 = 20.72 ~ 21 dan 1122.5 / 43 = 26.10 ~ 26)

(Bar 1/3 oktaf akan memberi Anda sekitar 30 bar antara ~ 40hz dan ~ 20khz). Seperti yang dapat Anda ketahui sekarang, semakin tinggi kita akan rata-rata rentang angka yang lebih besar. Bilah rendah biasanya hanya mencakup 1 atau sejumlah kecil titik data. Sedangkan batang yang lebih tinggi rata-rata bisa mencapai ratusan poin. Alasannya karena 86hz adalah satu oktaf di atas 43hz ... sedangkan 10086hz terdengar hampir sama dengan 10043hz.


10

yang Anda miliki adalah sampel yang lamanya waktu 256/44100 = 0,00580499 detik. Ini berarti resolusi frekuensi Anda adalah 1 / 0,00580499 = 172 Hz. 256 nilai yang Anda peroleh dari Python sesuai dengan frekuensi, pada dasarnya, dari 86 Hz hingga 255 * 172 + 86 Hz = 43946 Hz. Bilangan yang Anda keluarkan adalah bilangan kompleks (karena itu "j" di akhir setiap bilangan detik).

DIEDIT: INFORMASI SALAH TETAP

Anda perlu mengubah bilangan kompleks menjadi amplitudo dengan menghitung akar (i 2 + j 2 ) di mana i dan j adalah bagian nyata dan imajiner, resp.

Jika Anda ingin memiliki 32 batang, sejauh yang saya mengerti, Anda harus mengambil rata-rata dari empat amplitudo yang berurutan, mendapatkan 256/4 = 32 batang sesuai keinginan Anda.


4
Harap dicatat bahwa, jika c adalah bilangan kompleks, akar kuadrat (c.real 2 + c.imag 2) == abs (c)
tzot

0

FFT mengembalikan nilai kompleks N yang mana di antara Anda dapat menghitung module=sqrt(real_part^2+imaginary_part^2). Untuk mendapatkan nilai dari setiap band Anda harus menjumlahkan modul tentang semua harmonisa di dalam band. Di bawah ini Anda dapat melihat contoh tentang penganalisis spektrum 10 bar. Kode c harus dibungkus untuk mendapatkan modul 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;

        }

Saya merancang dan membuat 10 penganalisis spektrum bar yang dipimpin oleh Python. Alih-alih menggunakan pustaka nunmpy (terlalu besar dan tidak berguna untuk hanya mendapatkan FFT), modul python pyd (hanya 27KB) untuk mendapatkan FFT dan untuk membagi seluruh spektrum audio menjadi band telah dibuat.

Selain itu, untuk membaca audio keluaran, modul pyd WASapi portaudio loopback telah dibuat. Anda dapat melihat proyek (diagram blok) pada gambar 10BarsSpectrumAnalyzerWithWASapi.jpg

Baru saja menambahkan video tutorial di saluran YouTube saya: cara merancang dan membuat Bar Led Penganalisis Spektrum 10 Python yang sangat cerdas

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.