MATLABを用いて信号処理の基礎の基礎
最終更新:2022/10/07
信号を読んで, 可視化して, FFTして, フィルターして, 逆FFTして, 可視化する.
研究室でフーリエ変換を教えるために作った教育用のコード. MATLABの公式のFFT関数の説明に少し書き足した感じ.
コード
使う信号
MATLABにデフォルトで入っている gong.mat という信号を使う.
信号 y
と サンプリングレート Fs
がロードされる.
ちなみに, sound(y, Fs)
で音を聞ける.
ゴングの音かな.
MATLAB
load gong.mat t = (0:length(y)-1)/Fs; d = y; % 特に意味は無いが, dという名前に変えた plot(t, d); xlabel('time [sec]'); ylabel('amp [?]') ylim([-1.5, 1.5]) axis tight
信号の切り抜き
$t_1 = 1$ [sec] から $t_2 = 2$ [sec] を抜き出して可視化してみる.
MATLAB
%%%% t1とt2を入力 %%%% t1 = 1; t2 = 2; %%%%%%%%%%%%%%%%%%%%% isIn = (t1 < t) & (t < t2); dp = d(isIn); % data partially のつもり tp = t(isIn); % time partially のつもり plot(tp, dp); xlabel('time [sec]'); ylabel('amp [?]')
FFTをかける
本家の解説 に基づいて作成.
MATLAB
L = length(dp); Y = fft(dp); P2 = abs(Y/L); P1 = P2(1:L/2+1); P1(2:end-1) = 2*P1(2:end-1); f = Fs*(0:(L/2))/L; plot(f, P1) % plot(f, P1) % logをとると見やすい. 必要ならコメントアウト. xlabel('f (Hz)') ylabel('|P1(f)|') axis tight
band-pass フィルター
$f_1 - f_2$ [Hz] を残してフィルタリング ( band-pass フィルター ).
MATLAB
%%%% f1とf2を入力 %%%% f1 = 500; f2 = 1500; %%%%%%%%%%%%%%%%%%%%% isOmit = ~((f1 < f) & (f < f2)); Y_filtered = Y; % 左側をフィルタ tmp = Y_filtered(1:length(isOmit)); tmp(isOmit) = 0; Y_filtered(1:length(isOmit)) = tmp; % 右側をフィルタ isOmit = fliplr(isOmit); tmp = Y_filtered(end-length(isOmit)+1:end); tmp(isOmit) = 0; Y_filtered(end-length(isOmit)+1:end) = tmp; % フィルタ後を可視化 plot(abs(Y_filtered)) xlabel('f (Hz)') ylabel('|P1(f)|') axis tight
逆FFT
逆FFTして ( ifft
) , フィルタの効果をみる.
MATLAB
d_filtered = real(ifft(Y_filtered)); t = tiledlayout(2, 1); t.Padding = 'compact'; t.TileSpacing = 'compact'; nexttile plot(tp, dp); xlabel('time [sec]'); ylabel('amp [?]'); legend('before filter', box='off') nexttile plot(tp, d_filtered); xlabel('time [sec]'); ylabel('amp [?]'); legend('after filter', box='off')
よわからないけど, 拡大するとなめらかになっているかも.
MATLAB
t = tiledlayout(2, 1); t.Padding = 'compact'; t.TileSpacing = 'compact'; nexttile plot(tp, dp); ylabel('amp [?]'); legend('before filter', box='off') xlim([1.1, 1.2]) nexttile plot(tp, d_filtered); xlabel('time [sec]'); ylabel('amp [?]'); legend('after filter', box='off') xlim([1.1, 1.2])