第4回目の解説では、第2回で作成した音声データを
実際にスピーカーから出力して
それを内臓のマイクで録音して比較を行います。
その前に、FFT(フーリエ変換),IFFT(逆フーリエ変換)について説明します。
##2成分Sin波形の作成
import numpy as np
import matplotlib.pyplot as plt
#n_channels = 1
a1, a2 = 0.4, 0.6 #amplitude
f1, f2 = 10.0, 100.0 #frequency
framerate = 44100
sampwidth = 2 #16bit
total_secs = 2
data_num = int(total_secs * framerate)
t = np.linspace(0, total_secs, data_num)
wav = 32767 * a1 * (np.sin(np.pi*f1*t)) + 32767 * a2 * (np.sin(np.pi*f2*t))
plt.plot(t,wav)
plt.show()
##FFT(フーリエ変換)
freq = np.linspace(0,framerate*2, data_num)
f = np.fft.fft(wav)
f_abs = np.abs(f)
plt.plot(freq[:int(framerate/200)+1], f_abs[:int(framerate/200)+1])
plt.show()
指定した周波数、10[Hz]と100[Hz]において
スペクトルを観測できたことがわかります。
基本周波数を変えてみたり、トータル時間を変えても正しく表示されることを確認してください。
##注意点
パラメータ(total_secs)を2から3に変更してみましょう。
total_secs = 3 #2から3に変更
すると、FFT結果が以下のようになります。
100[Hz]は正しく、スペクトルを観察できていますが
15[Hz]はスペクトルがぼやけています。これはプログラムが間違っているのではなく
FFTの計算過程上発生してしまう数学的な問題となります。
高速フーリエ変換(FFT)は変換元の波形が繰り返し発生しているという前提で算出しているためです。
そのため、入力するサンプル数Nの測定データが、0番目とN番目で連続していない場合、高速フーリエ変換すると、本来含まれていないスペクトル(ノイズ)も出現し、周波数特性を解析しにくくなります。
わかりやすく、15[Hz]だけの信号としました。
この波形が繰り返されているということを前提でFFTしています。
何かおかしいこと気づきましたか?
この波形は凸から始まって、最後に凸で終わっています。
これでは、本来の凸凹という波形ではないため
FFTが思ったように実行されていません。
一見、0で終わっているため問題ないと思う場合もあるかもしれませんが
注意が必要です。
そこで窓関数を用います。(窓関数にはハニング窓、ハミング窓、ブラックマン窓があります)
window_hn = np.hanning(data_num)
元のサイン波形に窓関数をかけてみましょう。
wav_hnd = window_hn * wav
f_hnd = np.fft.fft(wav_hnd)
f_abs_hnd = np.abs(f_hnd)
plt.plot(freq[:int(framerate/100)+1], f_abs_hnd[:int(framerate/100)+1])
plt.show()
では、解析の準備ができたので次から
MacBook(M1)のスピーカから発生させた音声を
内臓のマイクを用いて録音してスピーカーの周波数特性の観察をしてみましょう。