導航:首頁 > 編程語言 > 快速傅里葉變換及其c程序

快速傅里葉變換及其c程序

發布時間:2023-08-17 04:33:45

⑴ 基於FFT的演算法優化 要C語言完整程序(利用旋轉因子的性質),有的請留言,答謝!!!(有核心代碼,望指教

實現(C描述)

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

//#include "complex.h"

// --------------------------------------------------------------------------

#define N 8 //64

#define M 3 //6 //2^m=N

#define PI 3.1415926

// --------------------------------------------------------------------------

float twiddle[N/2] = {1.0, 0.707, 0.0, -0.707};

float x_r[N] = {1, 1, 1, 1, 0, 0, 0, 0};

float x_i[N]; //N=8

/*

float twiddle[N/2] = {1, 0.9951, 0.9808, 0.9570, 0.9239, 0.8820, 0.8317, 0.7733,

0.7075, 0.6349, 0.5561, 0.4721, 0.3835, 0.2912, 0.1961, 0.0991,

0.0000,-0.0991,-0.1961,-0.2912,-0.3835,-0.4721,-0.5561,-0.6349,

-0.7075,-0.7733, 0.8317,-0.8820,-0.9239,-0.9570,-0.9808,-0.9951}; //N=64

float x_r[N]={1,1,1,1,1,1,1,1,

1,1,1,1,1,1,1,1,

1,1,1,1,1,1,1,1,

1,1,1,1,1,1,1,1,

0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,};

float x_i[N];

*/

FILE *fp;

// ----------------------------------- func -----------------------------------

/**

* 初始化輸出虛部

*/

static void fft_init( void )

{

int i;

for(i=0; i<N; i++) x_i[i] = 0.0;

}

/**

* 反轉演算法.將時域信號重新排序.

* 這個演算法有改進的空間

*/

static void bitrev( void )

{

int p=1, q, i;

int bit_rev[ N ]; //

float xx_r[ N ]; //

bit_rev[ 0 ] = 0;

while( p < N )

{

for(q=0; q<p; q++)

{

bit_rev[ q ] = bit_rev[ q ] * 2;

bit_rev[ q + p ] = bit_rev[ q ] + 1;

}

p *= 2;

}

for(i=0; i<N; i++) xx_r[ i ] = x_r[ i ];

for(i=0; i<N; i++) x_r[i] = xx_r[ bit_rev[i] ];

}

/* ------------ add by sshc625 ------------ */

static void bitrev2( void )

{

return ;

}

/* */

void display( void )

{

printf("\n\n");

int i;

for(i=0; i<N; i++)

printf("%f\t%f\n", x_r[i], x_i[i]);

}

/**

*

*/

void fft1( void )

{ fp = fopen("log1.txt", "a+");

int L, i, b, j, p, k, tx1, tx2;

float TR, TI, temp; // 臨時變數

float tw1, tw2;

/* 深M. 對層進行循環. L為當前層, 總層數為M. */

for(L=1; L<=M; L++)

{

fprintf(fp,"----------Layer=%d----------\n", L);

/* b的意義非常重大,b表示當前層的顆粒具有的輸入樣本點數 */

b = 1;

i = L - 1;

while(i > 0)

{

b *= 2;

i--;

}

// -------------- 是否外層對顆粒循環, 內層對樣本點循環邏輯性更強一些呢! --------------

/*

* outter對參與DFT的樣本點進行循環

* L=1, 循環了1次(4個顆粒, 每個顆粒2個樣本點)

* L=2, 循環了2次(2個顆粒, 每個顆粒4個樣本點)

* L=3, 循環了4次(1個顆粒, 每個顆粒8個樣本點)

*/

for(j=0; j<b; j++)

{

/* 求旋轉因子tw1 */

p = 1;

i = M - L; // M是為總層數, L為當前層.

while(i > 0)

{

p = p*2;

i--;

}

p = p * j;

tx1 = p % N;

tx2 = tx1 + 3*N/4;

tx2 = tx2 % N;

// tw1是cos部分, 實部; tw2是sin部分, 虛數部分.

tw1 = ( tx1>=N/2)? -twiddle[tx1-N/2] : twiddle[ tx1 ];

tw2 = ( tx2>=N/2)? -twiddle[tx2-(N/2)] : twiddle[tx2];

/*

* inner對顆粒進行循環

* L=1, 循環了4次(4個顆粒, 每個顆粒2個輸入)

* L=2, 循環了2次(2個顆粒, 每個顆粒4個輸入)

* L=3, 循環了1次(1個顆粒, 每個顆粒8個輸入)

*/

for(k=j; k<N; k=k+2*b)

{

TR = x_r[k]; // TR就是A, x_r[k+b]就是B.

TI = x_i[k];

temp = x_r[k+b];

/*

* 如果復習一下 (a+j*b)(c+j*d)兩個復數相乘後的實部虛部分別是什麼

* 就能理解為什麼會如下運算了, 只有在L=1時候輸入才是實數, 之後層的

* 輸入都是復數, 為了讓所有的層的輸入都是復數, 我們只好讓L=1時候的

* 輸入虛部為0

* x_i[k+b]*tw2是兩個虛數相乘

*/

fprintf(fp, "tw1=%f, tw2=%f\n", tw1, tw2);

x_r[k] = TR + x_r[k+b]*tw1 + x_i[k+b]*tw2;

x_i[k] = TI - x_r[k+b]*tw2 + x_i[k+b]*tw1;

x_r[k+b] = TR - x_r[k+b]*tw1 - x_i[k+b]*tw2;

x_i[k+b] = TI + temp*tw2 - x_i[k+b]*tw1;

fprintf(fp, "k=%d, x_r[k]=%f, x_i[k]=%f\n", k, x_r[k], x_i[k]);

fprintf(fp, "k=%d, x_r[k]=%f, x_i[k]=%f\n", k+b, x_r[k+b], x_i[k+b]);

} //

} //

} //

}

/**

* ------------ add by sshc625 ------------

* 該實現的流程為

* for( Layer )

* for( Granule )

* for( Sample )

*

*

*

*

*/

void fft2( void )

{ fp = fopen("log2.txt", "a+");

int cur_layer, gr_num, i, k, p;

float tmp_real, tmp_imag, temp; // 臨時變數, 記錄實部

float tw1, tw2;// 旋轉因子,tw1為旋轉因子的實部cos部分, tw2為旋轉因子的虛部sin部分.

int step; // 步進

int sample_num; // 顆粒的樣本總數(各層不同, 因為各層顆粒的輸入不同)

/* 對層循環 */

for(cur_layer=1; cur_layer<=M; cur_layer++)

{

/* 求當前層擁有多少個顆粒(gr_num) */

gr_num = 1;

i = M - cur_layer;

while(i > 0)

{

i--;

gr_num *= 2;

}

/* 每個顆粒的輸入樣本數N' */

sample_num = (int)pow(2, cur_layer);

/* 步進. 步進是N'/2 */

step = sample_num/2;

/* */

k = 0;

/* 對顆粒進行循環 */

for(i=0; i<gr_num; i++)

{

/*

* 對樣本點進行循環, 注意上限和步進

*/

for(p=0; p<sample_num/2; p++)

{

// 旋轉因子, 需要優化...

tw1 = cos(2*PI*p/pow(2, cur_layer));

tw2 = -sin(2*PI*p/pow(2, cur_layer));

tmp_real = x_r[k+p];

tmp_imag = x_i[k+p];

temp = x_r[k+p+step];

/*(tw1+jtw2)(x_r[k]+jx_i[k])

*

* real : tw1*x_r[k] - tw2*x_i[k]

* imag : tw1*x_i[k] + tw2*x_r[k]

* 我想不抽象出一個

* typedef struct {

* double real; // 實部

* double imag; // 虛部

* } complex; 以及針對complex的操作

* 來簡化復數運算是否是因為效率上的考慮!

*/

/* 蝶形演算法 */

x_r[k+p] = tmp_real + ( tw1*x_r[k+p+step] - tw2*x_i[k+p+step] );

x_i[k+p] = tmp_imag + ( tw2*x_r[k+p+step] + tw1*x_i[k+p+step] );

/* X[k] = A(k)+WB(k)

* X[k+N/2] = A(k)-WB(k) 的性質可以優化這里*/

// 旋轉因子, 需要優化...

tw1 = cos(2*PI*(p+step)/pow(2, cur_layer));

tw2 = -sin(2*PI*(p+step)/pow(2, cur_layer));

x_r[k+p+step] = tmp_real + ( tw1*temp - tw2*x_i[k+p+step] );

x_i[k+p+step] = tmp_imag + ( tw2*temp + tw1*x_i[k+p+step] );

printf("k=%d, x_r[k]=%f, x_i[k]=%f\n", k+p, x_r[k+p], x_i[k+p]);

printf("k=%d, x_r[k]=%f, x_i[k]=%f\n", k+p+step, x_r[k+p+step], x_i[k+p+step]);

}

/* 開跳!:) */

k += 2*step;

}

}

}

/*

* 後記:

* 究竟是顆粒在外層循環還是樣本輸入在外層, 好象也差不多, 復雜度完全一樣.

* 但以我資質愚鈍花費了不少時間才弄明白這數十行代碼.

* 從中我發現一個於我非常有幫助的教訓, 很久以前我寫過一部分演算法, 其中絕大多數都是遞歸.

* 將數據量減少, 減少再減少, 用歸納的方式來找出數據量加大代碼的規律

* 比如FFT

* 1. 先寫死LayerI的代碼; 然後再把LayerI的輸出作為LayerII的輸入, 又寫死代碼; ......

* 大約3層就可以統計出規律來. 這和遞歸也是一樣, 先寫死一兩層, 自然就出來了!

* 2. 有的功能可以寫偽代碼, 不急於求出結果, 降低復雜性, 把邏輯結果定出來後再添加.

* 比如旋轉因子就可以寫死, 就寫1.0. 流程出來後再寫旋轉因子.

* 寥寥數語, 我可真是流了不少汗! Happy!

*/

void dft( void )

{

int i, n, k, tx1, tx2;

float tw1,tw2;

float xx_r[N],xx_i[N];

/*

* clear any data in Real and Imaginary result arrays prior to DFT

*/

for(k=0; k<=N-1; k++)

xx_r[k] = xx_i[k] = x_i[k] = 0.0;

// caculate the DFT

for(k=0; k<=(N-1); k++)

{

for(n=0; n<=(N-1); n++)

{

tx1 = (n*k);

tx2 = tx1+(3*N)/4;

tx1 = tx1%(N);

tx2 = tx2%(N);

if(tx1 >= (N/2))

tw1 = -twiddle[tx1-(N/2)];

else

tw1 = twiddle[tx1];

if(tx2 >= (N/2))

tw2 = -twiddle[tx2-(N/2)];

else

tw2 = twiddle[tx2];

xx_r[k] = xx_r[k]+x_r[n]*tw1;

xx_i[k] = xx_i[k]+x_r[n]*tw2;

}

xx_i[k] = -xx_i[k];

}

// display

for(i=0; i<N; i++)

printf("%f\t%f\n", xx_r[i], xx_i[i]);

}

// ---------------------------------------------------------------------------

int main( void )

{

fft_init( );

bitrev( );

// bitrev2( );

//fft1( );

fft2( );

display( );

system( "pause" );

// dft();

return 1;

}

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/sshcx/archive/2007/06/14/1651616.aspx

⑵ 急求 快速傅里葉變換的程序 會的大俠幫忙做一個~

以前用FFT都是直接用Matlab裡面的,可是如果實際工程裡面需要,還是得寫一個C語言版本的。C++處理復數比較容易,但目前嵌入式開發還是C語言的天下,因此C語言的FFT應用起來更方便。寫完貼出來,希望對大家有一些幫助。貼出來排版可能有點亂,那不是我的原因,我寫的程序都是整整齊齊的,可以直接點擊文章後面的目錄下載源程序。
最近C程序寫的比較多,C++好久不寫,有點荒廢了。。。
/**
* FFT - Fast Fourier transform. The length of X must be a power
* of two, for a fast radix-2 fast-Fourier transform algorithm
* is used. spadger@bmy <[email protected]> 2007.9.2
*/

#i nclude <math.h>
#i nclude <stdio.h>

#define M_PI 3.14159265358979323846

typedef struct { double r,i; } cplx_t;

void cplx_mul(cplx_t *x, cplx_t *y, cplx_t *r)
{
r->r=x->r*y->r-x->i*y->i;
r->i=x->r*y->i+x->i*y->r;
}

void cplx_exp(cplx_t *x, cplx_t *r)
{
double expx=exp(x->r);
r->r=expx*cos(x->i);
r->i=expx*sin(x->i);
}

void bit_reverse(cplx_t *x, int N)
{
double t;
cplx_t tmp;
unsigned int i=0,j=0,k=0;
for(i=0; i<N; i++) {
k=i;
j=0;
t=log(0.0+N)/log(2.0);
while((t--)>0) {
j<<=1;
j|=k&1;
k>>=1;
}
if(j>i) {
tmp=x[i];
x[i]=x[j];
x[j]=tmp;
}
}
}

void fft(cplx_t *x, int N)
{
cplx_t u,d,p,W,tmp;
int i=0,j=0,k=0,l=0,M=floor(log(0.0+N)/log(2.0));
if(log(0.0+N)/log(2.0)-M > 0){
printf("The length of x (N) must be a power of two!!!\n");
return;
}
bit_reverse(x,N);
for(i=0; i<M; i++) {
l=1<<i;
for(j=0; j<N; j+=2*l ) {
for(k=0; k<l; k++) {
tmp.r=0.0;
tmp.i=-2*M_PI*k/2/l;
cplx_exp(&tmp,&W);
cplx_mul(&x[j+k+l],&W,&p);
u.r=x[j+k].r+p.r;
u.i=x[j+k].i+p.i;
d.r=x[j+k].r-p.r;
d.i=x[j+k].i-p.i;
x[j+k]=u;
x[j+k+l]=d;
}
}
}
}

/**
* for test and demonstation, set '#if 0' to comment this out.
*/
#if 1
#define DATA_LEN 64
int main()
{
int i;
cplx_t x[DATA_LEN];
for(i=0;i<DATA_LEN;i++){
x[i].r=i;
x[i].i=0;
}

printf("Before...\nReal\t\tImag\n");
for(i=0;i<DATA_LEN;i++)
printf("%f\t%f\n",x[i].r,x[i].i);

fft(x,DATA_LEN);

printf("After...\nReal\t\tImag\n");
for(i=0;i<DATA_LEN;i++)
printf("%f\t%f\n",x[i].r,x[i].i);

return 0;
}
#endif
源程序下載:
http://www.blog.com.cn/user88/spadger/upload/92271850.rar

⑶ 傅里葉變換用C語言程序怎麼實現

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

#define N 8

void kkfft(double pr[], double pi[], int n, int k, double fr[], double fi[], int l, int il);
void main()
{
double xr[N],xi[N],Yr[N],Yi[N],l=0,il=0;
int i,j,n=N,k=3;
for(i=0;i<N;i++)
{
xr[i]=i;
xi[i]=0;
}
printf("------FFT------\n");
l=0;
kkfft(xr,xi,n,k,Yr,Yi,l,il);
for(i=0;i<N;i++)
{
printf("%-11lf + j* %-11lf\n",Yr[i],Yi[i]);
}

printf("-----DFFT-------\n");
l=1;
kkfft(Yr,Yi,n,k,xr,xi,l,il);
for(i=0;i<N;i++)
{
printf("%-11lf + j* %-11lf\n",xr[i],xi[i]);
}
getch();
}

void kkfft(double pr[], double pi[], int n, int k, double fr[], double fi[], int l, int il)
{
int it,m,is,i,j,nv,l0;
double p,q,s,vr,vi,poddr,poddi;
for (it=0; it<=n-1; it++)
{
m = it;
is = 0;
for(i=0; i<=k-1; i++)
{
j = m/2;
is = 2*is+(m-2*j);
m = j;
}
fr[it] = pr[is];
fi[it] = pi[is];
}

pr[0] = 1.0;
pi[0] = 0.0;
p = 6.283185306/(1.0*n);
pr[1] = cos(p);
pi[1] = -sin(p);

if (l!=0)
pi[1]=-pi[1];

for (i=2; i<=n-1; i++)
{
p = pr[i-1]*pr[1];
q = pi[i-1]*pi[1];
s = (pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
pr[i] = p-q;
pi[i] = s-p-q;
}

for (it=0; it<=n-2; it=it+2)
{
vr = fr[it];
vi = fi[it];
fr[it] = vr+fr[it+1];
fi[it] = vi+fi[it+1];
fr[it+1] = vr-fr[it+1];
fi[it+1] = vi-fi[it+1];
}
m = n/2;
nv = 2;

for (l0=k-2; l0>=0; l0--)
{
m = m/2;
nv = 2*nv;
for(it=0; it<=(m-1)*nv; it=it+nv)
for (j=0; j<=(nv/2)-1; j++)
{
p = pr[m*j]*fr[it+j+nv/2];
q = pi[m*j]*fi[it+j+nv/2];
s = pr[m*j]+pi[m*j];
s = s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
poddr = p-q;
poddi = s-p-q;
fr[it+j+nv/2] = fr[it+j]-poddr;
fi[it+j+nv/2] = fi[it+j]-poddi;
fr[it+j] = fr[it+j]+poddr;
fi[it+j] = fi[it+j]+poddi;
}
}

/*逆傅立葉變換*/
if(l!=0)
{
for(i=0; i<=n-1; i++)
{
fr[i] = fr[i]/(1.0*n);
fi[i] = fi[i]/(1.0*n);
}
}

/*是否計算模和相角*/
if(il!=0)
{
for(i=0; i<=n-1; i++)
{
pr[i] = sqrt(fr[i]*fr[i]+fi[i]*fi[i]);
if(fabs(fr[i])<0.000001*fabs(fi[i]))
{
if ((fi[i]*fr[i])>0)
pi[i] = 90.0;
else
pi[i] = -90.0;
}
else
pi[i] = atan(fi[i]/fr[i])*360.0/6.283185306;
}
}
return;
}

⑷ 求FFT的c語言程序

快速傅里葉變換 要用C++ 才行吧 你可以用MATLAB來實現更方便點啊

此FFT 是用.0編寫,由FFT.CPP;STDAFX.H和STDAFX.CPP三個文件組成,編譯成功。程序可以用文件輸入和輸出為文件。文件格式為TXT文件。測試結果如下:

輸入文件:8.TXT 或手動輸入

8 //N

1

2

3

4

5

6

7

8

輸出結果為:或保存為TXT文件。(8OUT.TXT)

8

(36,0)

(-4,9.65685)

(-4,4)

(-4,1.65685)

(-4,0)

(-4,-1.65685)

(-4,-4)

(-4,-9.65685)

下面為FFT.CPP文件:

// FFT.cpp : 定義控制台應用程序的入口點。

#include "stdafx.h"

#include <iostream>

#include <complex>

#include <bitset>

#include <vector>

#include <conio.h>

#include <string>

#include <fstream>

using namespace std;

bool inputData(unsigned long &, vector<complex<double> >&); //手工輸入數據

void FFT(unsigned long &, vector<complex<double> >&); //FFT變換

void display(unsigned long &, vector<complex<double> >&); //顯示結果

bool readDataFromFile(unsigned long &, vector<complex<double> >&); //從文件中讀取數據

bool saveResultToFile(unsigned long &, vector<complex<double> >&); //保存結果至文件中

const double PI = 3.1415926;

int _tmain(int argc, _TCHAR* argv[])

{

vector<complex<double> > vecList; //有限長序列

unsigned long ulN = 0; //N

char chChoose = ' '; //功能選擇

//功能循環

while(chChoose != 'Q' && chChoose != 'q')

{

//顯示選擇項

cout << "\nPlease chose a function" << endl;

cout << "\t1.Input data manually, press 'M':" << endl;

cout << "\t2.Read data from file, press 'F':" << endl;

cout << "\t3.Quit, press 'Q'" << endl;

cout << "Please chose:";

//輸入選擇

chChoose = getch();

//判斷

switch(chChoose)

{

case 'm': //手工輸入數據

case 'M':

if(inputData(ulN, vecList))

{

FFT(ulN, vecList);

display(ulN, vecList);

saveResultToFile(ulN, vecList);

}

break;

case 'f': //從文檔讀取數據

case 'F':

if(readDataFromFile(ulN, vecList))

{

FFT(ulN, vecList);

display(ulN, vecList);

saveResultToFile(ulN, vecList);

}

break;

}

}

return 0;

}

bool Is2Power(unsigned long ul) //判斷是否是2的整數次冪

{

if(ul < 2)

return false;

while( ul > 1 )

{

if( ul % 2 )

return false;

ul /= 2;

}

return true;

}

bool inputData(unsigned long & ulN, vector<complex<double> >& vecList)

{

//題目

cout<< "\n\n\n==============================Input Data===============================" << endl;

//輸入N

cout<< "\nInput N:";

cin>>ulN;

if(!Is2Power(ulN)) //驗證N的有效性

{

cout<< "N is invalid (N must like 2, 4, 8, .....), please retry." << endl;

return false;

}

//輸入各元素

vecList.clear(); //清空原有序列

complex<double> c;

for(unsigned long i = 0; i < ulN; i++)

{

cout << "Input x(" << i << "):";

cin >> c;

vecList.push_back(c);

}

return true;

}

bool readDataFromFile(unsigned long & ulN, vector<complex<double> >& vecList) //從文件中讀取數據

{

//題目

cout<< "\n\n\n===============Read Data From File==============" << endl;

//輸入文件名

string strfilename;

cout << "Input filename:" ;

cin >> strfilename;

//打開文件

cout << "open file " << strfilename << "......." <<endl;

ifstream loadfile;

loadfile.open(strfilename.c_str());

if(!loadfile)

{

cout << "\tfailed" << endl;

return false;

}

else

{

cout << "\tsucceed" << endl;

}

vecList.clear();

//讀取N

loadfile >> ulN;

if(!loadfile)

{

cout << "can't get N" << endl;

return false;

}

else

{

cout << "N = " << ulN << endl;

}

//讀取元素

complex<double> c;

for(unsigned long i = 0; i < ulN; i++)

{

loadfile >> c;

if(!loadfile)

{

cout << "can't get enough infomation" << endl;

return false;

}

else

cout << "x(" << i << ") = " << c << endl;

vecList.push_back(c);

}

//關閉文件

loadfile.close();

return true;

}

bool saveResultToFile(unsigned long & ulN, vector<complex<double> >& vecList) //保存結果至文件中

{

//詢問是否需要將結果保存至文件

char chChoose = ' ';

cout << "Do you want to save the result to file? (y/n):";

chChoose = _getch();

if(chChoose != 'y' && chChoose != 'Y')

{

return true;

}

//輸入文件名

string strfilename;

cout << "\nInput file name:" ;

cin >> strfilename;

cout << "Save result to file " << strfilename << "......" << endl;

//打開文件

ofstream savefile(strfilename.c_str());

if(!savefile)

{

cout << "can't open file" << endl;

return false;

}

//寫入N

savefile << ulN << endl;

//寫入元素

for(vector<complex<double> >::iterator i = vecList.begin(); i < vecList.end(); i++)

{

savefile << *i << endl;

}

//寫入完畢

cout << "save succeed." << endl;

//關閉文件

savefile.close();

return true;

}

void FFT(unsigned long & ulN, vector<complex<double> >& vecList)

{

//得到冪數

unsigned long ulPower = 0; //冪數

unsigned long ulN1 = ulN - 1;

while(ulN1 > 0)

{

ulPower++;

ulN1 /= 2;

}

//反序

bitset<sizeof(unsigned long) * 8> bsIndex; //二進制容器

unsigned long ulIndex; //反轉後的序號

unsigned long ulK;

for(unsigned long p = 0; p < ulN; p++)

{

ulIndex = 0;

ulK = 1;

bsIndex = bitset<sizeof(unsigned long) * 8>(p);

for(unsigned long j = 0; j < ulPower; j++)

{

ulIndex += bsIndex.test(ulPower - j - 1) ? ulK : 0;

ulK *= 2;

}

if(ulIndex > p)

{

complex<double> c = vecList[p];

vecList[p] = vecList[ulIndex];

vecList[ulIndex] = c;

}

}

//計算旋轉因子

vector<complex<double> > vecW;

for(unsigned long i = 0; i < ulN / 2; i++)

{

vecW.push_back(complex<double>(cos(2 * i * PI / ulN) , -1 * sin(2 * i * PI / ulN)));

}

for(unsigned long m = 0; m < ulN / 2; m++)

{

cout<< "\nvW[" << m << "]=" << vecW[m];

}

//計算FFT

unsigned long ulGroupLength = 1; //段的長度

unsigned long ulHalfLength = 0; //段長度的一半

unsigned long ulGroupCount = 0; //段的數量

complex<double> cw; //WH(x)

complex<double> c1; //G(x) + WH(x)

complex<double> c2; //G(x) - WH(x)

for(unsigned long b = 0; b < ulPower; b++)

{

ulHalfLength = ulGroupLength;

ulGroupLength *= 2;

for(unsigned long j = 0; j < ulN; j += ulGroupLength)

{

for(unsigned long k = 0; k < ulHalfLength; k++)

{

cw = vecW[k * ulN / ulGroupLength] * vecList[j + k + ulHalfLength];

c1 = vecList[j + k] + cw;

c2 = vecList[j + k] - cw;

vecList[j + k] = c1;

vecList[j + k + ulHalfLength] = c2;

}

}

}

}

void display(unsigned long & ulN, vector<complex<double> >& vecList)

{

cout << "\n\n===========================Display The Result=========================" << endl;

for(unsigned long d = 0; d < ulN;d++)

{

cout << "X(" << d << ")\t\t\t = " << vecList[d] << endl;

}

}

下面為STDAFX.H文件:

// stdafx.h : 標准系統包含文件的包含文件,

// 或是常用但不常更改的項目特定的包含文件

#pragma once

#include <iostream>

#include <tchar.h>

// TODO: 在此處引用程序要求的附加頭文件

下面為STDAFX.CPP文件:

// stdafx.cpp : 只包括標准包含文件的源文件

// FFT.pch 將成為預編譯頭

// stdafx.obj 將包含預編譯類型信息

#include "stdafx.h"

// TODO: 在 STDAFX.H 中

//引用任何所需的附加頭文件,而不是在此文件中引用

⑸ 誰會GUI設計我需要做一個快速傅里葉變換的演示程序 急!!!

程序如下,把「lpk..."改成你需要的文件夾的名字,或者把文件夾名字改了。function varargout = lpkfft(varargin)% LPKFFT M-file for lpkfft.fig% LPKFFT, by itself, creates a new LPKFFT or raises the existing% singleton*.%% H = LPKFFT returns the handle to a new LPKFFT or the handle to% the existing singleton*.%% LPKFFT('CALLBACK',hObject,eventData,handles,...) calls the local% function named CALLBACK in LPKFFT.M with the given input arguments.%% LPKFFT('Property','Value',...) creates a new LPKFFT or raises the% existing singleton*. Starting from the left, property value pairs are% applied to the GUI before lpkfft_OpeningFcn gets called. An% unrecognized property name or invalid value makes property application% stop. All inputs are passed to lpkfft_OpeningFcn via varargin.%% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one% instance to run (singleton)".%% See also: GUIDE, GUIDATA, GUIHANDLES % Edit the above text to modify the response to help lpkfft % Last Modified by GUIDE v2.5 20-Dec-2010 22:21:43 % Begin initialization code - DO NOT EDITgui_Singleton = 1;gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @lpkfft_OpeningFcn, ... 'gui_OutputFcn', @lpkfft_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []);if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1});end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});else gui_mainfcn(gui_State, varargin{:});end% End initialization code - DO NOT EDIT % --- Executes just before lpkfft is made visible.function lpkfft_OpeningFcn(hObject, eventdata, handles, varargin)% This function has no output args, see OutputFcn.% hObject handle to figure% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)% varargin command line arguments to lpkfft (see VARARGIN) % Choose default command line output for lpkffthandles.output = hObject; % Update handles structureguidata(hObject, handles); % UIWAIT makes lpkfft wait for user response (see UIRESUME)% uiwait(handles.figure1); % --- Outputs from this function are returned to the command line.function varargout = lpkfft_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT);% hObject handle to figure% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA) % Get default command line output from handles structurevarargout{1} = handles.output; % --- Executes on button press in chushi.function kaishi_Callback(hObject, eventdata, handles)% hObject handle to chushi (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)N=64;n=0:127;x=cos(14*pi*n/N)+1/2*cos(38*pi*n/N); plot(handles.chushi,n,x,'-g');set(handles.chushi,'XGrid','on','YGrid','on');title(handles.chushi,'x(n)'); % --- Executes on button press in fd.function fd_Callback(hObject, eventdata, handles)% hObject handle to fd (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA) N=64;n=0:127;x=cos(14*pi*n/N)+1/2*cos(38*pi*n/N);X=fft(x);X1=abs(X);plot(handles.fd1,n,X1,'-r');set(handles.fd1,'XGrid','on','YGrid','on');title(handles.fd1,'幅度'); % --- Executes on button press in xw.function xw_Callback(hObject, eventdata, handles)% hObject handle to xw (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)N=64;n=0:127;x=cos(14*pi*n/N)+1/2*cos(38*pi*n/N);X=fft(x);X1=angle(X);stem(handles.xw1,n,X1,'*');set(handles.xw1,'XGrid','on','YGrid','on');title(handles.xw1,'相位'); % --- Executes on button press in clr.function clr_Callback(hObject, eventdata, handles)% hObject handle to clr (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)try delete(allchild(handles.chushi)); delete(allchild(handles.fd1)); delete(allchild(handles.xw1));end % --- Executes on button press in chushi.function kaishi_Callback(hObject, eventdata, handles)% hObject handle to chushi (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)

⑹ 怎樣用C語言實現FFT演算法啊

1、二維FFT相當於對行和列分別進行一維FFT運算。具體的實現辦法如下:
先對各行逐一進行一維FFT,然後再對變換後的新矩陣的各列逐一進行一維FFT。相應的偽代碼如下所示:
for (int i=0; i<M; i++)
FFT_1D(ROW[i],N);
for (int j=0; j<N; j++)
FFT_1D(COL[j],M);
其中,ROW[i]表示矩陣的第i行。注意這只是一個簡單的記法,並不能完全照抄。還需要通過一些語句來生成各行的數據。同理,COL[i]是對矩陣的第i列的一種簡單表示方法。
所以,關鍵是一維FFT演算法的實現。

2、常式:

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#defineN1000
/*定義復數類型*/
typedefstruct{
doublereal;
doubleimg;
}complex;
complexx[N],*W;/*輸入序列,變換核*/
intsize_x=0;/*輸入序列的大小,在本程序中僅限2的次冪*/
doublePI;/*圓周率*/
voidfft();/*快速傅里葉變換*/
voidinitW();/*初始化變換核*/
voidchange();/*變址*/
voidadd(complex,complex,complex*);/*復數加法*/
voidmul(complex,complex,complex*);/*復數乘法*/
voidsub(complex,complex,complex*);/*復數減法*/
voidoutput();
intmain(){
inti;/*輸出結果*/
system("cls");
PI=atan(1)*4;
printf("Pleaseinputthesizeofx: ");
scanf("%d",&size_x);
printf("Pleaseinputthedatainx[N]: ");
for(i=0;i<size_x;i++)
scanf("%lf%lf",&x[i].real,&x[i].img);
initW();
fft();
output();
return0;
}
/*快速傅里葉變換*/
voidfft(){
inti=0,j=0,k=0,l=0;
complexup,down,proct;
change();
for(i=0;i<log(size_x)/log(2);i++){/*一級蝶形運算*/
l=1<<i;
for(j=0;j<size_x;j+=2*l){/*一組蝶形運算*/
for(k=0;k<l;k++){/*一個蝶形運算*/
mul(x[j+k+l],W[size_x*k/2/l],&proct);
add(x[j+k],proct,&up);
sub(x[j+k],proct,&down);
x[j+k]=up;
x[j+k+l]=down;
}
}
}
}
/*初始化變換核*/
voidinitW(){
inti;
W=(complex*)malloc(sizeof(complex)*size_x);
for(i=0;i<size_x;i++){
W[i].real=cos(2*PI/size_x*i);
W[i].img=-1*sin(2*PI/size_x*i);
}
}
/*變址計算,將x(n)碼位倒置*/
voidchange(){
complextemp;
unsignedshorti=0,j=0,k=0;
doublet;
for(i=0;i<size_x;i++){
k=i;j=0;
t=(log(size_x)/log(2));
while((t--)>0){
j=j<<1;
j|=(k&1);
k=k>>1;
}
if(j>i){
temp=x[i];
x[i]=x[j];
x[j]=temp;
}
}
}
/*輸出傅里葉變換的結果*/
voidoutput(){
inti;
printf("Theresultareasfollows ");
for(i=0;i<size_x;i++){
printf("%.4f",x[i].real);
if(x[i].img>=0.0001)printf("+%.4fj ",x[i].img);
elseif(fabs(x[i].img)<0.0001)printf(" ");
elseprintf("%.4fj ",x[i].img);
}
}
voidadd(complexa,complexb,complex*c){
c->real=a.real+b.real;
c->img=a.img+b.img;
}
voidmul(complexa,complexb,complex*c){
c->real=a.real*b.real-a.img*b.img;
c->img=a.real*b.img+a.img*b.real;
}
voidsub(complexa,complexb,complex*c){
c->real=a.real-b.real;
c->img=a.img-b.img;
}

⑺ 一個關於128點的快速傅立葉的C語言程序

這是我寫的1024點的快速傅里葉變換程序,下面有驗證,你把數組
double A[2049]={0};
double B[1100]={0};
double powerA[1025]={0};

改成 A[256]={0};
B[130]={0};
power[129]={0};就行了,
void FFT(double data[], int nn, int isign)

的程序可以針對任何點數,只要是2的n次方
具體程序如下:
#include <iostream.h>
#include "math.h"
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include <fstream.h>
#include <afx.h>

void FFT(double data[], int nn, int isign)
{
//復數的快速傅里葉變換
int n,j,i,m,mmax,istep;
double tempr,tempi,theta,wpr,wpi,wr,wi,wtemp;
n = 2 * nn;
j = 1;
for (i = 1; i<=n ; i=i+2) //這個循環進行的是碼位倒置。
{
if( j > i)
{
tempr = data[j];
tempi = data[j + 1];
data[j] = data[i];
data[j + 1] = data[i + 1];
data[i] = tempr;
data[i + 1] = tempi;
}
m = n / 2;
while (m >= 2 && j > m)
{
j = j - m;
m = m / 2;
}
j = j + m;
}
mmax = 2;
while( n > mmax )
{
istep = 2 * mmax; //這里表示一次的數字的變化。也體現了級數,若第一級時,也就是書是的第0級,其為兩個虛數,所以對應數組應該增加4,這樣就可以進入下一組運算
theta = -6.28318530717959 / (isign * mmax);
wpr = -2.0 * sin(0.5 * theta)*sin(0.5 * theta);
wpi = sin(theta);
wr = 1.0;
wi = 0.0;
for( m = 1; m<=mmax; m=m+2)
{
for (i = m; i<=n; i=i+istep)
{
j = i + mmax;
tempr=double(wr)*data[j]-double(wi)*data[j+1];//這兩句表示蝶形因子的下一個數乘以W因子所得的實部和虛部。
tempi=double(wr)*data[j+1]+double(wi)*data[j];
data[j] = data[i] - tempr; //蝶形單元計算後下面單元的實部,下面為虛部,注意其變換之後的數組序號與書上蝶形單元是一致的
data[j + 1] = data[i + 1] - tempi;
data[i] = data[i] + tempr;
data[i + 1] = data[i + 1] + tempi;
}
wtemp = wr;
wr = wr * wpr - wi * wpi + wr;
wi = wi * wpr + wtemp * wpi + wi;
}
mmax = istep;
}

}

void main()
{
//本程序已經和MATLAB運算結果對比,准確無誤,需要注意的的是,計算中數組都是從1開始取得,丟棄了A[0]等數據
double A[2049]={0};
double B[1100]={0};
double powerA[1025]={0};
char line[50];
char dataA[20], dataB[20];
int ij;
char ch1[3]="\t";
char ch2[3]="\n";
int strl1,strl2;
CString str1,str2;
ij=1;
//********************************讀入文件data1024.txt中的數據, 其中的數據格式見該文件
FILE *fp = fopen("data1024.txt","r");
if(!fp)
{
cout<<"Open file is failing!"<<endl;
return;
}

while(!feof(fp)) //feof(fp)有兩個返回值:如果遇到文件結束,函數feof(fp)的值為1,否則為0。
{
memset(line,0,50); //清空為0
memset(dataA,0,20);
memset(dataB,0,20);

fgets(line,50,fp); //函數的功能是從fp所指文件中讀入n-1個字元放入line為起始地址的空間內

sscanf(line, "%s%s", dataA, dataB); //我同時讀入了兩列值,但你要求1024個,那麼我就只用了第一列的1024個值
//dataA讀入第一列,dataB讀入第二列
B[ij]=atof(dataA); //將字元型的dataA值轉化為float型
ij++;
}

for (int mm=1;mm<1025;mm++)//A[2*mm-1]是實部,A[2*mm]是虛部,當只要輸入實數時,那麼保證虛部A[mm*2]為零即可
{
A[2*mm-1]=B[mm];
A[2*mm]=0;

}
//*******************************************正式計算FFT
FFT(A,1024,1);
//********************************************寫入數據到workout.txt文件中

for (int k=1;k<2049;k=k+2)
{
powerA[(k+1)/2]=sqrt(pow(A[k],2.0)+pow(A[k+1],2.0));//求功率譜

FILE *pFile=fopen("workout.txt","a+"); //?a+只能在文件最後補充,游標在結尾。沒有則創建
memset(ch1,0,15);

str1.Format("%.4f",powerA[(k+1)/2]);
if (A[k+1]>=0)
str2.Format("%d\t%6.4f%s%6.4f %s",(k+1)/2,A[k],"+",A[k+1],"i");//保存fft計算的頻譜,是復數頻譜
else
str2.Format("%d\t%6.4f%6.4f %s",(k+1)/2,A[k],A[k+1],"i");

strl1=strlen(str1);
strl2=strlen(str2);
// 用 法:fwrite(buffer,size,count,fp);
// buffer:是一個指針,對fwrite來說,是要輸出數據的地址。
// size:要寫入的位元組數;
// count:要進行寫入size位元組的數據項的個數;
// fp:目標文件指針。
fwrite(str2,1,strl2,pFile);
fwrite(ch1,1,3,pFile);
fwrite(ch1,1,3,pFile);
fwrite(str1,1,strl1,pFile);
fwrite(ch2,1,3,pFile);
fclose(pFile);
}
cout<<"計算完畢,到fft_test\workout.txt查看結果"<<endl;
}

閱讀全文

與快速傅里葉變換及其c程序相關的資料

熱點內容
日本蘋果66g多少錢 瀏覽:93
個性的文件夾名稱 瀏覽:697
怎麼設置文件打開密碼 瀏覽:811
手機版qq客服代碼怎麼用 瀏覽:24
fme可以打開哪些文件 瀏覽:339
好看的qq密碼 瀏覽:293
安卓唯一標識有哪些 瀏覽:243
win10ime 瀏覽:271
手機號大數據保護停機是什麼意思 瀏覽:81
兩個蘋果手機怎麼隔空投送app 瀏覽:903
ps修改有褶皺的文件 瀏覽:417
javadbfreader 瀏覽:307
蘋果手機數字代碼是什麼 瀏覽:66
驅動程序順序安裝腳本 瀏覽:665
word文件里怎樣查重 瀏覽:219
mx5系統基帶版本 瀏覽:184
ntlea全域通win10 瀏覽:171
qq怎麼查看別人的收藏 瀏覽:135
地震三參數matlab程序 瀏覽:57
怎樣給優盤文件加密軟體 瀏覽:7

友情鏈接