フーリエ変換とは何か
波形・信号の処理ではフーリエ変換がよく使われる。 コンピュータによる変換では高速フーリエ変換(FFT: Fast Fourier Transform)、離散フーリエ変換が使われる。 具体的には音楽や写真のフィルター処理などで使われている。 以下ものすごくざっくりに説明する。
音の分析を例に挙げる。
ド、レ、ミの音の波形を以下に示す。
これらの音を同時に鳴らすと音楽でいうCコードになるが、これは物理的には3つの波を重ね合わせることに等しい。 重ね合わせた波は以下のようになる。
さて、今回はド、レ、ミの音を重ね合わせるとしているので、この波はド、レ、ミの音の周波数成分を持っている。
これをフーリエ変換すると以下のような出力が得られる。 261.63 , 330.0 , 391.1 のところの波が立っている(ピークが得られている)。
このようなグラフを周波数スペクトルという。
つまりフーリエ変換によって上記の重ね合わせた音はド、レ、ミの音で構成されていることがわかる(ド、レ、ミの音の周波数はそれぞれ261.63 , 330.0 , 391.1 )。
フーリエ変換によって任意の波形からその波形を構成する周波数成分を取り出すことができる。
適当にピアノで鳴らした音を録音してコンピュータでフーリエ変換することによってその構成音を調べることができる。
またこの逆変換もできることができる(フーリエ逆変換という)。 この変換では周波数成分のグラフから波形を復元することができる。
あるノイズを含んだ音源を録音したとしよう。 その音源をフーリエ変換すると周波数スペクトルが得られる。 ノイズは高周波成分が多いので、上記で得られたスペクトルを加工してある一定よりも高い周波数成分を0にしてやる。 この加工したスペクトルをフーリエ逆変換してやることによって、ノイズを除去した音源を得ることができる。 このようにして音声のノイズ処理が行われる。 画像処理についても同様のことが言える。
以下に上記のグラフを作成したPythonコードをのせておく。
import numpy as np
from matplotlib import pyplot as plt
import matplotlib_fontja # 追加
### 量子化(離散化) ###
f_s = 44100 # サンプリングレート f_s[Hz] (任意)
t_fin = 1 # 収録終了時刻 [s] (任意)
dt = 1 / f_s # サンプリング周期 dt[s]
N = int(f_s * t_fin) # サンプル数 [個]
### 入力信号 y(t) ###
f0 = 261.63 # 周波数 f0[Hz] ドの音
t = np.arange(0, t_fin, dt) # 離散時間 t[s]
y = np.sin(2 * np.pi * f0 * t) # y(t) を生成
f1 = 330 # 周波数 f1[Hz] ミの音
y1 = np.sin(2 * np.pi * f1 * t) # y(t) を生成
f2 = 391.1 # 周波数 f2[Hz] ソの音
y2 = np.sin(2 * np.pi * f2 * t) # y(t) を生成
y_all = y + y1 + y2
### 3つの信号を縦に並べてプロット ###
fig, axs = plt.subplots(3, 1, figsize=(10, 8))
axs[0].plot(t, y)
axs[0].set_xlim(0, 10 * 10**-3)
axs[0].set_title("ドの音の波形")
axs[0].set_xlabel("時間 [s]")
axs[0].set_ylabel("振幅")
axs[1].plot(t, y1)
axs[1].set_xlim(0, 10 * 10**-3)
axs[1].set_title("ミの音の波形")
axs[1].set_xlabel("時間 [s]")
axs[1].set_ylabel("振幅")
axs[2].plot(t, y2)
axs[2].set_xlim(0, 10 * 10**-3)
axs[2].set_title("ソの音の波形")
axs[2].set_xlabel("時間 [s]")
axs[2].set_ylabel("振幅")
plt.tight_layout()
plt.show()
### 3つの信号を足し合わせた波形 ###
plt.figure(figsize=(10, 4))
plt.plot(t, y_all)
plt.xlim(0, 10 * 10**-3)
plt.title("3つの音の波形")
plt.xlabel("時間 [s]")
plt.ylabel("振幅")
plt.show()
## FFT
### FFT: tの関数をfの関数にする ###
y_fft = np.fft.fft(y_all) # 離散フーリエ変換
freq = np.fft.fftfreq(N, d=dt) # 周波数を割り当てる(※後述)
Amp = abs(y_fft / (N / 2)) # 音の大きさ(振幅の大きさ)
plt.plot(freq[1 : int(N / 2)], Amp[1 : int(N / 2)])
plt.xscale("log") # 横軸を対数軸にセット
plt.show()
plt.plot(freq[1 : int(N / 2)], Amp[1 : int(N / 2)])
plt.xlim(225, 425)
plt.xlabel("周波数 [Hz]")
plt.ylabel("振幅")
plt.show()
👈 Go back