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

如何将Wav文件加载到内存以使用PlaySound播放?

解决PlaySound播放WAV时图形冻结的问题

你的问题核心有两点:一是磁盘IO阻塞主线程,二是默认同步播放会卡住UI。下面提供两种可行方案,同时解决这两个问题:

方案一:加载WAV到内存缓冲区播放

直接把WAV文件完整读入内存,播放时从内存读取,同时开启异步播放避免阻塞主线程。

实现代码

#include <windows.h>
#include <stdio.h>

BOOL LoadWavToMemory(LPCWSTR filePath, BYTE** outBuffer, DWORD* outSize) {
    // 打开文件
    HANDLE hFile = CreateFileW(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) return FALSE;

    // 获取文件大小
    *outSize = GetFileSize(hFile, NULL);
    if (*outSize == INVALID_FILE_SIZE) {
        CloseHandle(hFile);
        return FALSE;
    }

    // 分配内存
    *outBuffer = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *outSize);
    if (*outBuffer == NULL) {
        CloseHandle(hFile);
        return FALSE;
    }

    // 读取文件到内存
    DWORD bytesRead;
    BOOL success = ReadFile(hFile, *outBuffer, *outSize, &bytesRead, NULL);
    CloseHandle(hFile);

    return success && (bytesRead == *outSize);
}

// 使用示例
int main() {
    BYTE* wavBuffer = NULL;
    DWORD wavSize = 0;

    if (LoadWavToMemory(TEXT("C:\\DEV\\beep-07a.wav"), &wavBuffer, &wavSize)) {
        // 异步播放内存中的WAV,SND_MEMORY表示从内存读取,SND_ASYNC表示非阻塞
        PlaySound((LPCSTR)wavBuffer, NULL, SND_MEMORY | SND_ASYNC);
        
        // 这里可以正常执行图形绘制逻辑,不会被阻塞
        // ...你的图形代码...

        // 不再使用时释放内存
        HeapFree(GetProcessHeap(), 0, wavBuffer);
    }

    return 0;
}

方案二:将WAV作为资源嵌入程序

把WAV文件编译进程序资源,播放时直接从资源读取,无需磁盘IO,同样配合异步播放。

步骤1:添加资源脚本

创建一个.rc文件(比如Resource.rc),添加以下内容:

MY_BEEP_WAV WAVE "C:\\DEV\\beep-07a.wav"

将这个资源脚本和你的代码一起编译链接。

步骤2:播放资源中的WAV

#include <windows.h>

// 使用示例
int main() {
    // 从资源异步播放WAV,SND_RESOURCE表示读取资源,第二个参数是模块句柄
    PlaySound(TEXT("MY_BEEP_WAV"), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC);

    // 图形绘制逻辑可以正常运行
    // ...你的图形代码...

    return 0;
}

关键注意点

  • 必须加上SND_ASYNC标志:默认PlaySound是同步播放,会阻塞主线程直到声音播放完毕,这是图形冻结的重要原因,哪怕从内存/资源读取也需要异步播放。
  • 内存缓冲区要包含完整的WAV文件数据(包括RIFF头),不能只读取音频采样部分。
  • 资源播放时,确保资源名称和.rc中定义的一致,模块句柄用GetModuleHandle(NULL)即可获取当前程序的模块句柄。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:45:32