저 여자친구 있어요. 건들지 마세요.

FFT Source

Jan.06, 2009 : FFT의 개괄적인 이해는 2d fast fourier transform 을 참조하세요

FFT 소스를 요청하는 분들이 많이 계셔서 소스코드를 공개합니다. 이게 기본틀은 어디서 코드를 분석한 것이라서 거의 똑같다고 보시면 됩니다. 간단한 주석을 달았구요. 도움이 되시길 빕니다.

/* File		:	struct.h
 * Creator	:	BlackEngine
 * Date		:	2006/03/28
 * Version	:	0.0.1 ( created )
 * Descript	:	Definition of Complex Number , and etc
 */
 
typedef struct _COMPLEX {
	double	real;
	double	imag;
} COMPLEX, *pCOMPLEX;
/* File		:	fft.h
 * Creator	:	BlackEngine
 * Date		:	2006/03/28
 * Version	:	0.0.1 ( created )
 * Descript	:	Perform the FFT Algorithm
 */
#ifndef _BLACKENGINE_FFT_H_
#define _BLACKENGINE_FFT_H_
 
#include "struct.h"
/* TODO : at 03/29 , decision the return values of FFT Function. */
int fft_2d(COMPLEX ** ,int ,int ,int );
int fft(int ,int ,double *,double *);
#endif /* ifndef _BLACKENGINE_FFT_H_ */
/* File		:	fft.c
 * Creator	:	BlackEngine
 * Date		:	2006/03/28
 * Version	:	0.0.1 ( created )
 * Descript	:	Perform the FFT Algorithm ( 2-D Image FFT )
 */
#include 
#include 
#include
 
#include "fft.h"
 
#define TRUE 1
#define FALSE 0
/*#define NULL 0*/
 
/* Powerof2 function : compare the integer with 2^m
 * and find maximum m , that is 2^m <= nx
 * twopm = 2^m
 */
int Powerof2(int nx, int* m, int* twopm) {
	int pwr;
	*m = 0;
	for ( pwr = 1 ; pwr < nx ; pwr = pwr*2) {
		*m = *m + 1;
	}
	*twopm = pwr;
	return(TRUE);
}
 
int fft_2d(COMPLEX **c, int nx, int ny, int dir) {
	int i,j;
	int m,twopm;
	double *real,*imag;
 
	/* Transform the rows */
	real = (double *)malloc(nx * sizeof(double));
	imag = (double *)malloc(nx * sizeof(double));
	if (real == NULL || imag == NULL)
		return(FALSE);
	if (!Powerof2(nx,&m,&twopm) || twopm != nx)
		return(FALSE);
	for (j=0;j<<= m;
 
	/* N의 절반값을 half에 저장한다. */
	half = N >> 1;
 
	/* Bit Reverse를 하는 과정 */
	for ( i = 0 , j = 0 ; i < N - 1 ; i++ ) {
		if ( i < j )
		{
			swap_x = x[i];
			swap_y = y[i];
			x[i] = x[j];
			y[i] = y[j];
			x[j] = swap_x;
			y[j] = swap_y;
		}
		step = half;
 
		while ( step <= j )
		{
			j = j - k;
			k >>= 1;
		}
		j = j + step;
	}
 
	/* 초기의 값을 입력하는 부분,
	 * factor의 역할은 각 단계(Stage)에서 omega의 값을 변경하기 위한
	 * 기본 값이다. 즉 omega N= 4일 경우에는 각도가 pi/2 만큼씩 변하므로
	 * exp(-j pi/2) 의 값을 가지고 있는 것이 factor이다
	 * factor는 각 stage가 올라갈 때 마다 변경되어야 한다.
	 * 그 각도가 절반으로 줄어야 하므로
	 * cos(t) + j sin(t) 가 cos(t/2) + jsin(t/2) 로 되어야 한다.
	 * cos(t) = 2cos^2(t/2) -1 이므로 cos(t/2) = sqrt((1+cos(t))/2)이고
	 * sin(t/2) = sqrt(1-cos^2(t/2))이므로 sqrt((1-cos(t))/2) 이다.
	 */
	factor_x = -1.0;
	factor_y = 0;
	butterfly = 1;
 
	for ( stage = 0 ; stage < m ; stage++ )
	{
		/* step 은 butterfly가 두개의 샘플을 가지고 작업하므로
		 * 현재 위치에서 몇번째 샘플을 가지고 해야 하는 가를
		 * 가리키는 변수이다.
		 * butterfly는 같은 omega 값에의해 반복되는 butterfly가
		 * 존재하므로 그 위치를 가리키기 위한 값이다.
		 */
		step = butterfly;
		butterfly <<= 1;
		/* 각 단계에서 omega는 항상 1+j0으로 시작한다. */
		omega_x = 1.0;
		omega_y = 0;
		for ( numofbutter = 0 ; numofbutter < step ; numofbutter++)
		{
			for( i = numofbutter; i < N; i = i + butterfly)
			{
				/* omega_N(k) 일때 omega_N(k+N/2) = -omega_N(k)
				 * 의 성질을 이용한다. 그래서 두번째 샘플에 미리
				 * omega_N(k)를 곱한 후 결과의 처음 샘플에는
				 * 그냥 더하고 두번째 샘플에는 빼준다(-이므로)
				 */
				swap_x = x[i+step]* omega_x - y[i+step]*omega_y;
				swap_y = y[i+step]*omega_x + x[i+step]*omega_y;
 
				x[i+step] = x[i] - swap_x;
				y[i+step] = y[i] - swap_y;
 
				x[i] = x[i] + swap_x;
				y[i] = y[i] + swap_y;
 
			}
			/* 공통된 omega를 사용하는 샘플을 다 곱한 후
			 * omega를 factor의 각도만큼 증가시켜야 한다.
			 * omega(k+1) 의 값은 omega와 factor의 곱을 통해
			 * 구할 수 있다.
			 */
			swap_x = omega_x * factor_x - omega_y * factor_y;
			swap_y = omega_y * factor_x + omega_x * factor_y;
			omega_x = swap_x;
			omega_y = swap_y;
 
		}
		/* 한 단계가 끝났으므로 factor를 기존 값에서 각도가
		 * 절반인 값으로 구해야 한다.
		 */
		factor_y = sqrt((1.0+factor_x)/2.0);
		if( dir == 1)
			factor_y = -factor_y;
		factor_x = sqrt((1.0-factor_x)/2.0);
	}
	/* Inverse FFT 의 경우에는 sampling을 해줘야 한다.
	 * 다른 소스에서는 FFT의 값이 크게 나오므로 fft시에 sampling을
	 * 하고 inverse에서 안하는 경우도 있다 ( 상관없음 )
	 */
	if( dir == -1 )
	{
		for ( i = 0 ; i < N ; i++)
		{
			x[i] /= N;
			y[i] /= N;
		}
	}
 
	return TRUE;
}