基于C++任意点数的FFT/IFFT(时域和频域)实现
函数说明:更改主函数体中的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(时域和频域)实现的更多相关文章
- FFT通过傅里叶级数图解频域补零时域内插
在时域频域的信号分析的过程中,一个常见的说法叫:频域数据补零会让时域数据内插. 意思是在频域数据中多补几个零,再做ifft(逆傅里叶变换)后的时域数据,会变得更加"细腻",分辨率会 ...
- 基于python的快速傅里叶变换FFT(二)
基于python的快速傅里叶变换FFT(二)本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点 FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算法. ...
- python 实现wav的波形显示(时域和频域)
音频处理中,经常要看一下啊频域图是什么样子的,这里自己写了一个小程序,可以完美的同步显示时域和频域图,直接上代码: #wave data -xlxw #import import wave as we ...
- 基于MFC和opencv的FFT
在网上折腾了一阵子,终于把这个程序写好了,程序是基于MFC的,图像显示的部分和获取图像的像素点是用到了opencv的一些函数,不过FFT算法没有用opencv的(呵呵,老师不让),网上的二维的FFT程 ...
- FFT时域与频域的关系,以及采样速率与采样点的影响
首先对于FFT来说,输入的信号是一个按一定采样频率获得的信号序列,而输出是每个采样点对应的频率的幅度(能量). 下面详细分析: 在FFT的输出数据中,第一个值是直流分量的振幅(这样对应周期有无穷的可能 ...
- 时域,频域,s域和z域,一些网上的总结
https://www.jianshu.com/p/29f4a7663b14 https://wenku.baidu.com/view/26961183b9d528ea81c779e0.html ht ...
- LED音乐频谱之概述
点击打开链接 转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/37929733 这个LED音乐频谱是我在学51单片机的 ...
- 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)
再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...
- FFT算法
FFT算法的完整DSP实现 傅里叶变换或者FFT的理论参考: [1] http://www.dspguide.com/ch12/2.htm The Scientist and Engineer's G ...
随机推荐
- java对象流(一)
注意:字节数组流是可以不用关闭的(字符数组流要不要关闭暂时不清楚). 对象流的读数据和写数据方法分别是writeObject(Object o)和readObject(Object o). Objec ...
- js 图片加载失败处理方法
在项目中不可避免会用到图片,尤其是列表,有时候图片会加载失败:这样就会显示一个很难看的坏图片缩略图:下面介绍两种方法,解决这个问题: 1.如果在你的项目中有引入jQuery插件,你可以使用error( ...
- Office文件的实质是什么
Office文件的实质是什么 一.总结 一句话总结:对于一个Microsoft Office文件,其实质是一个Windows复合二进制文件(Windows Compound Binary File), ...
- 论文笔记 — L2-Net: Deep Learning of Discriminative Patch Descriptor in Euclidean Space
论文: 本文主要贡献: 1.提出了一种新的采样策略,使网络在少数的epoch迭代中,接触百万量级的训练样本: 2.基于局部图像块匹配问题,强调度量描述子的相对距离: 3.在中间特征图上加入额外的监督: ...
- web自动化:元素定位(二)
一. 实例 如何定位到下图第二个"抢投标",有一种方法是利用xpath定位 //a[@href="/loan/loan_detail/Id/7190.html" ...
- redhat linux 中设置网卡固定ip
更改 /etc/sysconfig/network-scripts/ifcfg-eth0(第一个网卡为eth0) DEVICE=eth0#网卡设备名称 ONBOOT=yes#启动时是否激活 yes | ...
- idea使用git上传项目到coding
1.VCS -> import into version control -> create git repository 2.选择要上传的项目根目录 3.选择后,项目里的文件名字变成了绿 ...
- 【暂时解决】win10下安装VS2017 15.3版本 提示 未能安装包“Microsoft.NET.4.6.FullRedist.NonThreshold.Resources,version=4.6.81.9,language=zh-CN”。
win10下安装VS2017 15.3版本的时候,出现以上错误日志提示,请问如何解决的哇? 这个问题,开始我以为是我的安装包所在的路径问题引起的,但是我将安装包移动到了磁盘根目录进行安装,依然出现这个 ...
- BEC listen and translation exercise 12
More than 220 cities now have air quality monitoring systems and 42 others will have systems in plac ...
- 基于zepto移动4*3九宫格转奖
最近根据公司需求,要把移动端的圆形转盘抽奖,改为九宫格的形式,查找资料搞定了,纪录下demo代码. 页面的展现样式,如下 比较简单,就是红色的背景图,在这10个格子里转动 具体代码如下 html &l ...