⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testfilterdlg.cpp

📁 在VC下实现FFT对信号滤波,包括实现低通和带通滤波,图形显示
💻 CPP
字号:
//TestFilterDlg.cpp : implementation file

#include "stdafx.h"
#include "TestFilter.h"
#include "TestFilterDlg.h"
#include <math.h>

#include <stdlib.h>   
#include <stdio.h>   
#include <time.h>   

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#endif

typedef struct TWaveFileHeadStruct{	char FileHead1[4];	int  FileLength;	char FileHead2[8];	int	 Reserve;	PCMWAVEFORMAT PcmWaveFormat;	char DataPoint[4];	int	 nWaveLength;}WAVEFILEHEADSTRUCT;
typedef struct TWave{	WAVEFILEHEADSTRUCT WaveFileHead;	byte *lpChannelData[2];	byte *lpWaveData;}WAVE;
//CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

//Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD=IDD_ABOUTBOX };
	//}}AFX_DATA

	//ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);//DDX/DDV support
	//}}AFX_VIRTUAL

//Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		//No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//CTestFilterDlg dialog

CTestFilterDlg::CTestFilterDlg(CWnd* pParent/*=NULL*/)
	: CDialog(CTestFilterDlg::IDD,pParent)
{
	//{{AFX_DATA_INIT(CTestFilterDlg)
	m_bFilter=FALSE;
	m_FilterLow = 0;
	m_FilterHigh=0;
	m_bBaudPass = FALSE;
	//}}AFX_DATA_INIT
	//Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTestFilterDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTestFilterDlg)
	DDX_Control(pDX, IDC_EDIT_FILTER3, m_FreqList);
	DDX_Control(pDX, IDC_STATIC_WAVE2, m_CtrlWave2);
	DDX_Control(pDX, IDC_STATIC_FREQ, m_CtrlFreq);
	DDX_Control(pDX, IDC_STATIC_WAVE, m_CtrlWave);
	DDX_Check(pDX,IDC_CHECK_FILTER,m_bFilter);
	DDX_Text(pDX, IDC_EDIT_FILTER, m_FilterLow);
	DDX_Text(pDX, IDC_EDIT_FILTER2, m_FilterHigh);	
	DDX_Check(pDX, IDC_CHECK_BAUDPASS, m_bBaudPass);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTestFilterDlg,CDialog)
	//{{AFX_MSG_MAP(CTestFilterDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BTN_GENWAVE,OnBtnGenwave)
	ON_BN_CLICKED(IDC_BTN_FFT,OnBtnFft)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//CTestFilterDlg message handlers

BOOL CTestFilterDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	//IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX<0xF000);

	CMenu* pSysMenu=GetSystemMenu(FALSE);
	if(pSysMenu!=NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if(!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
		}
	}

	//Set the icon for this dialog.  The framework does this automatically
	//when the application's main window is not a dialog
	SetIcon(m_hIcon,TRUE);			//Set big icon
	SetIcon(m_hIcon,FALSE);			//Set small icon
	
	//TODO: Add extra initialization here
	m_CtrlWave.GetClientRect(&m_WaveRect);
	m_CtrlWave2.GetClientRect(&m_Wave2Rect);
	m_CtrlFreq.GetClientRect(&m_FreqRect);

	pWaveDC=m_CtrlWave.GetDC();
	memWaveDC.CreateCompatibleDC(pWaveDC);
	memBitmapWave.CreateCompatibleBitmap(pWaveDC,m_WaveRect.Width(),m_WaveRect.Height());
	memWaveDC.SelectObject(&memBitmapWave);

	pFreqDC=m_CtrlFreq.GetDC();
	memFreqDC.CreateCompatibleDC(pFreqDC);
	memBitmapFreq.CreateCompatibleBitmap(pFreqDC,m_FreqRect.Width(),m_FreqRect.Height());
	memFreqDC.SelectObject(&memBitmapFreq);

	pWave2DC=m_CtrlWave2.GetDC();
	memWave2DC.CreateCompatibleDC(pWave2DC);
	memBitmapWave2.CreateCompatibleBitmap(pWave2DC,m_Wave2Rect.Width(),m_Wave2Rect.Height());
	memWave2DC.SelectObject(&memBitmapWave2);

	fMaxFreq=1024;
	fdt=1/fMaxFreq;

	//创建字体
    NONCLIENTMETRICS ncm;
    ncm.cbSize=sizeof(NONCLIENTMETRICS);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&ncm,0);
    mWaveFont.CreateFontIndirect(&(ncm.lfMessageFont));

	DrawWaveData(&memWaveDC,m_WaveRect,fAccWave,N,1.2,TIME_FIELD);
	DrawWaveData(&memFreqDC,m_FreqRect,fFreqData,N,30,FREQ_FIELD);
	DrawWaveData(&memWave2DC,m_Wave2Rect,fAcc2Wave,N,0.5,TIME_FIELD);

	SetTimer(1,100,NULL);

	return TRUE;//return TRUE  unless you set the focus to a control
}

void CTestFilterDlg::OnSysCommand(UINT nID,LPARAM lParam)
{
	if((nID&0xFFF0)==IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID,lParam);
	}
}

//If you add a minimize button to your dialog,you will need the code below
//to draw the icon.  For MFC applications using the document/view model,
//this is automatically done for you by the framework.

void CTestFilterDlg::OnPaint() 
{
	if(IsIconic())
	{
		CPaintDC dc(this);//device context for painting

		SendMessage(WM_ICONERASEBKGND,(WPARAM) dc.GetSafeHdc(),0);

		//Center icon in client rectangle
		int cxIcon=GetSystemMetrics(SM_CXICON);
		int cyIcon=GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x=(rect.Width()-cxIcon+1)/2;
		int y=(rect.Height()-cyIcon+1)/2;

		//Draw the icon
		dc.DrawIcon(x,y,m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

//The system calls this to obtain the cursor to display while the user drags
//the minimized window.
HCURSOR CTestFilterDlg::OnQueryDragIcon()
{
	return(HCURSOR) m_hIcon;
}

void CTestFilterDlg::DrawWaveData(CDC *pDC,CRect mRect,FLOAT data[],INT ptNum,FLOAT fDataMax,int Mode)
{
	CPen GrayPen;
	CPen GreenPen;
	CPen *pOldPen;
	INT	nIndex;
	FLOAT fX0,fY0,fW,fH;
	FLOAT fTemp;
	INT	nTemp;
	INT	i;
	CString str;
	CRect mInRect;
	
	mInRect=mRect;

	pDC->SetTextColor(RGB(255,255,255));
	pDC->SetBkMode(TRANSPARENT);
	pDC->SelectObject(&mWaveFont);

	GrayPen.CreatePen(PS_SOLID,1,RGB(128,128,128));
	GreenPen.CreatePen(PS_SOLID,1,RGB(0,255,0));
	//绘制波形部分
	pOldPen=pDC->SelectObject(&GrayPen);
	pDC->Rectangle(mInRect);
	pDC->FillSolidRect(mInRect,RGB(50,50,50));

	mInRect.left=mInRect.left+30;
	mInRect.bottom=mInRect.bottom-20;
	
	fX0=(FLOAT)mInRect.left;
	fY0=(FLOAT)(mInRect.top+mInRect.bottom)/2.0f;
	fW=(FLOAT)mInRect.Width();
	fH=(FLOAT)mInRect.Height()/2.0f;

	//垂直线
	for(nIndex=0;nIndex<10;nIndex++)
	{
		fTemp=fX0+fW*nIndex/10.0f;
		nTemp=(INT)fTemp;
		pDC->MoveTo(nTemp,mInRect.top);
		pDC->LineTo(nTemp,mInRect.bottom);

		if(Mode==TIME_FIELD)
		{
			str.Format(_T("0.%d"),nIndex);
		}
		else
		{
			str.Format(_T("%d"),nIndex*100);
		}
		pDC->TextOut(nTemp,mRect.bottom-15,str);
	}
	if(Mode==TIME_FIELD)
		pDC->TextOut(mRect.right-15,mRect.bottom-15,"S");
	else
		pDC->TextOut(mRect.right-15,mRect.bottom-15,"Hz");
	//水平线
	for(nIndex=0;nIndex<5;nIndex++)
	{
		fTemp=fH*2.0f*nIndex/4.0f;
		nTemp=mInRect.top+(INT)fTemp;
		pDC->MoveTo(mInRect.left,nTemp);
		pDC->LineTo(mInRect.right,nTemp);
	}
	for(nIndex=0;nIndex<3;nIndex++)
	{
		fTemp=fH*2.0f*nIndex/4.0f;
		nTemp=mInRect.top+(INT)fTemp;

		if(Mode==TIME_FIELD)
		{
			str.Format(_T("%d"),1-nIndex);
		}
		else
		{
			str.Format(_T("%d"),200-nIndex*200);
		}
		pDC->TextOut(mRect.left+5,mRect.top+20+fTemp,str);
	}
	//绘制曲线
	pOldPen=pDC->SelectObject(&GreenPen);
	fTemp=SetWaveDataInScope(data[0],fDataMax);
	pDC->MoveTo((INT)(fX0+fW*0/ptNum),(INT)(fY0-fTemp/fDataMax*fH));

	for(i=1;i<=ptNum-1;i++)
	{
		//限制波形范围
		fTemp=SetWaveDataInScope(data[i],fDataMax);
		pDC->LineTo((INT)(fX0+fW*i/ptNum),(INT)(fY0-fTemp/fDataMax*fH));
	}

	pDC->SelectObject(pOldPen);

	GreenPen.DeleteObject();
	GrayPen.DeleteObject();
}

//设置在波形的范围内
float CTestFilterDlg::SetWaveDataInScope(FLOAT fValue,FLOAT fMax)
{
	FLOAT fTemp=0.0f;

	if((fValue<fMax)&&(fValue>(-1.0f)*fMax))
	{
		fTemp=fValue;
	}
	else if(fValue>=fMax)
	{
		fTemp=fMax;
	}
	else if(fValue<=(-1.0f)*fMax)
	{
		fTemp=fMax*(-1.0f);
	}

	return  fTemp;
}

void CTestFilterDlg::OnBtnGenwave() 
{
	//TODO: Add your control notification handler code here
	int	i;
	CString str;
	int freq0=rand()%10;
	int freq1=rand()%100;
	int freq2=rand()%200;
	int freq3=rand()%500;
	int freq4=rand()%10;

	str.Format("%d,%d,%d,%d,%d",freq0,freq1,freq2,freq3,freq4);
	m_FreqList.SetWindowText(str);
	for(i=0;i<N;i++)
	{
		fAccWave[i]=0.7*sin(2*PI*freq0*i*fdt)+0.5*sin(2*PI*freq1*i*fdt)
			+0.2*sin(2*PI*freq2*i*fdt)+0.1*sin(2*PI*freq3*i*fdt)+0.7*sin(2*PI*freq4*i*fdt);
	}
	DrawWaveData(&memWaveDC,m_WaveRect,fAccWave,N,1.2,TIME_FIELD);
	OnBtnFft();
}

//设置在频谱的范围内
FLOAT CTestFilterDlg::SetFreqDataInScope(FLOAT fValue,FLOAT fMax)
{
	FLOAT fTemp=0.0f;

	//限制范围
	if((fValue<fMax)&&(fValue>(-1*fMax)))
	{
		fTemp=fValue;
	}
	else
	{
		fTemp=0.5f;
	}

	return  fTemp;
}

void CTestFilterDlg::OnBtnFft() 
{
	//TODO: Add your control notification handler code here
	//计算频谱
	//时域 -FFT-- >频域 --> 滤波 -IFFT-->时域 

	int	i;
	float xreal[N],ximag[N],xres[N];

	UpdateData(TRUE);

	for(i=0;i<N;i++)
	{
		xreal[i]=fAccWave[i];
		ximag[i]=0.0;
	}

	FourieTrans(xreal,ximag,N);
	GetResult(xreal,ximag,xres,N);

	//在频域上滤波
	if(m_bFilter)
	{
		if(m_FilterLow>=0 && m_FilterLow<N/2 &&m_FilterHigh>m_FilterLow && m_FilterHigh<N/2)
		{
			if(m_bBaudPass)
			{
				for(i=0;i<m_FilterLow;i++)
				{
					xres[i]=0;
					xres[N-i]=0;
				}
				for(i=m_FilterHigh;i<N/2;i++)
				{
					xres[i]=0;
					xres[N-i]=0;
				}
			}
			else
			{
				for(i=m_FilterLow;i<m_FilterHigh;i++)
				{
					xres[i]=0;
					xres[N-i]=0;
				}
			}
		}
	}

	for(i=0;i<N;i++)
	{
		fFreqData[i]=xres[i];
	}

	for(i=0;i<N;i++)
	{
		xreal[i]=xres[i];
		ximag[i]=0.0;
	}
	IFourieTrans(xreal,ximag,N);
	for(i=0;i<N;i++)
	{
		xres[i]=(1/(float)N)*4*(xreal[i]+ximag[i]);
	}

	for(i=0;i<N;i++)
	{
		fAcc2Wave[i]=xres[i];
	}
	DrawWaveData(&memFreqDC,m_FreqRect,fFreqData,N,30,FREQ_FIELD);
	DrawWaveData(&memWave2DC,m_Wave2Rect,fAcc2Wave,N,0.5,TIME_FIELD);
}

void CTestFilterDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default

	pWaveDC->BitBlt(m_WaveRect.left,m_WaveRect.top,m_WaveRect.right,m_WaveRect.bottom,
		&memWaveDC,0,0,SRCCOPY);
	pFreqDC->BitBlt(m_FreqRect.left,m_FreqRect.top,m_FreqRect.right,m_FreqRect.bottom,
		&memFreqDC,0,0,SRCCOPY);
	pWave2DC->BitBlt(m_Wave2Rect.left,m_Wave2Rect.top,m_Wave2Rect.right,m_Wave2Rect.bottom,
		&memWave2DC,0,0,SRCCOPY);

	CDialog::OnTimer(nIDEvent);
}

⌨️ 快捷键说明

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