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

📄 recorderdlg.cpp

📁 录音程序开发实例 EVC 4.0编译通过 ARMV4I 运行成功
💻 CPP
字号:
/****************************************Copyright (c)**************************************************
**						Guangzhou ZHIYUAN electronics Co.,LTD.
**                                     
**							http://www.embedtools.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name:				RecorderDlg.cpp
** Last modified Date: 		2007.12.20
** Last Version:			V1.0
** Description: 			录音示例程序对话框类
**                          	 
**------------------------------------------------------------------------------------------------------
** Created By: 				Fuqiang Song 宋福强
** Created date: 			2007.12.20
** Version: 				V1.0
** Descriptions:			The original version 初始版本
**
**
*********************************************************************************************************/
// RecorderDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Recorder.h"
#include "RecorderDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CRecorderDlg dialog

CRecorderDlg::CRecorderDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CRecorderDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CRecorderDlg)
	m_strRecLen = _T("");
	m_strSavePath = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CRecorderDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CRecorderDlg)
	DDX_Control(pDX, IDC_EDIT_POS, m_btnPos);
	DDX_Text(pDX, IDC_EDIT_LEN, m_strRecLen);
	DDV_MaxChars(pDX, m_strRecLen, 2);
	DDX_Text(pDX, IDC_EDIT_SAVEPATH, m_strSavePath);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CRecorderDlg, CDialog)
	//{{AFX_MSG_MAP(CRecorderDlg)
	ON_BN_CLICKED(IDC_BUTTON_RECORD, OnButtonRecord)
	ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnButtonBrowse)
	ON_BN_CLICKED(IDC_BUTTON_STOP, OnButtonStop)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRecorderDlg message handlers

/********************************************************************************************************
** Function name:           CRecorderDlg::OnInitDialog()
** Descriptions:            对话框初始化事件处理函数
** Input parameters:        无
** Output parameters:		无
** Returned value:			TRUE
*********************************************************************************************************/
BOOL CRecorderDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 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
	
	CenterWindow(GetDesktopWindow());	// center to the hpc screen

	// TODO: Add extra initialization here
	m_bRec = FALSE;
	m_pBuffer = NULL;
	m_RecFormat.wFormatTag = 1;											/*	PCM格式音频					*/
	m_RecFormat.nChannels = 1;											/*	声道数为1(单声道)			*/
	m_RecFormat.nSamplesPerSec = 11025;									/*	采样率						*/
	m_RecFormat.nAvgBytesPerSec = 22050;								/*	每秒字节数					*/
	m_RecFormat.nBlockAlign = 2;										/*	块字节长度					*/
	m_RecFormat.wBitsPerSample = 16;									/*	采样位数					*/
	m_RecFormat.cbSize = 0;												/*	附加数据长度				*/
	m_hRecStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);			/*	创建录音结束或停止通知事件	*/
	m_btnPos.SetWindowText(_T("0"));									/*	设置“录音进度”编辑框初值	*/
	m_strRecLen = _T("10");												/*	“录音长度”编辑框初始值	*/
	m_strSavePath = _T("\\RecordTest.wav");								/*	“保存路径”编辑框初始值	*/
	UpdateData(FALSE);

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

/********************************************************************************************************
** Function name:           CRecorderDlg::OnButtonRecord()
** Descriptions:            “开始”按钮单击事件处理函数
** Input parameters:        无
** Output parameters:		无
** Returned value:			无
*********************************************************************************************************/
void CRecorderDlg::OnButtonRecord() 
{
	// TODO: Add your control notification handler code here
	CButton		*pBtnRec	= (CButton *)GetDlgItem(IDC_BUTTON_RECORD);	/*	“开始”按钮指针			*/
	CButton		*pBtnStop	= (CButton *)GetDlgItem(IDC_BUTTON_STOP);	/*	“停止”按钮指针			*/
	DWORD		dwRecLen;
	MMRESULT	rst;
	WAVEHDR		Head;

	UpdateData(TRUE);
	_stscanf(m_strRecLen, _T("%d"), &dwRecLen);							/*	得到"录音长度"编辑框的值	*/
	if (!dwRecLen) {													/*	判断录音长度值是否为0		*/
		MessageBox(_T("录音长不能为0!"));
		return;
	}
	if (!m_File.Open(m_strSavePath, CFile::modeCreate | CFile::modeWrite)) {
																		/*	判断创建用于保存录音的文件	*/
																		/*	是否成功					*/
		MessageBox(_T("写入文件失败!"));
		return;
	}
	rst = waveInOpen(&m_hwi, WAVE_MAPPER, &m_RecFormat,					/*	打开波形音频输入设备		*/
					(DWORD)m_hRecStopEvent, 0, CALLBACK_EVENT);
	if (FAILED(rst)) {													/*	判断打开音频输入设备是否成	*/
																		/*	功							*/
		MessageBox(_T("打开录音设备失败!"));
		return;
	}
	m_dwBufferLen = m_RecFormat.nAvgBytesPerSec * dwRecLen;
	Head.dwBufferLength = m_dwBufferLen;
	m_pBuffer = new BYTE[m_dwBufferLen];
	Head.lpData = (char *)m_pBuffer;
	rst = waveInPrepareHeader(m_hwi, &Head, sizeof(WAVEHDR));			/*	准备录音缓冲区				*/
	if (FAILED(rst)) {
		MessageBox(_T("准备录音缓冲区失败!"));
		delete[] m_pBuffer;
		return;
	}
	rst = waveInAddBuffer(m_hwi, &Head, sizeof(WAVEHDR));				/*	添加录音缓冲添加录音缓冲	*/
	if (FAILED(rst)) {
		MessageBox(_T("添加录音缓冲区失败!"));
		delete[] m_pBuffer;
		return;
	}
	rst = waveInStart(m_hwi);											/*	开始录音					*/
	if (FAILED(rst)) {
		MessageBox(_T("启动录音失败!"));
		delete[] m_pBuffer;
		return;
	}
	ResetEvent(m_hRecStopEvent);
	DWORD dwId;
	HANDLE hThread = CreateThread(NULL, 0, RecordThread, this, 			/*	创建录音线程				*/
									0, &dwId);
	CloseHandle(hThread);
	pBtnRec->EnableWindow(FALSE);										/*	"开始"按钮变灰				*/
	pBtnStop->EnableWindow(TRUE);										/*	"开始"按钮变亮				*/
	m_bRec = TRUE;
}

/********************************************************************************************************
** Function name:           CRecorderDlg::RecordThread()
** Descriptions:            录音线程函数
** Input parameters:        pData:	线程传入参数
** Output parameters:		无
** Returned value:			0
*********************************************************************************************************/
DWORD CRecorderDlg::RecordThread(LPVOID pData)
{
	CRecorderDlg	*pDlg		= (CRecorderDlg *)pData;
	CButton			*pBtnRec	= (CButton *)pDlg->GetDlgItem(IDC_BUTTON_RECORD);
	CButton			*pBtnStop	= (CButton *)pDlg->GetDlgItem(IDC_BUTTON_STOP);
	DWORD			dwCurRecLen	= 0;
	CString			strInfo;											/*	用于打印已录音秒数的字符串类*/
	MMTIME			MmTime;												/*	多媒体数据时间信息结构体	*/
	WAVEFILEHEAD	FileHead;

	MmTime.wType = TIME_SAMPLES;										/*	设置要获取的时间类型为采样数*/
	while (TRUE) {
		DWORD dwObjectId = WaitForSingleObject(pDlg->m_hRecStopEvent, 100);
		if (waveInGetPosition(pDlg->m_hwi, &MmTime, sizeof(MMTIME)) == 0) {	
																		/*	取得当前录音位置,并判断是	*/
																		/*	否成功						*/
			dwCurRecLen = (DWORD)((double)MmTime.u.sample 
						  / pDlg->m_RecFormat.nSamplesPerSec 
						  * pDlg->m_RecFormat.nAvgBytesPerSec);
			strInfo.Format(_T("%.1f"), (float)dwCurRecLen				/*	将录音秒数打印到strInfo字符	*/
				           / pDlg->m_RecFormat.nAvgBytesPerSec);		/*	串							*/
			pDlg->m_btnPos.SetWindowText(strInfo);						/*	在编辑框中显示已录音秒数	*/
		}
		if (dwObjectId == WAIT_OBJECT_0) {								/*	判断是否等到录音停止通知事	*/
																		/*	件被标记					*/
			break;														/*	跳出循环					*/
		}
	}
	pDlg->m_btnPos.SetWindowText(_T("正在保存"));
	waveInStop(pDlg->m_hwi);											/*	停止录音					*/
	waveInClose(pDlg->m_hwi);											/*	关闭音频输入设备			*/
	pDlg->m_File.SeekToBegin();
	pDlg->BuildWaveFileHead(&FileHead, pDlg->m_RecFormat, dwCurRecLen);	/*	构建WAV文件头信息			*/
	pDlg->m_File.Write(&FileHead, sizeof(WAVEFILEHEAD));				/*	写入文件头信息				*/
	pDlg->m_File.Write(pDlg->m_pBuffer, dwCurRecLen);					/*	写入录音流数据				*/
	pDlg->m_File.Close();												/*	关闭文件					*/
	delete[] pDlg->m_pBuffer;
	pDlg->m_pBuffer = NULL;
	pDlg->m_bRec = FALSE;
	pBtnRec->EnableWindow(TRUE);
	pDlg->m_btnPos.SetWindowText(_T("0"));
	pBtnStop->EnableWindow(FALSE);

	return 0;
}

/********************************************************************************************************
** Function name:           CRecorderDlg::OnButtonBrowse()
** Descriptions:            “浏览”按钮单击事件处理函数
** Input parameters:        无
** Output parameters:		无
** Returned value:			无
*********************************************************************************************************/
void CRecorderDlg::OnButtonBrowse() 
{
	// TODO: Add your control notification handler code here
	CFileDialog dlg(FALSE, _T("*.wav"), _T("RecordTest"), 				/*	定义文件对话框类变量,默认	*/ 
					OFN_HIDEREADONLY, 									/*	扩展名为“.wav”,默认文件	*/
					_T("波形音频文件 (*.WAV)|*.wav||"), NULL);			/*	名为"RecordTest",隐藏只读	*/
																		/*	复选框,过滤掉"*.wav"以外	*/
																		/*	类型文件					*/
	if (dlg.DoModal() == IDOK) {										/*	判断是否单击了OK按钮		*/
		m_strSavePath = dlg.GetPathName();								/*	取得文件路径				*/
		UpdateData(FALSE);
	}
}

/********************************************************************************************************
** Function name:           CRecorderDlg::BuildWaveFileHead()
** Descriptions:            构建WAV文件头
** Input parameters:        format:		波形音频扩展格式
							dwDataLen:	流数据长度
** Output parameters:		无
** Returned value:			无
*********************************************************************************************************/
void CRecorderDlg::BuildWaveFileHead(WAVEFILEHEAD *filehead, 
									 WAVEFORMATEX format, 
									 DWORD dwDataLen)
{
	if (!filehead) return;
	memcpy(filehead->szRIFF, "RIFF", 4);
	filehead->dwTotalSize = dwDataLen + sizeof(WAVEFILEHEAD) - 8;
	memcpy(filehead->szWAVE, "WAVE", 4);
	memcpy(filehead->szFMT, "fmt ", 4);
	filehead->dwChunk0Size = 16;
	memcpy(filehead->Format, &format, 16);
	memcpy(filehead->szDATA, "data", 4);
	filehead->dwChunk1Size = dwDataLen;
}

/********************************************************************************************************
** Function name:           CRecorderDlg::OnButtonStop()
** Descriptions:            "停止"按钮单击事件处理函数
** Input parameters:        无
** Output parameters:		无
** Returned value:			无
*********************************************************************************************************/
void CRecorderDlg::OnButtonStop() 
{
	// TODO: Add your control notification handler code here
	SetEvent(m_hRecStopEvent);
}

/********************************************************************************************************
** Function name:           CRecorderDlg::OnDestroy()
** Descriptions:            窗口销毁事件处理函数
** Input parameters:        无
** Output parameters:		无
** Returned value:			无
*********************************************************************************************************/
void CRecorderDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
	if (m_bRec) {
		waveInReset(m_hwi);												/*	先复位录音位置才能停止录音	*/
		waveInStop(m_hwi);												/*	停止录音					*/
		waveInClose(m_hwi);												/*	关闭录音					*/
	}
	if (m_pBuffer) {
		delete[] m_pBuffer;												/*	释放申请的内存				*/
	}
}

⌨️ 快捷键说明

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