You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断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的流程

  1. 解析WAV文件的格式信息(WAVEFORMAT)和音频数据
  2. 用waveOutOpen打开音频设备并指定回调
  3. 准备WAV缓冲区(waveOutPrepareHeader)
  4. 提交播放(waveOutWrite)
  5. 在回调/消息里处理播放完成,然后重复上述流程播放下一个文件

内容的提问来源于stack exchange,提问作者OutOfTime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:44:59