#include "stdafx.h"
#include "Fft.h"
#include "math.h"
const double MOD_MAX = 65535.0;
const double DISP_MAX = 1.0/255.0;
extern FILE *fp;
//FFT运算必须参数
int fft_point,fft_order,fft_divide,fft_window,fft_scale;
bool fft_cover;
float filter[7];//FIR滤波参数
extern FILE *fpIandQ;
extern bool m_bIqWrite;
double prFilter[256],piFilter[256];
/**************************************************************************************
0 RectangleWindow矩形窗
FFT变换结果为对称型,矩形窗是使信号突然截断,旁瓣会很大,且衰减较慢,旁瓣的第一个负
峰值为主瓣的21%,第一个正峰值为主瓣的12.6%,第二个负峰值为主瓣的9%,效果一般,泄
漏较大。
**************************************************************************************/
double WINAPI RectangleWindow(int t)
{
double wt;
wt=1.0;
return wt;
}
/**************************************************************************************
1 TriangleWindow三角窗,也称费杰(Fejer)窗,Bartlett
**************************************************************************************/
double WINAPI TriangleWindow(int t)
{
double wt;
wt=1-t/fft_point;
return wt;
}
/**************************************************************************************
2 HanningWindwo汉宁窗,即升余弦窗
**************************************************************************************/
double WINAPI HanningWindow(int t)
{
double wt;
wt=(1-cos(2*PI*t/fft_point))/2;
return wt;
}
/**************************************************************************************
3 HammingWindow海明窗,即改进的升余弦窗
**************************************************************************************/
double WINAPI HammingWindow(int t)
{
double wt;
wt=0.54-0.46*cos(2*PI*t/fft_point);
return wt;
}
/**************************************************************************************
4 BlackmanWindow布来克曼窗,即三阶升余弦窗
**************************************************************************************/
double WINAPI BlackmanWindow(int t)
{
double wt;
wt=0.42-0.5*cos(2*PI*t/fft_point)+0.08*cos(4*PI*t/fft_point);
return wt;
}
/**************************************************************************************
5 CosgradeWindow余弦坡度窗
**************************************************************************************/
double WINAPI CosgradeWindow(int t)
{
double wt;
if(t<= int(4*fft_point/5) )
wt=1.0;
else
wt=(1+cos(5*PI*t/fft_point))/2;
return wt;
}
/**************************************************************************************
6 ParzenWindow帕曾窗
**************************************************************************************/
double WINAPI ParzenWindow(int t)
{
double wt;
if(t<= int(fft_point/2) )
wt=1-6*pow(t/fft_point,2)+6*pow(t/fft_point,3);
else
wt=2*pow(1-t/fft_point,3);
return wt;
}
/**************************************************************************************
7 ExponentWindow指数窗
**************************************************************************************/
double WINAPI ExponentWindow(int t)
{
double wt,alf;
alf=0.0001;
wt=exp((-1.0)*alf*t);
return wt;
}
/**************************************************************************************
8 GaussWindow高斯窗
**************************************************************************************/
double WINAPI GaussWindow(int t)
{
double wt,alf;
alf=0.0001;
wt=exp(-1*alf*t*t);
return wt;
}
/**************************************************************************************
9 KaiserWindow凯泽窗,
凯泽在1966(1974)发现,利用第一类零阶修正(变形)贝赛尔函数可以构成一种近似最佳的窗
最主要参数:beat-可同时调整主瓣宽度和旁瓣,beat越大,窗越窄,频谱旁瓣越小,但主瓣相应增加
beta=0相当与矩形窗
**************************************************************************************/
double WINAPI KaiserWindow(int t)
{
double wt,alfa,beta;
alfa=(fft_point-1)/2;
beta=0;
//Bessel零阶第一类贝塞尔函数
wt=Jim_Bessel0_R(0,beta*sqrt(1-pow((t-alfa)/alfa,2)))/Jim_Bessel0_R(0,beta);
return wt;
}
/**************************************************************************************
10 ChebWindow契比雪夫窗
**************************************************************************************/
double WINAPI ChebWindow(int t)
{
double wt;
wt=1.0;
return wt;
}
/**************************************************************************************
11 BartlettWindow巴特利特窗
**************************************************************************************/
double WINAPI BartlettWindow(int t)
{
double wt;
wt=1.0;
return wt;
}
bool WINAPI fftInit(int point,int order,int divide,bool cover,int scale)
{
fft_point=point;
fft_order=order;
fft_divide=divide;
fft_cover=cover;
fft_scale=scale;
//采用8阶的FIR滤波
Jim_FirFilter(7,3,50,7800/2.0,7800.0,1,filter);
return TRUE;
}
BOOL WINAPI fftEnd()
{
return TRUE;
}
//傅立叶变换
BOOL WINAPI fftTransform(VOID *inBuf,VOID *outBuf,int windows,int scale,int nProbe,int nWork)
{
BYTE *srcPtr = (BYTE*)inBuf;//数据源1024字节
BYTE *dstPtr = (BYTE*)outBuf;//数据果256字节
//double *testPtr =(double *)testBuf;
WORD Ivalue,Qvalue;
//WORD IvalueRev,QvalueRev;
unsigned char flagQ,flagI;
//double alfa,e;
int i,j,Iorg=0,Qorg=0;
double mod = 0;
if(nProbe==LEFT_PROBE)
{
flagQ=0x30,flagI=0x20;
}
else
{
flagQ=0x10,flagI=0x0;
}
//每次取4个字节数据,分离I/Q分量,判断db(12),0表示I分量,1表示Q分量
if (((srcPtr[1]&0xf0) ==flagQ) && ((srcPtr[3]&0xf0) ==flagI))
{
Iorg = 2;
Qorg = 0;
}
if (((srcPtr[1]&0xf0) ==flagI) && ((srcPtr[3]&0xf0) ==flagQ))
{
Iorg = 0;
Qorg = 2;
}
double pr[256],pi[256],w;
//计算自相关函数和互相关函数
//double Rii=0.0,Rqq=0.0,Riq=0.0;
for ( i=0;i<fft_point;i++ )
{
//更改存储的偏移地址分离I/Q,
Ivalue = *((short*)(srcPtr + i*4 + Iorg));
Qvalue = *((short*)(srcPtr + i*4 + Qorg));
//~位非运算,低12位位有效数据
pr[i]=double(Ivalue & 0xfff);
pi[i]=double(Qvalue & 0xfff);
/*Rii=Rii+double(pr[i]*pr[i]);
Rqq=Rqq+double(pi[i]*pi[i]);
Riq=Riq+double(pr[i]*pi[i]);*/
}
/*Rii=Rii/fft_point;
Rqq=Rqq/fft_point;
Riq=Riq/fft_point;
alfa=asin(Riq/sqrt(Rii*Rqq));
e=sqrt(Rqq/Rii)-1;*/
for ( i=0;i<fft_point;i++ )
{
//防止谱泄漏,进行加窗处理
switch(windows)
{
case WND_RECTANGLE: w=RectangleWindow(i); break;
case WND_TRIANGLE: w=TriangleWindow(i); break;
case WND_HANNING: w=HanningWindow(i); break;
case WND_HAMMING: w=HammingWindow(i); break;
case WND_BLACKMAN: w=BlackmanWindow(i); break;
case WND_COSGRADE: w=CosgradeWindow(i); break;
case WND_PARZEN: w=ParzenWindow(i); break;
case WND_EXPONENT: w=ExponentWindow(i); break;
case WND_GAUSS: w=GaussWindow(i); break;
case WND_KAISER: w=KaiserWindow(i); break;
case WND_CHEB: w=ChebWindow(i); break;
case WND_BARTLETT: w=BartlettWindow(i); break;
default: w=RectangleWindow(i); break;
}
/*pr[i]=((1+e)*cos(alfa)*pr[i])/((1+e)*cos(alfa))*w;
pi[i]=(pi[i]-(1+e)*sin(alfa)*pr[i])/((1+e)*cos(alfa))*w;*/
pr[i]=pr[i]*w;
pi[i]=pi[i]*w;
prFilter[i]=piFilter[i]=0.0;
for(j=0;j<7;j++)
{
if(i+j>255)
{
prFilter[i]=prFilter[i];
piFilter[i]=piFilter[i];
}
else
{
prFilter[i]=prFilter[i]+pr[i+j]*w*filter[j];
piFilter[i]=piFilter[i]+pi[i+j]*w*filter[j];
}
}
//fprintf(fp,"%d,%f\n",i,filter[i]);
//pr[i]=pr[i]*filter[i];
//pi[i]=pi[i]*filter[i];
}
//fclose(fpIandQ);
//fft处理
//Jim_FFT(pr,pi,fft_point,fft_order,0,1);
Jim_FFT(prFilter,piFilter,fft_point,fft_order,0,1);
/*for(int t=0;t<256;t++)
{
fpri