2009년 03월 20일
13강 - MATLAB 때려잡기 - FFT 2부

이번 시간은 저번 시간에 이어 FFT 계속입니다. MATLAB에서 직접 FFT 해보죠~
Fourier Analysis에 관해서 자세하게 알고 싶은 분은 아래 link를 참조하세요.
두 문서를 읽어 보시길 적극 추천합니다. 아주 쉽게 잘 설명해 놓았습니다.
Fourier Analysis 1
Fourier Analysis 2

다시 한번 말하지만 위의 사각파의 경우 수많은 Cosine의 합으로 표현 될 수 있습니다. FFT를 통해 얻고자 하는 우리의 궁극적인 목적은 어떤 주파수(fn)가 포함되어 있고 그 각각의 주파수의 크기(또는 기여도) An를 구하는 겁니다.
우선 간단한 Sine波 하나로 시작합시다.
Script를 하나 만듭니다. 아래 코드를 M-File Editor 창에 Copy & Paste !!
(코드는 blinkdagger.com를 참조하였습니다.)
fo = 4; %frequency of the sine wave
Fs = 100; %sampling rate
Ts = 1/Fs; %sampling time interval
t = 0:Ts:1-Ts; %sampling period
n = length(t); %number of samples
y = 2*sin(2*pi*fo*t); %the sine curve
%plot the cosine curve in the time domain
sinePlot = figure;
plot(t,y)
xlabel('time (seconds)')
ylabel('y(t)')
title('Sample Sine Wave')
grid
Sampling Rate(Fs)란 1초에 몇번이나 데이터를 측정하겠나는 말입니다.
위의 코드 대로라면 1초에 100번 측정하는 군요. 즉 0.01초 마다 데이터를 측정한다는 말이죠(Ts)~
측정된 데이터 하나를 샘플(sample)이라고 합니다. 나머지는 문제없습니다.
F5를 살며시 눌러 줍시다. Sinewave.m 으로 저장하시구요~

위의 Code를 보세요. 우리가 그린 sin 그래프는 fo(frequency)가 4이고 크기(Amplitude)가 2였습니다(y = 2*sin(2*pi*fo*t)). 그럼 FFT를 했을 때 4Hz 주파수에서만 Peak가 뜨고 나머지 주파수는 다 '0'이나와야 됩니다. 즉 위의 Sine은 4Hz 이외에는 어떤 주파수 성분도 담고 있지 않습니다.
자 그럼 FFT 해봅시다. MATLAB에서 FFT를 수행하는 함수는 fft 입니다.
>>fft(a)'
ans =
.
.
-0.0000 +0.0000i
어라!! 주파수와 크기 정보를 얻으려고 했는데 이건 뭐여!?? 당췌~~ 냠냠...
그러나 걱정할 필요 없습니다.저만 잘 따라오세요~ ^^ 우선 아래 그림을 봐주세요

지금 우리가 관심 있는건 바로바로바로 크기 A입니다. 어떤 주파수가 얼마나 들어있나에 관심있으므로 phase(위상)은 잠시 접어둡시다. MATLAB에서 복소수의 크기(Megnitude)를 돌려주는 함수는 abs 입니다.
그럼 크기 A를 그래프로 그려봅시다.
새로 Editor 창을 띄워서 아래 Code를 Copy & Paste!!
%plot the frequency spectrum using the MATLAB fft command
matlabFFT = figure; %create a new figure
YfreqDomain = fft(y); %take the fft of our sin wave, y(t)
stem(abs(YfreqDomain)); %use abs command to get the magnitude
%similary, we would use angle command to get the phase plot!
%we'll discuss phase in another post though!
xlabel('Sample Number')
ylabel('Amplitude')
title('Using the Matlab fft command')
grid on
axis([0 100 0 120]) %resizing axis size
stem은 그래프의 한 종류입니다. Graph Catalog에서 확인해 보세요
F5 , FreqDomain.m 저장하시구요

오홋!! 뭔가 나온것 같기는한데... 그런데 자세히 보니 뭔가 좀 맞지 않군요 -_-;;
1. x축(Frequency)가 맞지 않습니다. 우리가 기대하는 값은 4Hz(Frequency)였는데 말이죠..
2. y축(Amplitude)도 맞질 않군요 -_-;; 흠..
3. 그리고 왜 Peak가 2개나 뜰까요?..
왜 위와 같은 결과가 나왔을 까요? 밑으로 내려가기 전에 한번 생각해보시기 바랍니다.
첫번째로 x축이 맞지 않는 이유는 우리가 FFT한 y에 시간 정보가 담겨져 있지 않기 때문입니다.
>>plot(y)해보세요. x축이 맞지 않는 이유와 같습니다. 그러므로 우리가 수동으로 x축을 수정해 주어야 합니다.
두번째로 y축을 Nomalize(%로 표현) 해주기 위해 sample수로 나주어 주면 됩니다.
마지막으로 쉽게 설명하자면 Cosine은 y축에 대칭이죠? cos(-1) = cos(1). 그래서 대칭된 2개의 Peak를 돌려줍니다. 즉 위의 그래프는 그래프의 w정중앙을 중심으로 서로 대칭입니다. 그럼 각각의 피크는 +4Hz와 -4Hz 이겠군요. 대개의 경우 + 주파수 값을 사용합니다. 대칭이니까 반은 잘라서 버려버리고 +주파수에만 집중합시다.
그런데 반으로 잘라 버리면 문제가 발생합니다. 예를 들어 2 = cos(2π) + cos(-2π) (주파수는 1Hz)인데 대칭이니까 cos(-2π)성분을 버려 버리면 1Hz의 기여도가 1/2로 줄어 들어 버립니다. 그래서 Normalize한 y값에 2를 곱해주어야 합니다.
이런 내용을 마음에 두고 다시 그래프를 그려 보겠습니다.
positiveFFT라는 함수를 하나 만들어 놓으면 두고 두고 편합니다.
function [X,freq]=positiveFFT(x,Fs)
N=length(x); %get the number of points
k=0:N-1; %create a vector from 0 to N-1
T=N/Fs; %get the frequency interval
freq=k/T; %create the frequency range
X=fft(x)/N*2; % normalize the data
%only want the first half of the FFT, since it is redundant
cutOff = ceil(N/2);
%take only the first half of the spectrum
X = X(1:cutOff);
freq = freq(1:cutOff);
다른 것은 문제없고 ceil 이라는 함수만 알면 되겠군요. ceil함수는 올림을 해주는 함수입니다. 예를 들어 ceil(4.2)은 올림을 해서 5가 됩니다.
Command Window에 아래 코드를 붙여 넣어 보세요~
[YfreqDomain,frequencyRange] = positiveFFT(y,Fs);
stem(frequencyRange,abs(YfreqDomain));
xlabel('Freq (Hz)')
ylabel('Amplitude')
title('Using the positiveFFT function')
grid on
axis([0,20,0,1.5])

위의 그래프를 분석해보자면 주파수는 4Hz이고 크기는 2가되겠습니다.
2*sin(2*pi*4*t)와 정확히 일치힙니다.
MATLAB FFT 끝~~ ^^
실전 연습해보죠~
제가 좋아하는 Radiohead 노래를 가지고 놀아 보죵 ^^
Radiohead의 Creep 시작부분에서 베이스 기타 소리만 죽여 보겠습니다~
FFT를 통해 주파수 분석한 다음 베이스 기타를 제외한 주파수만 살리고 베이스 기타 주파수는 죽여 버립시다.
그리고 다시 Time domain으로 되돌려 주면 됩니다.Frequency Domain에서 Time Domain으로 되돌리려면 ifft 함수(Inverse FFT)를 사용하시면 됩니다 그런데 베이스 기타 주파수가 어디냐구요?? 아무래도 베이스니까 주파수가 낮겠죠 그래서 낮은 주파수를 죽여 버렸습니다.

원본 음악은 이렇습니다. 베이스 일렉 소리를 잘 들어보세요.
# by | 2009/03/20 17:11 | MATLAB | 트랙백 | 덧글(102)





☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
갈수록 매트랩에 빠져 들게 되네요.. 설명도 매우 좋으시고요..
항상 감사드립니다.
빨리 다음 강의가 보고 싶어 지는군요.
그... 어떤 함수를(저같은 경우는 버터워스필터를 통과시킨...)그걸 샘플링 하는 메트랩을 구현할수 있나요..?
MATLAB에서 Filter Design Toolbox를 제공하고 있으니 Help Browser에서
Butterworth 라고 검색해보시면 적당한 함수가 나올 겁니다.
(an introduction with applications using matlab)
저자 amos gilat and vish subramaniam
이책 공부하시는분 있으신가요ㅠㅠㅠ 여기서 매트랩 공부하는 학생인데요ㅠㅠ
도저히 모르겠네요 ,,, 원본에다가 매트랩이 너무 어렵네요 ㅠㅠ
도움좀 주세요ㅠㅠ
성심을 다하여 답변해드리겠습니다 ^^
여쭤볼 말이 있는데 jhk7010@nate.com 으로 메일 주시면 감사하겠습니다.
질문내용을 메일을 통해 보낼려고 하는데 메일주소를 못찾겠어요ㅠㅜ
nycj0901@naver.com 으로 메일 한통 보내주시면 감사하겠습니다..^^
leegunsuck@hotmail.com입니다.
,,,찾을 수가 없네요
가르쳐 주세요....
']' 옆에 있습니다
\\\\\\ ^^
어제까지 내는 과제가 있었는데 결국 시간맞춰 내는건 포기하고
되는 데로 짜본 소스가 있습니다. 메일로 보냈는데 보시고 수정.. 이 힘드시면
충고라도...ㅠㅠ 부탁드릴께요.
시험기간이신가 보네요..ㅋ 미분방정식 특강 계속 기다리는데 많이 바쁘신가 보네요..ㅋ
다른 일이 좀 있어서 Update가 계속 늦어 지내요 -_-;;
미방은 반쯤 써놓기는 했는데 ...
더욱 분발 하겠습니다요~ :D
힘내세요~
메일로 질문하나 드렷어요~
앞으로도 화이팅해주세요~ ㅎ
동영상이라는 것이 어차피 정지된 Image의 연속이니까요
실제로 MATLAB에 컬러 동영상을 불러 들여보시면 4d(RxGxBxTime) matrix가 만들어 집니다.
굉장히 큰 matrix를 만들때 Out of Memory라는 error를 가끔 만나기도 합니다만
메모리만 충분하다면 충분히 큰 동영상도 가능하리라고 생각됩니다. ^^
위 소스를 구현해볼려고 하는데 계속 안되어서 그런데 소스를 좀 주시면 제가 그것을 보고 공부좀 할려고 합니다.
좀 도와주십시요. 선처 부탁드립니다.
a20105@nate.com 답변 부탁드립니다.
메일로 보내 드리겠습니다.
그런데 매트랩 버전은 맞는데 실행하니 에러가 뜨네요?
파일이 더필요한건가요???
open(fn);
이런 에러가 뜨네요.ㅠ
일단 제 컴퓨터 환경(xp,matlab 2008b)에서는 문제없이 돌아가구요
특별히 필요한 toolbox도 없는데...
메일이 날아가는 도중에 깨어졌을 지도 모르니 다시한번 메일 보내드리겠습니다.
FFT 부분이라 질문합니다.
그 임펄스 함수 하나는 어떻게 그냥 델타 함수 써서 그리겠는데
주기가 2초인(크기가1인) 임펄스 함수를 그리라는데...ㅠㅠ
도통 모르겠어욤 ㅠㅠㅠ 제발 좀 가르쳐주세요 ㅠ
rect ? 그 함수 쓰는거 같기도 하고...
GUI를 구현할때 wave파일을 어떻게 읽어오고 저장하고 차례대로 그리셨는지요 ㅠ
C언어로 구현을 해보려는데 FFT에 관해서는 잘 몰라서요
혹 MATLAB소스라도 보내주시면 안될까요 ㅠㅠ
ararjen@nate.com
wave 파일을 재생 할 때는 wavplay
wave 파일을 저장 할 때는 wavwrite
함수를 사용하시면 됩니다.~ ^^
sinc(100*t)를 fft 했을 때 사각파의 높이가 '0.01'이 나오는 것이 맞습니까?
다시 한번 검토해보시기 바랍니다.
솔직히 저도 뭐가 문제인지 잘 모르겠습니다 -_-;;
구글링을 꽤 해도 이유를 알 수 없군요.
그러나 간단한 파형으로 위의 코드를 검증해보면 바른 값을 돌려주므로
위의 코드가 틀렸다고 하기는 어려울 것 같습니다.
위의 코드는 blankdagger.com의 코드를 참조하였습니다.
오류가 나는 이유를 밝혀 내시면 정보 공유 부탁드립니다 ^^
strings passed to eval cannot contain function declaratoins 라고 뜨네요.
아무것도 모르는 놈이라 그러지 부디 잘 가르쳐 주세요 ;ㅁ;
Post의 처음부터 code를 차례대로 붙여 넣으시고 실행하셔야 합니다~
원래는 1이 나와야하지 않나요?
오른쪽만 봤을때 magnitude는 1
왼쪽만 봤을때 magnitude는 1
하지만 영자님은 오른쪽만 나타내셨고
마지막 사진봐도 magnitude 1이 나오잔아요
근데 코드대로하면 magnitude 2나옵니다
funtion부분에서 X=fft(x)/N*2; 를 X=fft(x)/N; 로 고쳐야 영자님처럼 나오던데요;;
+ 주파수만 나타내었을 때 2가 나오는 것이 맞습니다.
원래의 식이 y= 2*sin(2*pi*fo*t)) 였으므로 magnitude가 2가 맞지요
그림은 수정하도록 하겠습니다. ^^
sin함수를 오일러 공식에 의해서 exp함수로 바꾸면 진폭이 1/2로 줄어들어서 진폭이 1이 되는지 알았는데;;
음의 주파수 -4Hz 진폭 1과 양의 주파수 +4Hz 진폭 1 이런식으로...
영자님은 positive만 나타내셔서 좀 헷갈리지만...좌측의 진폭을 Positive로 몰아서 합치면 진폭이 2인건 맞는거 같네요..
제가 틀렸을수도 있죠..;;
phase spectrum은 angle 함수 쓰시면 되고요~
Amplitude 의 log spectrum은 7강을 참조하셔서 Plot Catalog에서
stem말고 적절한 plot함수를 사용하시면 간단히 해결되겠죠? ^^
강의가 정말 이해가 잘 되게 친절히 설명해 주셨네요.^^
한 가지 궁금한게 있는데요.
fourier transform signal의 (주파수 영역)
amplitude말고 phase를 보려면 어떻게 해야 하나요?
abs 함수 대신에 angle 함수를 쓰시면됩니다.
노말라이즈 이런거는 필요 없습니다~
급한데로 Youtube에 'matlab ode45'라고 검색하시면
ODE에 관한 tutorial 동영상이 있으니 참고하시기 바랍니다.
이산신호를 DTFT를 통하여 변환하려고 합니다. 매틀랩으로 어떻게 해야하는지 난감하네요..
FFT와 DTFT와는 차이가 있는거 같네요 이론시간에는 DTFT만 배웠거든요.
또 매틀랩에서는 DTFT를 사용할 수가없는지요.. FFT만 있는거 같아요..
회로 관련문제를 풀면서 그래프를 하나 그리려는데
t=[0:1/256:50];
이때 0<t<10 이면
v=12-12*exp(-t/6);
수식을 plot 하고
t>=10 이면
v=9.7335*exp(-(t-10)/6);
수식을 plot 하고 싶은데요.. 10을 기준으로 10이전엔 증감하다 10이후로는 감소하는..
그냥 if 0<t<10
...
else
...
end
이렇게 하니까 안되네요.ㅠㅠ 이거 어떻게 해야 하죠 ㅠㅠ 교주님의 말씀 기다리겠습니다.ㅠㅠㅠㅠ
t=[0:1/256:50];
v=zeros(1,length(t));
for i=1:length(t)
if t(i)<10
v(i)=12-12*exp(-t(i)/6);
else
v(i)=9.7335*exp(-(t(i)-10)/6);
end
end
plot(t,v);
C스타일올 이렇게 coding 하셔도 되고요
되도록이면 for문은 피하시는게 좋겠죠? ^^
MATLAB 스타일로 코딩하시려면
t=[0:1/256:50];
v=zeros(1,length(t));
a=length(find(t<10));
v(1:a)=12-12*exp(-t(1:a)/6);
v(a+1:end)=9.7335*exp(-(t(a+1:end)-10)/6);
plot(t,v);
이렇게 하셔도 됩니다. 속도는 밑의 코드가 훨씬 빠르겠죵?
제가 보내드린 파일에 문제가 있는 것 같군요.
같은 error를 호소하시는 걸 보니..;;
제 컴에서는 잘 돌아가는데요... 흠...
code를 다시 한번 검토해보겠습니다.
언제 쯤 미방 강좌를 볼수 있을런지요.
언제 다시 시작한다고 확답을 못드리겠어요 ;;
MIT OCW에 Differential equation 강좌가 있으니 참조하시기 바랍니다.
http://ocw.mit.edu/OcwWeb/Mathematics/18-03Spring-2006/VideoLectures/index.htm
fft 함수를 구현해볼려고 하는데
너무 어렵네요. 그래서 말인데요.
fft 알고리즘을 보내주시면 안될까요?
그것을 보고 공부좀 할려고 합니다.
좀 가르쳐 주세요..!!
좋은 강의 잘 보고 가요.!
gogildong81@naver.com
답변 부탁드립니다.
굉장히 많은 자료가 있으니 googling 해보시는 것을 권해드립니다요~ ^^
친절히 답변해주셔서 감사하구요^^
구체적으로 fourier transform 된 함수 F(f) 있으면,
이걸 곧바로 plot(angle(F)); 이런식으로 하면 된다는 말씀이시죠?
질문이있는데요.. 근궤적에대해 공부하고있는데
셈툴에 rlocus라는 근의 위치를 찾아주는 함수가있는데
예를들어서 s=1+3j 라고하면 rlocus(num,den,s) 이렇게 하면 s에 가장 가까운 근을
찾아 주는거요.. 매트랩에 이에 상응하는 명령어가 없을까요?
3차 차분방정식을 매틀랩으로 입력해야 하는데 어떻게 입력해야할지 이해가 안되요 ㅠㅠ
y[n] = 0.0181x[n] + 0.0543x[n-1] + 1.76y[n-1] 이런식입니다.. ㅠㅠ
n-salan@nate.com 이에요! 답변 부탁드려요!
여튼 나름대로 한번 해봤는데 wavread해서 위의 과정대로 적용까진 됩니다만
그걸 cut이란곳에 저장후
변환후 cut(0:1000) = 0; (정확한 코드는 지금 기억이;;) 이런식으로 특정 부분만 0으로 값을 조정하고 저장하여 특정 주파수만 죽여볼까했는데요,
wavwirte해서 결과물을 들어보니 영 아니더군요. 어떤과정으로 베이스 음역대를 줄이셨는지 궁금합니다.
wav 읽기 - FFT 변환 - 특정음역 줄이기 - iFFT 변환 - wav 저장
이런순인가요? 좀 자세한 과정을 알려주시면 정말 감사하겠습니다 ㅜㅜ
변환하는 함수는 어떤것들이 잇나요? ㅠ
메일주소좀 알려주실수 있나요??
여기서는 메일을 어떻게 보내야 되는지 잘 모르겠어서요...
그래프에서 추세선을 그리고 싶은데 추세선은 어떻게 그리는지 잘 모르겠어요..
알려주세요~
그리고 질문 하나 있는데,,,이번에 여러개의 엑셀파일을 읽어 처리 할려고 하는데,,
그래서 uigetfile을 써서
File_Name = uigetfile('*.*','All Files','MultiSelect','on')
A = csvread(File_Name(1,1),0,0)
% 실제로는 이렇지 않고 간단하게 보였습니다.
이렇게 했는데 File_Name 이 문자열이 아니라서 csvread을 쓰지
못한다고 뜨네요..ㅡㅡ;; 그냥 봐선 문자열인데,,
만약 File_Name(1,1) = 'data01.csv' 이라면 이걸 어떻게 문자열로
변환할수 있을까요? 도와주세요~
출처:13강 - MATLAB 때려잡기 - FFT 2부
MATLAB 때려잡기 Data Type 강좌를 참조하세요
File_Name{1,1} 로 참조하시면 될겁니다
2개의 m file이 있는데요~첫번째 mfile에서는 uicontrol을 이용하여 edit와 push 버튼을 생성하도록 했습니다. 생성되고 나서 push버튼을 누르면 두번째 mfile 실행시켜서 계산한 값을 첫번째 mfile의 edit에 다시 넣고 싶습니다.
아래와 같이 했는데,,push버튼을 누르니 에러가 나오네요
>> Button2 = uicontrol(gcf,'unit','nor','pos',[0.4 0.55 0.2 0.1],'callback', ...
'RT("Run")');
>>set(Button2,'string','계산시작');
여기서 RT는 두번째 mfile의 이름입니다.
좀 도와주세요~
>>guide
Study 카테고리에서 'MATLAB GUI Tutorial' 포스트를 참조하세요
그리고 이 데이터(복소수)를 저장 할려고 하는데 txt 또는 엑셀 파일로 save라는 명령어로 해서 할려고 하니 잘 안됩니다. 물론 ascii 말고 double 또는 tabs 써봐지만 잘 안되요~갈켜주세요~
마지막의 x 3 각각에 RGB정보를 담고 있습니다.
MATLAB 때려잡기 - Quiz 풀이를 참조하세요
matrix의 크기(차원)를 조정하고 싶으시면 reshape 함수를 사용하세요
data 저장과 관련해서는
1. xlswrite 함수를 사용하시면 원하시는 변수를 Excel파일로 저장 하실 수 있습니다. 예를 들어 MATLAB 상의 변수 A를 엑셀파일로 저장하시고 싶으시면
>>xlswrite('result.xls',A);
변수 A에 상응하는 엑셀파일이 생성됩니다.(current directory에 저장됨)
2.csvwrite 함수를 사용하시면 csv(comma seperated value) 형식(txt)으로 저장할 수 있습니다.
>>csvwrite('result.txt',A);
마지막 부분에 MATLAB GUI 구현한건 어떻게 한건지 궁금합니다..
답변부탁드립니다 ㅎ jong8688@naver.com
대략적인 흐름은 아래와 같습니다. 참고하시 바랍니다.
wavread로 함수 음악파일을 읽어드림
fft 함수로 시간 도메인을 주파수 도메인으로 변경
원하는 특정 주파수 성분을 0으로 채움
ifft 함수로 시간 도메인으로 돌림
wavplay 함수로 재생
wavwrite로 저장
도움이 되었으면 합니다 ^^
사인파로 피아노와 비슷한 음색만드는 과제였는데
matlab강의덕에 쉽게한거같에요 ^^
감사합니다~
하나 질문이 있습니다
fft 함수에서 입력을 위에서 보면 sine 형태로 연속함수로 넣었는데요...
입력을 이산화된 값으로 넣을려면 어떻게 해야 하는건가요?
curve fitting을 통해서 함수를 만든다음 다시 fft를 통해서 주파수 분석을 해야 하는 건가요?
요청하신 GUI 소스는 날아 갔습니다 -_-;;
대략적인 흐름은 위에 위에 위에 답변 보시면 될것 같구요
embedded 쪽이시면 xPC Target 쪽이신가요?
좋은 결과 있으시길 바랍니다 ^^
그럼 질문이 있는데요
Studio LGS님의 강의를보고 약간 응용해서
세가지 유형의 사인파를 합쳐서
찌글찌글하면서도 규칙적인 파형을 만들어냈습니다.
그것을 Positive FFT하여 주파수측면에서 봤을때 세 개의 막대기가 서도록 만들었습니다.
크기도 제각각이도록 만들었구요 주파수도 세가지 다 다르게 만들었습니다.
이제 그중 하나만 남기고 나머지는 죽여보고싶은데 어떤식으로 해야할지..
C언어도 먹는다고해서 제가 C언어는 어느정도 제가 원하는 프로그램은 짤수있을정도라서 C언어식으로 해보려고 삽질도해봤는데..
절망.. ㅠㅠ
필요하지 않은 신호를 죽이는 방법이 궁금합니다.
FreqDomain.m에 있는
matlabFFT = figure; %create a new figure
-> 이게 무슨 뜻인지 모르겠습니다.
빼고 돌려도 잘 돌아가는 거 같은데요.
figure object의 handle 값을 matlabFFT 에 저장하겠다는 말인데요
새로운 figure 창을 띄울려고 쓴것입니다.
figure 창을 새로 띄우지 않으면 current figure에 덮어 그리기 때문인데요
프로그램의 흐름상 없어도 상관 없습니다
graphic object는 제 블로그 동영상 강좌를 참조하세요 ^^