當前位置:首頁 » 操作系統 » cfft演算法實現

cfft演算法實現

發布時間: 2023-03-16 19:53:45

⑴ 實序列的FFT演算法

在以上討論FFT演算法中,均假定序列x(l)為復的,但實際問題中的序列大多為實的。當然,我們可以把實序列處理成虛部為零的復序列。因此,就要引進許多零參加運算。這樣一來,在機器運算時間和存儲單元方面都將造成很大的浪費。在本段中,我們介紹對實序列x(l)應用FFT演算法的一個有效方法。

1.同時計算兩個實序列的FFT演算法

設有N=4的兩個實序列x1(l)與x2(l)。為了求得它們的譜X1(m)與X2(m),我們用此二實序列構造成如下復序列

物探數字信號分析與處理技術

利用上一段的方法,可以求得復序列x(l)的譜X(m)。根據(7-3-1)得到

物探數字信號分析與處理技術

上式中的m用N-m代替,則得

物探數字信號分析與處理技術

將上式兩端取共軛,根據對稱性有

物探數字信號分析與處理技術

根據DFT的復共軛性質,對於實序列x1(l)與x2(l),有

物探數字信號分析與處理技術

於是從(7-3-4)得到

物探數字信號分析與處理技術

聯立求解(7-3-2)和(7-3-6)便得到

物探數字信號分析與處理技術

例如設有兩個N=4點的實序列,

物探數字信號分析與處理技術

我們用它們構造一個N=4點的復序列

物探數字信號分析與處理技術

利用FFT演算法求X(m),m=0,1,2,3(圖7-3-1),

圖7-3-1 N=4點的FFT演算法流程圖

於是得到

物探數字信號分析與處理技術

因此從式(7-3-7)得到

物探數字信號分析與處理技術

物探數字信號分析與處理技術

2.實序列的FFT演算法

設有N點的實序列x(l),l=0,1,2,…,N-1。按照點的奇偶編號,將它們分成N/2個點的兩個子序列

物探數字信號分析與處理技術

設x1(l)的譜與x2(l)的譜分別為X1(m)與X2(m)

物探數字信號分析與處理技術

其中

於是可以將實序列x(l)的譜X(m),用兩個子序列x1(l),x2(l)的譜X1(m),X2(m)來表示

物探數字信號分析與處理技術

其中

物探數字信號分析與處理技術

注意,x1(l),x2(l)與X1(m),X2(m)均以N/2為周期,

利用x1(l)、x2(l)構成如下復序列

物探數字信號分析與處理技術

利用FFT演算法可以求得復序列 的譜 。根據(7-3-7)就求得兩個實子序列的譜X1(m)與X2(m)

物探數字信號分析與處理技術

有了X1(m),X2(m),根據(7-3-10)就可求得X(m)。以上就是用FFT演算法求實序列x(l)的譜X(m)的方法。必須指出,用公式(7-3-10)求X(m)時,第一,兩個實子序列的譜X1(m),X2(m)及復序列x珓(l)的譜珘X(m)均是以N/2為周期的周期序列;第二,由於x

(l)是實序列,根據DFT的復共軛性質有X(m)=X*(N-m),m=0,1,…,N/2,故只需求得前(N/2)+1個點的X(m),就得到全部N個點的X(m)了

例如,有N=8點的實序列,

物探數字信號分析與處理技術

首先,按點的奇偶編號分成兩個實子序列,

物探數字信號分析與處理技術

其次用它們構造如下復序列,

物探數字信號分析與處理技術

用FFT演算法求此復序列的譜 (圖7-3-2)

圖7-3-2 N=4點的FFT演算法流程圖

於是得到:

根據周期性,有

物探數字信號分析與處理技術

根據(7-3-12)式,

物探數字信號分析與處理技術

根據周期性,有

物探數字信號分析與處理技術

故最終由(7-3-10)得到

物探數字信號分析與處理技術

⑵ 怎樣用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;
}

⑶ 怎麼用C語言實現FFT演算法 呀

float ar[1024],ai[1024];/* 原始數據實部,虛部 */
float a[2050];

void fft(int nn) /* nn數據長度 */
{
int n1,n2,i,j,k,l,m,s,l1;
float t1,t2,x,y;
float w1,w2,u1,u2,z;
float fsin[10]={0.000000,1.000000,0.707107,0.3826834,0.1950903,0.09801713,0.04906767,0.02454123,0.01227154,0.00613588,};
float fcos[10]={-1.000000,0.000000,0.7071068,0.9238796,0.9807853,0.99518472,0.99879545,0.9996988,0.9999247,0.9999812,};

switch(nn)
{
case 1024: s=10; break;
case 512: s=9; break;
case 256: s=8; break;
}

n1=nn/2; n2=nn-1;
j=1;
for(i=1;i<=nn;i++)
{
a[2*i]=ar[i-1];
a[2*i+1]=ai[i-1];
}
for(l=1;l<n2;l++)
{
if(l<j)
{
t1=a[2*j];
t2=a[2*j+1];
a[2*j]=a[2*l];
a[2*j+1]=a[2*l+1];
a[2*l]=t1;
a[2*l+1]=t2;
}
k=n1;
while (k<j)
{
j=j-k;
k=k/2;
}
j=j+k;
}
for(i=1;i<=s;i++)
{
u1=1;
u2=0;
m=(1<<i);
k=m>>1;
w1=fcos[i-1];
w2=-fsin[i-1];
for(j=1;j<=k;j++)
{
for(l=j;l<nn;l=l+m)
{
l1=l+k;
t1=a[2*l1]*u1-a[2*l1+1]*u2;
t2=a[2*l1]*u2+a[2*l1+1]*u1;
a[2*l1]=a[2*l]-t1;
a[2*l1+1]=a[2*l+1]-t2;
a[2*l]=a[2*l]+t1;
a[2*l+1]=a[2*l+1]+t2;
}
z=u1*w1-u2*w2;
u2=u1*w2+u2*w1;
u1=z;
}
}
for(i=1;i<=nn/2;i++)
{
ar[i]=4*a[2*i+2]/nn; /* 實部 */
ai[i]=-4*a[2*i+3]/nn; /* 虛部 */
a[i]=4*sqrt(ar[i]*ar[i]+ai[i]*ai[i]); /* 幅值 */
}
}

(http://..com/question/284943905.html?an=0&si=2)

⑷ FFT原理的FFT基本原理

FFT是一種DFT的高效演算法,稱為快速傅立葉變換(fast Fourier transform)。FFT演算法可分為按時間抽取演算法和按頻率抽取演算法,先簡要介紹FFT的基本原理。從DFT運算開始,說明FFT的基本原理。
DFT的運算為:

式中

由這種方法計算DFT對於X(K)的每個K值,需要進行4N次實數相乘和(4N-2)次相加,對於N個k值,共需N*N乘和N(4N-2)次實數相加。改進DFT演算法,減小它的運算量,利用DFT中

的周期性和對稱性,使整個DFT的計算變成一系列迭代運算,可大幅度提高運算過程和運算量,這就是FFT的基本思想。
FFT基本上可分為兩類,時間抽取法和頻率抽取法,而一般的時間抽取法和頻率抽取法只能處理長度N=2^M的情況,另外還有組合數基四FFT來處理一般長度的FFT 設N點序列x(n),,將x(n)按奇偶分組,公式如下圖

改寫為:

一個N點DFT分解為兩個 N/2點的DFT,繼續分解,迭代下去,其運算量約為

其演算法有如下規律
兩個4點組成的8點DFT

四個2點組成的8點DFT
按時間抽取的8點DFT
原位計算
當數據輸入到存儲器中以後,每一級運算的結果仍然儲存在同一組存儲器中,直到最後輸出,中間無需其它存儲器
序數重排
對按時間抽取FFT的原位運算結構,當運算完畢時,這種結構存儲單元A(1)、A(2),…,A(8)中正好順序存放著X(0),X(1),X(2),…,X(7),因此可直接按順序輸出,但這種原位運算的輸入x(n)卻不能按這種自然順序存入存儲單元中,而是按X(0),X(4),X(2),X(6),…,X(7)的順序存入存儲單元,這種順序看起來相當雜亂,然而它也是有規律的。當用二進製表示這個順序時,它正好是「碼位倒置」的順序。
蝶形類型隨迭代次數成倍增加
每次迭代的蝶形類型比上一次蝶代增加一倍,數據點間隔也增大一倍 頻率抽取2FFT演算法是按頻率進行抽取的演算法。
設N=2^M,將x(n)按前後兩部分進行分解,
按K的奇偶分為兩組,即
得到兩個N/2 點的DFT運算。如此分解,並迭代,總的計算量和時間抽取(DIT)基2FFT演算法相同。
演算法規律如下:
蝶形結構和時間抽取不一樣但是蝶形個數一樣,同樣具有原位計算規律,其迭代次數成倍減小 時,可採取補零使其成為
,或者先分解為兩個p,q的序列,其中p*q=N,然後進行計算。 前面介紹,採用FFT演算法可以很快算出全部N點DFT值,即z變換X(z)在z平面單位圓上的全部等間隔取樣值。實際中也許①不需要計算整個單位圓上z變換的取樣,如對於窄帶信號,只需要對信號所在的一段頻帶進行分析,這時希望頻譜的采樣集中在這一頻帶內,以獲得較高的解析度,而頻帶以外的部分可不考慮,②或者對其它圍線上的z變換取樣感興趣,例如語音信號處理中,需要知道z變換的極點所在頻率,如極點位置離單位圓較遠,則其單位圓上的頻譜就很平滑,這時很難從中識別出極點所在的頻率,如果采樣不是沿單位圓而是沿一條接近這些極點的弧線進行,則在極點所在頻率上的頻譜將出現明顯的尖峰,由此可較准確地測定極點頻率。③或者要求能有效地計算當N是素數時序列的DFT,因此提高DFT計算的靈活性非常有意義。
螺旋線采樣是一種適合於這種需要的變換,且可以採用FFT來快速計算,這種變換也稱作Chirp-z變換。

⑸ 在DSP上實現FFT演算法

void FFT( COMPLEX *Y, int N) /* input sample array, number of points */
{
COMPLEX temp1,temp2; /*temporary storage variables */蔽型
int i,j,k; /*loop counter variables */
int upper_leg, lower_leg; /*index of upper/lower butterfly leg */
int leg_diff; /宏握猜*difference between upper/lower leg */
int num_stages=0; /*number of FFT stages, or iterations */
int index, step; /*index and step between twiddle factor*/

/* log(base 2) of # of points = # of stages */
i=1;
do
{
num_stages+=1;
i = i *2 ;
} while (i!=N);

/* starting difference between upper and lower butterfly legs*/
leg_diff = N/2;

/* step between values in twiddle factor array twiddle.h */
step = 512 / N;

/* For N-point FFT */

for ( i = 0 ; i < num_stages ; i++ )
{
index = 0;

for ( j = 0; j < leg_diff ; j++ )
{

for ( upper_leg = j; upper_leg < N ; upper_leg += (2*leg_diff) )
{
lower_leg = upper_leg + leg_diff;
temp1.real=(Y[upper_leg]).real + (Y[lower_leg]).real;
temp1.imag=(Y[upper_leg]).imag + (Y[lower_leg]).imag;
temp2.real=(Y[upper_leg]).real - (Y[lower_leg]).real;
temp2.imag=(Y[upper_leg]).imag - (Y[lower_leg]).imag;

(Y[lower_leg]).real = ((long)temp2.real * (w[index]).real)/8192;
(Y[lower_leg]).real -= ((long)temp2.imag * (w[index]).imag)/8192;

(Y[lower_leg]).imag = ((long)temp2.real * (w[index]).imag)/8192;
(Y[lower_leg]).imag += ((long)temp2.imag * (w[index]).real)/8192;

(Y[upper_leg]).real = temp1.real;

(Y[upper_leg]).imag = temp1.imag;
}
index+=step;
}
leg_diff = leg_diff / 2;
step *= 2;
}

/* bit reversal for resequencing data */
j=0;
for ( i=1 ; i < (N-1) ; i++ )
{
k = N / 2;

while ( k <= j)
{
j = j - k;
k >>皮旅= 1;
}

j = j + k;

if ( i < j )
{
temp1.real = (Y[j]).real;
temp1.imag = (Y[j]).imag;
(Y[j]).real = (Y[i]).real;
(Y[j]).imag = (Y[i]).imag;
(Y[i]).real = temp1.real;
(Y[i]).imag = temp1.imag;
}
}
return;
}
參考一下的吧,這個是TI官方的在5416上實現的程序~

⑹ FFT運算,在信號處理中是怎樣運用的啊

FFT演算法實現因為PIC16F877片內有高達368×8位(相當於184×16位)的數據存儲器(RAM),故用片內RAM最多可以完成64點FFT(16位實部和虛部數據)。現在僅實現16點FFT,主要神塌是起拋磚引玉的謹瞎嫌作用。這里的FFT是按頻率抽取的。在調用FFT子程序前,輸入數據按正常次序輸入,而輸出數據是經FFT變換整序處理後輸出。原始數據被變換後的數據覆蓋存放在RAM中,這是通過分解序列實現的;然而分解序列將引起DFT的項序混亂,所以在變換結束,所有的數據需要進行「整序」,以恢復DFT的正常次序。某些應用可以不進行整序;因而整序程序編成子程序形式,當需要時隨時可以調用。輸入數據為32位祥手,前為16位實部,後為16位虛部,中間結果為32位;輸出數據也是前為實部,後為虛部。這樣計算的結果具有相當高的精度。

⑺ 16點DFT的FFT演算法

FFT(快速傅里葉變換)是DFT的一種特殊情況,就是當運算點的個數是2的整數次冪的時候進行的運算(不夠用0補齊)。

FFT計算原理及流程圖:

原理:FFT的計算要求點數必須為2的整數次冪,如果點數不夠用0補齊。例如計算{2,3,5,8,4}的16點FFT,需要補11個0後進行計算。FFT計算運用蝶形運算,在蝶形運算中變化規律由W(N, p)推導,其中N為FFT計算點數,J為下角標的值。

L = 1時,W(N, p) = W(N, J) = W(2^L, J),其中J = 0;

L = 2時,W(N, p) = W(N, J) = W(2^L, J),其中J = 0, 1;

L = 3時,W(N, p) = W(N, J) = W(2^L, J),其中J = 0, 1, 2, 3;

所以,W(N, p) = W(2^L, J),其中J = 0, 1, ..., 2^(L-1)-1

又因為2^L = 2^M*2^(L-M) = N*2^(L-M),這里N為2的整數次冪,即N=2^M,

W(N, p) = W(2^L, J) = W(N*2^(L-M), J) = W(N, J*2^(M-L))

所以,p = J*2^(M-L),此處J = 0, 1, ..., 2^(L-1)-1,當J遍歷結束但計算點數不夠N時,J=J+2^L,後繼續遍歷,直到計算點數為N時不再循環。

流程圖:

/*======================================================================
*方法名:fft
*方法功能:計算數組的FFT,運用蝶形運算
*
*變數名稱:
*yVector-原始數據
*length-原始數據長度
*N-FFT計算點數
*fftYreal-FFT後的實部
*fftYImg-FFT後的虛部
*
*返回值:是否成功的標志,若成功返回true,否則返回false
*=====================================================================*/

+(BOOL)fft:(floatfloat*)yVectorandOriginalLength:(NSInteger)lengthandFFTCount:(NSInteger)NandFFTReal:(floatfloat*)fftYRealandFFTYImg:(floatfloat*)fftYImg
{
//確保計算時時2的整數冪點數計算
NSIntegerN1=[selfnextNumOfPow2:N];

//定義FFT運算是否成功的標志
BOOLisFFTOK=false;

//判斷計算點數是否為2的整數次冪
if(N!=N1)
{
//不是2的整數次冪,直接計算DFT
isFFTOK=[selfdft:yVectorandOriginalLength:lengthandFFTCount:NandFFTReal:fftYRealandFFTYImg:fftYImg];
轎譽
閉肢段//返回成功標志
returnisFFTOK;
}


//如果計算點數位2的整數次冪,用FFT計算,如下
//定義變數
floatyVectorN[N1];//N點運算的原始數據
NSIntegerpowOfN=log2(N1);//N=2^powOfN,用於標記最大運算級數(公式中表示為:M)
NSIntegerlevel=1;//運算級數(第幾次運算),最大為powOfN,初值為第一級飢模運算(公式中表示為:L)
NSIntegerlineNum;//行號,倒序排列後的蝶形運算行號(公式中表示為:k)
floatinverseOrderY[N1];//yVector倒序x
NSIntegerdistanceLine=1;//行間距,第level級運算每個蝶形的兩個節點距離為distanceLine=2^(L-1)(公式中表示為:B)
NSIntegerp;//旋轉因子的階數,旋轉因子表示為W(N,p),p=J*2^(M-L)
NSIntegerJ;//旋轉因子的階數,旋轉因子表示為W(2^L,J),J=0,1,2,...,2^(L-1)-1=distanceLine-1
floatrealTemp,imgTemp,twiddleReal,twiddleImg,twiddleTheta,twiddleTemp=PI_x_2/N1;
NSIntegerN_4=N1/4;

//判斷點數是否夠FFT運算點數
if(length<=N1)
{
//如果N至少為length,先把yVector全部賦值
for(NSIntegeri=0;i<length;i++)
{
yVectorN[i]=yVector[i];
}

if(length<N1)
{
//如果N>length後面補零
for(NSIntegeri=length;i<N1;i++)
{
yVectorN[i]=0.0;
}
}
}
else
{
//如果N<length截取相應長度的數據進行運算
for(NSIntegeri=0;i<N1;i++)
{
yVectorN[i]=yVector[i];
}
}

//調用倒序方法
[selfinverseOrder:yVectorNandN:N1andInverseOrderVector:inverseOrderY];

//初始值
for(NSIntegeri=0;i<N1;i++)
{
fftYReal[i]=inverseOrderY[i];
fftYImg[i]=0.0;
}

//三層循環
//第三層(最里):完成相同旋轉因子的蝶形運算
//第二層(中間):完成旋轉因子的變化,步進為2^level
//第一層(最外):完成M次迭代過程,即計算出x(k)=A0(k),A1(k),...,Am(k)=X(k)

//第一層循環
while(level<=powOfN)
{
distanceLine=powf(2,level-1);//初始條件distanceLine=2^(level-1)
J=0;
NSIntegerpow2_Level=distanceLine*2;//2^level
NSIntegerpow2_NSubL=N1/pow2_Level;//2^(M-L)

//第二層循環
while(J<distanceLine)
{
p=J*pow2_NSubL;
lineNum=J;
NSIntegerstepCount=0;//J運算的步進計數

//求旋轉因子
if(p==0)
{
twiddleReal=1.0;
twiddleImg=0.0;
}
elseif(p==N_4)
{
twiddleReal=0.0;
twiddleImg=-1.0;
}
else
{
//計算尤拉公式中的θ
twiddleTheta=twiddleTemp*p;

//計算復數的實部與虛部
twiddleReal=cos(twiddleTheta);
twiddleImg=-11*sin(twiddleTheta);
}

//第三層循環
while(lineNum<N1)
{
//計算下角標
NSIntegerfootNum=lineNum+distanceLine;

/*---------------------------------------
*用復數運算計算每級中各行的蝶形運算結果
*X(k)=X(k)+X(k+B)*W(N,p)
*X(k+B)=X(k)-X(k+B)*W(N,p)
*---------------------------------------*/
realTemp=fftYReal[footNum]*twiddleReal-fftYImg[footNum]*twiddleImg;
imgTemp=fftYReal[footNum]*twiddleImg+fftYImg[footNum]*twiddleReal;

//將計算後的實部和虛部分別存放在返回數組中
fftYReal[footNum]=fftYReal[lineNum]-realTemp;
fftYImg[footNum]=fftYImg[lineNum]-imgTemp;
fftYReal[lineNum]=fftYReal[lineNum]+realTemp;
fftYImg[lineNum]=fftYImg[lineNum]+imgTemp;

stepCount+=pow2_Level;

//行號改變
lineNum=J+stepCount;
}

//旋轉因子的階數變換,達到旋轉因子改變的效果
J++;
}

//運算級數加一
level++;
}

isFFTOK=true;
returnisFFTOK;
}

⑻ 基-2fft演算法的軟體實現 matlab代碼

% 基於Matlab的時間抽取基2FFT演算法
function y=myditfft(x)
%本程序對輸入序列實現DIT-FFT基2演算法,點數取大於等於長度的2的冪次
%------------------------------------
% Leo's fft program(改編網上的一個程序)
%------------------------------------
m=log2(2^nextpow2(length(x))); %求的x長度對應的2的最低冪次m
N=2^m;
if length(x)<N
x=[x,zeros(1,N-length(x))]; %若長度不是2的冪,補0到2的整數冪
end
x;
%--------------------------------------------------------------------------
%對輸入序列進行倒序
%如果輸入序列的自然順序號I用二進制數(例如n2n1n0)表示
%則其倒位序J對應的二進制數就是(n0n1n2),這樣,在原來自然順序時應該放x(I)的
%單元,現在倒位序後應放x(J)。
%--------------------------------------------------------------------------
%以下程序相當於以下程序:
%nxd=bin2dec(fliplr(dec2bin([1:N]-1,m)))+1; %求1:2^m數列的倒序
%y=x(nxd); %將倒序排列作為初始值
%--------------------------------------------------------------------------
NV2=N/2;
NM1=N-1;
I=0;
J=0;
while I<NM1
if I<J
T=x(J+1);
x(J+1)=x(I+1);
x(I+1)=T;
end
K=NV2;

while K<=J
J=J-K;
K=K/2;
end
J=J+K;
I=I+1;
end
x;
%--------------------------------------------------------------------------
%以下程序解釋:
%第一級從x(0)開始,跨接一階蝶形,再取每條對稱
%第二級從x(0)開始,跨接兩階蝶形,再取每條對稱
%第m級從x(0)開始,跨接2^(m-1)階蝶形,再取每條對稱....
%--------------------------------------------------------------------------
for mm=1:m %將DFT做m次基2分解,從左到右,對每次分解作DFT運算
Nmr=2^mm;
u=1; %旋轉因子u初始化
WN=exp(-j*2*pi/Nmr); %本次分解的基本DFT因子WN=exp(-i*2*pi/Nmr)
for n=1:Nmr/2 %本次跨越間隔內的各次碟形運算
for k=n:Nmr:N %本次碟形運算的跨越間隔為Nmr=2^mm
kp=k+Nmr/2; %確定碟形運算的對應單元下標(對稱性)
t=x(kp)*u; %碟形運算的乘積項
x(kp)=x(k)-t; %碟形運算的加法項
x(k)=x(k)+t;
end
u=u*WN; %修改旋轉因子,多乘一個基本DFT因子WN
end
end
y=x; %輸出

⑼ 求用C++實現的FFT演算法

很早以前的,如果管用別忘了給我加分呀
/*
This computes an in-place complex-to-complex FFT
x and y are the real and imaginary arrays of 2^m points.
dir = 1 gives forward transform
dir = -1 gives reverse transform
*/
short FFT(short int dir,long m,double *x,double *y)
{
long n,i,i1,j,k,i2,l,l1,l2;
double c1,c2,tx,ty,t1,t2,u1,u2,z;

/* Calculate the number of points */
n = 1;
for (i=0;i<m;i++)
n *= 2;

/* Do the bit reversal */
i2 = n >> 1;
j = 0;
for (i=0;i<n-1;i++) {
if (i < j) {
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j) {
j -= k;
k >>= 1;
}
j += k;
}

/* Compute the FFT */
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l=0;l<m;l++) {
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for (j=0;j<l1;j++) {
for (i=j;i<n;i+=l2) {
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = sqrt((1.0 - c1) / 2.0);
if (dir == 1)
c2 = -c2;
c1 = sqrt((1.0 + c1) / 2.0);
}

/* Scaling for forward transform */
if (dir == 1) {
for (i=0;i<n;i++) {
x[i] /= n;
y[i] /= n;
}
}

return(TRUE);
}

---------------------------------------------------------------------------------
/*****************fft programe*********************/
#include "typedef.h"
#include "math.h"

struct compx EE(struct compx b1,struct compx b2)
{
struct compx b3;
b3.real=b1.real*b2.real-b1.imag*b2.imag;
b3.imag=b1.real*b2.imag+b1.imag*b2.real;
return(b3);
}

void FFT(struct compx *xin,int N)
{
int f,m,nv2,nm1,i,k,j=1,l;
/*int f,m,nv2,nm1,i,k,j=N/2,l;*/
struct compx v,w,t;
nv2=N/2;
f=N;
for(m=1;(f=f/2)!=1;m++){;}
nm1=N-1;

/*變址運算*/
for(i=1;i <=nm1;i++)
{
if(i <j){t=xin[j];xin[j]=xin[i];xin[i]=t;}
k=nv2;
while(k <j){j=j-k;k=k/2;}
j=j+k;
}

{
int le,lei,ip;
float pi;
for(l=1;l <=m;l++)
{ le=pow(2,l);// 這里用的是L而不是1 !!!!
lei =le/2;
pi=3.14159;
v.real=1.0;
v.imag=0.0;
w.real=cos(pi/lei);
w.imag=-sin(pi/lei);
for(j=1;j <=lei;j++)
{
/*double p=pow(2,m-l)*j;
double ps=2*pi/N*p;
w.real=cos(ps);
w.imag=-sin(ps);*/
for(i=j;i <=N;i=i+le)
{ /* w.real=cos(ps);
w.imag=-sin(ps);*/
ip=i+lei;
t=EE(xin[ip],v);
xin[ip].real=xin[i].real-t.real;
xin[ip].imag=xin[i].imag-t.imag;
xin[i].real=xin[i].real+t.real;
xin[i].imag=xin[i].imag+t.imag;
}
v=EE(v,w);
}
}
}
return;
}

/*****************main programe********************/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "typedef.h"

float result[257];
struct compx s[257];
int Num=256;
const float pp=3.14159;

main()
{

int i=1;
for(;i <0x101;i++)
{
s[i].real=sin(pp*i/32);
s[i].imag=0;
}

FFT(s,Num);

for(i=1;i <0x101;i++)
{
result[i]=sqrt(pow(s[i].real,2)+pow(s[i].imag,2));
}

}

-----------------------------------------------------------------------------------
FFT變換 C源代碼

FFT C source code (Simple radix-2)

void fft_float (
unsigned NumSamples,
int InverseTransform,
float *RealIn,
float *ImagIn,
float *RealOut,
float *ImagOut )
{
unsigned NumBits; /* Number of bits needed to store indices */
unsigned i, j, k, n;
unsigned BlockSize, BlockEnd;
double angle_numerator = 2.0 * DDC_PI;
double tr, ti; /* temp real, temp imaginary */
if ( !IsPowerOfTwo(NumSamples) )
{
fprintf (
stderr,
"Error in fft(): NumSamples=%u is not power of two\n",
NumSamples );
exit(1);
}
if ( InverseTransform )
angle_numerator = -angle_numerator;
CHECKPOINTER ( RealIn );
CHECKPOINTER ( RealOut );
CHECKPOINTER ( ImagOut );
NumBits = NumberOfBitsNeeded ( NumSamples );
/*
** Do simultaneous data and bit-reversal ordering into outputs...
*/
for ( i=0; i < NumSamples; i++ )
{
j = ReverseBits ( i, NumBits );
RealOut[j] = RealIn;
ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn;
}
/*
** Do the FFT itself...
*/
BlockEnd = 1;
for ( BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1 )
{
double delta_angle = angle_numerator / (double)BlockSize;
double sm2 = sin ( -2 * delta_angle );
double sm1 = sin ( -delta_angle );
double cm2 = cos ( -2 * delta_angle );
double cm1 = cos ( -delta_angle );
double w = 2 * cm1;
double ar[3], ai[3];
double temp;
for ( i=0; i < NumSamples; i += BlockSize )
{
ar[2] = cm2;
ar[1] = cm1;
ai[2] = sm2;
ai[1] = sm1;
for ( j=i, n=0; n < BlockEnd; j++, n++ )
{
ar[0] = w*ar[1] - ar[2];
ar[2] = ar[1];
ar[1] = ar[0];
ai[0] = w*ai[1] - ai[2];
ai[2] = ai[1];
ai[1] = ai[0];
k = j + BlockEnd;
tr = ar[0]*RealOut[k] - ai[0]*ImagOut[k];
ti = ar[0]*ImagOut[k] + ai[0]*RealOut[k];
RealOut[k] = RealOut[j] - tr;
ImagOut[k] = ImagOut[j] - ti;
RealOut[j] += tr;
ImagOut[j] += ti;
}
}
BlockEnd = BlockSize;
}
/*
** Need to normalize if inverse transform...
*/
if ( InverseTransform )
{
double denom = (double)NumSamples;
for ( i=0; i < NumSamples; i++ )
{
RealOut /= denom;
ImagOut /= denom;
}
}
}

int IsPowerOfTwo ( unsigned x )
{
if ( x < 2 )
return FALSE;
if ( x & (x-1) ) // Thanks to 'byang' for this cute trick!
return FALSE;
return TRUE;
}

unsigned NumberOfBitsNeeded ( unsigned PowerOfTwo )
{
unsigned i;
if ( PowerOfTwo < 2 )
{
fprintf (
stderr,
">>> Error in fftmisc.c: argument %d to NumberOfBitsNeeded is too small.\n",
PowerOfTwo );
exit(1);
}
for ( i=0; ; i++ )
{
if ( PowerOfTwo & (1 << i) )
return i;
}
}

unsigned ReverseBits ( unsigned index, unsigned NumBits )
{
unsigned i, rev;
for ( i=rev=0; i < NumBits; i++ )
{
rev = (rev << 1) | (index & 1);
index >>= 1;
}
return rev;
}

double Index_to_frequency ( unsigned NumSamples, unsigned Index )
{
if ( Index >= NumSamples )
return 0.0;
else if ( Index <= NumSamples/2 )
return (double)Index / (double)NumSamples;
return -(double)(NumSamples-Index) / (double)NumSamples;
}

⑽ fft窄帶高解析度演算法

fft演算法是什麼
FFT演算法(fast Fourier transform),即快速傅里葉變換,是指利用計算機計算離散傅里葉變換(DFT)的高效、快速計算方法的統稱,簡稱FFT。快速傅里葉變換是1965年由J.W.庫利和T.W.圖基提出的。採用這種演算法能使計算機計算離散傅里葉變換所需要的乘法次數大為減少,特別是被變換的抽樣點數N越多,FFT演算法計算量的節省就越顯著。



概念
有限長睜賣序列可以通過離散傅里葉變換(DFT)將其頻域也離散化成有限長序列。但其計算量太大,很難實時地處理問題,因此引出了快速傅里葉變換(FFT)。 1965年,Cooley和Tukey提出了計算離散傅里葉變換(DFT)的快速演算法,將DFT的運算量減少了幾個數量級。從此,對快速傅里葉變換(FFT)演算法的研究便不斷深入,數字信號處理這門新興學科也隨FFT的出現和發展而迅速發展。根據對序列分解與選取方法的不同而產生了FFT的多種演算法,基本演算法是基2DIT和基2DIF。FFT在離散傅里葉反變換、線性卷積和線性相關等方面也有重要應用。

快速傅氏變換(FFT),是離散傅氏變換的快速演算法,它是根據離散傅氏變換的奇、偶枯做、虛、實等特性,對離散傅立葉變換的演算法進行改進獲得的。它對傅氏變換的理論並沒有新的發現,但是對於在計算機系統或者說數字系統中應用離散傅立葉變換,可以說是進了一大步。

設x(n)為N項的復數序列,由DFT變換,任一X(m)的計算都需要N次復數乘法和N-1次復數加法,而一次復數乘法等於四次實數乘法和兩次實數加法,一次復數加法等於兩次實數加法,即使把一次復數乘法和一次復數加法定義成一次「運算」(四次實數乘法和四次實數加法),那麼求出N項復數序列的X(m),即N點DFT變換大約就需要N^2次運算。當N=1024點甚至更多的時候,需要N2=1048576次運算,在FFT中,利用WN的周期性和對稱性,把一個N項序列(設N=2k,k為正整數),分為兩個N/2項的子序列,每個N/2點DFT變換需要(N/2)^2次運算,再用N次運算把兩個N/2點的DFT變換組合成一個N點的DFT變換。這樣變換以後,總的運算次數就變成N+2*(N/2)^2=N+N^2/2。繼續上面的例子,N=1024時,總的運算次數就變成了525312次,節省了大約50%的運算量。而如果我們將這種「一分為二」的思想不斷進行下去,直到分成兩兩一組的DFT運算單元,那麼N點的DFT變換就只需要Nlog2N次的運算,N在1024點時,運算量僅有10240次,是先前的直接演算法的1%,點數越多,運算量的節約就越大,這就是FFT的優越性。

如何提高fft演算法解析度
FFT程序,輸入是一組復數,輸出也是一組復數,想問一下輸入到底應該輸入什麼,輸出的復數的含義是什麼。

給定一組序列的抽樣值,如何用FFT確定它的頻率。

首先,fft函數出來的應該是個復數,每一個點分實部虛部兩部分。

假設採用1024點fft,悉敗逗采樣頻率是fs,那麼第一個點對應0頻率點,第512點對應的就是fs/2的頻率點。然後從頭開始找模值最大的那個點,其所對應的頻率值應該就是要的基波頻率了。

FFT是離散傅立葉變換的快速演算法,可以將一個信號變換到頻域。

有些信號在時域上是很難看出什麼特徵的,但是如果變換到頻域之後,就很容易看出特徵了。

這就是很多信號分析採用FFT變換的原因。

另外,FFT可以將一個信號的頻譜提取出來,這在頻譜分析方面也是經常用的。

雖然很多人都知道FFT是什麼,可以用來做什麼,怎麼去做,但是卻不知道FFT之後的結果是什麼意思、如何決定要使用多少點來做FFT。

一個模擬信號,經過ADC采樣之後,就變成了數字信號。

采樣定理告訴,采樣頻率要大於信號頻率的兩倍,這些就不在此羅嗦了。

采樣得到的數字信號,就可以做FFT變換了。

N個采樣點,經過FFT之後,就可以得到N個點的FFT結果。

為了方便進行FFT運算,通常N取2的整數次方。

熱點內容
我的世界手機無人管理伺服器 發布:2025-08-24 16:57:54 瀏覽:190
androidsdk32下載 發布:2025-08-24 16:36:35 瀏覽:266
安卓手機忘了解鎖密碼怎麼辦 發布:2025-08-24 16:35:09 瀏覽:789
存儲過程在java代碼 發布:2025-08-24 16:32:11 瀏覽:498
寫編譯器需要哪些知識 發布:2025-08-24 16:09:06 瀏覽:330
資料庫的關系符號 發布:2025-08-24 16:02:29 瀏覽:626
sqlserver表值函數 發布:2025-08-24 15:56:27 瀏覽:554
linuxc內存泄露 發布:2025-08-24 15:54:30 瀏覽:112
python讀取文件每一行 發布:2025-08-24 15:32:27 瀏覽:83
abbplc編程軟體 發布:2025-08-24 15:31:43 瀏覽:209