2009-03-02 29 views
95

Tôi đang cố gắng tạo một bộ phân tích phổ đồ họa trong python.Phân tích âm thanh bằng Fast Fourier Transform

Tôi hiện đang đọc 1024 byte của kênh âm thanh tốc độ mẫu kênh 16,100 Hz kênh đôi 16 bit và tính trung bình biên độ của 2 kênh với nhau. Vì vậy, bây giờ tôi có một loạt 256 quần short đã ký. Bây giờ tôi muốn tạo thành một fft trên mảng đó, sử dụng một mô-đun như numpy, và sử dụng kết quả để tạo ra các phân tích phổ đồ họa, trong đó, để bắt đầu sẽ chỉ là 32 thanh.

Tôi đã đọc các bài viết wikipedia về Chuyển đổi Fourier nhanh và Biến đổi Fourier rời rạc nhưng tôi vẫn chưa rõ những gì mảng kết quả đại diện. Đây là những gì các mảng trông giống như sau khi tôi phôi một FFT trên mảng của tôi sử dụng 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... 

tôi tự hỏi chính xác những gì những con số đại diện và làm thế nào tôi sẽ chuyển đổi những con số này thành một tỷ lệ phần trăm của một chiều cao cho mỗi 32 vạch. Ngoài ra, tôi có nên tính trung bình 2 kênh với nhau không?

Trả lời

187

Mảng bạn đang hiển thị là hệ số biến đổi Fourier của tín hiệu âm thanh. Các hệ số này có thể được sử dụng để lấy nội dung tần số của âm thanh. FFT được định nghĩa cho các hàm đầu vào có giá trị phức tạp, do đó các hệ số bạn nhận được sẽ là số ảo mặc dù đầu vào của bạn là tất cả các giá trị thực. Để có được công suất trong mỗi tần số, bạn cần tính toán độ lớn của hệ số FFT cho mỗi tần số. Đây là không phải là chỉ là thành phần thực của hệ số, bạn cần tính căn bậc hai của tổng bình phương của các thành phần thực và tưởng tượng của nó. Tức là, nếu hệ số của bạn là + b * j, thì độ lớn của nó là sqrt (a^2 + b^2).

Khi bạn đã tính toán độ lớn của từng hệ số FFT, bạn cần tìm ra tần số âm thanh mà mỗi hệ số FFT thuộc về. Một điểm F FFT sẽ cho bạn biết nội dung tần số của tín hiệu tại N tần số đều nhau, bắt đầu từ 0. Vì tần số lấy mẫu của bạn là 44100 mẫu/giây. và số điểm trong FFT của bạn là 256, khoảng cách tần số của bạn là 44100/256 = 172 Hz (khoảng)

Hệ số đầu tiên trong mảng của bạn sẽ là hệ số 0 tần số. Đó là cơ bản mức năng lượng trung bình cho tất cả các tần số. Phần còn lại của hệ số của bạn sẽ đếm từ 0 trong bội số của 172 Hz cho đến khi bạn nhận được đến 128. Trong một FFT, bạn chỉ có thể đo tần số lên đến một nửa số điểm mẫu của bạn. Đọc các liên kết này trên Nyquist FrequencyNyquist-Shannon Sampling Theorem nếu bạn là người ham muốn trừng phạt và cần biết lý do tại sao, nhưng kết quả cơ bản là tần số thấp hơn của bạn sẽ được nhân rộng hoặc aliased trong các nhóm tần số cao hơn.Vì vậy, các tần số sẽ bắt đầu từ 0, tăng 172 Hz cho mỗi hệ số lên đến hệ số N/2, sau đó giảm 172 Hz cho đến khi hệ số N-1.

Đó phải là đủ thông tin để bạn bắt đầu. Nếu bạn muốn giới thiệu nhiều hơn về FFTs hơn là được đưa ra trên Wikipedia, bạn có thể thử Understanding Digital Signal Processing: 2nd Ed.. Nó rất hữu ích cho tôi.

Vì vậy, đó là những gì những con số đó đại diện. Việc chuyển đổi thành phần trăm chiều cao có thể được thực hiện bằng cách nhân rộng từng cường độ thành phần tần số theo tổng của tất cả các độ lớn thành phần. Mặc dù, điều đó sẽ chỉ cung cấp cho bạn một đại diện của phân phối tần số tương đối, và không phải là công suất thực tế cho mỗi tần số. Bạn có thể thử mở rộng phạm vi tối đa có thể cho một thành phần tần số, nhưng tôi không chắc chắn rằng nó sẽ hiển thị rất tốt. Cách nhanh nhất để tìm một yếu tố mở rộng khả thi là thử nghiệm trên các tín hiệu âm thanh lớn và mềm để tìm cài đặt phù hợp.

Cuối cùng, bạn nên lấy trung bình hai kênh lại với nhau nếu bạn muốn hiển thị nội dung tần số của toàn bộ tín hiệu âm thanh. Bạn đang trộn âm thanh stereo thành âm thanh đơn âm và hiển thị tần số kết hợp. Nếu bạn muốn hai màn hình riêng biệt cho tần số phải và trái, thì bạn sẽ cần phải thực hiện biến đổi Fourier trên mỗi kênh riêng biệt.

+3

+1 cho câu trả lời tuyệt vời và làm cho tôi tìm hiểu một thành ngữ mới, như Tôi không phải là người nói tiếng Anh bản địa.;) – macbirdie

+1

+1 Tuyệt vời, điều này đã giúp tôi hiểu những gì tôi đã làm sai. – Davido

+4

+1 - Mặc dù tôi đã biết về FFTs - một trong những giải thích tiếng Anh đơn giản nhất trên web. – OldTinfoil

10

những gì bạn có là mẫu có thời lượng là 256/44100 = 0,00580499 giây. Điều này có nghĩa là độ phân giải tần số của bạn là 1/0.00580499 = 172 Hz. 256 giá trị bạn nhận được từ Python tương ứng với các tần số, về cơ bản, từ 86 Hz đến 255 * 172 + 86 Hz = 43946 Hz. Những con số bạn nhận ra là những con số phức tạp (vì thế chữ "j" ở cuối mỗi số thứ hai).

EDITED: CỐ ĐỊNH SAI THÔNG TIN

Bạn cần phải chuyển đổi các số phức vào biên độ bằng cách tính toán sqrt (i + j), nơi i và j là phần thực và phần ảo, resp.

Nếu bạn muốn có 32 thanh, bạn nên theo như tôi hiểu lấy trung bình của bốn biên độ liên tiếp, nhận được 256/4 = 32 thanh như bạn muốn.

+0

Xin chào, xin lỗi vì câu trả lời ban đầu (sai) ... đã không nhận được quyền tính toán. Điều này sẽ đúng ngay bây giờ. –

+4

Xin lưu ý rằng, nếu c là một số phức, sqrt (c.real ** 2 + c.imag ** 2) == abs (c) – tzot

25

Mặc dù chủ đề này là năm cũ, tôi thấy nó rất hữu ích. Tôi chỉ muốn cung cấp cho đầu vào của tôi cho bất cứ ai tìm thấy điều này và đang cố gắng để tạo ra một cái gì đó tương tự.

Đối với việc chia thành các thanh, điều này không nên được thực hiện như antti gợi ý, bằng cách chia dữ liệu bằng nhau dựa trên số lượng thanh. Điều hữu ích nhất là chia dữ liệu thành các phần quãng tám, mỗi quãng tám sẽ tăng gấp đôi tần số trước đó. (nghĩa là 100Hz là một quãng tám trên 50Hz, đó là một quãng tám trên 25Hz).

Tùy thuộc vào số lượng thanh bạn muốn, bạn chia toàn bộ dải ô thành các phạm vi octave 1/X. Dựa trên một tần số trung tâm nhất định của A trên quầy bar, bạn sẽ có được các giới hạn trên và dưới của thanh từ:

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

Để tính toán tiếp theo tần số trung tâm liền kề bạn sử dụng một tính toán tương tự:

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

Sau đó, bạn trung bình dữ liệu phù hợp với các phạm vi này để nhận được biên độ cho mỗi thanh.

Ví dụ: Chúng tôi muốn chia thành 1/3 quãng tám quãng và bắt đầu với tần số trung tâm là 1khz.

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

44100hz Do và 1024 mẫu (43hz giữa mỗi điểm dữ liệu) chúng ta nên trung bình ra khỏi giá trị 21 thông qua 26. (890,9/43 = 20,72 ~ 21 và 1122,5/43 = 26.10 ~ 26)

(1/3 thanh octave sẽ giúp bạn có được khoảng 30 thanh giữa ~ 40Hz và ~ 20khz). Như bạn có thể tìm ra ngay bây giờ, khi chúng tôi đi cao hơn, chúng tôi sẽ trung bình một phạm vi số lớn hơn. Các thanh thấp thường chỉ bao gồm 1 hoặc một số lượng nhỏ các điểm dữ liệu. Trong khi các thanh cao hơn có thể là trung bình của hàng trăm điểm. Lý do là 86Hz là một quãng tám trên 43Hz ... trong khi 10086hz âm thanh gần như giống như 10043Hz.