Cải thiện độ phân giải phổ trong Python?


21

Tôi đang sử dụng specgram()chức năng này matplotlibđể tạo ra các phổ của các tệp sóng giọng nói trong Python, nhưng đầu ra luôn có chất lượng kém hơn nhiều so với những gì phần mềm sao chép thông thường của tôi, Praat, có thể tạo ra. Ví dụ: cuộc gọi sau:

specgram(
    fromstring(spf.readframes(-1), 'Int16'),
    Fs=framerate,
    cmap=cm.gray_r,
)

Tạo ra điều này:

nhập mô tả hình ảnh ở đây

Trong khi Praat, làm việc trên cùng một mẫu âm thanh với các cài đặt sau:

  • Phạm vi xem: 0-8000Hz
  • Chiều dài cửa sổ: 0,005s
  • Dải động: 70dB
  • Các bước thời gian: 1000
  • Các bước tần số: 250
  • Hình dạng cửa sổ: Gaussian

Tạo ra điều này:

nhập mô tả hình ảnh ở đây

Tôi đang làm gì sai? Tôi đã thử thay đổi tất cả các specgram()tham số, nhưng dường như không có gì cải thiện độ phân giải. Tôi hầu như không có kinh nghiệm với FFT.


Bạn có thể cung cấp ví dụ về các cấu hình tham số matplotlib.specgram mà bạn đã thử không? Bạn đưa ra một ví dụ rất cụ thể về các tham số cho Praat nhưng không hiển thị cùng cấu hình cho matplotlib.specgram?
Christopher Felton

Câu trả lời:


11

Dưới đây là các tham số matplotlib.specgram

matplotlib.mlab.specgram(x, 
                         NFFT=256, 
                         Fs=2, 
                         detrend=<function detrend_none at 0x1dd6410>, 
                         window=<function window_hanning at 0x1e0b1b8>, 
                         noverlap=128, 
                         pad_to=None, 
                         sides='default', 
                         scale_by_freq=None)

Các tham số được cung cấp trong mô tả câu hỏi cần được chuyển đổi thành các tham số mpl.specgram tương đương. Sau đây là một ví dụ về ánh xạ:

View range: 0-8000Hz            Fs=16000
Window length: 0.005s           NFFT = int(Fs*0.005) = 80
                                noverlap = int(Fs*0.0025) = 40
Dynamic range: 70dB             n/a
Time steps: 1000                n/a
Frequency steps: 250            
Window shape: Gaussian          default window is hanning change to gaussian

Nếu bạn sử dụng 8ms, bạn sẽ nhận được sức mạnh là 2 FFT (128). Sau đây là mô tả về cài đặt Praat từ trang web của họ

Xem phạm vi (Hz) : phạm vi tần số sẽ hiển thị. Tiêu chuẩn là 0 Hz ở phía dưới và 5000 Hz ở phía trên. Nếu tần số tối đa này cao hơn tần số Nyquist của Âm thanh (bằng một nửa tần số lấy mẫu của nó), một số giá trị trong biểu đồ phổ sẽ bằng 0 và tần số cao hơn sẽ được vẽ bằng màu trắng. Bạn có thể thấy điều này nếu bạn ghi lại Âm thanh ở mức 44100 Hz và đặt phạm vi xem từ 0 Hz đến 25000 Hz.

Chiều dài cửa sổ : thời lượng của cửa sổ phân tích. Nếu đây là 0,005 giây (tiêu chuẩn), Praat sử dụng cho mỗi khung hình một phần âm thanh nằm trong khoảng từ 0,0025 giây trước và 0,0025 giây sau trung tâm của khung đó (đối với cửa sổ Gaussian, Praat thực sự sử dụng nhiều hơn một chút). Độ dài cửa sổ xác định băng thông của phân tích quang phổ, tức là độ rộng của đường ngang trong biểu đồ phổ của sóng hình sin thuần túy (xem bên dưới). Đối với cửa sổ Gaussian, băng thông -3 dB là 2 * sqrt (6 * ln (2)) / (π * Chiều dài cửa sổ) hoặc 1.2982804 / Chiều dài cửa sổ. Để có được broad-band' spectrogram (bandwidth 260 Hz), keep the standard window length of 5 ms; to get aphổ tần số hẹp (băng thông 43 Hz), hãy đặt thành 30 ms (0,03 giây). Các hình dạng cửa sổ khác cho giá trị hơi khác nhau.

Phạm vi động (dB) : Tất cả các giá trị lớn hơn Phạm vi động dưới mức tối đa (có lẽ sau khi nén động, xem Cài đặt phổ phổ nâng cao ...) sẽ được vẽ bằng màu trắng. Các giá trị ở giữa có các màu xám thích hợp. Do đó, nếu đỉnh cao nhất trong phổ phổ có độ cao 30 dB / Hz và dải động là 50 dB (là giá trị tiêu chuẩn), thì các giá trị dưới -20 dB / Hz sẽ được vẽ bằng màu trắng và các giá trị nằm giữa -20 dB / Hz và 30 dB / Hz sẽ được vẽ bằng nhiều màu xám khác nhau.

Liên kết đến cài đặt Praat

Câu hỏi của OP có thể liên quan đến sự khác biệt tương phản giữa sơ đồ Praat và sơ đồ mpl (matplotlib). Praat có cài đặt Dải động ảnh hưởng đến độ tương phản. Hàm mpl không có cài đặt / tham số tương tự. Mpl.specgram không trả về mảng 2D của các mức công suất (biểu đồ phổ), dải động có thể được áp dụng cho mảng trả về và được vẽ lại.

Sau đây là đoạn mã để tạo các ô bên dưới. Ví dụ là bài phát biểu ~ 1m15 với tiếng kêu từ 20Hz-8000Hz.

import numpy
import pylab
import wave
import array
pylab.close('all')
w1 = wave.open('example_no_noise.wav')
w2 = wave.open('example_noise.wav')
# hmmm, probably a better way to do this, scipy.io function?
x1 = numpy.array(array.array('h', w1.readframes(w1.getnframes())))
x2 = numpy.array(array.array('h', w2.readframes(w2.getnframes())))
x1 = x1 / (2.**(16-1))  # normalize
x2 = x2 / (2.**(16-1))  # normalize
Fs = 16000.
NFFT = int(Fs*0.005)  # 5ms window
noverlap = int(Fs*0.0025)
pylab.figure(1)
pylab.specgram(x1, NFFT=NFFT, Fs=Fs, noverlap=noverlap, 
               cmap=pylab.get_cmap('Greys'))
pylab.title('Full 1m15s example min noise')
pylab.figure(2)
pylab.specgram(x2, NFFT=NFFT, Fs=Fs, noverlap=noverlap, 
               cmap=pylab.get_cmap('Greys'))
pylab.title('Full 1m15s example more noise')
pylab.figure(3); n=2100*176;
pylab.specgram(x2[n:n+256*256], NFFT=NFFT, Fs=Fs, noverlap=noverlap, 
               cmap=pylab.get_cmap('Greys'))
pylab.title('Full ~4s example min noise')
pylab.figure(4); pylab.plot(x1[n:n+256*256])


1
Nghĩ về điều này nhiều hơn một chút, tham số "Phạm vi động" của Praat có thể là yếu tố chính cho sự khác biệt trong cách nhìn của các ô. "Phạm vi động" của Praat có thể giới hạn phạm vi (nén) để bạn có được độ tương phản lớn hơn trong cốt truyện. BOMK MPL không có tính năng tương tự nhưng có thể được thêm vào.
Christopher Felton

6

Nó dường như là một vấn đề độ phân giải thời gian / tần số. Biểu đồ Praat của bạn có độ phân giải tần số kém hơn (thậm chí bạn không thể nhìn rõ sóng hài) và độ phân giải thời gian tốt hơn. Hãy thử giảm kích thước cửa sổ (NFFT) xuống 16000 x 0,05 = 80 mẫu. Tôi khuyên bạn nên sử dụng công suất lớn hơn là 2 trong pad_to (128 hoặc 256).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.