📄 windowfilterview.cpp
字号:
for (i=0; i<n; i++)
{
temp = 1.0-2.0*i/(n-1);
temp *= temp;
temp = 1.0 - temp;
temp = sqrt(temp);
real[i] = ino(beta * temp) / ino(beta);
imag[i] = 0.0;
}
}
//理想低通滤波器的脉冲相应
void CWindowFilterView::CreateHd(float *real, float *imag, int n, float wc)
{
int i;
int a;
float a2;
int m;
float m2;
//通过内部转换,在输入的时候不必再乘以pi
wc = wc * PI;
if (n % 2)
{
a = n / 2;
for (i=0; i<n; i++)
{
m = i - a ; //+0.0001;
if (i == a)
{
real[i] = wc / PI;
}
else
{
real[i] = sin(wc*m) / (PI*m);
}
imag[i] = 0.0;
}
}
else
{
a2 = (n-1) / 2.0;
for (i=0; i<n; i++)
{
m2 = i - a2 ; //+0.0001;
real[i] = sin(wc*m2) / (PI*m2);
imag[i] = 0.0;
}
}
}
//对低通频率的采样函数 单位为 rad*pi
void CWindowFilterView::CreateSample(float *real, float *imag, int n, float wc)
{
int i;
for (i=0; i<= wc*n/2; i++)
{
real[i] = 1.0;
imag[i] = 0.0;
}
for (; i<=n/2; i++ )
{
real[i] = 0.0;
imag[i] = 0.0;
}
for (; i<n; i++)
{
real[i] = real[n - i];
imag[i] = 0.0;
}
}
//选择窗函数的类型
void CWindowFilterView::OnSelchangeWindowtipe()
{
// TODO: Add your control notification handler code here
int index = ((CComboBox *)GetDlgItem (IDC_WINDOWTIPE))->GetCurSel();
m_iWindowType = index;
if (index == 5)
{
(CStatic *)GetDlgItem(IDC_STATIC_BETY)->EnableWindow(TRUE);
(CEdit *)GetDlgItem(IDC_EDIT_BETY)->EnableWindow(TRUE);
}
else
{
(CStatic *)GetDlgItem(IDC_STATIC_BETY)->EnableWindow(false);
(CEdit *)GetDlgItem(IDC_EDIT_BETY)->EnableWindow(false);
}
}
//选择是低通还是高通滤波器
void CWindowFilterView::OnSelchangeFiltertype()
{
// TODO: Add your control notification handler code here
int index = ((CComboBox *)GetDlgItem (IDC_FILTERTYPE))->GetCurSel();
m_iFilterType = index;
switch (index)
{
case 0:
case 1:
(CStatic *)GetDlgItem(IDC_HIGHWC)->EnableWindow(false);
(CEdit *)GetDlgItem(IDC_EDIT_HIGH)->EnableWindow(false);
break;
case 2:
case 3:
(CStatic *)GetDlgItem(IDC_HIGHWC)->EnableWindow(TRUE);
(CEdit *)GetDlgItem(IDC_EDIT_HIGH)->EnableWindow(TRUE);
break;
}
}
//根据选择创建窗函数
void CWindowFilterView::CreateWindowFun(int index, int length)
{
//不传递额外的参数,直接调用成员变量。
// UpdateData(TRUE);
if (pWindowReal!=NULL)
{
delete []pWindowReal;
pWindowReal = NULL;
}
if (pWindowImag!=NULL)
{
delete []pWindowImag;
pWindowImag = NULL;
}
pWindowReal = new float[length];
pWindowImag = new float[length];
memset(pWindowReal, 0, sizeof(float)*length);
memset(pWindowImag, 0, sizeof(float)*length);
switch (m_iWindowType)
{
case 0:
CreateRect(pWindowReal,pWindowImag,length);
break;
case 1:
CreateTriang(pWindowReal,pWindowImag,length);
break;
case 2:
CreateHanning(pWindowReal,pWindowImag,length);
break;
case 3:
CreateHamming(pWindowReal,pWindowImag,length);
break;
case 4:
CreateBlackman(pWindowReal,pWindowImag,length);
break;
case 5:
CreateKaiser(pWindowReal,pWindowImag,length,m_bety);
break;
}
}
//创建加窗口的实际时间序列
//index为滤波器的类型,如低通还是高通
void CWindowFilterView::CreateHFun(int index, int n)
{
int i;
// UpdateData(TRUE);
//不传递参数,直接调用成员变量
if (pHdImag!=NULL)
{
delete []pHdImag;
pHdImag = NULL;
}
if (pHdReal!=NULL)
{
delete []pHdReal;
pHdReal = NULL;
}
if (pReal!=NULL)
{
delete []pReal;
pReal = NULL;
}
if (pImag!=NULL)
{
delete []pImag;
pImag = NULL;
}
//类的成员变量
pHdImag = new float[n];
pHdReal = new float[n];
float *pHdImag2 = new float [n];
float *pHdReal2 = new float [n];
float *pHdImag3 = new float [n];
float *pHdReal3 = new float [n];
pReal = new float [n];
pImag = new float [n];
memset(pHdImag, 0,sizeof(float)*n);
memset(pHdReal,0,sizeof(float)*n);
memset(pHdImag2, 0,sizeof(float)*n);
memset(pHdReal2,0,sizeof(float)*n);
memset(pHdImag3, 0,sizeof(float)*n);
memset(pHdReal3,0,sizeof(float)*n);
memset(pReal, 0,sizeof(float)*n);
memset(pImag,0,sizeof(float)*n);
switch (index)
{
case 0: //低通
CreateHd(pHdReal,pHdImag,n,m_WcLow);
break;
case 1: //高通
CreateHd(pHdReal,pHdImag,n,m_WcLow);
CreateHd(pHdReal2,pHdImag2,n,1);
for (i=0; i<n; i++)
{
pHdReal[i] = pHdReal2[i] - pHdReal[i];
}
break;
case 2: //带通
CreateHd(pHdReal,pHdImag,n,m_WcLow);
CreateHd(pHdReal2,pHdImag2,n,m_WcHigh);
for (i=0; i<n; i++)
{
pHdReal[i] = pHdReal2[i] - pHdReal[i];
}
break;
case 3: //带阻
CreateHd(pHdReal,pHdImag,n,m_WcLow);
CreateHd(pHdReal2,pHdImag2,n,m_WcHigh);
CreateHd(pHdReal3,pHdImag3,n,1);
for (i=0; i<n; i++)
{
pHdReal[i] = pHdReal3[i] + pHdReal[i] - pHdReal2[i];
}
break;
}
delete []pHdImag2;
delete []pHdReal2;
delete []pHdImag3;
delete []pHdReal3;
CreateWindowFun(m_iWindowType, n);
if (pImag!=NULL)
{
delete []pImag;
pImag = NULL;
}
if (pReal!=NULL)
{
delete []pReal;
pReal = NULL;
}
pImag = new float[n];
pReal = new float[n];
memset(pImag, 0,sizeof(float)*n);
memset(pReal,0,sizeof(float)*n);
for (i=0; i<n; i++)
{
pReal[i] = pHdReal[i] * pWindowReal[i];
pImag[i] = 0.0;
}
}
//清除画板函数
void CWindowFilterView::CleanPalette(int index)
{
if (m_bClean == FALSE)
{
m_bClean = TRUE;
}
else
{
//清除画板;
Invalidate();
}
}
//函数重载
//这次用到的函数
//需要详细修改
//x轴的标注范围和y的取值
void CWindowFilterView::Plot(int n, int length, float max,float *num, float xmax,
float ymin, float ymax)
{
float detaX ,detaY;
CRect rect;
CStatic *pWndLine;
//目前只标注5个点。
int biaozhunum = 5;
int xbiaozhu = length / biaozhunum;
//得到对应的画板
switch (n)
{
case 1:
pWndLine = (CStatic *)GetDlgItem(IDC_PALETTE1);
break;
case 2:
pWndLine = (CStatic *)GetDlgItem(IDC_PALETTE2);
break;
case 3:
pWndLine = (CStatic *)GetDlgItem(IDC_PALETTE3);
break;
}
//得到画板的大小
pWndLine->GetClientRect(&rect);
CClientDC pLinwDC(pWndLine);
pLinwDC.SetBkMode(TRANSPARENT); //设置文字背景颜色
pLinwDC.SetMapMode(MM_TEXT); //Y轴向下,画图时候要加负号
//设置原点
// pLinwDC.SetViewportOrg(int(rect.right/(length+2)),int(rect.bottom/2));
detaX = (float)(rect.right/(length+2)); //x轴间距
// detaY = (float)(0.5 * (rect.Height()-30) / max); //y轴间距,重新计算,以及y的大小
detaY = (float)((rect.Height()-30) / (ymax - ymin));
//重新设置原点
// 15 = 30 / 2;
// pLinwDC.SetViewportOrg(int(rect.right/(length+2)),int( rect.bottom-15 + ymin * detaY)));
int y0 = rect.Height();
//如果算出来的x原点为 0,则修正值为 15
pLinwDC.SetViewportOrg(int(rect.right/(length+2) + 15 ),int(rect.bottom-15-(-ymin * detaY)));
CPen axisPen, pointPen;
CPen *pOldPen;
CFont bigFont, smallFont;
CFont *pOldFont;
axisPen.CreatePen(PS_SOLID,2,RGB(0,0,0)); //黑线
pointPen.CreatePen(PS_SOLID,1,RGB(255,0,0)); //红线
bigFont.CreatePointFont(100,"Arial",NULL);
smallFont.CreatePointFont(80,"Arial",NULL);
pOldPen = pLinwDC.SelectObject(&axisPen);
//绘制x,y坐标轴
//y轴的坐标要重新计算
pLinwDC.MoveTo(0, - ymax * detaY);
pLinwDC.LineTo((int)(detaX*length), - ymax * detaY);
pLinwDC.MoveTo((int)(detaX*length), - ymax * detaY);
pLinwDC.LineTo((int)(detaX*length-8), - ymax * detaY -4);
pLinwDC.MoveTo((int)(detaX*length), - ymax * detaY );
pLinwDC.LineTo((int)(detaX*length-8), - ymax * detaY +4);
//绘制y轴
pLinwDC.MoveTo(0, - ymin * detaY);
pLinwDC.LineTo(0, - ymax * detaY);
CString str;
pOldFont = pLinwDC.SelectObject(&bigFont);
str.Format("%.1f", ymax);
pLinwDC.TextOut(0 + 2,- ymax * detaY,str);
// pLinwDC.SelectObject(&smallFont);
// int yymax =(int)log10(max);
str.Format("%.1f", ymin);
pLinwDC.TextOut(0 + 2, - ymin * detaY,str);
//绘制线段
pLinwDC.SelectObject(&pointPen);
pLinwDC.SelectObject(pOldFont);
//关键是第一个点的位置,要考虑到是不是在表示的范围
//very important
int i,x,y;
float y1;
int j = 0;
bool firstPoint = TRUE;
for (i=0; i<length; i++)
{
if (i % xbiaozhu == 0 && i !=0) //x轴坐标值标注
{
j ++ ;
str.Format("%.1f",(float )j / biaozhunum * xmax);
pLinwDC.TextOut((int)(i * detaX - 4) , 3, str);
}
x = (int)(i * detaX);
y1 = num[i];
if (y1 > ymax)
continue;
if (y1 < ymin)
continue;
y = (int)(y1 * detaY);
//第一个点能够画出的点
if (m_bFirst)
{
// CPoint firstPt(x,-y);
// pLinwDC.SetPixel(firstPt,RGB(255,0,0));
pLinwDC.MoveTo(x, - y);
m_bFirst = FALSE;
}
else
{
pLinwDC.LineTo(x,-y);
}
}
pLinwDC.SelectObject(pOldPen);
axisPen.DeleteObject();
pointPen.DeleteObject();
bigFont.DeleteObject();
smallFont.DeleteObject();
}
//知识设置了x轴的标注范围
void CWindowFilterView::Plot(int n, int length, float max,float *num, float xmax)
{
float detaX ,detaY;
CRect rect;
CStatic *pWndLine;
//目前只标注5个点。
int biaozhunum = 5;
int xbiaozhu = length / biaozhunum;
//得到对应的画板
switch (n)
{
case 1:
pWndLine = (CStatic *)GetDlgItem(IDC_PALETTE1);
break;
case 2:
pWndLine = (CStatic *)GetDlgItem(IDC_PALETTE2);
break;
case 3:
pWndLine = (CStatic *)GetDlgItem(IDC_PALETTE3);
break;
}
//得到画板的大小
pWndLine->GetClientRect(&rect);
CClientDC pLinwDC(pWndLine);
pLinwDC.SetBkMode(TRANSPARENT); //设置文字背景颜色
pLinwDC.SetMapMode(MM_TEXT); //Y轴向下,画图时候要加负号
//设置原点
//15为修正的偏倚量
pLinwDC.SetViewportOrg(int(rect.right/(length+2) + 15 ),int(rect.bottom/2));
detaX = (float)(rect.right/(length+2)); //x轴间距
detaY = (float)(0.5 * (rect.Height()-30) / max); //y轴间距,重新计算,以及y的大小
CPen axisPen, pointPen;
CPen *pOldPen;
CFont bigFont, smallFont;
CFont *pOldFont;
axisPen.CreatePen(PS_SOLID,2,RGB(0,0,0)); //黑线
pointPen.CreatePen(PS_SOLID,1,RGB(255,0,0)); //红线
bigFont.CreatePointFont(100,"Arial",NULL);
smallFont.CreatePointFont(80,"Arial",NULL);
pOldPen = pLinwDC.SelectObject(&axisPen);
//绘制x,y坐标轴
pLinwDC.MoveTo(0,0);
pLinwDC.LineTo((int)(detaX*length),0);
pLinwDC.MoveTo((int)(detaX*length),0);
pLinwDC.LineTo((int)(detaX*length-8),-4);
pLinwDC.MoveTo((int)(detaX*length),0);
pLinwDC.LineTo((int)(detaX*length-8),4);
pLinwDC.MoveTo(0,rect.bottom/2-10);
pLinwDC.LineTo(0,-1*(rect.bottom/2-10));
//求最大值的次方数,用于标注10的几次方
//之后要创建字体
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -