扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:王结太 来源:CSDN 2007年10月19日
关键字:
void CPlayWaveDlg::OnPlay() { LPSTR szFileName;//声音文件名 LPSTR szPathName; MMCKINFO mmckinfoParent; MMCKINFO mmckinfoSubChunk; DWORD dwFmtSize; DWORD m_WaveLong; WAVEFORMATEX* lpFormat; DWORD m_dwDataOffset; DWORD m_dwDataSize; WAVEOUTCAPS pwoc; LONG lSoundOffset; LONG lSoundLong; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_FILE); pEdit->GetWindowText(m_strFileName); if (m_strFileName == "") { ShowMsg("Please select a wave file to play!"); return; } szPathName = m_strPathName.GetBuffer(0); szFileName = m_strFileName.GetBuffer(0); //打开波形文件 if (!(m_hmmio = mmioOpen(szPathName, NULL, MMIO_READ | MMIO_ALLOCBUF))) { /*------------------------------------------------------------------------------- 信息显示函数ShowMsg(): void CPlayWaveDlg::ShowMsg(char* szMsg, ...) { va_list vl; char szBuf[256]; va_start(vl, szMsg); vsprintf(szBuf, szMsg, vl); va_end(vl); ::MessageBox(NULL, szBuf, "WavePlayer", MB_OK | MB_ICONEXCLAMATION); } ---------------------------------------------------------------------------------*/ ShowMsg("Failed to open file: %s", szFileName); return; } //进入块,检查打开文件是否是wave文件 mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(m_hmmio, (LPMMCKINFO) & mmckinfoParent, NULL, MMIO_FINDRIFF)) { ShowMsg("%s is an invalid wave file!", szFileName); mmioClose(m_hmmio, NULL); return; } //寻找 'fmt' 块 mmckinfoSubChunk.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(m_hmmio, &mmckinfoSubChunk, &mmckinfoParent, MMIO_FINDCHUNK)) { ShowMsg("Cannot find fmt chunk in %s!", szFileName); mmioClose(m_hmmio, NULL); return; } //获得 'fmt '块的大小,申请内存 dwFmtSize = mmckinfoSubChunk.cksize ; m_hFormat = LocalAlloc(LMEM_MOVEABLE, LOWORD(dwFmtSize)); if (!m_hFormat) { ShowMsg("Alloc memory failed!"); return; } lpFormat = (WAVEFORMATEX *) LocalLock(m_hFormat); if (!lpFormat) { ShowMsg("Lock memory failed!"); OnStop(); return; } if ((unsigned long) mmioRead(m_hmmio, (HPSTR) lpFormat, dwFmtSize) != dwFmtSize) { ShowMsg("Read format chunk of %s failed!", szFileName); OnStop(); return; } //离开 fmt 块 mmioAscend(m_hmmio, &mmckinfoSubChunk, 0); //寻找 'data' 块 mmckinfoSubChunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(m_hmmio, &mmckinfoSubChunk, &mmckinfoParent, MMIO_FINDCHUNK)) { ShowMsg("Cannot find data chunk in: %s", szFileName); OnStop(); return; } //获得 'data'块的大小 m_dwDataSize = mmckinfoSubChunk.cksize ; m_dwDataOffset = mmckinfoSubChunk.dwDataOffset ; if (m_dwDataSize == 0L) { ShowMsg("%s has no data!", szFileName); OnStop(); return; } //为音频数据分配内存 lpData = new char[m_dwDataSize]; if (!lpData) { ShowMsg("Alloc memory for wave data failed!"); OnStop(); return; } lSoundOffset = m_dwDataOffset; LONG lSize = mmioSeek(m_hmmio, lSoundOffset, SEEK_SET); if (lSize < 0) { ShowMsg("Seek data chunk of %s failed!", szFileName); OnStop(); return; } lSoundLong = m_dwDataSize; m_WaveLong = mmioRead(m_hmmio, lpData, lSoundLong); if (m_WaveLong < 0) { ShowMsg("Read data chunk of %s failed!", szFileName); OnStop(); return; } //检查音频设备,返回音频输出设备的性能 if (waveOutGetDevCaps(WAVE_MAPPER, &pwoc, sizeof(WAVEOUTCAPS)) != 0) { ShowMsg("waveOutGetDevCaps() failed!"); OnStop(); return; } //检查音频输出设备是否能播放指定的音频文件 /*---------------------------------------------------------------------------------------------- waveOutOpen函数最后三个参数的设置对消息处理方式起决定性作用,需要特别注意,通常我们用下列处理方法: 1. 使用窗口作为消息的接收者,则第四个参数设置为该窗口的句柄,则和这次播放有关的消息都将进入该窗口的消息队列,这时 第五个参数为NULL,第六个参数为CALLBACK_WINDOW,表明由窗口的过程来处理消息。 2. 直接使用回调函数来处理消息,则第四个参数设置为该回调函数的指针,则和这次播放有关的消息都将由该函数处理,这时第 五个参数为传入该函数的参数,第六个参数为CALLBACK_FUNCTION,表明由指定函数来处理消息。 3. 使用新的线程来处理消息,则第四个参数设置为该线程函数的指针,和这次播放有关的消息都将由该线程处理,这时第五个参 数为传入该函数的参数,第六个参数为CALLBACK_THREAD,表明由线程来处理消息。 4. 如果你不需要处理消息,这后面三个参数分别为NULL,NULL,CALLBACK_NULL ----------------------------------------------------------------------------------------------*/ if (waveOutOpen(&hWaveOut, WAVE_MAPPER, lpFormat, (ULONG)m_hWnd, NULL, CALLBACK_WINDOW) != 0) { ShowMsg("Open the wave out devices failed!"); OnStop(); return; } //准备待播放的数据 pWaveOutHdr.lpData = (HPSTR) lpData; pWaveOutHdr.dwBufferLength = m_WaveLong; pWaveOutHdr.dwFlags = 0; pWaveOutHdr.dwLoops = 5; if (waveOutPrepareHeader(hWaveOut, &pWaveOutHdr, sizeof(WAVEHDR)) != 0) { ShowMsg("Failed to prepare the wave data buffer!"); OnStop(); } //将数据写入设备并开始播放 if (waveOutWrite(hWaveOut, &pWaveOutHdr, sizeof(WAVEHDR)) != 0) { ShowMsg("Failed to write the wave data buffer"); OnStop(); } } |
void CPlayWaveDlg::OnStop() { if (m_hmmio != NULL) { mmioClose(m_hmmio, NULL); } //停止播放并重置管理器 waveOutReset(hWaveOut); //关闭播放设备 waveOutClose(hWaveOut); //清理用WaveOutPrepareHeader准备的Wave。 waveOutUnprepareHeader(hWaveOut, &pWaveOutHdr, sizeof(WAVEHDR)); //释放内存 if (m_hFormat != NULL) { LocalUnlock(m_hFormat); m_hFormat = NULL; } if (m_hFormat != NULL) { LocalFree(m_hFormat); m_hFormat = NULL; } if (lpData != NULL) { delete[] lpData; lpData = NULL; } } |
void CPlayWaveDlg::OnMMWomDone(UINT wParam, LONG lParam) { // ShowMsg("Play finished!"); OnStop(); } |
/*------------------------------------------------------ 说明:本文介绍的操作函数的声明包含在mmsystem.h头文件中,因此在程序中必须用#include "mmsystem.h"语句加入头文件。同时在编译时要加入动态连接导入库winmm.lib,具体实现方法有两种: 1. 从Developer Studio的Project菜单中选择Settings,然后在Link选项卡上的Object/Library Modules控制中加入winmm.lib 2. 如下所示在代码中加入#pragma comment(lib, "winmm.lib") -------------------------------------------------------------------------------*/ #include "mmsystem.h" #pragma comment(lib, "winmm.lib") class CPlayWaveDlg : public CDialog { //省略与播放无关部分 //................ protected: HANDLE m_hData; HWAVEOUT hWaveOut; WAVEHDR pWaveOutHdr; HANDLE m_hFormat; HPSTR lpData;//音频数据 HMMIO m_hmmio;//音频文件句柄 CString m_strPathName; CString m_strFileName; void ShowMsg(char *szMsg, ...); afx_msg void OnPlay(); afx_msg void OnStop(); afx_msg void OnMMWomDone(UINT wParam, LONG lParam); DECLARE_MESSAGE_MAP() }; |
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者