将.wav加载到内存中,然后在c++中播放



我能找到的其他答案似乎都不适合我。我已经将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。在诊断问题时,观察错误应该是您的第一要务。

相关内容

最新更新