科学計算ライブラリ「numpy」を用いて、waveファイルの情報から高速フーリエ変換(FFT)による周波数解析を行います。C#でのFFTは既に「C#によるWaveデータのFFT処理」で行いました。今回は「SPH0645LM4H搭載 I2S MEMSマイクを使ってRaspberry Pi 3で録音」で録音したwaveファイルを用いて、pythonの科学計算ライブラリ「numpy」を使用します。
周波数解析プログラムの作成
周波数解析プログラム「fftmodule.py」を次に示します。
- 28行目で1フレーム4バイトのため、「dtype= “int32″」として、-1~1に正規化します。
- 32行目で高速フーリエ変換を行います。
- 35行目で周波数解析した周波数リストを取得します。
- 39-43行目で波形サンプル画面を描画します。
- 46-50行目で振幅スペクトルを描画します。
fftmodule.py
# -*- coding: utf-8 -*- import wave import numpy as np import matplotlib.pyplot as plt def main(): filename = "mic500hz.wav" wf = wave.open(filename, "r" ) # WAVファイルの情報を表示 print ("オーディオチャンネル数(モノラル: 1 ステレオ:2 ) : ", wf.getnchannels()) print ("サンプルサイズ(バイト数) : ", wf.getsampwidth()) print ("サンプリングレート : ", wf.getframerate()) print ("オーディオフレーム数 : ", wf.getnframes()) print ("圧縮形式 : ", wf.getcomptype()) print ("(圧縮形式) : ", wf.getcompname()) print ("パラメータ : ", wf.getparams()) print ("記録時間(Sec) : ", float(wf.getnframes()) / wf.getframerate() ) fs = wf.getframerate() # サンプリング周波数 g = wf.readframes(wf.getnframes()) print('00: {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X} - {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X}\n'. format(g[0],g[1],g[2],g[3],g[4],g[5],g[6],g[7],g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15])) print('10: {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X} - {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X}\n'. format(g[16],g[17],g[18],g[19],g[20],g[21],g[22],g[23],g[24],g[25],g[26],g[27],g[28],g[29],g[30],g[31])) print('10: {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X} - {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X}\n'. format(g[32],g[33],g[34],g[35],g[36],g[37],g[38],g[39],g[40],g[41],g[42],g[43],g[44],g[45],g[46],g[47])) g = np.frombuffer(g, dtype= "int32")/2147483648.0 # -1~1に正規化 wf.close() n0 = 168912 # サンプリング開始位置 N = 4096 # サンプル数 G = np.fft.fft(g[n0:n0+N]) # 高速フーリエ変換 amp = [np.sqrt(c.real ** 2 + c.imag ** 2) for c in G] # 振幅スペクトル phase = [np.arctan2(int(c.imag), int(c.real)) for c in G] # 位相スペクトル flist = np.fft.fftfreq(N, d=1.0/fs) # 周波数リスト # 波形サンプルを描画 plt.figure("FFT解析 "+filename,figsize=(12,7)) plt.subplot(211) plt.plot(range(n0, n0+N), g[n0:n0+N]) plt.axis([n0, n0+N, -0.2, 0.2]) plt.xlabel("Time [sample]") plt.ylabel("Amplitude") # 振幅スペクトルを描画 plt.subplot(212) plt.plot(flist, amp, marker='o', linestyle='-') plt.axis([0, fs/2, 0, 15]) plt.xlabel("Frequency [Hz]") plt.ylabel("Amplitude spectrum") plt.show() if __name__ == '__main__': main()
周波数解析プログラムの実行
作成した周波数解析プログラム「fftmodule.py」を次のコマンドで実行します。
$ python3 fftmodule.py オーディオチャンネル数(モノラル: 1 ステレオ:2 ) : 1 サンプルサイズ(バイト数) : 4 サンプリングレート : 48000 オーディオフレーム数 : 479232 圧縮形式 : NONE (圧縮形式) : not compressed パラメータ : _wave_params(nchannels=1, sampwidth=4, framerate=48000, nframes=479232, comptype='NONE', compname='not compressed') 記録時間(Sec) : 9.984 00: 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 10: 0 0 0 0 0 80 61 B - 0 0 5 E7 0 80 2 FA 10: 0 80 2 FA 0 C0 2 FA - 0 C0 5 FA 0 0 9 FA
画面に表示された周波数解析結果を次に示します。
周波数解析結果の500Hz近辺を拡大表示します。