夏バテで酸っぱいものばかり食べてます。ko_ya346です。
最近はもずく酢がお気に入り。
再生中の楽曲に合わせてスペクトルがうねうねするあれ。
フーリエ変換の勉強の息抜きにpythonで作ってみました。
コードは下の参考記事そのまんまです。
import wave import numpy as np import pyaudio import pyqtgraph as pg from pyqtgraph.Qt import QtGui, QtCore def spectrumAnalyzer(filename): chunk = 1024 signal_scale = 1 #wavファイル読み込み wf = wave.open(filename, "r") fs = wf.getframerate() #ハミング窓設定(なぜかchunkを2倍にしないとエラーが出た) hammingWindow = np.hamming(chunk*2) #再生用 p = pyaudio.PyAudio() stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), channels=wf.getnchannels(), rate=wf.getframerate(), output=True) # ======== # Layout # ======== ### アプリケーション作成 app = QtGui.QApplication([]) app.quitOnLastWindowClosed() ### メインウィンドウ mainWindow = QtGui.QMainWindow() mainWindow.setWindowTitle("Spectrum Analyzer") # Title mainWindow.resize(800, 300) # Size ### キャンパス centralWid = QtGui.QWidget() mainWindow.setCentralWidget(centralWid) ### レイアウト!! lay = QtGui.QVBoxLayout() centralWid.setLayout(lay) ### スペクトル表示用ウィジット specWid = pg.PlotWidget(name="spectrum") specItem = specWid.getPlotItem() specItem.setMouseEnabled(y=True) # y軸方向に動かせなくする specItem.setYRange(0, 200) specItem.setXRange(0, chunk/2, padding=0) ### Axis specAxis = specItem.getAxis("bottom") specAxis.setLabel("Frequency [Hz]") specAxis.setScale(fs/2./(chunk/2+1)) hz_interval = 1000 newXAxis = (np.arange(int(fs/2/hz_interval))+1) * hz_interval oriXAxis = newXAxis/(fs/2./(chunk/2+1)) specAxis.setTicks([zip(oriXAxis, newXAxis)]) ### キャンパスにのせる lay.addWidget(specWid) ### ウィンドウ表示 mainWindow.show() #chunk単位でサンプリング x = wf.readframes(chunk) while True: #再生 stream.write(x) data = np.frombuffer(x, dtype="int16")/32768.0 if len(data) < chunk*2: exit() #切り出した波形データ wind_data = hammingWindow*data #FFT変換 fftspec = np.fft.fft(wind_data) #グラフ出力 specItem.plot(abs(fftspec*signal_scale), clear=True) QtGui.QApplication.processEvents() #次のchunkを読み込む x = wf.readframes(chunk) stream.close() p.terminate()
この関数にwavファイルを渡すと実行できます。
pyaudioはpython 3.7以降では使用出来ない?ようなのでご注意ください。知らなかったので環境構築時にかなり時間を溶かしました。
while内では
・wavファイルをchunk単位で呼び出す
・データを再生用の関数に渡す
・データを窓関数を通してFFT変換
・スペクトルを出力
の4つの仕事をしています。
numpyの機能を呼び出すだけなのでむっちゃ楽ですね。
とりあえず動いたんですが、肝心のFFTはイマイチ理解出来てないのでもう少し勉強します…
下の資料がとても分かりやすい。
www.ic.is.tohoku.ac.jp
あとオススメの参考書があれば是非教えてください。