파이썬에서 스펙트로 그램 해상도를 향상 시킵니까?


21

파이썬에서 음성 웨이브 파일의 스펙트로 그램을 생성하기 위해 specgram()함수를 사용하고 matplotlib있지만 출력은 항상 필사 표준 소프트웨어 인 Praat이 생성 할 수있는 품질보다 열등합니다. 예를 들어 다음과 같은 호출이 있습니다.

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

이것을 생성합니다 :

여기에 이미지 설명을 입력하십시오

Praat 동안 다음 설정을 사용하여 동일한 오디오 샘플에서 작업합니다.

  • 보기 범위 : 0-8000Hz
  • 창 길이 : 0.005s
  • 다이나믹 레인지 : 70dB
  • 시간 단계 : 1000
  • 주파수 단계 : 250
  • 창 모양 : 가우스

이것을 생성합니다 :

여기에 이미지 설명을 입력하십시오

내가 무엇을 잘못하고 있지? 모든 specgram()매개 변수를 다루려고했지만 해상도를 향상시키는 것은 없습니다. FFT에 대한 경험이 거의 없습니다.


시도한 matplotlib.specgram 매개 변수 구성의 예를 제공 할 수 있습니까? Praat에 대한 매개 변수의 매우 구체적인 예를 제공하지만 matplotlib.specgram에 대해 동일한 구성을 표시하지 않습니까?
Christopher Felton

답변:


11

다음은 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)

질문 설명에 제공된 매개 변수는 비슷한 mpl.specgram 매개 변수로 변환해야합니다. 다음은 매핑의 예입니다.

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

8ms를 사용하면 2FFT (128)의 거듭 제곱이됩니다. 다음은 웹 사이트의 Praat 설정에 대한 설명입니다

보기 범위 (Hz) : 표시 할 주파수 범위. 표준은 하단이 0Hz이고 상단이 5000Hz입니다. 이 최대 주파수가 사운드의 나이키 스트 주파수 (샘플링 주파수의 절반)보다 높으면 스펙트로 그램의 일부 값이 0이되고 높은 주파수는 흰색으로 표시됩니다. 44100Hz에서 사운드를 녹음하고보기 범위를 0Hz에서 25000Hz로 설정하면이 정보를 볼 수 있습니다.

창 길이 : 분석 창의 기간. 이 값이 0.005 초 (표준) 인 경우, Praat은 각 프레임에 대해 해당 프레임 중심에서 0.0025 초 전과 0.0025 초 사이에있는 사운드 부분을 사용합니다 (가우시안 윈도우의 경우 Praat는 실제로 그보다 조금 더 많이 사용함). 창 길이는 스펙트럼 분석의 대역폭, 즉 순수한 사인파의 스펙트로 그램에서 수평선의 너비를 결정합니다 (아래 참조). 가우스 윈도우의 경우 -3dB 대역폭은 2 * sqrt (6 * ln (2)) / (π * Window length) 또는 1.2982804 / Window length입니다. broad-band' spectrogram (bandwidth 260 Hz), keep the standard window length of 5 ms; to get a협 대역 스펙트로 그램 (대역폭 43Hz) 을 얻으려면 30ms (0.03 초)로 설정하십시오. 다른 창 모양은 약간 다른 값을 제공합니다.

다이나믹 레인지 (dB) : 다이나믹 레인지 dB보다 최대 값 이하인 모든 값은 (아마도 다이나믹 압축 후, 고급 스펙트로 그램 설정 ... 참조) 흰색으로 표시됩니다. 사이의 값은 적절한 회색 음영을 갖습니다. 따라서 스펙트로 그램에서 가장 높은 피크의 높이가 30dB / Hz이고 동적 범위가 50dB (표준 값)이면 -20dB / Hz 미만의 값은 흰색으로 표시되고 그 사이의 값은 -20 dB / Hz 및 30 dB / Hz가 다양한 회색 음영으로 그려집니다.

Praat 설정에 연결

OP의 질문은 Praat specgram과 mpl (matplotlib) specgram의 명암 차이에 관한 것일 수 있습니다. Praat에는 명암에 영향을주는 다이나믹 레인지 설정이 있습니다. mpl 기능은 비슷한 설정 / 파라미터가 없습니다. mpl.specgram은 다이나믹 레인지가 리턴 배열에 적용되어 다시 표시 될 수있는 2D 전력 레벨 배열 (스펙트로 그램)을 반환합니다.

다음은 아래 그림을 작성하는 코드 스 니펫입니다. 예는 20Hz-8000Hz의 처프가있는 ~ 1m15s 음성입니다.

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
이것에 대해 조금 더 생각해 보면, Praat "Dynamic Range"파라미터가 플롯의 모양 차이에 대한 주요 요인 일 수 있습니다. Praat "동적 범위"는 범위를 제한하여 (압축) 플롯에서 더 큰 대비를 얻을 수 있습니다. BOMK MPL에는 비슷한 기능이 없지만 추가 할 수 있습니다.
Christopher Felton

6

시간 / 주파수 해상도 문제인 것 같습니다. Praat 플롯의 주파수 분해능이 더 좋지 않고 (고조파를 명확하게 볼 수조차 없음) 시간 분해능이 더 좋습니다. 창 크기 (NFFT)를 16000 x 0.05 = 80 샘플로 줄이십시오. pad_to (128 또는 256)에서 2의 더 큰 제곱을 사용하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.