우선, 전체적인 프로그램 틀은 저번 Fourier Series에서 사용했던 프로그램에서 메뉴를 추가한 방식으로 추가했다.
위 식이 Fourier Transform 식이다.
위식을 Fourier Transform 클래스를 새로 만들어서 구현해보았다.
void FourierTransform::Foruiertransform()
{
double m_Real, m_Image;
double T_Real, T_Image;
for (int fre = 0; fre < 1024; fre++) {
T_Real = T_Image = 0;
for (int n = 0; n < 1024; n++) {
m_Real = m_InFTData[n] * cos(2 * Pi * fre * n / 512);
m_Image = m_InFTData[n] * sin(2 * Pi * fre * n / 512);
T_Real += m_Real;
T_Image += m_Image;
}
m_OutFTData[fre] = sqrt(T_Real * T_Real + T_Image * T_Image);
}
}
위 코드가 FourierTransform 클래스를 만들어서 직접 구현해본 과정이다.
헤더파일에서 m_InFTData와 m_OutFTData를 만들어서 구현해 보았다. 여기서 중요한건 지수함수 e이다. 오일러 공식에 의해서 위 식은 sin과 cos의 합으로 나타내지게 된다.
즉, 컴퓨터로 복소수를 다뤄야 하는 문제가 생기게 된다. 물론 복소수파트와 실수파트를 따로따로 계산해서 나타내는 방법도 있겠지만, 통신에서는 그 방법보다는 크기(magnitude)와 위상(phase)로 나누어서 확인하는것이 더 일반적이다. 이번 미니프로젝트에서는 크기만 확인하였다. 코드를 확인하면 볼 수 있겠지만, Real값과 Image값 즉 실수부와 허수부를 분류 한 후에, 둘을 제곱하여 더하여 루트를 씌우면, 그 크기를 구할 수있다.
void CPhaseView::Onsumsin1to10()
{
// TODO: 여기에 명령 처리기 코드를 추가합니다.
for (int n = 0; n < No_Total; n++)
{
m_display1[n] = 0;
m_display4[n] = 0;
m_InFTData[n] = 0;
}
Gen_Signal GS;
GS.m_string = "sin";
GS.DATA_No = No_Total/2;
GS.m_A = 1;
GS.m_Ph = 0;
GS.Signal_Phase_Data();
for (int x = 0; x < 10; x++) {
GS.m_FreQ = x;
GS.Signal_Phase_Data();
for (int n = 0; n < No_Total; n++)
{
m_display1[n] += GS.result_Data[n];
m_InFTData[n] += GS.result_Data[n];
}
}
Invalidate();
}
신호들은 위처럼 sin 1Hz~sin10Hz를 다 더하기도하고, 단순하게 한두개의 신호를 보기도 하며, 이전에 만들어본 백색잡음을 섞어서 만들어보기도 하면서 작성했다.
sin 1Hz를 512개의 샘플을 가지고 출력했고, 출력범위는 1024개까지 출력했다. 굳이 1024개까지 출력한 이유가 있는데, 이는 조금 있다가 설명하겠다. 위 그래프에서 보면 sin 1Hz즉, 주파수가 1이기때문에 1의 값을 가진다는것을 알 수있다.
sin10Hz를 푸리에변환하면, 10Hz성분이 나오는것을 확인할 수 있다. 이때 10Hz성분이 한개가 아니라 여러개가 나오는것을 확인할 수 있는데, 이는 디지털신호에서 갖게 되는 특성이다. 512개의 샘플을 가지고 분석하면, 512번째 점에서 똑같이 좌우로 신호가 나누어서 전개되게 되며, 이는 무한히 반복된다.
이 10Hz성분의 값을 찍어보면 255라는 값을 가지게 된다 즉, 512개의 샘플의 값을 음수방향과 양수방향으로 반씩 나누어서 가진다는 의미이다. 즉, 음수방향으로 -10Hz방향으로도 값이 솟아있을 것이다.
같은 맥락으로 sin1Hz부터 10Hz까지의 값을 모두 더하면 위처럼 주파수 성분이 나오는 것을 알 수 있다.
위는 10Hz부터 10Hz단위로 끊어가며 더한 sin신호이다. 이제 시간축그래프에서는 분석하기 어려운 그래프가, 주파수축에서 보다 분석하기 편해진 것을 알 수 있다.
백색잡음과 sin10Hz를 더한신호를 분석해보았다. 이전에, 잡음은 모든 주파수를 가진 신호라고 말한바가있다. 그 값이 매우 작긴하나, 아주작은 주파수 값들이 전반적으로 퍼져있음을 알 수 있다.
위는 sin 400Hz이다. 언뜻보면, 신호가 잘 나온것 같아보인다. 하지만 그렇지 않다. 500Hz를 한번 넣어보겠다.
뭔가 이상하다고 느껴야 정상이다. 분명 500Hz를 썼는데, sin이 뒤집힌 12Hz와 유사한 모양이 나왔다. 이는 나이퀴스트율로 설명이 가능하다. 400Hz나 되는 주파수를 512개로 샘플링하다보면, 한 400Hz의 한주기당 대략 512/400개 즉, 1.xx개의 샘플을 하게된다. 즉 한두픽셀만 넘어가면 다음주기로 넘어가기때문에 충분한 값을 샘플링하지 못하게 된다. 이가 나이퀴스트 율이다. 샘플링주파수는 해당신호 주파수의 최소 2배가 되어야한다. 즉, 400Hz의 신호를 분석하기 위해서는 최소 800개의 샘플링을 해야한다는 소리이다.
500Hz의 신호를 하면 거의 한 주기(sin)당 한 값만 찍는데 조금씩 뒤로 밀리면서 찍게된다. 그래서 마치 12Hz를 가진것처럼 나오게 되는것이다. 방금 한설명은 사실 이해하긴 어려울 수 있으나, 컴퓨터가 계산하면서 우연찮게 나온 규칙정도이고, 중요한것은 우리가원하는 500Hz의 신호가 나오지 않았다는 것이다.
즉, 나이퀴스트율을 충족하지않으면 Fourier 변환을 제대로 사용할수 없다!
'C++ > 신호처리 프로젝트 mfc.ver' 카테고리의 다른 글
04_mfc를 활용한 Fourier Series (0) | 2021.11.09 |
---|---|
03_mfc를 활용한 correlation (4) | 2021.11.09 |
02_mfc를 활용한 convolution (0) | 2021.11.09 |
01_mfc를 이용한 신호의 파형출력 (0) | 2021.11.09 |