sndPlaySound 雖簡單(單行代碼即可異步播放),但要求整個 WAV 檔案完整載入實體記憶體,限制約 100KB。多媒體應用常需播放數 MB 甚至更大的音訊,必須改用媒體控制介面 (MCI),以串流方式分段讀取,突破記憶體限制。
封裝 MCI 指令與資料結構,對外僅暴露四個核心方法:
OpenDevice():開啟波形音訊裝置,取得裝置 ID。Play(CWnd* pParentWnd, LPCSTR pFileName):開啟指定 WAV 檔並異步播放,播放完成透過 MM_MCINOTIFY 通知指定視窗。Stop():關閉檔案元素。CloseDevice():關閉波形裝置(解構函式自動呼叫)。DWORD CWave::OpenDevice() {
MCI_OPEN_PARMS mciOpenParms;
mciOpenParms.lpstrDeviceType = (LPSTR)MCI_DEVTYPE_WAVEFORM_AUDIO;
DWORD dwResult = mciSendCommand(NULL, MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_WAIT,
(DWORD)(LPVOID)&mciOpenParms);
if (!dwResult) m_nDeviceID = mciOpenParms.wDeviceID;
return dwResult;
}
DWORD CWave::Play(CWnd* pWnd, LPCSTR pFileName) {
MCI_OPEN_PARMS mciOpenParms; memset(&mciOpenParms, 0, sizeof(mciOpenParms));
mciOpenParms.lpstrElementName = pFileName;
DWORD dwResult = mciSendCommand(m_nDeviceID, MCI_OPEN,
MCI_OPEN_ELEMENT, (DWORD)(LPVOID)&mciOpenParms);
if (dwResult) return dwResult;
m_nElementID = mciOpenParms.wDeviceID;
MCI_PLAY_PARMS mciPlayParms;
mciPlayParms.dwCallback = (DWORD)pWnd->m_hWnd; // 接收完成通知
return mciSendCommand(m_nElementID, MCI_PLAY,
MCI_NOTIFY, (DWORD)(LPVOID)&mciPlayParms);
}
DWORD CWave::Stop() {
if (m_nElementID) {
DWORD dwResult = mciSendCommand(m_nElementID, MCI_CLOSE, NULL, NULL);
if (!dwResult) m_nElementID = 0;
return dwResult;
}
return 0;
}
CWave wave;
wave.OpenDevice();
wave.Play(this, "large_audio.wav");
// ... 播放完成後自動收到 MM_MCINOTIFY
wave.Stop();
wave.CloseDevice(); // 或由解構函式自動處理
將 CWave 類整合專案,即可輕鬆播放任意大小的 WAV 檔案,避免記憶體溢位,適合多媒體應用開發。