如何判断PlaySound()是否已完成WAV文件播放?
实现WAV播放完成的回调通知
核心结论
PlaySound 没有内置的播放完成回调机制,想要可靠判断播放结束并触发后续逻辑(比如依次播放多个文件),必须改用Windows Waveform Audio API(也就是你贴出的waveOut系列函数),它原生支持播放完成的回调通知,比定时器估测、waveOutGetPosition轮询都更可靠高效。
具体实现思路
1. 选择回调模式
调用waveOutOpen时,通过最后一个参数指定回调类型:
CALLBACK_WINDOW:向指定窗口发送MM_WOM_DONE消息,适合带UI的程序CALLBACK_FUNCTION:直接调用你指定的回调函数,适合无UI或后台程序
你贴的代码里已经用了CALLBACK_WINDOW,对应的窗口句柄是hwndApp,当waveOutWrite提交的缓冲区播放完成时,系统会给这个窗口发送MM_WOM_DONE消息。
2. 处理播放完成事件
以窗口回调为例,在你的窗口过程函数里添加对MM_WOM_DONE消息的处理:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case MM_WOM_DONE: { // 解析参数:wParam是音频设备句柄,lParam是WAVEHDR指针 HWAVEOUT hWaveOut = (HWAVEOUT)wParam; LPWAVEHDR pWaveHdr = (LPWAVEHDR)lParam; // 1. 清理当前播放资源 waveOutUnprepareHeader(hWaveOut, pWaveHdr, sizeof(WAVEHDR)); GlobalUnlock(pWaveHdr->lpData); GlobalFree(pWaveHdr->lpData); GlobalUnlock(pWaveHdr); GlobalFree(pWaveHdr); waveOutClose(hWaveOut); // 2. 触发后续逻辑:比如播放下一个WAV文件 PlayNextWaveFile(); // 你自己实现的下一个文件播放函数 return 0; } // 其他窗口消息的处理逻辑... default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } }
3. 关于waveOutGetPosition
这个函数是用来获取当前播放的进度位置,适合做进度条显示这类需求,但如果只是判断播放完成,用回调更合适——不需要开线程轮询,系统会主动通知你播放结束,避免了轮询的资源消耗和精度问题。
替换PlaySound的流程
- 解析WAV文件的格式信息(
WAVEFORMAT)和音频数据 - 用
waveOutOpen打开音频设备并指定回调 - 准备WAV缓冲区(
waveOutPrepareHeader) - 提交播放(
waveOutWrite) - 在回调/消息里处理播放完成,然后重复上述流程播放下一个文件
内容的提问来源于stack exchange,提问作者OutOfTime
相关产品推荐
相关产品推荐

