Pythonでフーリエ変換を使って特定の周波数の波形を除去したい!
概要
今回の記事では、Pythonでフーリエ変換を使って特定の周波数の波形を除去するサンプルを掲載する。
自分がフーリエ変換を理解するためにサンプルで作ったコードです。
数学難しいよ!
仕様書
環境
- Python 3.10.6
手順書
440hzと880hzのサイン波の波形データを作り、フーリエ変換した後、振動スペクトログラムにから880hzの成分を除去して、逆フーリエ変換で波形データに戻すサンプル。
処理の効果を確認するために除去前後の波形データをwavファイルに出力する。
import numpy as np
from scipy.fft import fft, ifft
import wave
sampling_rate = 44100
duration = 1
gain = 0.5
t = np.arange(int(sampling_rate * duration)) / float(sampling_rate)
# 440Hzと880Hzのサイン波の作成する
waveform440 = np.sin(2 * np.pi * 440 * t) * gain
waveform880 = np.sin(2 * np.pi * 880 * t) * gain
# 440Hzと880Hzの波形を合成する
mixed_waveform = waveform440 + waveform880
# 波形をFFT
fft_result = fft(mixed_waveform)
# 880Hzの成分を除去
frequency_index = int(880 * duration)
fft_result[frequency_index] = 0
fft_result[-frequency_index] = 0
# IFFTで波形に戻す
ffted_waveform = ifft(fft_result)
# WAVファイルに出力
with wave.open('non_ffted_sin.wav', 'w') as mixed_wav:
mixed_wav.setnchannels(1)
mixed_wav.setsampwidth(2)
mixed_wav.setframerate(sampling_rate)
mixed_wav.writeframes((mixed_waveform * 32767).astype(np.int16).tobytes())
with wave.open('ffted_sin.wav', 'w') as filtered_wav:
filtered_wav.setnchannels(1)
filtered_wav.setsampwidth(2)
filtered_wav.setframerate(sampling_rate)
filtered_wav.writeframes((ffted_waveform.real * 32767).astype(np.int16).tobytes())
このサンプルを実行するとFFTする前のnon_ffted_sin.wav
とFFT・IFFTが終わって880hzのサイン波が除去されたffted_sin.wav
が出力される。
まとめ(感想文)
Python(というかnumpy)ってC++と比べてかなり簡単にサイン波の波形を作れちゃう。FFTも簡単に使えちゃう。
気軽に数学的な実験をするのに良いと思った今日この頃。
ここまでは良いんだけども、VSTプラグインにすることを考えるとフレーム処理・オーバーラップ処理などが必要なってきて、段々とややこしくなっていくのであった。