from scipy import signal
from scipy import fftpack
import numpy as np
import matplotlib.pyplot as plt
# オーバーラップ処理
def ov(data, samplerate, Fs, overlap):
Ts = len(data) / samplerate # 全データ長
Fc = Fs / samplerate # フレーム周期
x_ol = Fs * (1 - (overlap / 100)) # オーバーラップ時のフレームずらし幅
N_ave = int((Ts - (Fc * (overlap / 100))) / (Fc * (1 - (overlap / 100)))) # 抽出するフレーム数(平均化に使うデータ個数)
array = [] # 抽出したデータを入れる空配列の定義
# forループでデータを抽出
for i in range(N_ave):
ps = int(x_ol * i) # 切り出し位置をループ毎に更新
array.append(data[ps:ps + Fs:1]) # 切り出し位置psからフレームサイズ分抽出して配列に追加
return array, N_ave # オーバーラップ抽出されたデータ配列とデータ個数を戻り値にする
# 窓関数処理(ハニング窓)
def hanning(data_array, Fs, N_ave):
han = signal.hann(Fs) # ハニング窓作成
acf = 1 / (sum(han) / Fs) # 振幅補正係数(Amplitude Correction Factor)
# オーバーラップされた複数時間波形全てに窓関数をかける
for i in range(N_ave):
data_array[i] = data_array[i] * han # 窓関数をかける
return data_array, acf
# FFT処理
def fft_ave(data_array, samplerate, Fs, N_ave, acf):
fft_array = []
for i in range(N_ave):
fft_array.append(acf * np.abs(fftpack.fft(data_array[i]) / (Fs / 2))) # FFTをして配列に追加、窓関数補正値をかけ、(Fs/2)の正規化を実施。
fft_axis = np.linspace(0, samplerate, Fs) # 周波数軸を作成
fft_array = np.array(fft_array) # 型をndarrayに変換
fft_mean = np.mean(fft_array, axis=0) # 全てのFFT波形の平均を計算
return fft_array, fft_mean, fft_axis
# 波形生成
samplerate = 25600
x = np.arange(0, 12800)/samplerate
data = signal.sawtooth(2 * np.pi * 50 * x)
Fs = 4096 # フレームサイズ
overlap = 75 # オーバーラップ率
# 作成した関数を実行:オーバーラップ抽出された時間波形配列
time_array, N_ave = ov(data, samplerate, Fs, overlap)
# 作成した関数を実行:ハニング窓関数をかける
time_array, acf = hanning(time_array, Fs, N_ave)
# 作成した関数を実行:FFTをかける
fft_array, fft_mean, fft_axis = fft_ave(time_array, samplerate, Fs, N_ave, acf)
# ここからグラフ描画
# フォントの種類とサイズを設定する。
plt.rcParams['font.size'] = 14
plt.rcParams['font.family'] = 'Times New Roman'
# 目盛を内側にする。
plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['ytick.direction'] = 'in'
# グラフの上下左右に目盛線を付ける。
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.yaxis.set_ticks_position('both')
ax1.xaxis.set_ticks_position('both')
ax2 = fig.add_subplot(212)
ax2.yaxis.set_ticks_position('both')
ax2.xaxis.set_ticks_position('both')
ax2.set_xticks(np.arange(0, samplerate, 200))
ax2.set_xlim(0, 1000)
ax2.set_yscale('log')
# 軸のラベルを設定する。
ax1.set_xlabel('Time [s]')
ax1.set_ylabel('y')
ax2.set_xlabel('Frequency [Hz]')
ax2.set_ylabel('y')
# データプロットの準備とともに、ラベルと線の太さ、凡例の設置を行う。
ax1.plot(x, data, label='sawtooth', lw=1)
ax2.plot(fft_axis, fft_mean, label='sawtooth', lw=1)
# レイアウト設定
fig.tight_layout()
# グラフを表示する。
plt.show()
plt.close()
コメント