これが私がやりたいことです。その.wavファイルの1ミリ秒ごとに.wavファイルのオーディオ周波数と振幅を見つけて、ファイルに保存したいと思います。周波数と振幅をグラフ化し、時間の経過に伴う振幅をグラフにしましたが、時間の経過とともに周波数を把握できません。私の最終的な目標は、ファイルを読み取り、それらの振幅を使用して変数を調整し、どの変数が使用されているかをトリガーする頻度を使用できるようにすることです。これは簡単な部分のようです。私はnumpy、audiolab、matplotlibなどを使用してきました... FFTを使用していますが、これを理解することはできません。ありがとう!
1 に答える
スペクトログラムを推定するには、ウィンドウが重なっているSTFTを使用します。自分でロールする手間を省くために、Matplotlibのmlabのspecgramメソッドを使用できます。オーディオがほぼ静止している十分に小さいウィンドウを使用することが重要です。一般的な基数2fftを効率的に使用するには、バッファサイズを2の累乗にする必要があります。512サンプル(48kspsで約10.67ms、またはビンあたり93.75 Hz)で十分です。サンプリングレートが48kspsの場合、1ミリ秒ごとにスライディングウィンドウを評価するために464サンプルをオーバーラップします(つまり、48サンプルずつシフトします)。
編集:
mlab.specgram
これは、2kHzから16kHzまでの1秒あたり1トーンの8秒信号を使用する例です。過渡時の応答に注意してください。応答をより詳細に表示するために、4秒でズームインしました。周波数は正確に4秒でシフトしますが、トランジェントが通過するのにバッファ長(512サンプル;約+/- 5 ms)がかかります。これは、非定常遷移がバッファを通過するときに発生するスペクトル/時間スミアの種類を示しています。さらに、信号が静止している場合でも、データのウィンドウ処理によって引き起こされるスペクトル漏れの問題があることがわかります。漏れのサイドローブを最小限に抑えるためにハミングウィンドウ関数が使用されましたが、これによりメインローブも広がります。
import numpy as np
from matplotlib import mlab, pyplot
#Python 2.x:
#from __future__ import division
Fs = 48000
N = 512
f = np.arange(1, 9) * 2000
t = np.arange(8 * Fs) / Fs
x = np.empty(t.shape)
for i in range(8):
x[i*Fs:(i+1)*Fs] = np.cos(2*np.pi * f[i] * t[i*Fs:(i+1)*Fs])
w = np.hamming(N)
ov = N - Fs // 1000 # e.g. 512 - 48000 // 1000 == 464
Pxx, freqs, bins = mlab.specgram(x, NFFT=N, Fs=Fs, window=w,
noverlap=ov)
#plot the spectrogram in dB
Pxx_dB = np.log10(Pxx)
pyplot.subplots_adjust(hspace=0.4)
pyplot.subplot(211)
ex1 = bins[0], bins[-1], freqs[0], freqs[-1]
pyplot.imshow(np.flipud(Pxx_dB), extent=ex1)
pyplot.axis('auto')
pyplot.axis(ex1)
pyplot.xlabel('time (s)')
pyplot.ylabel('freq (Hz)')
#zoom in at t=4s to show transient
pyplot.subplot(212)
n1, n2 = int(3.991/8*len(bins)), int(4.009/8*len(bins))
ex2 = bins[n1], bins[n2], freqs[0], freqs[-1]
pyplot.imshow(np.flipud(Pxx_dB[:,n1:n2]), extent=ex2)
pyplot.axis('auto')
pyplot.axis(ex2)
pyplot.xlabel('time (s)')
pyplot.ylabel('freq (Hz)')
pyplot.show()