fft

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
//const float PI = 3.1416; 


inline void swap (float &a, float &b) 
{ 
	float t; 
	t = a; 
	a = b; 
	b = t; 
} 
void bitrp (float xreal [], float ximag [], int n) 
{ 
	//位反转置换Bit-reversal Permutation 
	int i, j, a, b, p; 
	for (i = 1, p = 0; i < n; i *= 2) 
	{ 
		p ++;
	} 
	for (i = 0; i < n; i ++) 
	{ 
		a = i; 
		b = 0; 
		for (j = 0; j < p; j ++) 
		{ 
			b = (b << 1) + (a & 1); // b = b * 2 + a % 2; 
			a >>= 1; // a = a / 2; 
		} 
		if ( b > i) 
		{ 
			swap (xreal [i], xreal [b]); 
			swap (ximag [i], ximag [b]); 
		} 
	} 
}

void FFT(float xreal[], float ximag[], int n) 
{ 
	//快速傅立叶变换,将复数x 变换后仍保存在x 中,xreal, ximag 分别是x 的实部和虚部
	float wreal[128];
	float wimag[128];
	float treal,timag,ureal,uimag,arg;
	int m, k, j, t, index1, index2; 
	bitrp (xreal, ximag, n); 
	// 计算1 的前n / 2 个n 次方根的共轭复数W'j = wreal [j] + i * wimag [j] , j = 0, 1, , n / 2 - 1 
	
	arg = - 2 * PI / n; 
	treal = cos (arg); 
	timag = sin (arg); 
	wreal [0] = 1.0; 
	wimag [0] = 0.0; 
	for (j = 1; j < n / 2; j ++) 
	{ 
		wreal [j] = wreal [j - 1] * treal - wimag [j - 1] * timag; 
		wimag [j] = wreal [j - 1] * timag + wimag [j - 1] * treal; 
	} 
	for (m = 2; m <= n; m *= 2)  
	{ 
		for (k = 0; k < n; k += m)
		{ 
			for (j = 0; j < m / 2; j ++) 
			{ 
				index1 = k + j;
				index2 = index1 + m / 2; 
				t = n * j / m; 
				// 旋转因子w 的实部在wreal [] 中的下标为t 
				
				treal = wreal [t] * xreal [index2] - wimag [t] * ximag [index2]; 
				timag = wreal [t] * ximag [index2] + wimag [t] * xreal [index2]; 
				ureal = xreal [index1]; 
				uimag = ximag [index1]; 
				xreal [index1] = ureal + treal; 
				ximag [index1] = uimag + timag; 
				xreal [index2] = ureal - treal; 
				ximag [index2] = uimag - timag; 
			} 
		} 
	} 
} 

// 
// void IFFT (float xreal [], float ximag [], int n) 
// { 
// 	// 快速傅立叶逆变换
// 	float wreal [128], wimag [128], treal, timag, ureal, uimag, arg; 
// 	int m, k, j, t, index1, index2; 
// 	bitrp (xreal, ximag, n); 
// 	// 计算1 的前n / 2 个n 次方根Wj = wreal [j] + i * wimag [j] , j = 0, 1, , n / 2 - 1 
// 	
// 	arg = 2 * PI / n; 
// 	treal = cos (arg); 
// 	timag = sin (arg); 
// 	wreal [0] = 1.0; 
// 	wimag [0] = 0.0; 
// 	for (j = 1; j < n / 2; j ++) 
// 	{ 
// 		wreal [j] = wreal [j - 1] * treal - wimag [j - 1] * timag; 
// 		wimag [j] = wreal [j - 1] * timag + wimag [j - 1] * treal; 
// 	} 
// 	for (m = 2; m <= n; m *= 2) 
// 	{ 
// 		for (k = 0; k < n; k += m)  
// 		{ 
// 			for (j = 0; j < m / 2; j ++)
// 			{ 
// 				index1 = k + j; 
// 				index2 = index1 + m / 2; 
// 				t = n * j / m; 
// 				// 旋转因子w 的实部在wreal [] 中的下标为t 
// 				treal = wreal [t] * xreal [index2] - wimag [t] * ximag [index2];
// 				timag = wreal [t] * ximag [index2] + wimag [t] * xreal [index2]; 
// 				ureal = xreal [index1]; 
// 				uimag = ximag [index1];
// 				xreal [index1] = ureal + treal;
// 				ximag [index1] = uimag + timag; 
// 				xreal [index2] = ureal - treal; 
// 				ximag [index2] = uimag - timag; 
// 			} 
// 		} 
// 	} 
// 	for (j=0; j < n; j ++) 
// 	{ 
// 		xreal [j] /= n; 
// 		ximag [j] /= n; 
// 	} 
// } 


    #include "math.h"  
    #include "fft.h"  
    //精度0.0001弧度  
      
    void conjugate_complex(int n,complex in[],complex out[])  
    {  
      int i = 0;  
      for(i=0;i<n;i++)  
      {  
        out[i].imag = -in[i].imag;  
        out[i].real = in[i].real;  
      }   
    }  
      
    void c_abs(complex f[],float out[],int n)  
    {  
      int i = 0;  
      float t;  
      for(i=0;i<n;i++)  
      {  
        t = f[i].real * f[i].real + f[i].imag * f[i].imag;  
        out[i] = sqrt(t);  
      }   
    }  
      
      
    void c_plus(complex a,complex b,complex *c)  
    {  
      c->real = a.real + b.real;  
      c->imag = a.imag + b.imag;  
    }  
      
    void c_sub(complex a,complex b,complex *c)  
    {  
      c->real = a.real - b.real;  
      c->imag = a.imag - b.imag;   
    }  
      
    void c_mul(complex a,complex b,complex *c)  
    {  
      c->real = a.real * b.real - a.imag * b.imag;  
      c->imag = a.real * b.imag + a.imag * b.real;     
    }  
      
    void c_div(complex a,complex b,complex *c)  
    {  
      c->real = (a.real * b.real + a.imag * b.imag)/(b.real * b.real +b.imag * b.imag);  
      c->imag = (a.imag * b.real - a.real * b.imag)/(b.real * b.real +b.imag * b.imag);  
    }  
      
    #define SWAP(a,b)  tempr=(a);(a)=(b);(b)=tempr  
      
    void Wn_i(int n,int i,complex *Wn,char flag)  
    {  
      Wn->real = cos(2*PI*i/n);  
      if(flag == 1)  
      Wn->imag = -sin(2*PI*i/n);  
      else if(flag == 0)  
      Wn->imag = -sin(2*PI*i/n);  
    }  
      
    //傅里叶变化  
    void fft(int N,complex f[])  
    {  
      complex t,wn;//中间变量  
      int i,j,k,m,n,l,r,M;  
      int la,lb,lc;  
      /*----计算分解的级数M=log2(N)----*/  
      for(i=N,M=1;(i=i/2)!=1;M++);   
      /*----按照倒位序重新排列原信号----*/  
      for(i=1,j=N/2;i<=N-2;i++)  
      {  
        if(i<j)  
        {  
          t=f[j];  
          f[j]=f[i];  
          f[i]=t;  
        }  
        k=N/2;  
        while(k<=j)  
        {  
          j=j-k;  
          k=k/2;  
        }  
        j=j+k;  
      }  
      
      /*----FFT算法----*/  
      for(m=1;m<=M;m++)  
      {  
        la=pow(2,m); //la=2^m代表第m级每个分组所含节点数       
        lb=la/2;    //lb代表第m级每个分组所含碟形单元数  
                     //同时它也表示每个碟形单元上下节点之间的距离  
        /*----碟形运算----*/  
        for(l=1;l<=lb;l++)  
        {  
          r=(l-1)*pow(2,M-m);     
          for(n=l-1;n<N-1;n=n+la) //遍历每个分组,分组总数为N/la  
          {  
            lc=n+lb;  //n,lc分别代表一个碟形单元的上、下节点编号       
            Wn_i(N,r,&wn,1);//wn=Wnr  
            c_mul(f[lc],wn,&t);//t = f[lc] * wn复数运算  
            c_sub(f[n],t,&(f[lc]));//f[lc] = f[n] - f[lc] * Wnr  
            c_plus(f[n],t,&(f[n]));//f[n] = f[n] + f[lc] * Wnr  
          }  
        }  
      }  
    }  
      
    //傅里叶逆变换  
    void ifft(int N,complex f[])  
    {  
      int i=0;  
      conjugate_complex(N,f,f);  
      fft(N,f);  
      conjugate_complex(N,f,f);  
      for(i=0;i<N;i++)  
      {  
        f[i].imag = (f[i].imag)/N;  
        f[i].real = (f[i].real)/N;  
      }  
    }  

matlab仿真

%例1:x=0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t)。采样频率fs=100Hz,分别绘制N=128、1024点幅频图。

clf;
fs=100;N=128;   %采样频率和数据点数
n=0:N-1;t=n/fs;   %时间序列
x=0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t); %信号
y=fft(x,N);    %对信号进行快速Fourier变换
mag=abs(y);     %求得Fourier变换后的振幅
f=n*fs/N;    %频率序列
subplot(2,2,1),plot(f,mag);   %绘出随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('N=128');grid on;
subplot(2,2,2),plot(f(1:N/2),mag(1:N/2)); %绘出Nyquist频率之前随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('N=128');grid on;
%对信号采样数据为1024点的处理
fs=100;N=1024;n=0:N-1;t=n/fs;
x=0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t); %信号
y=fft(x,N);   %对信号进行快速Fourier变换
mag=abs(y);   %求取Fourier变换的振幅
f=n*fs/N;
subplot(2,2,3),plot(f,mag); %绘出随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('N=1024');grid on;
subplot(2,2,4)
plot(f(1:N/2),mag(1:N/2)); %绘出Nyquist频率之前随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('N=1024');grid on;


DFT

#include <stdio.h>  
#include <math.h> 
#include "fft.h" 
#define N   SAMPLEPOINTS
              //序列长度   
 
    
typedef float ElementType; //原始数据序列的数据类型,可以在这里设置   
typedef struct              //复数结构体,用于实现傅里叶运算   
{  
    ElementType real,imag;  
}complex;  
complex dataResult[N];      //傅里叶运算的频域结果序列的值(复数)  
ElementType dataSource[N];  //输入的原始数据序列   
ElementType dataFinualResult[N]; //最终频域序列结果(dataResult[N]的模,实数)  
void FFT_Calculate_OneNode(int k)//计算频域上一个点的DFT值   
{  
    int n = 0;  
    complex ResultThisNode;  
    complex part[N];  
    ResultThisNode.real = 0;  
    ResultThisNode.imag = 0;  
    for(n=0; n<N; n++)  
    {  
        part[n].real = cos(2*PI/N*k*n)*dataSource[n];//运用欧拉公式把复数拆分成实部和虚部   
        part[n].imag = sin(2*PI/N*k*n)*dataSource[n];  
		
        ResultThisNode.real += part[n].real;  
        ResultThisNode.imag += part[n].imag;  
    }  
    dataResult[k].real = ResultThisNode.real;  
    dataResult[k].imag = ResultThisNode.imag;  
}  
void FFT_Calculate()//对输入序列全部计算DFT  
{  
    int i = 0;  
    for(i=0; i<N; i++)  
    {  
        FFT_Calculate_OneNode(i);  
        dataFinualResult[i] = sqrt(dataResult[i].real * dataResult[i].real + dataResult[i].imag * dataResult[i].imag);  
    }  
}  
int testdftmain(float * input,float * output)  
{  
    int i = 0;  
    for(i=0; i<N; i++)//制造输入序列   
    {  
        dataSource[i] = input[i];  
        
    }  
    FFT_Calculate();//进行DFT计算   
    
    for(i=0; i<N; i++)  
	{
		output[i]=dataFinualResult[i];
	}  
    return 0;  
}  



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值