aiff/au 文件头需手动构造,标准库不提供封装:aiff 基于 iff,须严格写入 form/aiff/comm/ssnd 四 chunk(comm 在 ssnd 前),comm 不可遗漏;au 仅 24 字节固定头,含 magic、偏移、大小、encoding、采样率、声道数,整数字段须大端序;pcm 数据须字节序转换(如 __builtin_bswap16),且 ofstream 必须以 binary 模式打开以防换行符被篡改。

AIFF/AU 文件头结构必须手动构造,标准库不提供封装
AIFF 和 AU 都是纯二进制容器格式,没有现成的 C++ 标准库或 STL 类支持写入。你得自己按规范填充文件头字段——不是调用一个 write_aiff() 就完事。AIFF 基于 IFF(Interchange File Format),AU 则是 Sun/NeXT 的简单头+数据结构,两者都要求严格字节序(AIFF 大端,AU 默认大端但可标为小端)和对齐(如 AIFF 的 chunk size 必须为偶数)。漏填 COMM chunk 或错设 SSND 偏移,会导致 QuickTime 或 Audacity 无法识别。
- AIFF 必须写入
FORM、AIFF、COMM、SSND四个 chunk,且COMM必须在SSND之前 - AU 只需写 24 字节固定头:
.sndmagic + data offset + data size + encoding + sample rate + channel count,注意encoding值:1 表示 8-bit linear,2 是 16-bit linear,3 是 24-bit,10 是 32-bit float - 所有整数字段(如采样率、声道数、帧数)必须用大端序写入,C++ 中可用
htons()/htonl(),或手动位移((val >> 8) & 0xFF等)
写入 PCM 数据前必须处理字节序与样本对齐
AIFF 要求 PCM 数据为大端序,而 x86/ARM 主机默认小端。如果你的 int16_t* 缓冲区是本地内存布局(小端),直接 fwrite 会出错。AU 同理,除非你显式声明 encoding=3(24-bit)或 10(32-bit float),否则它也期望大端 PCM。别指望 std::ofstream 自动转换——它只管写字节流。
- 16-bit PCM:对每个
int16_t执行__builtin_bswap16()(GCC/Clang)或_byteswap_ushort()(MSVC) - 32-bit float:IEEE 754 格式本身与字节序无关,但 AU 规范仍要求大端存储 float 字节,所以仍需
__builtin_bswap32()处理其整数表示 - AIFF 的
SSNDchunk 头部还有 8 字节额外字段(offset=0, blocksize=0),不能跳过,否则播放器读取数据位置偏移错误
用 std::ofstream 写二进制文件时必须禁用文本模式换行转换
Windows 下默认 std::ofstream 是文本模式,遇到 0x0A 可能被悄悄转成 0x0D 0x0A,彻底破坏二进制结构。AIFF/AU 文件任意位置出现意外回车换行都会让解析失败,而且这种 bug 极难排查——文件看起来“差不多”,但 hexdump 一对比就露馅。
- 打开文件必须加
std::ios::binary标志:std::ofstream f("out.aif", std::ios::binary) - 写 chunk size 等字段时,务必用
write(reinterpret_cast<const char>(&val), sizeof(val))</const>,不能用流插入操作符 - 写完所有头再写 PCM 数据;不要分多次 open/close,避免缓存或权限问题导致中间文件损坏
验证是否写对:用 hexdump + 预期字段交叉比对
写完文件别急着双击播放。先用命令行工具确认关键字段是否到位——这是最可靠、最快速的调试方式。比如 AIFF 的 FORM 开头 4 字节必须是 46 4F 52 4D('FORM' ASCII),紧接着是 4 字节总长度(大端),然后是 41 49 46 46('AIFF')。AU 文件前 4 字节必须是 2E 73 6E 64('.snd')。
- Linux/macOS:
xxd -g1 -l 64 out.aif查看前 64 字节 - Windows:
certutil -hashfile out.au SHA256不行,改用Format-Hex out.au -Count 64(PowerShell) - 重点核对:
COMMchunk 的采样率字段(AIFF 中为 10 字节 chunk,第 8–11 字节是 uint32_t 采样率,大端)、AU 头中第 20–23 字节是否为预期采样率(大端)
COMM chunk 中「采样帧数」字段是 int32_t,但它表示的是 *总帧数*(不是样本数),即 sample_count / channel_count;填错这个值,Audacity 会显示错误时长,但不一定报错。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











