📄 vib.cpp
字号:
static CPen penFreq;
static CPen penGrid;
static CPen penSignal;
if(cx!=rectClient.Width() || cy!=rectClient.Height() || nMaxFreq!=m_nDispMaxFreq)
{
cx=rectClient.Width();
cy=rectClient.Height();
nMaxFreq=m_nDispMaxFreq;
mdc.DeleteDC();
mdc.CreateCompatibleDC(pDC);
bmp.DeleteObject();
bmp.CreateCompatibleBitmap(pDC,cx,cy);
penEnvelop.DeleteObject();penEnvelop.CreatePen(PS_SOLID,1,RGB(0,0,128));
penFreq.DeleteObject();penFreq.CreatePen(PS_SOLID,1,RGB(255,0,0));
penGrid.DeleteObject();penGrid.CreatePen(PS_SOLID,1,RGB(0,0,0));
penSignal.DeleteObject();penSignal.CreatePen(PS_SOLID,1,RGB(0,128,0));
font.DeleteObject();
font.CreatePointFont(120,"Arial",pDC);
CFont* pOldFont=mdc.SelectObject(&font);
sizeText=pDC->GetTextExtent("字",2);
pDC->SelectObject(pOldFont);
nSubGrids=rectClient.Width()/sizeText.cx;
nMainSubs=8;
dScaleX=0;
dFreqTo=m_nDispMaxFreq;
CalcGrid(dScaleX,dFreqTo,nSubGrids,nMainSubs);
}
CPen* pOldPen=mdc.SelectObject(&penEnvelop);
CFont* pOldFont=mdc.SelectObject(&font);
CBitmap* pOldBmp=mdc.SelectObject(&bmp);
mdc.FillSolidRect(rectClient,RGB(255,255,255));
//画频谱
dScaleX=1000.0/m_msWinFFT*rectClient.Width()/dFreqTo;
dScaleY=rectClient.Height()/131072.0;
dScaleY=m_nDispFreqPlus<0?-dScaleY/m_nDispFreqPlus:dScaleY*m_nDispFreqPlus;
y0=rectClient.bottom-rectClient.Height()/4;
p=m_nDispMaxFreq*m_msWinFFT/1000+1;
for(i=0;i<p;i++)
{
x=rectClient.left+(int)(i*dScaleX+0.5);
y=(int)(dScaleY*sqrt(m_aEnvelop[i])+0.5);
if(i)mdc.LineTo(x,y0-y);else mdc.MoveTo(x,y0-y);
}
c=RGB(128,128,128);
p0=-1;f0=(UINT)-1/2;
mdc.SelectObject(&penFreq);
for(i=0;i<p;i++)
{
x=rectClient.left+(int)(i*dScaleX+0.5);
y=(int)(dScaleY*sqrt(m_aFFTOut[i])+0.5);
if(i)mdc.LineTo(x,y0-y);else mdc.MoveTo(x,y0-y);
if(m_nFreqBlur)
{
if(y>f0)p0=i;
else if(y<f0 && p0>-1)
{
p0=(p0+i)/2;
x=rectClient.left+(int)(p0*dScaleX+0.5);
mdc.FillSolidRect(x,y0-f0,1,f0,c);
p0=-1;
}
f0=y;
}
}
//画刻度
mdc.FillSolidRect(rectClient.left,y0,rectClient.Width(),1,RGB(0,0,0));
mdc.SetBkColor(RGB(255,255,255));
mdc.SelectObject(&penGrid);
dScaleX=double(rectClient.Width())/nSubGrids;
dScaleY=dFreqTo/nSubGrids;
p=nSubGrids;
rect.top=y0+20;rect.bottom=rect.top+sizeText.cy;
for(i=1;i<p;i++)
{
x=rectClient.left+int(i*dScaleX+0.5);
if(i%nMainSubs){mdc.MoveTo(x,y0);mdc.LineTo(x,y0+10);}
else
{
mdc.MoveTo(x,y0);mdc.LineTo(x,y0+20);
str.Format("%g",i*dScaleY);
rect.left=x-sizeText.cx*3;
rect.right=x+sizeText.cx*3;
mdc.DrawText(str,&rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
}
//画数值
rect.left=rectClient.left;rect.right=rectClient.right;
rect.top=y0+sizeText.cy;rect.bottom=rectClient.bottom;
str.Format("当前振动值:%3d 峰值:%3d",m_nCurVibration,m_nPeakVibration);
mdc.SetTextColor(m_nCurVibration+m_nPeakVibration>0?RGB(255,0,0):RGB(0,0,128));
mdc.DrawText(str,&rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
mdc.SetTextColor(RGB(0,0,0));
//画曲线
p=m_nFFTPoint*m_msDispMaxTime/m_msWinFFT;
dScaleX=1.0*rectClient.Width()/p;
dScaleY=rectClient.Height()/131072.0;
dScaleY=m_nDispSignalPlus<0?-dScaleY/m_nDispSignalPlus:dScaleY*m_nDispSignalPlus;
y0=rectClient.bottom-rectClient.Height()*3/4;
mdc.FillSolidRect(rectClient.left,y0,rectClient.Width(),1,RGB(192,192,192));
mdc.SelectObject(&penSignal);
for(i=0;i<p;i++)
{
x=rectClient.left+(int)(i*dScaleX+0.5);
y=y0-(int)(dScaleY*m_aFFTIn[i]+0.5);
if(i)mdc.LineTo(x,y);else mdc.MoveTo(x,y);
}
pDC->BitBlt(rectClient.left,rectClient.top,
rectClient.Width(),rectClient.Height(),
&mdc,rectClient.left,rectClient.top,SRCCOPY);
mdc.SelectObject(pOldBmp);
mdc.SelectObject(pOldFont);
mdc.SelectObject(pOldPen);
}
BOOL CVibApp::CreateFIR(double* aw, int &N, double p1, double p2, double tw, double fs)
{
int nMode,i,n;
double w,w0,w1,dVal;
if(fs<=0 || tw<=0 || tw>=fs || p1>fs || (p1<=0 && p2<=0))return FALSE;
else if(p1<=0){nMode=1;w1=p2+tw/2;w0=fs;}
else if(p2<=0 || p2>=fs){nMode=2;w1=fs/2-p1+tw/2;w0=fs/2;}
else{nMode=3;w1=(p2-p1+tw)/2;w0=(p1+p2)/2;}
//i=(int)(5.98*fs/tw); //布莱克曼
//i=(int)(3.44*fs/tw); //哈明
i=(int)(3.32*fs/tw); //汉宁
if((i%2)==0)i++;
if(N<i){N=i;return FALSE;}
N=i;i=N/2;
w1*=2*MATH_PI/fs;
w0*=2*MATH_PI/fs;
w=MATH_PI/i;
aw[i]=w1/MATH_PI;
for(n=1;n<=i;n++)
{
dVal=sin(n*w1)/(n*MATH_PI);
//dVal*=0.42+0.5*cos(n*w)+0.08*cos(2*n*w); //布莱克曼
//dVal*=0.54+0.46*cos(n*w); //哈明
dVal*=0.50+0.50*cos(n*w); //汉宁
if(nMode>1)dVal*=cos(n*w0);
aw[i-n]=dVal;aw[n+i]=dVal;
}
for(i=0;i<N;i++)TRACE("aw[%d]=%.5f\r\n",i,aw[i]);
return TRUE;
}
void CVibApp::DefautConfig()
{
m_msWinFFT=200;
m_nFreqHalfLive=1;
m_nFreqValue=0;
m_nFreqBlur=100;
m_nPassbandFreq1=0;
m_nPassbandFreq2=0;
m_nTransbandWidth=500;
m_bModulate=FALSE;
m_nDispMaxFreq=5000;
m_msDispMaxTime=100;
m_nDispSignalPlus=1;
m_nDispFreqPlus=4;
}
void CVibApp::LoadConfig()
{
int i,i0,j;
m_msWinFFT=GetProfileInt("Config","WinFFT",m_msWinFFT);
m_nFreqHalfLive=GetProfileInt("Config","FreqHalfLive",m_nFreqHalfLive);
m_nFreqValue=GetProfileInt("Config","FreqValue",m_nFreqValue);
m_nFreqBlur=GetProfileInt("Config","FreqBlur",m_nFreqBlur);
m_nPassbandFreq1=GetProfileInt("Config","PassbandFreq1",m_nPassbandFreq1);
m_nPassbandFreq2=GetProfileInt("Config","PassbandFreq2",m_nPassbandFreq2);
m_nTransbandWidth=GetProfileInt("Config","TransbandWidth",m_nTransbandWidth);
m_bModulate=GetProfileInt("Config","Modulate",m_bModulate);
m_nDispMaxFreq=GetProfileInt("Config","DispMaxFreq",m_nDispMaxFreq);
m_msDispMaxTime=GetProfileInt("Config","DispMaxTime",m_msDispMaxTime);
m_nDispSignalPlus=GetProfileInt("Config","DispSignalPlus",m_nDispSignalPlus);
m_nDispFreqPlus=GetProfileInt("Config","DispFreqPlus",m_nDispFreqPlus);
//计算采样频率与FFT点数
i=1;
j=22050*m_msWinFFT/1000;
while(i<j)i*=2;
i0=i/2;
if((double)(i-j)/i > (double)(j-i0)/i0)i=i0;
m_nFFTPoint=i; if(m_nFFTPoint>30000)m_nFFTPoint/=2;
m_nSampleFreq=m_nFFTPoint*1000/m_msWinFFT;
//计算频谱的的半衰期差分系数
i=(int)(m_nFreqHalfLive*1000.0/m_msWinFFT+0.5);
m_dFreqHalfLive=i>1?exp(log(0.5)/i):0;
//安全
m_nDispMaxFreq=min(m_nDispMaxFreq,m_nFFTPoint*500/m_msWinFFT);
m_msDispMaxTime=min(m_msDispMaxTime,m_msWinFFT);
m_aData=new short[m_nFFTPoint];
m_aEnvelop=new double[m_nFFTPoint];
m_aFilter=new double[m_nFFTPoint];
m_aFFTIn=new double[m_nFFTPoint];
m_aFFTOut=new double[m_nFFTPoint];
m_aPeak=new double[m_nFFTPoint];
ZeroMemory(m_aData,sizeof(short)*m_nFFTPoint);
ZeroMemory(m_aEnvelop,sizeof(double)*m_nFFTPoint);
ZeroMemory(m_aFilter,sizeof(double)*m_nFFTPoint);
ZeroMemory(m_aFFTIn,sizeof(double)*m_nFFTPoint);
ZeroMemory(m_aFFTOut,sizeof(double)*m_nFFTPoint);
ZeroMemory(m_aPeak,sizeof(double)*m_nFFTPoint);
//创建频率模糊系数
i0=m_nFreqBlur*m_msWinFFT/1000;
for(i=1;i<i0;i++)
{
//m_aFilter[m_nFFTPoint-i]=0.50+0.50*cos(MATH_PI*i/i0); //汉宁
m_aFilter[m_nFFTPoint-i]=0.42+0.5*cos(MATH_PI*i/i0)+0.08*cos(2*MATH_PI*i/i0); //布莱克曼
}
//创建信号滤波系数
m_nFilterCnt=i=m_nFFTPoint-i0;
CreateFIR(m_aFilter,m_nFilterCnt,m_nPassbandFreq1,m_nPassbandFreq2,m_nTransbandWidth,m_nSampleFreq);
if(m_nFilterCnt>=i)m_nFilterCnt=0;
ConfigOption(FALSE);
m_bPause=FALSE;
}
void CVibApp::SaveConfig()
{
ConfigOption(TRUE);
delete[] m_aData;
delete[] m_aEnvelop;
delete[] m_aFilter;
delete[] m_aFFTIn;
delete[] m_aFFTOut;
delete[] m_aPeak;
WriteProfileInt("Config","WinFFT",m_msWinFFT);
WriteProfileInt("Config","FreqHalfLive",m_nFreqHalfLive);
WriteProfileInt("Config","FreqValue",m_nFreqValue);
WriteProfileInt("Config","FreqBlur",m_nFreqBlur);
WriteProfileInt("Config","PassbandFreq1",m_nPassbandFreq1);
WriteProfileInt("Config","PassbandFreq2",m_nPassbandFreq2);
WriteProfileInt("Config","TransbandWidth",m_nTransbandWidth);
WriteProfileInt("Config","Modulate",m_bModulate);
WriteProfileInt("Config","DispMaxFreq",m_nDispMaxFreq);
WriteProfileInt("Config","DispMaxTime",m_msDispMaxTime);
WriteProfileInt("Config","DispSignalPlus",m_nDispSignalPlus);
WriteProfileInt("Config","DispFreqPlus",m_nDispFreqPlus);
}
int CVibApp::CalcGrid(double& dFrom,double& dTo,int& nSubGrids,int &nMainSubs)
{
int m;
double b,dSub,dMain,dValue;
b=log10((dTo-dFrom)/nSubGrids);
m=(int)floor(b);b-=m;
if(b>0.875)b=10;
else if(b>0.544)b=5;
else if(b>0.176)b=2;
else b=1;
dSub=b*pow(10,m); //每小格单位
dValue=fmod(dFrom,dSub);
if(dValue>0)dFrom-=dValue<dSub?dValue:0;
else if(dValue<0)dFrom-=dValue>-dSub?dSub+dValue:0;
dValue=fmod(dTo,dSub);
if(dValue>0)dTo+=dValue<dSub?dSub-dValue:0;
else if(dValue<0)dTo-=dValue>-dSub?dValue:0;
b=(double)nMainSubs/nSubGrids;
nSubGrids=(int)((dTo-dFrom)/dSub+0.5); //确定小格总数
b=log10(b*nSubGrids);
m=(int)floor(b);b-=m;
if(b>0.875)b=10;
else if(b>0.544)b=5;
else if(b>0.176)b=2;
else b=1;
b*=pow(10,m);
nMainSubs=(int)(b+0.5); //每主格的小格数
dMain=nMainSubs*dSub; //每主格的单位
dValue=fmod(dFrom,dMain);
if(dValue>0)m=dValue<dMain?(int)((dMain-dValue)/dSub+0.5):0;
else if(dValue<0)m=dValue>-dMain?(int)(-dValue/dSub+0.5):0;
else m=0;
return m;
}
BOOL CVibApp::ConfigOption(BOOL bSave)
{
if(bSave)
{
WriteProfileString("Config","Envelop",m_strEnvelop);
WriteProfileInt("Config","EnvelopSense",m_bEnvelopSense);
}
else
{
int i,nAT;
int f,x1,y1,x2=-99999,y2=0;
double dVal;
CString s,str;
m_strEnvelop=GetProfileString("Config","Envelop");
str=m_strEnvelop+";99999=0;";
for(i=0;i<m_nFFTPoint;i++)
{
f=i*1000/m_msWinFFT;
while(x2<f)
{
nAT=str.Find(";");
s=str.Left(nAT);
str=str.Mid(nAT+1);
x1=x2;y1=y2;
x2=atoi(s);y2=atoi(s.Mid(s.Find('=')+1));
}
dVal=double(y2-y1)/(x2-x1);
dVal*=f-x1;dVal+=y1;
m_aEnvelop[i]=dVal*dVal;
}
m_bEnvelopSense=GetProfileInt("Config","EnvelopSense",1);
}
return TRUE;
}
void CVibApp::SetPause(BOOL bPause)
{
if(bPause)
{
CopyMemory(m_aFFTOut,m_aPeak,sizeof(double)*m_nFFTCnt/2);
m_pView->Invalidate(FALSE);
}
else
{
ZeroMemory(m_aFFTOut,sizeof(double)*m_nFFTCnt);
ZeroMemory(m_aPeak,sizeof(double)*m_nFFTCnt);
}
m_bPause=bPause;
}
BOOL CVibApp::OnIdle(LONG lCount)
{
// TODO: Add your specialized code here and/or call the base class
if(m_pView->m_bRestart)
{
m_pView->m_bRestart=FALSE;
m_pView->StartWave(TRUE);
}
return CWinApp::OnIdle(lCount);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -