函数说明:更改主函数体中的N和length(=log2(N))既可以实现任意点数(2的幂次)的FFT/ IFFT的实现,fft函数中flag标志位控制是正变换还是逆变换。

1.复数操作类

     定义复数类,重载复数四则运算符号,重载输出运算符,重载赋值运算符。

/**********预编译文件头文件complex.h********/
#include"iostream"
using namespace std;
class complex
{
double real,image;
public:
complex(){real=0;image=0;}
complex(float i,float j){real=i;image=j;}
double getr(){return real;}
double geti(){return image;}
void show()
{
if(image>=0)
cout<<real<<"+"<<image<<"j"<<" ";
else
cout<<real<<image<<"j"<<" ";
}
void setvalue(double i=0,double j=0)
{
real=abs(i)<0.0001?0:i;
image=abs(j)<0.0001?0:j;
}
complex operator +(complex&);
complex operator-(complex&);
complex operator*(complex&);
complex operator /(int n);
void operator+=(complex&);
void operator =(complex&);
friend complex W(int m,int n, int flag);
};
complex complex::operator +(complex& c)
{
complex t;
t.real=real+c.real;
t.image=image+c.image;
return t;
}
complex complex::operator*(complex& c)
{
complex t;
t.real=real*c.real-image*c.image ;
t.image=real*c.image+image*c.real;
return t; }
complex complex::operator/ (int n)
{
complex temp;
temp.real=real/n;
temp.image=image/n;
return temp;
}
complex complex::operator -(complex& c)
{
complex t;
t.real=real-c.real;
t.image=image-c.image;
return t;
}
void complex::operator+=(complex&c)
{
real=real+c.real;
image=image+c.image;
}
void complex::operator =(complex&c)
{
real=abs(c.real)<0.00001?0:(c.real);
image=abs(c.image)<0.00001?0:(c.image);
}



2.主函数

/*******************主函数体***********************/
#include "stdafx.h"
#include"iostream"
#include"cmath"
#include"complex.h"
#define pi 3.141592657
#define N 16//需要运算的fft的点数
#define length 4//存储需要的二进制位,即length=log2(N)
using namespace std;
/*********************重新排列输入序列函数****************************/
void bit_reversal(complex a[],int n)
{
int bitdesicion(unsigned);//用来重现排序原来的输入信号序列应该对应变换的信号的序号
complex temp;
int j;
for(int i=0;i<n;i++)
{
j=(int)bitdesicion(i);
if(i<j){temp=a[i];a[i]=a[j];a[j]=temp;}
}
}
int bitdesicion(unsigned n)
{
int j=0;
double k;
double result=0;
int bit[length]={0};
while(n){bit[j]=n%2;n=n/2;j++;}//将n分解成进制码存储于int指针类型bit中
j=0;
while(j<length)
{k=length-1-j;result=result+bit[j]*pow(2.0,k);j++;}
return (int)result;
} /*********************显示信号数组的元素的函数*********************************/
void play(complex a[],int len)
{
for(int i=0;i<len;i++)
{
a[i].show();
if((i+1)%4==0) cout<<" "<<endl;
}
cout<<'\n'<<endl;
} /************获得加权系数W,flag标记为正变换或者逆变换系数*******************/
void getW(complex w[],int len,int flag)
{
if(flag)
for(int i=0 ; i<len ; i++ )
w[i].setvalue(cos(pi*2*i/len),-sin(pi*2*i/len));
else
for(int j=0 ; j<len ; j++ )
w[j].setvalue(cos(pi*2*j/len),sin(pi*2*j/len) );
}
/****************************基2时域FFT算法***********************************/
void fft_temporal(complex input[],int len,int flag)
{
int i,j;int L,k;
void bit_reversal(complex a[],int);
bit_reversal(input,len);//len 代表输入数据的长度
cout<<"重新排序后输入信号为:"<<endl;play(input,len);
complex* w=new complex[len];getW(w,len,flag);//获得快速傅里叶的系数,flag为标志位,代表获得正变换系数,代表获得逆变换系数
if(flag)
cout<<"FFT系数如下"<<endl;
else
cout<<"IFFT系数如下"<<endl;
play(w,len);
complex* tempdata=new complex[len];
complex* tempw=new complex[len/2]; /*********************最核心--蝶形算法**************************************/
for(i=1;i<=length;i++)//i代表第i级蝶形,length表示log2(N)
{
L=(int)pow(2.0,i);
for(j=0;j<len;j+=L)//L为相应单个蝶形运算包含的节点数也是每组蝶形运算的间隔数
{
for(k=0;k<L/2;k++)
tempw[k]=w[k*len/L]*input[j+L/2+k]; //傅里叶加权系数和对应输入信号的乘积事先准备好
for(k=0;k<L/2;k++)//L/2将每一个蝶形算法依据是加还是减够成两个部分,每个部分是蝶形点间隔数的一半
{
tempdata[j+k]=input[j+k]+tempw[k];
tempdata[j+L/2+k]=input[j+k]-tempw[k];
}
}
for(j=0;j<len;j++) input[j]=tempdata[j];
}
if(!flag) for(j=0;j<len;j++) input[j]=tempdata[j]/len;//逆变换必须乘加权系数/N才能得到正确的结果
delete[]w;
delete[]tempw;
delete[]tempdata;
} /**************************************基2频域FFT算法***********************************/
void fft_frequency(complex input[],int len,int flag)
{
int i,j;int L,k;
void bit_reversal(complex a[],int);
complex* w=new complex[len];getW(w,len,flag);//获得快速傅里叶的系数,flag为标志位,代表获得正变换系数,代表逆变换
complex* tempdata=new complex[len];
if(flag)
cout<<"FFT系数如下"<<endl;
else
cout<<"IFFT系数如下"<<endl;
play(w,len);
/********************************最核心--蝶形算法*****************************************/
for(i=1;i<=length;i++)//i代表第i级蝶形,length表示log2(N)
{
L=(int)pow(2.0,length+1-i);
for(j=0;j<len;j+=L)//L为相应单个蝶形运算包含的节点数也是每组蝶形运算的间隔数
{
for(k=0;k<L/2;k++)//L/2将每一个蝶形算法依据是加还是减够成两个部分,每个部分是蝶形点间隔数的一半
{
tempdata[j+k]=input[j+k]+input[j+L/2+k];
tempdata[j+L/2+k]=w[k*len/L]*(input[j+k]-input[j+L/2+k]);
}
for(k=0;k<len;k++) input[k]=tempdata[k];
}
}
if(!flag) for(j=0;j<len;j++) input[j]=input[j]/len;//逆变换必须乘加权系数/N才能得到正确的结果
bit_reversal(input,len);//len 代表输入数据的长度,频率的FFT在最后要重新排序
delete[]w;delete[]tempdata;
} /************************主函数********************************************/
int _tmain(int argc, _TCHAR* argv[])
{
/***********************函数声明*****************************/
void play(complex a[],int);//显示整个数组<pre name="code" class="cpp"> void getW(complex w[],int len,int flag);//获得正变换(flag=1)或者逆变换系数(flag=0)
void fft_temporal(complex input[],int len,int flag);//基时间的fft,flag控制为正变换或者逆变换
void fft_frequency(complex input[],int len,int flag);//基频率的fft
/************************************************************/
complex input[N];
   complex output[N];
for(int i=0;i<N;i++) input[i].setvalue(i,0);
cout<<"输入信号为:"<<endl;play(input,N);
fft_temporal(input,N,1);//"1控制为正变换"
cout<<"基2时域FFT输出信号为:"<<endl;play(input,N);
for(int j=0;j<N;j++) 
      output[j]=input[j];
fft_temporal(output,N,0);//"0"控制为逆变换
cout<<"基2时域IFFT输出信号为:"<<endl;play(output,N);
fft_frequency(output,N,1);
cout<<"基2频率FFT输出信号为:"<<endl;play(output,N);
fft_frequency(output,N,0);
cout<<"基2频率IFFT输出信号为:"<<endl;play(output,N);
return 0;
}






基于C++任意点数的FFT/IFFT(时域和频域)实现的更多相关文章

  1. FFT通过傅里叶级数图解频域补零时域内插

    在时域频域的信号分析的过程中,一个常见的说法叫:频域数据补零会让时域数据内插. 意思是在频域数据中多补几个零,再做ifft(逆傅里叶变换)后的时域数据,会变得更加"细腻",分辨率会 ...

  2. 基于python的快速傅里叶变换FFT(二)

    基于python的快速傅里叶变换FFT(二)本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点  FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算法. ...

  3. python 实现wav的波形显示(时域和频域)

    音频处理中,经常要看一下啊频域图是什么样子的,这里自己写了一个小程序,可以完美的同步显示时域和频域图,直接上代码: #wave data -xlxw #import import wave as we ...

  4. 基于MFC和opencv的FFT

    在网上折腾了一阵子,终于把这个程序写好了,程序是基于MFC的,图像显示的部分和获取图像的像素点是用到了opencv的一些函数,不过FFT算法没有用opencv的(呵呵,老师不让),网上的二维的FFT程 ...

  5. FFT时域与频域的关系,以及采样速率与采样点的影响

    首先对于FFT来说,输入的信号是一个按一定采样频率获得的信号序列,而输出是每个采样点对应的频率的幅度(能量). 下面详细分析: 在FFT的输出数据中,第一个值是直流分量的振幅(这样对应周期有无穷的可能 ...

  6. 时域,频域,s域和z域,一些网上的总结

    https://www.jianshu.com/p/29f4a7663b14 https://wenku.baidu.com/view/26961183b9d528ea81c779e0.html ht ...

  7. LED音乐频谱之概述

    点击打开链接       转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/37929733 这个LED音乐频谱是我在学51单片机的 ...

  8. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

  9. FFT算法

    FFT算法的完整DSP实现 傅里叶变换或者FFT的理论参考: [1] http://www.dspguide.com/ch12/2.htm The Scientist and Engineer's G ...

随机推荐

  1. review37

    线程的常用方法 1.start() 线程调用该方法将启动线程,使之从新建状态进入就绪队列排队. 2.run() 3.sleep() 4.isAlive() 线程处于新建状态时,线程调用isAlive( ...

  2. ActiveMQ 消息存储

    本章重点 ActiveMQ 中,队列和主题里的消息是怎么存储的 ActiveMQ 提供的四种消息存储形式 ActiveMQ 是怎么为消费者缓存消息的 使用订阅恢复模式,怎么控制消息缓存 简介 JMS ...

  3. jsonp 解决跨域传输

    JSONP是JSON with Padding的略称.它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅 ...

  4. 解决:xampp中Apache, MySql, Filezilla端口占用问题

    读 静觅 的python博客,学到requests库的用法,看到“”如果想请求JSON文件,可以利用 json() 方法解析 ”这里迷惑了: 我写了a.json文件放在本地,却不能被python调用, ...

  5. HDU 2203 kmp

    http://acm.hdu.edu.cn/showproblem.php?pid=2203 亲和串 Time Limit: 3000/1000 MS (Java/Others)    Memory ...

  6. Spring3.2.9 + JdbcTemplate 学习

    applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xm ...

  7. AI探索(一)基础知识储备

    AI的定义 凡是通过机器学习,实现机器替代人力的技术,就是AI.机器学习是什么呢?机器学习是由AI科学家研发的算法模型,通过数据灌输,学习数据中的规律并总结,即模型内自动生成能表达(输入.输出)数据之 ...

  8. 12-THREE.JS 自然光

    <!DOCTYPE html> <html> <head> <title></title> <script src="htt ...

  9. Zeroc Ice 负载均衡之Icegrid simple

    最近学习Icestorm的replicated例子,在本地计算机上面跑通了,但在两台机器上(一台服务器192.168.0.113,一台客户端192.168.0.188),怎么都跑不通.上网求助,大家给 ...

  10. 页面报错Uncaught SyntaxError: Unexpected identifier

    错误描述:未捕获的语法错误:意想不到的标识符. 如图所示:检查之后发现是页面js内缺少“,”引起的.添加之后就OK了.