www.pudn.com > hmmPlatform.rar > PlatformView.cpp


// PlatformView.cpp : CPlatformView 类的实现 
// 
 
#include "stdafx.h" 
#include "Platform.h" 
 
#include "PlatformDoc.h" 
#include "PlatformView.h" 
#include ".\platformview.h" 
#include  
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 
 
 
// CPlatformView 
 
IMPLEMENT_DYNCREATE(CPlatformView, CFormView) 
 
BEGIN_MESSAGE_MAP(CPlatformView, CFormView) 
	ON_WM_SIZE() 
	ON_COMMAND(ID_FILE_OPEN, OnFileOpen) 
	ON_BN_CLICKED(IDC_CONTROL_LOAD, OnBnClickedControlLoad) 
	ON_COMMAND(ID_DISPLAY_OPTION, OnDisplayOption) 
	ON_BN_CLICKED(IDC_CONTROL_PREVIOUS, OnBnClickedControlPrevious) 
	ON_BN_CLICKED(IDC_CONTROL_NEXT, OnBnClickedControlNext) 
	ON_BN_CLICKED(IDC_CONTROL_STOP, OnBnClickedControlStop) 
	ON_BN_CLICKED(IDC_CONTROL_PLAY, OnBnClickedControlPlay) 
	ON_COMMAND(ID_DISPLAY_WAVE, OnDisplayWave) 
	ON_COMMAND(ID_DISPLAY_ZERO, OnDisplayZero) 
	ON_COMMAND(ID_DISPLAY_POWER, OnDisplayPower) 
	ON_COMMAND(ID_DISPLAY_VIBRATION, OnDisplayVibration) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_WAVE, OnUpdateDisplayWave) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_ZERO, OnUpdateDisplayZero) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_POWER, OnUpdateDisplayPower) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_VIBRATION, OnUpdateDisplayVibration) 
	ON_COMMAND(ID_DISPLAY_ZOOMIN, OnDisplayZoomin) 
	ON_COMMAND(ID_DISPLAY_ZOOMOUT, OnDisplayZoomout) 
	ON_COMMAND(ID_DISPLAY_SPECTRUM, OnDisplaySpectrum) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_SPECTRUM, OnUpdateDisplaySpectrum) 
	ON_COMMAND(ID_DISPLAY_LOGSPECTRUM, OnDisplayLogspectrum) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_LOGSPECTRUM, OnUpdateDisplayLogspectrum) 
	ON_COMMAND(ID_DISPLAY_CEPSTRUM, OnDisplayCepstrum) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_CEPSTRUM, OnUpdateDisplayCepstrum) 
	ON_WM_MOUSEWHEEL() 
	ON_BN_CLICKED(IDC_CONTROL_DISPLAYWAVE_ALL, OnBnClickedControlDisplaywaveAll) 
	ON_COMMAND(ID_SECTION_END, OnSectionEnd) 
	ON_COMMAND(ID_SECTION_SY, OnSectionSy) 
	ON_COMMAND(ID_VQ_KMEANS, OnVqKmeans) 
	ON_COMMAND(ID_HMM_ADDMODEL, OnHmmAddmodel) 
	ON_COMMAND(ID_HMM_TRAINMODEL, OnHmmTrainmodel) 
	ON_COMMAND(ID_HMM_DEMO, OnHmmDemo) 
	ON_COMMAND(ID_DISPLAY_AFTERWINDOW, OnDisplayAfterwindow) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_BEFOREWINDOW, OnUpdateDisplayBeforewindow) 
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_AFTERWINDOW, OnUpdateDisplayAfterwindow) 
	ON_COMMAND(ID_DISPLAY_BEFOREWINDOW, OnDisplayBeforewindow) 
END_MESSAGE_MAP() 
 
// CPlatformView 构造/析构 
 
CPlatformView::CPlatformView() 
	: CFormView(CPlatformView::IDD) 
	, m_ctlDisplay(CWnd::GetSafeHwnd()) 
	, m_strResult(_T("")) 
{ 
	// TODO: 在此处添加构造代码 
	// 设置默认参数 
	this->m_nFrameSize = SETTING_FRAME_SIZE; 
	this->m_nTotalFrames = 0; 
	this->m_nCurrentFrame = 0; 
	this->m_ctlDisplay.SetXMetrics(SETTING_XMETRICS); 
	this->m_ctlDisplay.SetYMetrics(SETTING_YMETRICS); 
	this->m_ctlDisplay.SetZoomStep(SETTING_ZOOMSTEP); 
 
	// 默认显示时域波形 
	this->m_displayType = DisplayWave; 
 
	// 设定部分控件不可用 
	this->EnableControl(TRUE); 
} 
 
CPlatformView::~CPlatformView() 
{ 
} 
 
void CPlatformView::DoDataExchange(CDataExchange* pDX) 
{ 
	CFormView::DoDataExchange(pDX); 
	DDX_Control(pDX, IDC_DISPLAYAREA, m_ctlDisplay); 
	DDX_Text(pDX, IDC_EDIT_RESULT, m_strResult); 
} 
 
BOOL CPlatformView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: 在此处通过修改 CREATESTRUCT cs 来修改窗口类或 
	// 样式 
 
	return CFormView::PreCreateWindow(cs); 
} 
 
void CPlatformView::OnInitialUpdate() 
{ 
	CFormView::OnInitialUpdate(); 
	GetParentFrame()->RecalcLayout(); 
	ResizeParentToFit(); 
} 
 
 
// CPlatformView 诊断 
 
#ifdef _DEBUG 
void CPlatformView::AssertValid() const 
{ 
	CFormView::AssertValid(); 
} 
 
void CPlatformView::Dump(CDumpContext& dc) const 
{ 
	CFormView::Dump(dc); 
} 
 
CPlatformDoc* CPlatformView::GetDocument() const // 非调试版本是内联的 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPlatformDoc))); 
	return (CPlatformDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
 
// CPlatformView 消息处理程序 
 
////////////////////////////////////////////////////////////////////////// 
// 更改显示区域宽度 
void CPlatformView::OnSize(UINT nType, int cx, int cy) 
{ 
	CFormView::OnSize(nType, cx, cy); 
 
	// TODO: 在此处添加消息处理程序代码 
	CWnd* pWnd = NULL; 
	// 计算控件left 
	UINT nLeft = 0; 
	// 计算控件宽度 
	UINT nWidth = 0; 
 
	// 控件区域 
	CRect ctlRect; 
	// 视图区域 
	CRect viewRect; 
	CSize size; 
 
	// 若不是最小化窗口,更改显示控件宽度 
	if (this->m_ctlDisplay.m_hWnd && nType == SIZE_RESTORED) 
	{ 
		nWidth = cx - 20; 
		nLeft = 10; 
		CWnd::GetWindowRect(&viewRect); 
 
		// 取得显示区域当前位置和大小 
		this->m_ctlDisplay.GetWindowRect(&ctlRect); 
		size = ctlRect.Size(); 
 
		// 设置显示区域的新宽度和位置 
		this->m_ctlDisplay.SetWindowPos(NULL, nLeft, 10,  
			nWidth, size.cy, SWP_NOREDRAW); 
 
		// 修改Result信息控件宽度和长度 
		pWnd = CWnd::GetDlgItem(IDC_EDIT_RESULT); 
		pWnd->GetWindowRect(&ctlRect); 
 
		pWnd->SetWindowPos( 
			NULL, nLeft, ctlRect.top - viewRect.top,  
			nWidth, viewRect.bottom - ctlRect.top - 5, SWP_SHOWWINDOW); 
	} 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 打开Wave文件,计算总帧数,并设置语音参数显示 
void CPlatformView::OnFileOpen() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CFileDialog dlg(TRUE, "*.wav"); 
 
	if (dlg.DoModal() == IDOK) 
	{ 
		// 打开分析文件,设定回调方式 
		this->m_strWaveFile = dlg.GetPathName(); 
		this->m_fileWaveOut.LoadFile( 
			this->m_strWaveFile, (DWORD) this->GetSafeHwnd()); 
 
		// 设定控件显示 
		// 默认显示时域波形 
		this->m_displayType = DisplayWave; 
		this->EnableControl(TRUE); 
		this->EnableFrameControl(); 
		this->UpdateFrameControl(TRUE); 
	} 
} 
 
void CPlatformView::OnBnClickedControlLoad() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	this->OnFileOpen(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示参数设定对话框 
void CPlatformView::OnDisplayOption() 
{ 
	// 获取设置参数 
	this->m_dlgSetting.m_fXMetrics = this->m_ctlDisplay.GetXMetrics(); 
	this->m_dlgSetting.m_fYMetrics = this->m_ctlDisplay.GetYMetrics(); 
 
	// TODO: 在此添加命令处理程序代码 
	if (this->m_dlgSetting.DoModal() == IDOK) 
	{ 
		// 设定每帧包含样本数 
		if (this->m_nFrameSize != this->m_dlgSetting.m_nFrameSize) 
		{ 
			this->m_nFrameSize = this->m_dlgSetting.m_nFrameSize; 
			// 更新帧信息 
			this->UpdateFrameControl(TRUE); 
		} 
 
		// 设定Y放大系数 
		this->m_ctlDisplay.SetYMetrics(this->m_dlgSetting.m_fYMetrics); 
 
		// 设定X放大系数 
		this->m_ctlDisplay.SetXMetrics(this->m_dlgSetting.m_fXMetrics); 
 
		// 设定显示精度 
		this->m_ctlDisplay.SetPrecision(this->m_dlgSetting.m_nPrecision); 
 
		// 设定显示微调系数 
		this->m_ctlDisplay.SetZoomStep(this->m_dlgSetting.m_nZoomStep); 
 
		// 刷新显示 
		this->m_ctlDisplay.Invalidate(); 
	} 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 播放控制函数,播放上一帧数据 
void CPlatformView::OnBnClickedControlPrevious() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
 
	// 发送指定帧 
	if (this->m_nCurrentFrame > 1) 
	{ 
		this->m_nCurrentFrame -- ; 
 
		// 显示当前播放帧的参数信息 
		this->UpdateDisplay(TRUE,  
			this->m_nCurrentFrame - 1, this->m_nCurrentFrame); 
 
		// 显示帧数信息 
		this->UpdateFrameControl(); 
 
		// 播放指定数据 
		this->m_fileWaveOut.PlaySamples( 
			(this->m_nCurrentFrame - 1) * this->m_nFrameSize, this->m_nFrameSize); 
	} 
	else 
	{ 
		AfxMessageBox("已经是第1帧"); 
	} 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 播放控制函数,播放下一帧数据 
void CPlatformView::OnBnClickedControlNext() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
 
	// 发送指定帧 
	if (this->m_nCurrentFrame < this->m_nTotalFrames) 
	{ 
		this->m_nCurrentFrame ++ ; 
 
		// 显示当前播放帧的参数信息 
		this->UpdateDisplay(TRUE,  
			this->m_nCurrentFrame - 1, this->m_nCurrentFrame); 
 
		// 显示帧数信息 
		this->UpdateFrameControl(); 
 
		// 播放指定数据 
		this->m_fileWaveOut.PlaySamples( 
			(this->m_nCurrentFrame - 1) * this->m_nFrameSize, this->m_nFrameSize); 
	} 
	else 
	{ 
		AfxMessageBox("已经是最后帧"); 
	} 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 播放控制函数,结束播放 
void CPlatformView::OnBnClickedControlStop() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	// 停止当前播放 
	this->m_fileWaveOut.Stop(); 
 
	// 设置控件 
	this->EnableControl(FALSE); 
	this->EnableFrameControl(FALSE, FALSE); 
 
	// 清空显示 
	this->m_ctlDisplay.LoadData(NULL, 0); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 播放控制函数,连续播放 
void CPlatformView::OnBnClickedControlPlay() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	this->m_fileWaveOut.Start(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示类型为时域波形 
void CPlatformView::OnDisplayWave() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplayWave; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(TRUE,  
		this->m_nCurrentFrame - 1, this->m_nCurrentFrame); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示类型为短时过零率 
void CPlatformView::OnDisplayZero() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplayZero; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示类型为短时能量 
void CPlatformView::OnDisplayPower() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplayPower; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示类型为平均振幅 
void CPlatformView::OnDisplayVibration() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplayVibration; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 选择显示类型为时域波形 
void CPlatformView::OnUpdateDisplayWave(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplayWave); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 选择显示类型为短时过零率 
void CPlatformView::OnUpdateDisplayZero(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplayZero); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 选择显示类型为短时能量 
void CPlatformView::OnUpdateDisplayPower(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplayPower); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 选择显示类型为平均振幅 
void CPlatformView::OnUpdateDisplayVibration(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplayVibration); 
} 
////////////////////////////////////////////////////////////////////////// 
// 是否允许使用wav控制功能 
void CPlatformView::EnableControl(BOOL bEnabled /* = TRUE */) 
{ 
	CWnd* pWnd = NULL; 
	CString strInfo; 
	 
	// 设置部分控件是否可用 
	if (this->m_hWnd) 
	{ 
		// 设定播放按钮 
		pWnd = CWnd::GetDlgItem(IDC_CONTROL_PLAY); 
		pWnd->EnableWindow(bEnabled); 
 
		// 设定结束按钮 
		pWnd = CWnd::GetDlgItem(IDC_CONTROL_STOP); 
		pWnd->EnableWindow(bEnabled); 
 
		// 设定显示全部时域波形按钮 
		pWnd = CWnd::GetDlgItem(IDC_CONTROL_DISPLAYWAVE_ALL); 
		pWnd->EnableWindow(bEnabled); 
 
		// 若为打开文件,显示文件信息 
		if (bEnabled) 
		{ 
			// 获取文件格式信息			 
			WAVEFORMATEX fmt = this->m_fileWaveOut.m_wavFile.GetWaveFormat(); 
 
			// 显示文件格式信息 
			strInfo.Format("分析文件:%s\r\n采样频率:%d\r\n声道数:%d\r\n位数:%d\r\n样本点数:%d\r\n", 
				this->m_strWaveFile, 
				fmt.nSamplesPerSec, 
				fmt.nChannels, 
				fmt.wBitsPerSample, 
				this->m_fileWaveOut.m_wavFile.GetSampleFramesCount() 
				); 
			CWnd::SetDlgItemText(IDC_EDIT_VOICEINFO, strInfo); 
		} 
		// 若为关闭文件,清空文件信息 
		else 
		{ 
			CWnd::SetDlgItemText(IDC_VOICE_INFO, ""); 
			CWnd::SetDlgItemText(IDC_EDIT_VOICEINFO, ""); 
			CWnd::SetDlgItemText(IDC_EDIT_RESULT, ""); 
		} 
	} 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示指定帧或全部裸音频数据的相应波形 
void CPlatformView::UpdateDisplay(  
								  BOOL bDisplayByFrame /* = FALSE */,   
								  unsigned int nFromFrame /* = 0 */,   
								  unsigned int nToFrame /* = 0   */) 
{ 
	// 裸音频的数据 
	WAVEHDR waveHdr; 
	waveHdr.lpData = NULL; 
 
	// 待显示的数据 
	double* pData = NULL; 
	// 待显示得数据长度 
	UINT nCount = 0; 
	// wave裸音频数据长度 
	unsigned int nRawCount = 0; 
	// 用于数据转换的临时指针 
	double* pTemp = NULL; 
 
	// 获取裸音频的数据 
	if (bDisplayByFrame) 
	{ 
		if (nFromFrame < nToFrame) 
		{ 
			this->m_fileWaveOut.GetSamples( 
				&waveHdr, nFromFrame * this->m_nFrameSize,  
				(nToFrame - nFromFrame) * this->m_nFrameSize); 
		} 
	} 
	else 
	{ 
		this->m_fileWaveOut.GetSamples(&waveHdr, 0); 
	} 
 
	// 显示相应的波形 
	if (waveHdr.lpData != NULL) 
	{	 
		// 按输入音频格式进行数据转换 
		// 进行8位数据的转换 
		if (this->m_fileWaveOut.m_wavFile.GetWaveFormat().wBitsPerSample == 8) 
		{ 
			// 计算原始数据长度 
			nRawCount = waveHdr.dwBufferLength; 
 
			pTemp = new double[nRawCount]; 
 
			CWaveConvertor::ConvertToDoubleMono( 
				(byte*) waveHdr.lpData, waveHdr.dwBufferLength, pTemp); 
		} 
		// 进行16位数据转换 
		else 
		{ 
			// 计算原始数据长度 
			nRawCount = waveHdr.dwBufferLength / 2; 
			pTemp = new double[nRawCount]; 
 
			CWaveConvertor::ConvertToDoubleMono( 
				(int*) waveHdr.lpData, waveHdr.dwBufferLength, pTemp); 
		} 
 
		// 按选定的显示方式进行数据转换 
		switch (this->m_displayType) 
		{ 
			// 显示时域波形 
		case DisplayWave: 
			// 显示加窗前时域波形 
		case DisplayBeforeWindow: 
			{ 
				pData = pTemp; 
				nCount = nRawCount; 
 
				// 上下帧可用 
				this->EnableFrameControl(); 
 
				break; 
			} 
			// 显示加窗后时域波形 
		case DisplayAfterWindow: 
			{ 
				pData = pTemp; 
				nCount = nRawCount; 
 
				// 对输入数据进行加窗处理 
				CSpeech::AddWindow(this->m_nFrameSize, pData, nCount); 
 
				// 上下帧可用 
				this->EnableFrameControl(); 
 
				break; 
			} 
			// 显示平均过零率 
		case DisplayZero:	 
			{ 
				nCount = nRawCount / this->m_nFrameSize; 
				pData = new double[nCount]; 
 
				// 对输入数据进行加窗处理 
				CSpeech::AddWindow(this->m_nFrameSize, pData, nCount); 
				// 获取平均过零率 
				CSpeech::GetZero( 
					this->m_nFrameSize, pTemp, nRawCount, pData); 
 
				// 上下帧不可用 
				this->EnableFrameControl(FALSE, FALSE); 
 
				break; 
			} 
			// 显示短时能量 
		case DisplayPower: 
			{ 
				nCount = nRawCount / this->m_nFrameSize; 
				pData = new double[nCount]; 
 
				// 对输入数据进行加窗处理 
				CSpeech::AddWindow(this->m_nFrameSize, pData, nCount); 
				// 获取短时能量 
				CSpeech::GetEnergy( 
					this->m_nFrameSize, pTemp, nRawCount, pData); 
 
				// 上下帧不可用 
				this->EnableFrameControl(FALSE, FALSE); 
 
				break; 
			} 
			// 显示平均振幅 
		case DisplayVibration: 
			{ 
				nCount = nRawCount / this->m_nFrameSize; 
				pData = new double[nCount]; 
 
				// 对输入数据进行加窗处理 
				CSpeech::AddWindow(this->m_nFrameSize, pData, nCount); 
				// 获取平均振幅 
				CSpeech::GetAvgVibration( 
					this->m_nFrameSize, pTemp, nRawCount, pData); 
 
				// 上下帧不可用 
				this->EnableFrameControl(FALSE, FALSE); 
 
				break; 
			} 
			// 显示功率谱 
		case DisplaySpectrum: 
			{ 
				nCount = nRawCount; 
				pData = new double[nCount]; 
 
				// 对输入数据进行加窗处理 
				CSpeech::AddWindow(this->m_nFrameSize, pData, nCount); 
				// 获取功率谱 
				CWaveConvertor::ConvertToPowerSpectral( 
					nRawCount, this->m_nFrameSize, pTemp, pData); 
 
				// 上下帧可用 
				this->EnableFrameControl(); 
 
				break; 
			} 
			// 显示对数功率谱 
		case DisplayLogSpectrum: 
			{ 
				nCount = nRawCount; 
				pData = new double[nCount]; 
 
				// 对输入数据进行加窗处理 
				CSpeech::AddWindow(this->m_nFrameSize, pData, nCount); 
				// 获取对数功率谱 
				CWaveConvertor::ConvertToLogPowerSpectral( 
					nRawCount, this->m_nFrameSize, pTemp, pData); 
 
				// 上下帧可用 
				this->EnableFrameControl(); 
 
				break; 
			} 
			// 显示倒谱 
		case DisplayCepstrum: 
			{ 
				nCount = nRawCount; 
				pData = new double[nCount]; 
 
				// 对输入数据进行加窗处理 
				CSpeech::AddWindow(this->m_nFrameSize, pData, nCount); 
				// 获取倒谱 
				CWaveConvertor::ConvertToCepStrum( 
					nRawCount, this->m_nFrameSize, pTemp, pData); 
 
				// 上下帧可用 
				this->EnableFrameControl(); 
 
				break; 
			} 
		} 
	} 
 
	// 显示相关信息 
	this->UpdateResult(pData, nCount, this->m_displayType); 
	// 显示数据 
	this->m_ctlDisplay.LoadData(pData, nCount); 
 
	if (pTemp != NULL) 
	{ 
		delete[] pTemp; 
 
		if (pData != pTemp && pData != NULL) 
		{ 
			delete[] pData; 
		} 
	} 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 更新帧数信息 
void CPlatformView::UpdateFrameControl( BOOL bReset /* = FALSE   */) 
{ 
	CString strInfo; 
 
	// 是否重新计算帧数 
	if (bReset) 
	{ 
		// 获取文件格式信息			 
		WAVEFORMATEX fmt = this->m_fileWaveOut.m_wavFile.GetWaveFormat(); 
		// 计算总样本数 
		this->m_nTotalFrames =  
			ceil((double) this->m_fileWaveOut.m_wavFile.GetSampleFramesCount() / this->m_nFrameSize); 
		this->m_nCurrentFrame = 0; 
 
		// 显示第一帧信息 
		if (this->m_nTotalFrames > 0) 
		{ 
			this->OnBnClickedControlNext(); 
		} 
	} 
 
	// 显示帧数信息 
	strInfo.Format("每帧包含样本数: %d\t可播放帧数: %d\t当前播放帧: %d", 
		this->m_nFrameSize, 
		this->m_nTotalFrames,  
		this->m_nCurrentFrame); 
 
	CWnd::SetDlgItemText(IDC_VOICE_INFO, strInfo); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 按帧查看是否可用 
void CPlatformView::EnableFrameControl( BOOL bPre /* = TRUE */,  BOOL bNext /* = TRUE   */) 
{ 
	CWnd* pWnd = NULL; 
 
	// 设定上一帧按钮是否可用 
	pWnd = CWnd::GetDlgItem(IDC_CONTROL_PREVIOUS); 
	pWnd->EnableWindow(bPre); 
 
	// 设定下一帧按钮是否可用 
	pWnd = CWnd::GetDlgItem(IDC_CONTROL_NEXT); 
	pWnd->EnableWindow(bNext); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// Y放大倍数 *10 
void CPlatformView::OnDisplayZoomin() 
{ 
	// TODO: 在此添加命令处理程序代码 
	// 设定Y放大系数 
	this->m_dlgSetting.m_fYMetrics *= 10; 
	this->m_ctlDisplay.SetYMetrics(this->m_dlgSetting.m_fYMetrics); 
 
	// 刷新波形显示 
	this->m_ctlDisplay.Invalidate(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// Y放大倍数 /10 
void CPlatformView::OnDisplayZoomout() 
{ 
	// TODO: 在此添加命令处理程序代码 
	// 设定Y放大系数 
	this->m_dlgSetting.m_fYMetrics /= 10; 
	this->m_ctlDisplay.SetYMetrics(this->m_dlgSetting.m_fYMetrics); 
 
	// 刷新波形显示 
	this->m_ctlDisplay.Invalidate(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示类型为功率谱 
void CPlatformView::OnDisplaySpectrum() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplaySpectrum; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(TRUE,  
		this->m_nCurrentFrame - 1, this->m_nCurrentFrame); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 选择显示类型为功率谱 
void CPlatformView::OnUpdateDisplaySpectrum(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplaySpectrum); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示类型为对数功率谱 
void CPlatformView::OnDisplayLogspectrum() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplayLogSpectrum; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(TRUE,  
		this->m_nCurrentFrame - 1, this->m_nCurrentFrame); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 选择显示类型为对数功率谱 
void CPlatformView::OnUpdateDisplayLogspectrum(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplayLogSpectrum); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示类型为倒谱 
void CPlatformView::OnDisplayCepstrum() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplayCepstrum; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(TRUE,  
		this->m_nCurrentFrame - 1, this->m_nCurrentFrame); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 选择显示类型为倒谱 
void CPlatformView::OnUpdateDisplayCepstrum(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplayCepstrum); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 进行显示微调 
BOOL CPlatformView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{ 
	// TODO: 在此添加消息处理程序代码和/或调用默认值 
	return this->m_ctlDisplay.OnMouseWheel(nFlags, zDelta, pt); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示全部时域波形 
void CPlatformView::OnBnClickedControlDisplaywaveAll() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	this->m_displayType = DisplayWave; 
 
	this->UpdateDisplay(); 
} 
 
// 显示波形的相应信息 
void CPlatformView::UpdateResult( 
								 double* pData,			// 显示数据 
								 unsigned int nCount,	// 显示数据数量 
								 DisplayType disType	// 显示类型 
								 ) 
{ 
	// 格式化输出 
	CString strFormat; 
 
	// 清空原来的显示 
	this->m_strResult = ""; 
	CWnd::UpdateData(FALSE); 
 
	// 循环变量, ugly vc 
	unsigned int i = 0; 
 
	if (pData != NULL) 
	{ 
		// 根据显示类型设置相应的信息 
		switch (disType) 
		{ 
			// 显示时域波形 
		case DisplayWave: 
			{ 
				 
				break; 
			} 
			// 显示平均过零率 
		case DisplayZero:	 
			{ 
				// 显示每帧的过零率信息 
				for (i = 0; i < nCount; i ++) 
				{ 
					strFormat.Format("第%d帧的平均过零率: %f\r\n", i, pData[i]); 
 
					this->m_strResult += strFormat; 
				} 
 
				break; 
			} 
			// 显示短时能量 
		case DisplayPower: 
			{ 
				// 显示每帧的短时能量信息 
				for (i = 0; i < nCount; i ++) 
				{ 
					strFormat.Format("第%d帧的短时能量: %f\r\n", i, pData[i]); 
 
					this->m_strResult += strFormat; 
				} 
 
				break; 
			} 
			// 显示平均振幅 
		case DisplayVibration: 
			{ 
				// 显示每帧的平均振幅信息 
				for (i = 0; i < nCount; i ++) 
				{ 
					strFormat.Format("第%d帧的平均振幅: %f\r\n", i, pData[i]); 
 
					this->m_strResult += strFormat; 
				} 
 
				break; 
			} 
			// 显示功率谱 
		case DisplaySpectrum: 
			{ 
 
				break; 
			} 
			// 显示对数功率谱 
		case DisplayLogSpectrum: 
			{ 
				 
				break; 
			} 
			// 显示倒谱 
		case DisplayCepstrum: 
			{ 
				 
				break; 
			} 
		} 
 
		// 显示相关信息 
		CWnd::UpdateData(FALSE); 
	} 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示端点检测图形 
void CPlatformView::OnSectionEnd() 
{ 
	// TODO: 在此添加命令处理程序代码 
	WAVEHDR waveHdr; 
	waveHdr.lpData = NULL; 
	double* pRawData = NULL; 
	unsigned int nDataLen = 0; 
 
	// 原始数据是否已经设定 
	this->m_fileWaveOut.GetSamples(&waveHdr, 0); 
 
	if (waveHdr.lpData != NULL) 
	{ 
		// 获取原始数据 
		// 进行8位数据的转换 
		if (this->m_fileWaveOut.m_wavFile.GetWaveFormat().wBitsPerSample == 8) 
		{ 
			// 计算数据长度 
			nDataLen = waveHdr.dwBufferLength; 
			pRawData = new double[nDataLen]; 
 
			CWaveConvertor::ConvertToDoubleMono( 
				(byte*) waveHdr.lpData, waveHdr.dwBufferLength, pRawData); 
		} 
		// 进行16位数据转换 
		else 
		{ 
			// 计算数据长度 
			nDataLen = waveHdr.dwBufferLength / 2; 
			pRawData = new double[nDataLen]; 
 
			CWaveConvertor::ConvertToDoubleMono( 
				(int*) waveHdr.lpData, waveHdr.dwBufferLength, pRawData); 
		} 
 
		// 对输入数据进行加窗处理 
		// CSpeech::AddWindow(this->m_nFrameSize, pRawData, nDataLen); 
 
		// 设定显示数据 
		this->m_dlgSection.SetDisplayData( 
			pRawData, nDataLen, this->m_nFrameSize, SectionEnd); 
	} 
 
	this->m_dlgSection.DoModal(); 
	this->m_dlgSection.ReleaseData(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示声韵切割图形 
void CPlatformView::OnSectionSy() 
{ 
	// TODO: 在此添加命令处理程序代码 
	//WAVEHDR waveHdr; 
	//waveHdr.lpData = NULL; 
	//double* pRowData = NULL; 
	//double* pSectionData = NULL; 
	//double* pTemp = NULL; 
	//unsigned int nDataLen = 0; 
 
	//// 原始数据是否已经设定 
	//this->m_fileWaveOut.GetSamples( 
	//	0, this->m_nTotalFrames * this->m_nFrameSize, &waveHdr); 
 
	//if (waveHdr.lpData != NULL) 
	//{ 
	//	// 获取原始数据 
	//	// 进行8位数据的转换 
	//	if (this->m_fileWaveOut.m_wavFile.GetWaveFormat().wBitsPerSample == 8) 
	//	{ 
	//		// 计算数据长度 
	//		nDataLen = waveHdr.dwBufferLength; 
	//		pRowData = new double[nDataLen]; 
 
	//		CWaveConvertor::ConvertToDoubleMono( 
	//			(byte*) waveHdr.lpData, waveHdr.dwBufferLength, pRowData); 
	//	} 
	//	// 进行16位数据转换 
	//	else 
	//	{ 
	//		// 计算数据长度 
	//		nDataLen = waveHdr.dwBufferLength / 2; 
	//		pRowData = new double[nDataLen]; 
 
	//		CWaveConvertor::ConvertToDoubleMono( 
	//			(int*) waveHdr.lpData, waveHdr.dwBufferLength, pRowData); 
	//	} 
 
	//	// 设定显示数据 
	//	this->m_dlgSection.SetDisplayData( 
	//		pTemp, nDataLen, this->m_nFrameSize, SectionSY); 
	//} 
 
	//this->m_dlgSection.DoModal(); 
	//this->m_dlgSection.ReleaseData(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示K-Means VQ结果 
void CPlatformView::OnVqKmeans() 
{ 
	// TODO: 在此添加命令处理程序代码 
	WAVEHDR waveHdr; 
	waveHdr.lpData = NULL; 
	double* pRawData = NULL; 
	double* pTemp = NULL; 
	unsigned int nDataLen = 0; 
 
	// 原始数据是否已经设定 
	this->m_fileWaveOut.GetSamples(&waveHdr, 0); 
 
	if (waveHdr.lpData != NULL) 
	{ 
		// 获取原始数据 
		// 进行8位数据的转换 
		if (this->m_fileWaveOut.m_wavFile.GetWaveFormat().wBitsPerSample == 8) 
		{ 
			// 计算数据长度 
			nDataLen = waveHdr.dwBufferLength; 
			pTemp = new double[nDataLen]; 
 
			CWaveConvertor::ConvertToDoubleMono( 
				(byte*) waveHdr.lpData, waveHdr.dwBufferLength, pTemp); 
		} 
		// 进行16位数据转换 
		else 
		{ 
			// 计算数据长度 
			nDataLen = waveHdr.dwBufferLength / 2; 
			pTemp = new double[nDataLen]; 
 
			CWaveConvertor::ConvertToDoubleMono( 
				(int*) waveHdr.lpData, waveHdr.dwBufferLength, pTemp); 
		} 
 
		// 对输入数据进行加窗处理 
		CSpeech::AddWindow(this->m_nFrameSize, pTemp, nDataLen); 
 
		// 计算LPC倒谱 
		pRawData = new double[nDataLen]; 
		CWaveConvertor::ConvertToCepStrum( 
			nDataLen, this->m_nFrameSize, pTemp, pRawData); 
 
		// 设定显示数据 
		this->m_dlgCluster.LoadRawData(pRawData, nDataLen); 
	} 
 
	this->m_dlgCluster.DoModal(); 
 
	if (pRawData != NULL) 
	{ 
		delete[] pRawData; 
	} 
 
	if (pTemp != NULL) 
	{ 
		delete[] pTemp; 
	} 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 添加HMM模型 
void CPlatformView::OnHmmAddmodel() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CAddModelDlg dlg; 
 
	dlg.DoModal(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 训练HMM模型 
void CPlatformView::OnHmmTrainmodel() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CTrainModelDlg dlg; 
 
	dlg.DoModal(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// HMM数字识别演示 
void CPlatformView::OnHmmDemo() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CDemoHMMDlg dlg; 
 
	dlg.DoModal(); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示加窗后时域波形 
void CPlatformView::OnDisplayAfterwindow() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplayAfterWindow; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(TRUE,  
		this->m_nCurrentFrame - 1, this->m_nCurrentFrame); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 设定显示未加窗前时域波形 
void CPlatformView::OnUpdateDisplayBeforewindow(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplayBeforeWindow); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 设定显示加窗后时域波形 
void CPlatformView::OnUpdateDisplayAfterwindow(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck(this->m_displayType == DisplayAfterWindow); 
} 
 
////////////////////////////////////////////////////////////////////////// 
// 显示加窗前时域波形 
void CPlatformView::OnDisplayBeforewindow() 
{ 
	// TODO: 在此添加命令处理程序代码 
	this->m_displayType = DisplayBeforeWindow; 
 
	// 显示当前播放帧的参数信息 
	this->UpdateDisplay(TRUE,  
		this->m_nCurrentFrame - 1, this->m_nCurrentFrame); 
}