새신랑

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(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 <stdio.h>
#include <stdlib.h>
#include <math.h>
 
#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 &lt;= nx
 * twopm = 2^m
 */
int Powerof2(int nx, int* m, int* twopm) {
	int pwr;
	*m = 0;
	for ( pwr = 1 ; pwr &lt; nx ; pwr = pwr*2) {
		*m = *m + 1;
	}
	*twopm = pwr;
	return(TRUE);
}
 
/* Fast Fourier Transform 
 * dir	: 1 = forward fft, -1 = reverse fft
 * m	: exponent, 2^m = N
 * x	: real part
 * y	: imaginary part
 */
int fft(int dir,int m,double *x,double *y)
{
	int N, half, i , j, step , stage, numofbutter, butterfly;
	double swap_x, swap_y, factor_x, factor_y, omega_x, omega_y;
 
	/* 파라미터로 넘어온 m을 통해 sample size N을 구한다 */
	N = 1;
	N <<= 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 - step;
			step >>= 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를 기존 값에서 각도가
		 * 절반인 값으로 구해야 한다.
		 */
		/*canb38#nate.com 수정 : factor_y = sqrt((1.0+factor_x)/2.0);*/
		factor_y = sqrt((1.0 - factor_x)/2.0);
		if( dir == 1)
			factor_y = -factor_y;
		/*canb38#nate.com 수정 : factor_x = sqrt((1.0-factor_x)/2.0); */
		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;
}

Comments (3)

  1. 호호할아범 wrote::

    소스정보감사합니다.^^

    월요일, 9월 8, 2008 at 16:17 #
  2. canb38@nate.com wrote::

    코드 틀렸네요
    factory = sqrt((1.0+factorx)/2.0);
    if( dir == 1)
    factory = -factory;
    factorx = sqrt((1.0-factorx)/2.0);

    이거

    factory = sqrt((1.0-factorx)/2.0);
    if( dir == 1)
    factory = -factory;
    factorx = sqrt((1.0+factorx)/2.0);

    이렇게 부호 바껴야 맞는거임

    이거 땜에 고생햇어요 ㅋㅋㅋㅋ 암튼 ㄳ

    수요일, 3월 31, 2010 at 01:08 #
  3. BLACKENGINE wrote::

    canb38님 감사합니다. ^^ 버그 수정되기 전 소스가 남아있었나봐요 ^^

    수요일, 3월 31, 2010 at 13:15 #

Trackback/Pingback (1)

  1. [...] 많은 녀석은 나온지 1년밖에 안된 FFT Source 페이지 입니다. ( 링크 ) 많은 분들이 소스를 긁어가기위해 저에게 오는군요. .. 안타까운 [...]