📄 lcypldlg.cpp
字号:
// lcyPLDlg.cpp : implementation file
//
#include "stdafx.h"
#include "lcyPL.h"
#include "lcyPLDlg.h"
#include "LcyWaveIn.h"//新添加的头文件
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
float *CLcyPLDlg::x_lcy;
/*设置初始采样长度*/
unsigned long CLcyPLDlg::m_SAMPLE_NUM =32768;
/////////////////////////////////////////////////////////////////////////////
// CLcyPLDlg dialog
CLcyPLDlg::CLcyPLDlg(CWnd* pParent /*=NULL*/)
: CDialog(CLcyPLDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CLcyPLDlg)
m_f = 0;
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CLcyPLDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CLcyPLDlg)
DDX_Control(pDX, IDC_EDIT1, m_edit);
DDX_Text(pDX, IDC_EDIT1, m_f);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CLcyPLDlg, CDialog)
//{{AFX_MSG_MAP(CLcyPLDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
ON_BN_CLICKED(IDC_BUTTON3, OnButton3)
ON_WM_CTLCOLOR()
ON_WM_TIMER()
ON_WM_CLOSE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CLcyPLDlg message handlers
BOOL CLcyPLDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
Brush1.CreateSolidBrush(RGB(0,0,0));//创建黑色画刷
//创建字体
font.CreateFont(300,120,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,
ANSI_CHARSET,OUT_CHARACTER_PRECIS,CLIP_CHARACTER_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"Times New Roman");
fontL.CreateFont(300,95,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,
ANSI_CHARSET,OUT_CHARACTER_PRECIS,CLIP_CHARACTER_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"Times New Roman");
pengreen.CreatePen(PS_SOLID,16,RGB(0,255,0));//创建绿色画笔
pengray.CreatePen(PS_SOLID,16,RGB(190,190,190));//创建灰色画笔
CWnd *wnd;
wnd=GetDlgItem(IDC_Indicater);//获取电平指示显示窗口的指针
wnd->GetWindowRect(&m_Indicater_rect);//获取电平指示显示窗口的矩形框
m_Indicater_rect.OffsetRect(-4,-24);//位移电平指示显示窗口的矩形框
Indicater_centerH=m_Indicater_rect.CenterPoint();//获取电平指示显示窗口的矩形框中心
x_lcy=new float[m_SAMPLE_NUM+100];//开劈数据内存
m_f = 12345;
//调打开声卡函数
if(LCY_OpenSoundCardIn(
1,//单声道输入工作方式
m_SAMPLE_NUM,//采样频率(Hz)
1024,//每个声道缓冲区数量
lcy_Callback/*回调函数*/)!=0)
OnButton3();
return TRUE;
}
void CLcyPLDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
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;
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CLcyPLDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
/*采样回调函数*/
int CLcyPLDlg::lcy_Callback(
void *inputBuffer,
unsigned long framesPerBuffer)
{
short *rptr = (short *)inputBuffer;
float *wptr =&x_lcy[frameIndex];
int finished;
unsigned long framesToCalc,i;
unsigned long framesLeft =m_SAMPLE_NUM+100 - frameIndex;
/*把输入端缓冲区的数据写入开劈内存空间*/
if( framesLeft < framesPerBuffer ){
framesToCalc = framesLeft;
finished = 1;
}
else{
framesToCalc = framesPerBuffer;
finished = 0;
}
if( inputBuffer == NULL ){
for( i=0; i<framesToCalc; i++ ){
*wptr++ = 0;/*清零 */
}
}
else{
for( i=0; i<framesToCalc; i++ ){
*wptr++ = *rptr++;/* 读采样的数据 */
}
}
frameIndex+= framesToCalc;
return finished;
}
/*声卡采样及计算频率值函数*/
void CLcyPLDlg::lcycyFFTC(void)
{
if(StartRecord()!=0)//调声卡采样函数
OnButton3();
unsigned long i;
complex *xa=new complex[m_SAMPLE_NUM];//为FFTC开辟的内存空间
for(i=0;i<m_SAMPLE_NUM;i++){//把才得的数据存入为FFTC开辟的内存空间
xa[i].re=x_lcy[i+100];
xa[i].im=0;
}
long pos=m_SAMPLE_NUM;//FFTC长度
spfftc(xa, &pos, &neg_i1);//快速复数傅立叶变换(FFTC)函数
for(i=0;i<m_SAMPLE_NUM;i++){//把变换后的数据除以m_SAMPLE_NUM,以防数据溢出
xa[i].re=xa[i].re/m_SAMPLE_NUM;
xa[i].im=xa[i].im/m_SAMPLE_NUM;
}
for(i=0;i<m_SAMPLE_NUM;i++){//计算变换后复数数据的摸
xa[i].re=sqrtf(xa[i].re*xa[i].re+xa[i].im*xa[i].im);
}
xa[0].re=0;
float Max=0;
for(i=0;i<=m_SAMPLE_NUM/2;i++){//找出基波的位置及幅度
if(xa[i].re>Max){
Max=xa[i].re;
m_f=i;//被测信号大于等于5000Hz时的频率值
}
}
IndicaterL=(int)(Max/10);//信号幅度
if(IndicaterL<2)//如果信号幅度太小
m_f=0;//频率只值显示0
m_FL=0;
if(IndicaterL>10&&m_f>1&&m_f<5000){
unsigned long j0,j=50;
while(x_lcy[j]>=0&&j<m_SAMPLE_NUM/2)//信号幅值大于0时,循环
j++;
while(x_lcy[j]<=0&&j<m_SAMPLE_NUM/2)//信号幅值小于0时,循环
j++;
j0=j;//信号第一个由小于0变为大于0时的点
bool a=0,b=0;
unsigned long c=0,d=0;
while(j<m_SAMPLE_NUM){
while(x_lcy[j]>=0&&j<m_SAMPLE_NUM+100){//信号幅值大于0时,循环
j++;
a=1;//已进行了循环的标记
}
while(x_lcy[j]<=0&&j<m_SAMPLE_NUM+100){//信号幅值小于0时,循环
j++;
b=1;//已进行了循环的标记
}
if(a==1&&b==1){//a,b都进行循环时
c++;//采得被测信号的周期数
d=j-j0;//在采得被测信号的周期数内的采样点数
}
a=0;b=0;//循环标记复位
}
if(d!=0)//如果在采得被测信号的周期数内的采样点数不位0
m_FL=(float)m_SAMPLE_NUM*c/d;//被测信号小于5000Hz时的频率值
else
m_FL=0;
}
delete []xa;//释放为FFTC开辟的内存空间
}
/*画电平指示线函数*/
void CLcyPLDlg::lcyIndicaterLine(void)
{
CClientDC dc(this);
oldpen=dc.SelectObject(&pengray);//选择灰色画笔
dc.MoveTo(12,Indicater_centerH.y);
dc.LineTo(m_Indicater_rect.right-14,Indicater_centerH.y);//清除老指示线
dc.SelectObject(&pengreen);//选择绿色画笔
if(IndicaterL>m_Indicater_rect.Width()-14)
IndicaterL=m_Indicater_rect.Width()-14;
if(IndicaterL<12)
IndicaterL=12;
dc.MoveTo(12,Indicater_centerH.y);
dc.LineTo(IndicaterL,Indicater_centerH.y);//画新指示线
dc.SelectObject(oldpen);//恢复原画笔
}
/*“开始测量”按钮函数*/
void CLcyPLDlg::OnButton1()
{
SetTimer(1,100,NULL);//设置定时器
}
/*“暂停测量”按钮函数*/
void CLcyPLDlg::OnButton2()
{
KillTimer(1);//取消定时器
}
/*“退出程序”按钮函数*/
void CLcyPLDlg::OnButton3()
{
LCY_CloseSoundCardIn();//调关闭声卡函数
delete []x_lcy;//释放内存
CDialog::OnCancel();//关闭窗口
}
//WM_CTLCOLOR消息函数
HBRUSH CLcyPLDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if(m_edit.m_hWnd==pWnd->m_hWnd){
CString str,strL;
str.Format("%ld",m_f);//高频数据输出格式
pDC->SetTextColor(RGB(255,0,0));//文本色
pDC->SetBkColor(RGB(0,0,0));//背景色
float err=(float)m_f-m_FL;
if(m_f<5000&&m_FL>1&&err<1&&err>-1){
if(m_f>500)
strL.Format("%.1f",m_FL);//低频数据输出格式
else if(m_f>50)
strL.Format("%.2f",m_FL);
else
strL.Format("%.3f",m_FL);
oldfont=pDC->SelectObject(&fontL);//选择字体
pDC->TextOut(1,1,strL);//输出低频频率值
}
else{
oldfont=pDC->SelectObject(&font);//选择字体
pDC->TextOut(1,1,str);//输出高频频率值
}
pDC->SelectObject(oldfont);//恢复原笔
return (HBRUSH) Brush1;//返回黑色画刷
}
return hbr;
}
//定时器响应函数
void CLcyPLDlg::OnTimer(UINT nIDEvent)
{
lcycyFFTC();//调声卡采样及计算频率值函数
lcyIndicaterLine();//调画电平指示线函数
m_edit.SetRedraw(1); //刷新频率显示窗口
CDialog::OnTimer(nIDEvent);
}
//关闭程序响应函数
void CLcyPLDlg::OnClose()
{
LCY_CloseSoundCardIn();//调关闭声卡函数
delete []x_lcy;//释放内存
CDialog::OnClose();
}
/*快速复数傅立叶变换(FFTC)函数*/
void CLcyPLDlg::spfftc(complex *x, long *n, long *isign)
{
long i, l, m, mr,tmp_int;
complex t, tmp_complex, tmp;
float pisign;
pisign = (float) (*isign * PI);
mr = 0;
for (m = 1 ; m < *n ; ++m){
l = *n;
l /= 2;
while (mr + l >= *n){
l /= 2;
}
mr = mr % l + l;
if (mr > m){
t.re = x[m].re;
t.im = x[m].im;
x[m].re = x[mr].re;
x[m].im = x[mr].im;
x[mr].re = t.re;
x[mr].im = t.im;
}
}
l = 1;
while (l < *n){
for (m = 0 ; m < l ; ++m){
tmp_int = l * 2;
for (i = m ; tmp_int < 0 ? i >= (*n - 1) : i < *n ;
i += tmp_int){
tmp.re = 0.0;
tmp.im = (float) m * pisign / (float) l;
complex_exp(&tmp_complex, &tmp);//调数据变换函数
t.re = x[i + l].re * tmp_complex.re -
x[i + l].im * tmp_complex.im;
t.im = x[i + l].re * tmp_complex.im +
x[i + l].im * tmp_complex.re;
x[i + l].re = x[i].re - t.re;
x[i + l].im = x[i].im - t.im;
x[i].re = x[i].re + t.re;
x[i].im = x[i].im + t.im;
}
}
l *= 2;
}
}
/*数据变换函数*/
void CLcyPLDlg::complex_exp(complex *r, complex *z)
{
double expx;
expx = exp((double) z->re);
r->re = (float) (expx * cosf(z->im));
r->im = (float) (expx * sinf(z->im));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -