前回の続きです。
周辺のパワースペクトルの和を測ることで、周波数分解能の整数倍とのずれの影響をどれだけ抑えることができるか調べた。
周辺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()
※後の説明と比較できるように、和をとるパワースペクトルの数で割って移動平均としている。
最大値と最小値の差は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()
最大値と最小値の差は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)くらいの範囲が適切ではないかと思う。
有益な検証結果が得られたので、これを使ってアプリの精度を改良してみたい。