WAV文件本质是PCM数据加RIFF头关键字段为Subchunk2SizePCM总字节数、ChunkSize36Subchunk2Size、Subchunk1Size固定16及小端序的采样率/位深/声道数。直接说结论WAV 文件本质就是 PCM 数据加一个固定结构的 RIFF 头手写头不难但字节序、对齐、块大小算错一个就播不出。WAV 文件头必须填对的 4 个关键字段WAV 是 RIFF 容器格式头里最易出错的是 Subchunk2Size、ChunkSize、Subchunk1Size 和采样率/位深/声道数的组合。它们不是独立填写的而是强约束关系Subchunk2Size 必须等于 PCM 数据总字节数sample_count * channels * bits_per_sample / 8ChunkSize 36 Subchunk2Size因为 RIFF 头固定 8 字节 fmt 子块 24 字节 data 子块头 8 字节Subchunk1Size 固定为 16PCM 格式填 18 或 0 就被多数播放器拒识所有多字节整数如 SampleRate必须用小端序little-endianC 写文件时别用 std::cout 直接输出整数用 fwrite 写 WAV 头的典型错误常见现象是文件能生成、大小看起来合理但 VLC 播放报“无法识别格式”或 Windows 媒体播放器静音——大概率是头里某字段没按小端写或 ChunkSize 算少了 4。别用 int 直接 fwrite(x, sizeof(int), 1, fp)int 在不同平台可能是 4 或 8 字节且不保证小端改用 uint32_t 手动拆字节或 htole32()Linux/macOS或自写转换fmt 子块中 AudioFormat 字段必须是 1PCM填 0 或 65535 会被当其他编码忽略写完头后必须用 fseek(fp, 4, SEEK_SET) 回填 ChunkSize再 fseek(fp, 40, SEEK_SET) 回填 Subchunk2Size顺序错了会把数据覆盖成垃圾16-bit PCM 单声道 vs 双声道的字节对齐陷阱双声道数据不是“左右交替写”就完事——每个样本必须严格按通道数对齐否则播放器解包错位声音发啸或变调。 VWO 一个A/B测试工具