我能找到的其他答案似乎都不适合我。我已经将sound.wav
的内容放入一个变量中,以便将声音数据嵌入到可执行文件中,而不处理资源文件:
sound.h
:
std::string sound = R"(RIFFÆø^ WAVEfmt ...)";
由于这个声音文件大约30秒长,它是一个非常大的变量,包含12,624行垃圾(这可能是问题的根源)。
我在main.cpp
中包含sound.h
,然后尝试使用windowsplaysoundapi
播放声音:
int main() {
std::cout << "Hello" << std::endl;
PlaySoundA(sound.c_str(), nullptr, SND_MEMORY | SND_SYNC);
return 0;
}
程序简单地编译,打印"hello",然后退出,代码为0,没有任何错误。在这一点上,我感觉我已经尝试了所有的东西,所以任何信息都有帮助。
您正在调用的std::string
构造函数从源序列一直构造到第一个NUL字符的std::string
对象。
WAVE文件使用资源交换文件格式。在RIFF
块标识符之后,有一个4字节的序列指定长度。对于小于~16.4MiB的文件,第四个字节为零,因此最终得到长度为7的std::string
。即使对于较大的文件,最终也会有值为0的字节,导致std::string
存储输入的截断版本。
您有许多选项来处理这个问题(从最不推荐到最推荐):
- 使用显式接受
count
参数的std::string
构造函数。这避免了通常会发生的输入截断。 - 使用数组,例如
unsigned char const sound[] = R"(RIFF ...)";
。由于c++没有提供描述二进制字面值的方法,因此建议用数值初始化每个元素,例如unsigned char const sound[] = { 0x52, 0x49, 0x46, 0x46, ... };
。 - 链接音频文件到可执行映像的资源。这是将二进制资产放入可执行映像的推荐方法。播放WAVE资源有样本代码检索数据。
注意,PlaySound
有一个返回值,您的代码会忽略它。调用完全有可能以调用它的方式返回FALSE
。在诊断问题时,观察错误应该是您的第一要务。