fft
来源:互联网 发布:mp4下载视频软件 编辑:程序博客网 时间:2024/06/06 12:35
#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 0
- FFT
- "fft"
- FFT
- fft
- FFT
- fft
- FFT
- FFT
- FFT
- FFT
- fft
- FFT
- FFT
- fft
- FFT
- fft
- FFT
- fft
- iOS preferredstatusbarstyle 不执行
- Android Fragment生命周期深入探究
- JNI java调用c代码 (一)静态注册
- spring原理简介
- 建立Scrapy项目unicodeDecodeError_ascii错误的解决 (2014-10-22)
- fft
- android权限大全
- html+js图片上传预览
- python常见的错误类型和继承关系
- SVN版本冲突,遇到<<<<<<< .mine,=======,>>>>>>>.r3541怎么解决?
- flume实际应用架构图
- 操作系统常见面试题总结
- 实现对象的复用——享元模式(三):围棋棋子的解决方案
- PCA主成分分析