fft源码,VS2010上可编译运行

本文介绍了如何在Visual Studio 2010环境下使用C语言编写并编译运行快速傅立叶变换(FFT)程序,重点讲解了关键的蝶形运算流程。

#include<math.h>
#include<stdio.h>
#include <memory>

#define FFT_COUNT	256
#define PI	3.1415926f
int FFT_R = 0;

double val[FFT_COUNT][2];
double val2[FFT_COUNT][2];
double fft_w[FFT_COUNT][2];
double fft_x1[FFT_COUNT][2];
int pos[FFT_COUNT];
double anm[FFT_COUNT];

//fft 如果isr==1表示傅氏变换时域->频域,否则表示反变换频域->时域
void fft2(double (*val_in)[2], double (*X1)[2], int isr)
{
	double  rcos = 0.0f, isin  = 0.0f;	//中间临时变量
	int mmax = 0;
	int n = 0, i=0, k=0, j=0;
	
	//重新排序输入量
	for(i = 0; i<FFT_COUNT; i++)
	{
		X1[pos[i]][0] = val_in[i][0];
		X1[pos[i]][1] = val_in[i][1] * isr; //0;//
	}

	//第一层,表示几个蝶形
	for(k=0; k<FFT_R; k++ )
	{
		mmax = 1 << ( k + 1 ); //2,4,8
		for( j = 0; j <(mmax>>1) ; j++)		//	
		{
			int wk = j * ( 1 << ( FFT_R - k - 1) );
			for( i = j; i < FFT_COUNT; i+= mmax )
			{
				n = i + ( 1 << k );
				rcos = X1[n][0] * fft_w[wk][0] - X1[n][1] * fft_w[wk][1];
				isin = X1[n][0] * fft_w[wk][1] + X1[n][1] * fft_w[wk][0];

				X1[n][0] = X1[i][0] - rcos;
				X1[n][1] = X1[i][1] - isin;
				X1[i][0] += rcos;
				X1[i][1] += isin;
			}
		}
	}
	if(isr==1)
	{
	}
	else
	{
		for(i=0; i<FFT_COUNT; i++)
		{
			X1[i][0] = X1[i][0] / FFT_COUNT;
			X1[i][1] = X1[i][1] / (-FFT_COUNT);
		}
	}
}

void main()
{
	int i = 0;
	int j = 0;
	int k = 0;
	
	FFT_R = 0;
	while( (1 << FFT_R ) <  FFT_COUNT ) FFT_R++;	//变换次数是2的多少次方

	// 倒序排序 如二进制的 011 变成 110
	for(i=0; i<FFT_COUNT; i++)
	{
		k = 0;
		for(j=0; j<FFT_R; j++)
		{
			if( ( ( i >> j ) & 1 ) == 1 )  k |= ( 1 << ( FFT_R - j-1 ) );
		}
		pos[i] = k;
	}

	//生成变换因子w
	for(i = 0; i < FFT_COUNT / 2; i++)
	{
		fft_w[i][0] = cos( -2.0f * PI * i / FFT_COUNT );
		fft_w[i][1] = sin( -2.0f * PI * i / FFT_COUNT );
	}

	//生成需要变换的模拟向量
	for(i = 0; i<FFT_COUNT; i++)
	{
		val[i][0] = sqrt(2) * cos(2 * PI * i / FFT_COUNT ) + 0.0*sqrt(2) * cos(2 * PI * i *50.0f/49.0f/ FFT_COUNT );
		val[i][1] = 0;
	}
	
	fft2(val,fft_x1, 1 );
	fft2(fft_x1, val2, -1 );		//反变换

	char bufff[10];
	float anlog = 0.0f;
	for(i=0; i<FFT_COUNT>>1; i++)
	{
		fft_x1[i][0] /= FFT_COUNT/1.41421356f;
		fft_x1[i][1] /= (-FFT_COUNT/1.41421356f);
		
		//幅值
		anm[i] = sqrt(fft_x1[i][0] * fft_x1[i][0] + fft_x1[i][1] * fft_x1[i][1]);
		anlog += fft_x1[i][0] * fft_x1[i][0] + fft_x1[i][1] * fft_x1[i][1];
		memset(bufff, 0, 10);
		sprintf(bufff, "  %3.*f",  3, anm[i]);
		for(j=9; j>0; j--)
		{
			if( bufff[j]=='0' ) bufff[j] = 0;
			if( bufff[j]=='.')
			{
				bufff[j]=0; break;
			}
			if( bufff[j]!=0) break;
		}
		 printf(bufff);
		if( (i+1) % 16==0 ) printf("\r\n");
	}
	printf("\r\n");
	printf("%.4f", (float)sqrt(anlog) );

}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值