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

Loading a .wav into memory then playing it in C++

None 我能找到的其他答案似乎对我有用。我已经将 sound.wav 的内容放入一个变量中,以便将声音数据嵌入到可执行文件中 而无需处理资源文件 :

sound.h:

std::string sound = R"(RIFFÆø^ WAVEfmt ...)";

由于这个声音文件大约有 30 秒长,它是一个非常大的变量,由 12,624 行 垃圾组成(这可能是问题的根源)。

我在 main.cpp 中包含 sound.h 然后尝试使用 windows playsoundapi:

播放声音
int main() {
    std::cout << "Hello" << std::endl;
    PlaySoundA(sound.c_str(), nullptr, SND_MEMORY | SND_SYNC);

    return 0;
}

程序简单地编译,打印“Hello”,并以代码 0 退出,没有任何错误。感觉我此时已经尝试了所有方法,所以任何信息都有帮助。

您正在调用的 std::string 构造函数构造一个 std::string 从源序列到第一个 NUL 字符的对象。

WAVE 文件使用 Resource Interchange File Format。在 RIFF 块标识符之后,有一个指定长度的 4 字节序列。对于小于 ~16.4MiB 的文件,第四个字节为零,因此您得到长度为 7 的 std::string。即使对于较大的文件,最终也会有值为 0 的字节,导致 std::string 来存储输入的截断版本。

您有多种选择来处理这个问题(从最不推荐到最推荐):

  • 使用带有显式 count 参数的 std::string constructor。这避免了通常会发生的输入截断。
  • 使用数组,例如unsigned char const sound[] = R"(RIFF ...)";。由于 C++ 不提供描述二进制文字的方法,因此建议使用数值初始化每个元素,例如unsigned char const sound[] = { 0x52, 0x49, 0x46, 0x46, ... };.
  • Link将音频文件放入可执行映像的资源中。这是将二进制资产放入可执行映像的推荐方法。 Playing WAVE Resources 有用于检索数据的示例代码。

请注意 PlaySound 有一个 return 值,您的代码将忽略该值。完全有可能以您调用它的方式调用 return FALSE 。在诊断问题时,观察错误应该是您的首要行动。