TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

FFTとエネルギーについての考察(続き)

前回の続きです。

周辺のパワースペクトルの和を測ることで、周波数分解能の整数倍とのずれの影響をどれだけ抑えることができるか調べた。

周辺3つのパワースペクトルの和をとった場合のピークの値を、400Hzから500Hzの間を0.1Hz間隔で調べた結果、以下のようになった。

peaks = []
fset = np.linspace(400, 500, 1001)
for f in fset:
	y = np.sin(2 * np.pi * f * t)
	Y = np.fft.fft(y)
	P = abs(Y)**2
	P_around = np.convolve(P, np.ones(3)/3, 'valid')
	peaks.append(max(P_around))
plt.plot(fset, peaks)
plt.axis([400, 500, 0, 1500000])
plt.show()

※後の説明と比較できるように、和をとるパワースペクトルの数で割って移動平均としている。
f:id:TadaoYamaoka:20160831212828p:plain
最大値と最小値の差は1.16倍となり、FFTの値でピークを測定した場合が1.57倍であったのに比べて、周波数分解能の整数倍とのずれの影響を抑えられている。

最小値 1196968.76
最大値 1398278.11 最小値の1.16倍


次に、周辺のパワースペクトルの5つの和をとった場合は、以下のようになった。

peaks = []
fset = np.linspace(400, 500, 1001)
for f in fset:
	y = np.sin(2 * np.pi * f * t)
	Y = np.fft.fft(y)
	P = abs(Y)**2
	P_around = np.convolve(P, np.ones(5)/5, 'valid')
	peaks.append(max(P_around))
plt.plot(fset, peaks)
plt.axis([400, 500, 0, 1500000])
plt.show()

f:id:TadaoYamaoka:20160831213019p:plain
最大値と最小値の差は1.09倍となり、周波数分解能の整数倍とのずれの影響がほとんど抑えられている。

最小値 769718.54
最大値 839028.74 最小値の1.09倍

ただし、周辺5つの和を取ることで、周波数分解能(44.1kHz/4096=10.76Hz)の5倍の範囲(53.83Hz)の影響を受けることになるため、解析したい対象によっては注意が必要そうである。
単音の音声データを解析する場合でも、C1(32.7Hz)~B1(61.7Hz)あたりの低音では、1オクターブ上の音階と範囲が重複するので、周辺5つの和では期待する結果は得られないと思われる。
倍音にかぶらない範囲で選ぶと、周辺3つ(32.29Hz)くらいの範囲が適切ではないかと思う。


有益な検証結果が得られたので、これを使ってアプリの精度を改良してみたい。