signalcalc.cpp

来自「常用算法与数据结构原代码」· C++ 代码 · 共 1,624 行 · 第 1/3 页

CPP
1,624
字号
	
	efft(x,n,2);//window 2
	
	//if(x[0]<0)  phase[0]=180.0;
	//else    phase[0]=0.0;
	
	if(x[n/2]<0)  phase[n/2]=180.0;
	else    phase[n/2]=0.0;
	
	for(i=1;i<n/2;i++)
	{  if(fabs(x[i])<1.0e-6)  phase[i] = (float)PI/2;
	   else  phase[i] = (float)atan(x[n-i]/x[i]);
	   phase[i]=(float)(phase[i]*180./PI);
	   if(x[i]<0)  phase[i]=180+phase[i];
	   else if((x[i]>0)&&(x[n-i]<0))  phase[i]=360+phase[i];
	}

	x[0] = 0.0;					// for mm=1; while mm=1, mm / 2 = 0;
	phase[0] = 0.0;

	x[n/2]=(float)(2*fabs(x[n/2])/n);
	for( i=1;i<n/2;i++)
	   x[i]=(float)(2*sqrt(x[i]*x[i]+x[n-i]*x[n-i])/n);//please note x/n
	mm=(int)(rpm/60./(samplefrequence/n));//basic fre

	if(mm <= 5)	//smj modified,2001/2/27
	{	
		for(i=1;i<=5;i++)
		{    
			switch(i)
			{  
				case 1: position=(int)mm/2; break;
				case 2: position=mm;  break;
				case 3: position=2*mm; break;
				case 4: position=3*mm; break;
				case 5: position=4*mm; break;
        	}
			
			x[n-i] = x[position];
			if(phase[position]>0)  phase[position] = (int)phase[position] % 360;
			if(phase[position]<0)  phase[position] = (int)phase[position] % 360 + 360;
			x[n-i-8] = phase[position];
		}
		return;
	}
	
	int lastposi = 0;
	int searchrange=2;//smj 2001/2/27
	/*
	if      (mm>25) searchrange=6;
	else if (mm>21) searchrange=5;
	else if (mm>17) searchrange=4;
	else if (mm>13) searchrange=3;
	else if (mm>9)  searchrange=2;
	else            searchrange=1;
*/

	for(i=1;i<=5;i++)
	{    
		switch(i)
		{  case 1: position=(int)mm/2; break;
		    case 2: position=mm;  break;
			case 3: position=2*mm; break;
			case 4: position=3*mm; break;
            case 5: position=4*mm; break;
        }

		 max=-900.0;
		 
		 for(j=position-searchrange; j<=position+searchrange; j++)//search range,modified by smj 2001/2/27
		     if(j>=0 && max<x[j])
			 {  max=x[j];
				k=j;
             }
	
		if(k>=3 && k<=n/2-4 && x[k] != 0.0 && k != lastposi)
		{	
			if(x[k+1]>=x[k-1])
				dk=(2*x[k+1]-x[k])/(x[k+1]+x[k]);
			else  
				dk=(x[k]-2*x[k-1])/(x[k]+x[k-1]);
			x[k]=(float)(PI*dk*x[k]*2*(1-dk*dk)/sin(PI*dk));
			phase[k]=(float)(phase[k]-dk*180);
		 	if(phase[k]>360)  phase[k]=phase[k]-360;
		 	if(phase[k]<0)  phase[k]=phase[k]+360;
		}

		lastposi = k;	
		
		x[n-i] = x[k];
		if(phase[k]>0)  phase[k] = (int)phase[k] % 360;
		if(phase[k]<0)  phase[k] = (int)phase[k] % 360 + 360;
		x[n-i-8] = phase[k];
	}
}

//////////趋势图用数据/////////////////////////////////////
extern "C" __declspec(dllexport)void amendfft2( float *x, int n, float samplefrequence,float *FreqTable, int freqnum )
{                           
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	
	int i,j,k,position;
	float max,phase[513];
	float aver=0.0;

		//原始数据去均值2001/04/09  
    for(i=0;i<n;i++)
		aver+=x[i];
	aver=aver/n;
	for(i=0;i<n;i++)
		x[i]-=aver;
	
//	m = int (log(float(n))/log(2.0));
	
	efft(x,n,2);//window 2
	
	//if(x[0]<0)  phase[0]=180.0;
	//else    phase[0]=0.0;
	
	if(x[n/2]<0)  phase[n/2]=180.0;
	else    phase[n/2]=0.0;
	
	for(i=1;i<n/2;i++)
	{  if(fabs(x[i])<1.0e-6)  phase[i] = (float)PI/2;
	   else  phase[i] = (float)atan(x[n-i]/x[i]);
	   phase[i]=(float)(phase[i]*180./PI);
	   if(x[i]<0)  phase[i]=180+phase[i];
	   else if((x[i]>0)&&(x[n-i]<0))  phase[i]=360+phase[i];
	}

	x[0] = 0.0;					// for mm=1; while mm=1, mm / 2 = 0;
	phase[0] = 0.0;

	x[n/2]=(float)(2*fabs(x[n/2])/n);
	for( i=1;i<n/2;i++)
	   x[i]=(float)(2*sqrt(x[i]*x[i]+x[n-i]*x[n-i])/n);//please note x/n
//	mm=(int)(rpm/60./(samplefrequence/n));//basic fre

	for(i=1; i<=(freqnum>8 ? 8: freqnum);i++)
	{
		position = (int)FreqTable[i-1]/(samplefrequence/n);
		max=-900.0;
		 
		for(j=position-2; j<=position+2; j++)//search range,modified by smj 2001/2/27
		if(j>=0 && max<x[j])
		{	max=x[j];
			k=j;
		}
		
		x[n-i] = max;
		if(phase[k]>0)  phase[k] = (int)phase[k] % 360;
		if(phase[k]<0)  phase[k] = (int)phase[k] % 360 + 360;
		x[n-i-8] = phase[k];
	}

	/*
	if(mm <= 5)	//smj modified,2001/2/27
	{	
		for(i=1;i<=5;i++)
		{    
			switch(i)
			{  
				case 1: position=(int)mm/2; break;
				case 2: position=mm;  break;
				case 3: position=2*mm; break;
				case 4: position=3*mm; break;
				case 5: position=4*mm; break;
        	}
			
			x[n-i] = x[position];
			if(phase[position]>0)  phase[position] = (int)phase[position] % 360;
			if(phase[position]<0)  phase[position] = (int)phase[position] % 360 + 360;
			x[n-i-8] = phase[position];
		}
		return;
	}
	
	int lastposi = 0;
	int searchrange;//smj 2001/2/27
	if      (mm>25) searchrange=6;
	else if (mm>21) searchrange=5;
	else if (mm>17) searchrange=4;
	else if (mm>13) searchrange=3;
	else if (mm>9)  searchrange=2;
	else            searchrange=1;

	for(i=1;i<=5;i++)
	{    
		switch(i)
		{  case 1: position=(int)mm/2; break;
		    case 2: position=mm;  break;
			case 3: position=2*mm; break;
			case 4: position=3*mm; break;
            case 5: position=4*mm; break;
        }

		 max=-900.0;
		 
		 for(j=position-searchrange; j<=position+searchrange; j++)//search range,modified by smj 2001/2/27
		     if(j>=0 && max<x[j])
			 {  max=x[j];
				k=j;
             }
	
		if(k>=3 && k<=n/2-4 && x[k] != 0.0 && k != lastposi)
		{	
			if(x[k+1]>=x[k-1])
				dk=(2*x[k+1]-x[k])/(x[k+1]+x[k]);
			else  
				dk=(x[k]-2*x[k-1])/(x[k]+x[k-1]);
			x[k]=(float)(PI*dk*x[k]*2*(1-dk*dk)/sin(PI*dk));
			phase[k]=(float)(phase[k]-dk*180);
		 	if(phase[k]>360)  phase[k]=phase[k]-360;
		 	if(phase[k]<0)  phase[k]=phase[k]+360;
		}

		lastposi = k;	
		
		x[n-i] = x[k];
		if(phase[k]>0)  phase[k] = (int)phase[k] % 360;
		if(phase[k]<0)  phase[k] = (int)phase[k] % 360 + 360;
		x[n-i-8] = phase[k];
	}*/
}

////////////////////倒谱计算///////////////////////////////////////////
// 幅值倒谱计算
// x--输入实序列,输出的前N/2为倒谱;
// N--序列长度;
extern "C" __declspec(dllexport)void rceps(float *xr,int N)// 参考MATLAB得到的幅值倒谱  smj
 {                            //MATLAB中的算法为xhat = real(ifft(log(abs(fft(x)))))
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   int i,m0;
   float *xi;
   HANDLE  hFloatxi;
   hFloatxi=(HANDLE)GlobalAlloc(GMEM_MOVEABLE,N*sizeof(float));
   xi=(float *)GlobalLock(hFloatxi);

   //原始数据去均值2001/03/06
   float aver=0.0f;
   for(i=0;i<N;i++)	aver+=xr[i];
   aver=aver/N;
   for(i=0;i<N;i++) xr[i]-=aver;


   for(i=0;i<N;i++)
         xi[i]=0.0f;
   m0=CalculatePower(N);

   fft( xr,xi,m0,0 );
   for(i=0;i<N;i++)
   {  
	   xr[i]=(float)sqrt(xr[i]*xr[i]+xi[i]*xi[i]);
       if(xr[i]==0)xr[i]=1.0e-6;
	  xr[i]=(float)log(double(xr[i]));
      xi[i]=0.0f;
   }
   fft(xr,xi,m0,1);
   GlobalUnlock(hFloatxi);
   GlobalFree(hFloatxi);
}

extern "C" __declspec(dllexport) void waterfallfft( float *x,int n,float samplefrequence,int windowflag)
{   
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	 int i,k;
	float max,amplitude,phase,frequence;
	float  dk;
	max=-10.0;
	float* y = NULL;
	
	y = (float *)::VirtualAlloc(NULL, sizeof(float) * (n/2+1),
					MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
	::ZeroMemory(y, sizeof(float) * n/2);

	efft(x,n,windowflag);
	y[0]=(float)(2*fabs(x[0])/n);
	y[n/2]=(float)(2*fabs(x[n/2])/n);
	for( i=1;i<n/2;i++)
	   y[i]=(float)(2*sqrt(x[i]*x[i]+x[n-i]*x[n-i])/n);//please  note  x/n
    for(i=29;i<35;i++)    
	{   if(max<y[i])
	    {   max=y[i];
	        k=i;
		}
    }
	switch(windowflag)
	{    case 0:
		      if(y[k+1]>=y[k-1])
			  dk=y[k+1]/(y[k]+y[k+1]);
		      else dk=-y[k-1]/(y[k]+y[k-1]);
		      amplitude=(float)(PI*dk*y[k]/sin(PI*dk));
		      frequence=samplefrequence*(k+dk)/n;
		      phase=(float)atan(x[n-k]/x[k]);
		      if( x[n-k]<0.0 && x[k]<0.0)
		          phase=phase-(float)PI;
		      if( x[k]<0.0 && x[n-k]>0.0 )
			      phase=phase+(float)PI;
		      phase=phase-(float)(dk*PI);
			  break;
	     case 2:
		      if(y[k+1]>=y[k-1])
			  dk=(2*y[k+1]-y[k])/(y[k+1]+y[k]);
		      else  dk=(y[k]-2*y[k-1])/(y[k]+y[k-1]);
		      amplitude=(float)(PI*dk*y[k]*2*(1-dk*dk)/sin(PI*dk));
		      frequence=samplefrequence*(k+dk)/n;
		      phase=(float)atan(x[n-k]/x[k]);
		      if( x[n-k]<0.0 && x[k]<0.0)
			      phase=phase-(float)PI;
		      if( x[k]<0.0 && x[n-k]>0.0 )
			      phase=phase+(float)PI;
		      phase=phase-(float)(dk*PI);   //phase in -180-180
		      break;
	}
	if(phase>2*PI)
	    phase=phase-(float)(2*PI);
	if(phase<0)
	    phase=phase+(float)(2*PI);
	phase=(float)(phase*180.0/PI);
	x[n-1]=frequence;
	x[n-2]=amplitude;
	x[n-3]=phase;
	for(i=0;i<n/2;i++)
        x[i]=y[i]; 
	
	::VirtualFree(y, sizeof(float) * (n/2+1), MEM_DECOMMIT);
	::VirtualFree(y, 0, MEM_RELEASE);
}
//////////////////////希尔伯特变换及包络////////////////////////////////////////
extern "C" __declspec(dllexport)void Hilbert(float *x,float *xi,int N) 
{                              //N为信号序列长度,
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    int B,i;
	float *y;

	y=(float *)malloc(N*sizeof(float));
//	xi=(float *)malloc(N*sizeof(float));
	for(i=0;i<N;i++)
	{
		y[i]=x[i];
		xi[i]=0.0f;	
	}

	B=CalculatePower(N);

	fft(y,xi,B,0);
	
	for(i=1;i<N/2;i++)
	{
		y[i]=2*y[i];
	    xi[i]=2*xi[i];
	}
	for(i=N/2;i<N;i++)
	{
		y[i]=0.0f;
		xi[i]=0.0f;
	}

	fft(y,xi,B,1);
    
	free(y);
}
/*
extern "C" __declspec(dllexport)void Hilbert(float *x,float *xi,int N) 
{                              //N为信号序列长度,
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    int B,i;
	float *y;

	y=(float *)malloc(N*sizeof(float));
//	xi=(float *)malloc(N*sizeof(float));
	for(i=0;i<N;i++)
	{
		y[i]=x[i];
		xi[i]=0.0f;	
	}

	B=CalculatePower(N);

	fft(y,xi,B,0);
	
	for(i=1;i<N/2;i++)
	{
		y[i]=2*y[i];
	    xi[i]=2*xi[i];
	}
	for(i=N/2;i<N;i++)
	{
		y[i]=0.0f;
		xi[i]=0.0f;
	}

	fft(y,xi,B,1);
    
	free(y);
}*/

// 计算信号的希尔伯特包络
// x--输入实序列,输出为包络;
// N--序列长度。

extern "C" __declspec(dllexport)void Envelope(float *x,int N) 
{                              //N为信号序列长度,
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
	int i;
	float *xi;

	xi=(float *)malloc(N*sizeof(float));
    for(i=0;i<N;i++)
		     xi[i]=0.0f;
	Hilbert(x,xi,N);

	for(i=0;i<N;i++)
		x[i]=(float)sqrt(xi[i]*xi[i]+x[i]*x[i]);
}

//////////////////////////相关函数/////////////////////////////////////////
// x--输入实序列,输出为相关函数;
// y--输入实序列;
// N--序列长度;
extern "C" __declspec(dllexport) void correlation(float *x,float *y ,int N)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    int i,j;
	float sumx,sumy,averx,avery;
    float *z;
	HANDLE hFloatz;

    hFloatz=(HANDLE)GlobalAlloc(GMEM_MOVEABLE,(2*N-1)*sizeof(float));
    z=(float *)GlobalLock(hFloatz);

	sumx=sumy=0.0;
	for(i=0;i<N;i++)
	{
		sumx+=x[i];
		sumy+=y[i];
	}

	averx=sumx/N;
	avery=sumy/N;
	for(i=0;i<N;i++)
	{
		x[i]-=averx;
		y[i]-=avery;
	
	}
 
    for(j=-N+1;j<N;j++)
    {
 	   z[j+N-1]=0.0;
	   for(i=0;i<N;i++)
	   {
		   if(((i+j)>=0)&&((i+j)<N))
			   z[j+N-1]+=x[i]*y[i+j];
	   }
    }
	for(i=0;i<2*N-1;i++)
		x[i]=z[i]/N;


	GlobalUnlock(hFloatz);
    GlobalFree(hFloatz);
}
///////////////////////功率谱计算////////////////////////////////////
// 互谱估计
// x-输入序列,输出的前nfft/2+1个值为互功率谱值;
// y-输入序列;
// N-输入序列的长度,为2的幂次方;
// M-分段的长度,为2的幂次方;(M<=N)
// lag-估计功率谱所用相关函数的点数,其值不大于M/2+1;
// nfft-估计功率谱所用FFT长度,不小于2lag-1;
// windowflag-  窗函数类型;
extern "C" __declspec(dllexport)void csd(float *x,float *y,int N,int M,int lag,int nfft,int windowflag) 
{                              //N为信号序列长度,
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    int i,j,k,m,nSect;
	float sumx,sumy,averx,avery;
	float *u,*v,*z,*zi;
	HANDLE hFloatu,hFloatv,hFloatz,hFloatzi;
	
	hFloatu=(HANDLE)GlobalAlloc(GMEM_MOVEABLE,M*sizeof(float));
    u=(float *)GlobalLock(hFloatu);
	hFloatv=(HANDLE)GlobalAlloc(GMEM_MOVEABLE,M*sizeof(float));
    v=(float *)GlobalLock(hFloatv);
	hFloatz=(HANDLE)GlobalAlloc(GMEM_MOVEABLE,N*sizeof(float));
    z=(float *)GlobalLock(hFloatz);
	hFloatzi=(HANDLE)GlobalAlloc(GMEM_MOVEABLE,N*sizeof(float));
    zi=(float *)GlobalLock(hFloatzi);

    sumx=sumy=0.0;
	for(i=0;i<N;i++)
	{
		sumx+=x[i];
		sumy+=y[i];
	}

	averx=sumx/N;
	avery=sumy/N;
	for(i=0;i<N;i++)
	{
		x[i]=x[i]-averx;
		y[i]=y[i]-avery;
	}

	nSect=(N-M/2)/(M/2);

	for(i=0;i<M/2+1;i++)
	{
		z[i]=0.0;
	}

	for(k=0;k<nSect;k++)
	{
		for(i=0;i<M;i++)
		{
			u[i]=x[k*M/2+i];
		}
		for(i=0;i<M/2;i++)
		{
			v[i]=y[k*M/2+i];
		}
		for(i=M/2;i<M;i++)
		{
			v[i]=0.0;
		}
	
		for(i=0;i<M/2+1;i++)
		{
			zi[i]=0.0;
			for(j=0;j<M;j++)
			{
				if(((i+j)>=0)&&((i+j)<M))
			         zi[i]+=u[j+i]*v[j];  //zi存放每段的互相关值zi[2]=x2y0+x3y1+...+x(1+M/2)y(M/2-1);
			}
		}
		for(j=0;j<M/2+1;j++)
			z[j]+=zi[j];	//z将每段的第 j个互相关值累加;
	}
	
	for(i=0;i<M/2+1;i++)
	{
		z[i]=z[i]/N;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?