如何将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
相关产品推荐
相关产品推荐

