纯AI机翻

# 免费无损音频编解码器 (FLAC)  
## 摘要  
本文档定义了免费无损音频编解码器（FLAC）格式及其可流式传输的子集。FLAC 旨在减少存储数字音频信号所需的计算机存储空间。它通过无损方式实现这一点，即不丢失任何信息。FLAC 的“免费”体现在其规范是开放的，且参考实现为开源代码。与其他无损音频编码格式相比，FLAC 是一种低复杂度格式，仅需少量计算资源即可完成编码和解码。FLAC 解码已在多种不同平台上独立实现，且其编码和解码过程均无需浮点运算支持。

## 本文档状态  
本文档属于互联网标准跟踪文件。  

本文档是互联网工程任务组（IETF）的成果。它代表了 IETF 社区的共识，已通过公开评审并获互联网工程指导组（IESG）批准发布。关于互联网标准的更多信息请参阅 [RFC 7841](https://www.rfc-editor.org/info/rfc7841) 第 2 节。  

有关本文档的当前状态、勘误及反馈方式的信息，请访问 **<https://www.rfc-editor.org/info/rfc9639>**。  

## 版权声明  
版权所有 (c) 2024 IETF 信托及被标识为文档作者的个人。保留所有权利。  

本文档受限于 BCP 78 及 IETF 信托与 IETF 文档相关的法律条款（<https://trustee.ietf.org/license-info>），该条款于本文档发布之日生效。请仔细阅读这些条款，因其规定了您对本文档的权利和限制。从本文档提取的代码组件必须包含信托法律条款第4.e节所述的修订版 BSD 许可文本，且不附带修订版 BSD 许可证中声明的任何担保。

## 1. 引言  
本文档定义了免费无损音频编解码器（FLAC）格式及其可流式传输的子集。FLAC 文件和流可对脉冲编码调制（PCM）音频进行编码，支持 1 至 8 个通道、1 至 1048575 赫兹的采样率，以及 4 至 32 位的比特深度。大多数 FLAC 格式的编码和解码工具已针对 CD 音频（即 2 通道、44.1 kHz 采样率、16 位比特深度的 PCM 音频）进行了优化。  

FLAC 能够实现无损压缩，因为音频信号中的采样点通常与其邻近采样点高度相关。与通用压缩工具（通常使用字典、游程编码或利用长期重复性）不同，FLAC 仅通过极短时域冗余消除实现压缩，最多回溯 32 个采样点。  

FLAC 格式提供的编码方法在以下场景中表现最佳：采样点采用有符号表示且以零为中心的 PCM 音频信号。对于采样点采用无符号表示的音频信号，必须按本文档所述转换为有符号表示，方可实现合理压缩率。FLAC 格式不适用于非 PCM 音频的压缩。

## 2. 符号与约定  
本文档中使用的关键词“必须（MUST）”“禁止（MUST NOT）”“必需（REQUIRED）”“应（SHALL）”“不应（SHALL NOT）”“应该（SHOULD）”“不应（SHOULD NOT）”“推荐（RECOMMENDED）”“不推荐（NOT RECOMMENDED）”“可以（MAY）”和“可选（OPTIONAL）”应按照 BCP 14 [RFC2119] [RFC8174] 的规范进行解释，且仅当这些词汇以全大写形式出现时（如本文所示）适用。  

以 $u(n)$ 表示的值为无符号大端序整数，使用 $n$ 位表示。以 $s(n)$ 表示的值为有符号大端序整数，使用 $n$ 位表示，采用二进制补码形式。必要时，$n$ 可通过包含 *（乘法）、/（除法）、+（加法）或 -（减法）的算式表示。比特数的包含范围用省略号表示，例如 $u(m...n)$。  

本文档中提及的所有移位操作均为算术移位。  

尽管 FLAC 格式可存储数字音频及其他数字信号，但本文档使用特定于数字音频的术语。采用更通用的术语被认为会降低清晰度，因此对于希望在非音频场景使用 FLAC 格式的读者，需自行将音频专用术语转换为通用术语。  

## 3. 定义  
**无损压缩** ：  
在不删除或不可逆修改数据的前提下，减少存储数据所需的计算机存储空间。换言之，对无损压缩信息进行解压缩将完整还原原始数据。<br>  

**有损压缩** ：  
类似于无损压缩，但会通过删除、不可逆修改或近似处理信息的方式进一步减少所需存储空间。换言之，对有损压缩信息进行解压缩将返回原始数据的近似版本。<br>  

**块（Block）​** ：  
线性 PCM 音频中一个（较短的）片段，包含一个或多个通道。<br>  

**子块（Subblock）​** ：  
对应音频块中单个通道的所有采样点。一个或多个子块构成一个块，且同一块内的所有子块包含相同数量的采样点。<br>  

**帧（Frame）​** ：  
由帧头、一个或多个子帧及帧尾组成。它编码对应音频块的内容。<br>  

**子帧（Subframe）​** ：  
编码后的子块。同一帧内的所有子帧编码相同数量的采样点。当使用通道间去相关技术时，子帧可能对应两个子块的（逐采样点）平均值或差值，而非直接对应单个子块（参见第4.2节）。<br>  

**通道间样本数（Interchannel samples）​** ：  
适用于所有通道的采样点计数。例如，44.1 kHz 采样率的一秒音频包含 44100 个通道间样本数，即每个通道均有此数量的采样点。<br>  

**块大小（Block size）​** ：  
一个音频块包含或一帧编码的通道间样本数。<br>  

**比特深度/每样本比特数（Bit depth or bits per sample）​**：  
表示单个采样点所用的比特数。同一块内所有子块的比特深度必须相同，但同一帧内不同子帧的比特深度可能因通道间去相关而不同（详见第4.2节）。<br>  

**预测器（Predictor）​** ：  
基于历史采样点预测音频信号中后续采样点的模型。FLAC 使用此类预测器消除信号冗余以实现压缩。<br>  

**线性预测器（Linear predictor）​** ：  
采用线性预测的预测器（参见[线性预测]）。也称为线性预测编码（LPC）。线性预测器的每个预测值均为历史采样点的线性组合（因此得名）。线性预测器具有因果离散时间有限冲激响应（参见[有限冲激响应滤波器]）。<br>  

**固定预测器（Fixed predictor）​** ：  
模型参数在所有 FLAC 文件中保持一致的线性预测器，因此无需存储这些参数。<br>  

**预测器阶数（Predictor order）​** ：  
预测器使用的历史采样点数量。例如，4阶预测器使用某采样点前4个连续采样点进行预测。FLAC 中，预测器使用的采样点始终连续且位于被预测采样点之前。<br>  

**残差（Residual）​** ：  
从子块中减去预测器输出后剩余的音频信号。若预测器能有效消除信号冗余，剩余信号（残差样本）的数值平均将比原始信号更接近零。<br>  

**Rice码（Rice code）​** ：  
一种变长编码（参见[变长编码]）。它对接近零的样本使用短码，对远离零的样本使用渐长码。这利用了残差样本常接近零的特性。<br>  

**复用（Muxing）​**：  
“Multiplexing”的缩写。将多个流或文件合并为单一流或文件。在本文档中，复用特指按第10节所述将 FLAC 流嵌入容器中。  

## 4. 概念性概述  
与其他许多音频编码器类似，FLAC 文件的编码遵循以下步骤。解码 FLAC 文件时，这些步骤以相反顺序执行（即从下到上）：  

**分块处理（参见第4.1节）​** ：将输入音频分割为多个连续块。<br>  

**通道间去相关（参见第4.2节）​** ：对于立体声流，FLAC 格式允许将左右信号转换为中-侧（mid-side）信号、左-侧（left-side）信号或侧-右（side-right）信号以消除通道间冗余。每块独立选择是否应用此类变换。<br>  

**预测（参见第4.3节）​**：为消除信号冗余，每个子块或其变换结果均关联一个预测器。预测器通过数学描述预测当前采样点（基于前序采样点），并将预测误差传递至下一阶段。各子块的预测器相互独立。由于编解码器均已知预测方法，压缩流中仅需包含预测器参数。若某子块无法找到有效预测器，则直接存储原始信号并跳过后续阶段。<br>  

**残差编码（参见第4.4节）​** ：原始信号与预测信号的差值（即残差信号）通过无损编码处理。若预测器有效，残差信号的每样本比特需求将低于原始信号。FLAC 使用 Rice 编码（Golomb 编码子集）配合4位或5位参数对残差信号进行编码。<br>  

此外，FLAC 定义了元数据系统（参见第8节），允许在流起始位置嵌入任意流信息。  

### 4.1. 分块处理  
音频数据块大小直接影响压缩率。若块过小，大量帧将导致帧头占用过多字节；若块过大，信号特性变化可能使编码器无法找到有效预测器。为简化编解码器设计，FLAC 规定最小块大小为16样本（末块除外），最大块大小为65535样本。末块允许小于16样本以匹配音频长度（无需填充）。  

尽管 FLAC 文件中块大小可变化，但寻找最优分块方案通常困难。因此，FLAC 流需显式声明全局块大小恒定或可变。若块大小恒定，流中将存储块编号而非样本编号以轻微提升压缩率。  

### 4.2 声道间去相关<br>
许多音频文件中的声道存在相关性。FLAC格式可以通过对两个子块中所有样本的均值（中间声道）或差值（边声道）进行编码，而非直接将子块编码为子帧，从而利用立体声文件中的这种相关性。以下是可能的组合方式：

独立编码。所有声道独立编码。所有非立体声文件必须采用此方式编码。

**中间-边声道（Mid-side）** 左右子块被转换为中间和边声道子帧。计算中间子帧样本时，将对应的左右样本相加后右移1位；计算边子帧样本时，从对应的左样本中减去右样本。<br>
解码时，所有中间声道样本需左移1位。若边声道样本为奇数，则需在对应中间声道样本左移1位后加1。左声道的重构需要将中间和边子帧的对应样本相加后右移1位；右声道的重构需要从中间声道中减去边声道后右移1位。

**左-边声道（Left-side）** 对左子块进行编码，同时使用左右子块编码边子帧。边子帧的构建方式与中间-边声道相同。<br>
解码时，通过从左子帧样本中减去边子帧样本来恢复右子块。

**边-右声道（Side-right）** 使用左右子块编码边子帧，同时对右子块进行编码。边子帧的构建方式与中间-边声道相同。<br>
解码时，通过将边子帧样本与右子帧对应样本相加来恢复左子块。

边声道需要增加1位位深，因为减法运算可能产生两倍于当前位深最大值的样本。中间-边声道的中间声道无需额外位深，因为其已被右移1位。<br>
中间声道的右移操作不会导致有损压缩，因为中间子帧中的奇数样本必然对应边子帧中的奇数样本，这意味着被丢弃的最低有效位可以通过边子帧样本恢复。

### 4.3 预测
FLAC格式提供四种输入信号建模方法：

**原样（Verbatim）** 样本不经任何建模直接存储。此方法用于相关性较低的输入信号。由于原始信号实际未经过残差编码阶段（直接"原样"写入流），该方法与使用零阶固定预测器不同。

**恒定（Constant）** 仅存储单个样本值。此方法用于纯直流信号（"数字静音"），即全段保持恒定值的情况。

**固定预测器（Fixed predictor）** 使用五种固定（即预定义）预测器之一进行样本预测，预测误差由残差编码器处理。这些固定预测器特别适用于简单波形的预测。由于预测器固定，无需存储预测系数。<br>
从数学角度看，预测器通过前序样本进行信号外推。使用的前序样本数量等于预测器阶数。更多信息请参阅第9.2.5节。

**线性预测器（Linear predictor）** 使用历史样本和一组预测系数进行样本预测，预测误差由残差编码器处理。与固定预测器相比，通用线性预测器需要存储预测系数，因此会产生额外开销。<br>
当预测更复杂波形时，该预测方法最为适用，因为增加的系数开销会被更精确预测带来的残差编码空间节省所抵消。FLAC中的线性预测器除系数和阶数外，还有两个参数：系数存储位宽（系数精度）和预测右移量。<br>
预测值的计算方式为：将每个预测系数与对应历史样本相乘后求和，再通过指定右移量进行除法运算。更多信息请参阅第9.2.6节。

FLAC编码器可自由选择上述任意建模方法。但为确保无损编码，存在以下例外情况：

当待存储样本不全相同时（即信号非常量），不能使用恒定子帧；
当编码器无法找到符合第9.2.7节所述（所有残差样本均可用32位有符号整数表示）的固定或线性预测器时，需使用原样子帧。
关于固定和线性预测器的更多信息，请参阅[Lossless-Compression]和[Robinson-TR156]。

### 4.4 残差编码
若子帧使用预测器近似音频信号，需存储残差来将近似值"修正"为精确值。使用有效预测器时，残差样本的平均数值通常小于预测前样本的平均值。虽然多数残差值较小，但可能存在少量"异常值"远大于原始样本，有时甚至超出原始音频位深范围。

为高效编码这种以小数为主偶有大值的残差流，FLAC采用Rice编码（Golomb编码子集）。根据待编码数值的大小选择Rice参数。每个残差样本的数值通过除以2^Rice参数拆分为商和余数两部分：商以一元码存储，余数以二进制形式存储。<br>
当多数残差样本接近零且选用合适Rice参数时，这种变长编码形式相比未编码残差可节省空间。

由于Rice编码仅支持无符号数，有符号数需通过zigzag编码转换为折叠残差。完整说明请参阅第9.2.7节。

通常最优Rice参数在子帧内会变化。为此可将残差划分为多个分区，每个分区使用独立Rice参数。为控制开销和复杂度，子帧内分区数量限定为2的幂次。

FLAC格式采用两种Rice编码变体，其区别仅在于编码Rice参数所用的位数（4位或5位）。

## 5. 格式原则
FLAC格式不包含版本信息，但在多个位置设有保留空间。未来版本的格式规范可安全使用这些保留空间，而不会破坏旧版本流的结构。旧版解码器在遇到使用未知编码方法的数据时，可选择中止解码。<br>
除保留模式外，格式规范在特定位置还定义了禁止使用的模式，这些模式不得出现在任何比特流中。禁止模式如下表所示：
| 描述 | 参考章节 |
|---|---|
| 元数据块类型127 | 第8.1节 |
| 流信息元数据块中最小/最大块尺寸小于16 | 第8.2节 |
| 采样率位模式0b1111 | 第9.1.2节 |
| 非常规块尺寸65536 | 第9.1.6节 |
| 预测器系数精度位模式0b1111 | 第9.2.6节 |
| 预测器右移量为负值 | 第9.2.6节 |

FLAC比特流中所有数值均采用整数表示，不使用浮点数格式。除Vorbis注释中的字段长度采用小端序编码（参见第8.6节）外，其他所有数值均采用大端序编码。Vorbis注释的此例外设计是为了最大程度保持与Vorbis编解码器使用的Vorbis注释的兼容性（参见[Vorbis]）。<br>
所有数值均为无符号数，以下情况除外：线性预测器系数、线性预测右移量（参见第9.2.6节）以及直接表示样本的数值（这些数值为有符号数）。上述限制不适用于应用元数据块或Vorbis注释字段内容。

FLAC格式编码和解码的所有样本必须采用有符号表示法。

存在多种方法可将无符号样本表示法转换为有符号样本表示法，但FLAC格式的编码方法在处理数值围绕零对称（即无直流偏移）的样本时效果最佳。大多数无符号音频格式中，信号数值围绕所用无符号整数类型范围的中点对称。若需转换此类样本，可先将数值复制到具有足够范围的有符号整数类型中，再减去无符号整数类型范围的一半值，即可得到围绕零对称的信号。

FLAC比特流中的一元编码采用零比特后接终止符"1"的形式实现，例如数字5的一元编码为0b000001。这种编码方式可防止帧同步码出现在一元编码数值中。

当 FLAC 文件包含被禁止或无效的数据时，解码器的行为未作明确规定。解码器在遇到此类数据时可以选择停止解码。此类数据的示例包括以下内容：

- 解码后的一个或多个样本值超出该帧编码位深允许的范围。例如在位深为8位的帧中，任何不在[-128, 127]闭区间内的样本均为无效。
- 子帧使用的浪费位数（参见第9.2.2节）导致该子帧位深（子帧位深定义见第9.2.3节）等于零或为负数。
- 帧头循环冗余校验（CRC，参见第9.1.8节）或帧尾CRC校验失败。
- 使用了表1所述的禁止位模式。

## 6. 格式布局概览
FLAC比特流由起始处的`fLaC`标记（即`0x664C6143`）、紧随其后的一个强制元数据块（称为流信息元数据块）、任意数量的其他元数据块，以及随后的音频帧组成。

FLAC支持127种元数据块类型；目前第8节中定义了7种类型。

音频数据由一个或多个音频帧构成。每帧包含一个帧头，帧头中包括同步码、帧信息（如块大小、采样率和声道数）以及8位CRC校验码。帧头还包含帧内第一个采样的采样号（针对可变块大小流）或帧号（针对固定块大小流）。这使得快速、采样精确的定位得以实现。帧头之后是编码的子帧，每个声道对应一个子帧。帧数据随后通过零填充对齐到字节边界，并以包含帧校验和的帧尾结束。每个子帧均有独立的头部，用于说明子帧的编码方式。

为支持解码器从流的任意位置开始解码，每帧起始处都有一个按字节对齐的15位同步码。但由于无法保证同步码不会出现在帧内其他位置，解码器需通过解析帧头剩余部分并验证帧头CRC校验码来确认同步正确性。

此外，为允许解码器无需接收流信息元数据块即可从流的任意位置开始解码，每个帧头均包含流的基础信息，如采样率、采样位数、声道数等。由于帧头是开销数据，其大小直接影响压缩率。为最小化帧头体积，FLAC为最常用的帧属性值设置了查找表。当某属性的值未包含在查找表中时，解码器需在帧头末尾或流信息元数据块中查找该属性值（例如采样率）。若帧头引用了流信息元数据块，则该文件不具备"流传输性"；详见第7节说明。通过使用查找表，文件可保持流传输性，且针对最常见音频数据形式的帧头体积最小化。

单个子帧（每个声道对应一个）在帧内独立编码并按顺序排列于流中。换言之，编码音频数据不采用声道交错模式。这种方式以需要更大解码缓冲区为代价降低了解码器复杂度。每个子帧头部独立说明子帧属性，包括预测方法和阶数、残差编码参数等。子帧头部后紧跟对应声道的编码音频数据。

## 7. 流式传输子集规范
FLAC格式将自身的某个子集定义为FLAC流式传输子集。该规范旨在确保根据此子集编码的流能够实现真正的"流式传输"，即无法在流中定位的解码器仍能从流中间开始拾取并解码。同时，该规范通过限制编码参数使硬件解码器实现更为可行，从而便于确定解码器缓冲区大小及其他资源需求。流式传输子集对流中允许使用的参数作出如下限制：

- 帧头中的采样率位字段（参见第9.1.2节）必须为0b0001至0b1110，即帧头不得引用流信息元数据块描述采样率<br>
- 帧头中的位深位字段（参见第9.1.4节）必须为0b001至0b111，即帧头不得引用流信息元数据块描述位深<br>
- 流中不得包含跨声道样本数超过16384的块，即最大块大小不得超过16384<br>
- 采样率小于或等于48000 Hz的音频不得存储在跨声道样本数超过4608的块中，即此类音频使用的最大块大小不得超过4608<br>
- 针对采样率小于或等于48000 Hz音频的线性预测子帧（参见第9.2.6节），其预测器阶数必须小于或等于12，即子帧头中的子帧类型位字段（参见第9.2.1节）不得为0b101100至0b111111<br>
- Rice分区阶数（参见第9.2.7节）必须小于或等于8<br>
- 声道排列必须符合第9.1.3节定义的标准类型，即FLAC文件无需使用WAVEFORMATEXTENSIBLE_CHANNEL_MASK标签描述声道排列，具体说明详见第8.6.2节

## 8. 文件级元数据
在FLAC文件或流的起始位置，`fLaC` ASCII文件标识符之后、任何音频帧出现之前，必须存在一个或多个元数据块。首个元数据块必须是流信息元数据块。

### 8.1. 元数据块头部
每个元数据块以4字节头部起始。该头部的首个比特位标记当前元数据块是否为最后一个块：当后续存在其他元数据块时置0，否则置1。首字节剩余的7个比特位以无符号数的形式表示元数据块类型（取值范围0-126），具体对应关系见下方表格。禁止使用值127（即`0b1111111`）。后续三个字节以大端编码方式表示元数据块的大小（单位：字节），该值不包含头部的4个字节。

| 数值 | 元数据类型                     |
|------|-------------------------------|
| 0    | 流信息                        |
| 1    | 填充数据                      |
| 2    | 应用程序数据                  |
| 3    | 定位表                        |
| 4    | Vorbis注释                    |
| 5    | 提示表                        |
| 6    | 图片数据                      |
| 7-126| 保留                         |
| 127  | 禁用（避免与帧同步码混淆）     |

### 8.2. 流信息（Streaminfo）  
流信息元数据块包含关于整个音频流的信息，如采样率、声道数、总采样数等。它**必须**作为流中的第一个元数据块存在。其他元数据块**可以**跟随其后。每个 FLAC 流中**必须**不超过一个流信息元数据块。

如果流信息元数据块包含错误或不完整的信息，解码器的行为将不作规定（即由解码器实现自行决定）。当流信息元数据块提供的信息被证明错误或包含禁止值时，解码器**可以**选择停止进一步解码。若解码器未在音频帧解码期间进行进一步校验，而直接接受流信息元数据块中的信息（尤其是最大帧大小、最大块大小、音频声道数、每采样位数和总采样数），则可能面临缓冲区溢出的风险。另见第11章。

下表按顺序描述了流信息元数据块（不包括元数据块头）的结构：<br>

| 数据 | 描述 |
|---|---|
| u(16) | 流中使用的最小块大小（以采样数为单位），不包含最后一个块。 |
| u(16) | 流中使用的最大块大小（以采样数为单位）。 |
| u(24) | 流中使用的最小帧大小（以字节为单位）。值为0表示该值未知。 |
| u(24) | 流中使用的最大帧大小（以字节为单位）。值为0表示该值未知。 |
| u(20) | 采样率（单位：Hz）。 |
| u(3) | （声道数）-1。FLAC 支持1到8个声道。 |
| u(5) | （每采样的比特数）-1。FLAC 支持每采样4到32位。 |
| u(36) | 流中声道间采样的总数。值为0表示总采样数未知。 |
| u(128) | 未编码音频数据的MD5校验和。即使存在错误但比特流本身有效时，解码器可通过此值判断音频数据是否存在错误。值为0表示该值未知。 |

最小块大小和最大块大小**必须**在16-65535范围内。最小块大小**必须**小于或等于最大块大小。

除最后一帧外的所有帧**必须**具有大于或等于最小块大小的块大小，且**必须**具有小于或等于最大块大小的块大小。最后一帧**必须**具有小于或等于最大块大小的块大小；它无需遵守最小块大小限制，因为该帧的块大小必须能够容纳流中包含的音频数据长度。

若最小块大小等于最大块大小，则文件包含固定块大小的流（因为最小块大小不包含最后一个块）。注意：对于可变块大小的流，实际最大块大小**可能**小于流信息元数据块中列出的最大块大小，且除最后一个块外的实际最小块大小**可能**大于流信息元数据块中列出的最小块大小。这是因为编码器必须在接收任何输入音频数据之前填写这些字段，无法预先知道将使用的具体块大小，只能确定块大小的选择范围。

当FLAC文件包含音频时，采样率**不得**为0。采样率为0**可以**用于表示非音频数据。这在编码非时间轴数据或数据采样率超出流信息元数据块可表示范围时有用。若使用0采样率，建议将编码内容的含义存储在Vorbis注释字段（见第8.6节）或应用元数据块（见第8.4节）中，本文档不定义此类元数据。

MD5校验和通过应用[RFC1321]中的MD5消息摘要算法计算。算法的输入消息由所有声道的所有样本按交错排列方式组成，以有符号小端形式表示。这种交错以单个样本为单位，例如对于立体声文件，顺序为：第一声道的第一个样本，第二声道的第一个样本，第一声道的第二个样本，依此类推。在计算校验和前，所有样本**必须**按字节对齐。若位深度不是整数字节数，则每个样本值需符号扩展到下一个整数字节数。

对于含6位样本的双声道流，位排列示例如下：<br>
```
SSAAAAAASSBBBBBBSSCCCCCC<br>
^   ^   ^   ^   ^   ^<br>
|   |   |   |   |  第二声道的第二个样本的位<br>
|   |   |   |  第二声道的第二个样本的符号扩展位<br>
|   |   |  第二声道的第一个样本的位<br>
|   |  第二声道的第一个样本的符号扩展位<br>
|  第一声道的第一个样本的位<br>
第一声道的第一个样本的符号扩展位
```

在具有12位采样的1通道流的情况下，位按小端字节顺序排列如下：

```
AAAAAAAASSSSAAAABBBBBBBBSSSSBBBB<br>
   ^     ^   ^   ^       ^   ^<br>
   |     |   |   |       |  第二个样本的最高有效4位<br>
   |     |   |   |      第二个样本的符号扩展位<br>
   |     |   |  第二个样本的最低有效8位<br>
   |     |  第一个样本的最高有效4位<br>
   |    第一个样本的符号扩展位<br>
   第一个样本的最低有效8位
```

### 8.3. 填充（Padding）  
填充元数据块允许存在任意数量的填充空间。当已知元数据将在编码后被编辑时，此块非常有用；用户可指示编码器预留足够大小的填充块，这样在添加元数据时，只需覆盖填充块（这相对快速），而无需将元数据插入现有文件中（通常需要重写整个文件）。每个 FLAC 流中**可以**存在一个或多个填充元数据块。

| 数据 | 描述 |
|---|---|
| u(n) | n个"0"位（n**必须**是8的倍数，即整数字节数，且**可能**为0）。n是元数据块头中描述尺寸的8倍。 |

### 8.4. 应用（Application）  
应用元数据块专供第三方应用程序使用。唯一必填字段是32位应用标识符（Application ID）。应用标识符注册于IANA“FLAC Application Metadata Block IDs”注册表（见第12.2节）。

| 数据 | 描述 |
|---|---|
| u(32) | 注册的应用标识符。 |
| u(n) | 应用数据（n**必须**是8的倍数，即整数字节数）。n等于元数据块头中描述尺寸的8倍减去已使用的32位（用于应用标识符）。 |

## 8.5. 定位点表格  
定位点表格元数据块可用于存储定位点。即使没有定位点表格，也可以定位到 FLAC 流中的任意指定样本，但由于比特率在流中可能存在较大波动，延迟时间可能难以预测。通过向流中添加定位点，可以显著减少这种延迟。一个流中**不得**存在多个定位点表格元数据块，但该表格可以包含任意数量的定位点。

每个定位点占用 18 字节，因此在流中具有 1% 分辨率的定位点表格仅增加不到 2KB 的数据量。定位点数量由元数据块头部描述的大小隐式确定，即等于 $size / 18$。还存在一种特殊的"占位符"定位点，解码器会忽略此类定位点，但可用于为将来插入定位点预留空间。

| 数据 | 描述 |
| 定位点 | 零个或多个定位点（定义见第8.5.1节）。 |

定位点表格通常不适用于在封装容器（参见第10节）内嵌的FLAC文件中进行定位，因为此类容器通常会将FLAC数据与其他数据交错存储，而定位点中使用的偏移量对应的是未多路复用的FLAC流。此外，容器通常提供其自有的定位方法。然而，在将FLAC文件多路复用到容器中时，可将定位点表格与其他元数据一同存储在容器内，因此在将FLAC流解复用为独立FLAC文件时，可以恢复该存储的定位点表格。

### 8.5.1. 定位点

| 数据 | 描述 |
|------|------|
| $u(64)$ | 目标帧首样本的样本编号，若为占位符点则值为 `0xFFFFFFFFFFFFFFFF` |
| $u(64)$ | 偏移量（字节单位），从首个帧头的第一个字节到目标帧头的第一个字节 |
| $u(16)$ | 目标帧中包含的样本数 |

注释：

- 对于占位符点，第二、第三字段值未定义  
- 表格内定位点必须按样本号**升序排列**  
- 表格内定位点的样本号必须**唯一**​（占位符点除外）  
- 前两条注释意味着：  
  - 允许存在任意数量的占位符点  
  - 所有占位符点**必须**位于表格末尾  
- 样本偏移量对应未多路复用的FLAC流  
- 偏移量在多路复用时**不得更新**以反映容器中FLAC帧的新偏移位置  

### 8.6.2. 通道掩码
除了包含音频内容本身信息的字段外，出于技术原因定义了一个特殊字段：WAVEFORMATEXTENSIBLE_CHANNEL_MASK。该字段用于声明文件中的通道与第9.1.3节定义的默认通道不同。<br>
例如，默认情况下包含两个通道的FLAC文件会被解析为左/右声道，但通过此字段可以描述不同的通道内容。

通道掩码由标志位构成，用于指示存在的通道。这些标志仅说明存在哪些通道，而非通道顺序。<br>
因此，若待编码文件的通道顺序不同，则需要进行重排序。掩码以十六进制表示（前缀0x），参见下方示例。<br>
需注意，通过WAVEFORMATEXTENSIBLE_CHANNEL_MASK定义通道顺序的文件不具备流式传输能力（参见第7节），因为该字段不存在于每个帧头中。掩码位定义见下表。

| 位号 | 通道描述                     |
|------|----------------------------|
| 0    | 前左                        |
| 1    | 前右                        |
| 2    | 前中                        |
| 3    | 低频效果（LFE）             |
| 4    | 后左                        |
| 5    | 后右                        |
| 6    | 前中左                      |
| 7    | 前中右                      |
| 8    | 后中                        |
| 9    | 侧左                        |
| 10   | 侧右                        |
| 11   | 顶部中                      |
| 12   | 顶部前左                    |
| 13   | 顶部前中                    |
| 14   | 顶部前右                    |
| 15   | 顶部后左                    |
| 16   | 顶部后中                    |
| 17   | 顶部后右                    |

以下是三个例子：

示例文件1：<br>
单通道文件（仅含LFE通道）。<br>
Vorbis注释字段为 `WAVEFORMATEXTENSIBLE_CHANNEL_MASK=0x8`（对应位3被置位）。

示例文件2：<br>
四通道文件（前左、前右、顶部前左、顶部前右）。<br>
Vorbis注释字段为 `WAVEFORMATEXTENSIBLE_CHANNEL_MASK=0x5003`（位0、1、12、14被置位）。

示例文件3：<br>
输入通道顺序：后中、顶部前中、前中、顶部后中。<br>
需重排序为：前中（位2）、后中（位8）、顶部前中（位13）、顶部后中（位16）。<br>
最终Vorbis注释字段为 `WAVEFORMATEXTENSIBLE_CHANNEL_MASK=0x12104`（位2、8、13、16被置位）。

WAVEFORMATEXTENSIBLE_CHANNEL_MASK 字段**可**使用零填充，例如单LFE通道可表示为 `0x0008`。<br>
解析该字段时，字段名称和内容**必须**不区分大小写。

当音频文件的声道与扬声器位置无对应关系时（例如需要解码为扬声器位置的Ambisonics B格式音频，或包含多轨录音的场景），<br>
可使用 `WAVEFORMATEXTENSIBLE_CHANNEL_MASK=0x0` 表示该状态。

若 `WAVEFORMATEXTENSIBLE_CHANNEL_MASK` 字段编码的通道数少于实际音频通道数，<br>
则播放应用程序**不应**渲染其不明确用途的剩余通道。<br>
例如，Ambisonics UHJ 格式兼容立体声播放：其前两个通道可在立体声设备中播放，<br>
而全部四个通道可解码为环绕声。此时应设置Vorbis注释字段 `WAVEFORMATEXTENSIBLE_CHANNEL_MASK=0x3`，<br>
表示前两个通道为前左/前右声道，其他通道不直接对应扬声器位置。

若音频包含未分配至特定扬声器的通道且支持解码到扬声器位置，<br>
建议通过其他Vorbis注释字段或应用元数据块提供解码方式的元数据。<br>
本文档未对此类元数据进行定义。

### 8.7. 索引表  
索引表元数据块可用于存储光盘数字音频（CD-DA）的轨道与索引点结构及其音频数据，<br>
或提供存储FLAC文件中兴趣点位置的机制。该元数据块的某些特性直接源自CD-DA规范（即[IEC.60908.1999]，红皮书标准），<br>
以下描述是完整的，实现该元数据块时无需额外参考[IEC.60908.1999]。<br>
索引表元数据块的结构如下表所示。

|数据|描述|
|---|---|
|u(128 * 8)| 媒体目录号（ASCII可打印字符0x20-0x7E）|
|u(64)|前导样本数|
|u(1) | 1表示索引表对应CD-DA；否则为0|
|u(7+258 * 8) | 保留位（7+258 * 8 bits）。所有位**必须**置零|
|u(8) | 本索引表中轨道数量|
|索引表轨道| 由前文指定数量的轨道结构组成（具体结构见第8.7.1节）|

如果媒体目录号的长度小于128字节，则使用0x00字节进行右填充。对于CD-DA而言，这是一个13位数字后跟115个0x00字节。

前导区样本数仅对CD-DA提示单有意义；其他用途下该值应为0。对于CD-DA，前导区是存储内容表的**TRACK** 00区域；更准确地说，它是从媒体的第一个样本到第一条音轨第一个索引点的第一个样本之间的样本数。根据[IEC.60908.1999]，前导区**必须**保持静音，且CD抓取软件通常不存储它；此外，前导区**必须**至少持续两秒但可更长。因此此处存储前导区长度以便计算第一条音轨的绝对位置。需注意这里存储的前导区长度是到第一条音轨第一个索引点的样本数，不一定是到第一条音轨INDEX 01的样本数；甚至第一条音轨**可能**包含INDEX 00数据。

音轨数量**必须**至少为1，因为提示单区块**必须**包含一条引出轨。对于CD-DA，该数值**必须**不超过100（99条常规音轨加1条引出轨）。引出轨始终是提示单中的最后一条音轨。对于CD-DA，引出轨号**必须**为170（根据[IEC.60908.1999]规定）；其他情况下**必须**为255。

### 8.7.1. 提示单音轨
| 数据 | 描述 |
|---|---|
u(64) | 音轨第一个索引点的偏移量（以样本为单位），相对于FLAC音频流的起始位置。
u(8) | 音轨编号。
u(12 * 8) | 音轨ISRC（国际标准录音代码）。
u(1) | 音轨类型：0表示音频，1表示非音频。对应CD-DA Q通道控制位第3位。
u(1) | 预加重标志：0表示无预加重，1表示预加重。对应CD-DA Q通道控制位第5位。
u(6+13 * 8) | 保留区域。所有位必须设置为0。
u(8) | 音轨索引点数量。
提示单音轨索引点 | 对于除引出轨之外的所有音轨，按第8.7.1.1节规定的结构数量，等于先前指定的索引点数量。

需注意音轨偏移量与CD-DA标准不同：在CD-DA中，音轨在内容表(TOC)中的偏移量始终是该音轨INDEX 01的偏移量（即使存在INDEX 00）。对于CD-DA，音轨偏移量**必须**能被588个样本整除（588样本 = 44100样本/秒 × 1/75秒）。

音轨编号0不可用，因CD-DA规范将其保留给前导区。对于CD-DA，音轨号**必须**为1-99或引出轨的170；非CD-DA场景中引出轨号**必须**为255。建议从音轨1开始顺序递增，且音轨号在提示单中**必须**唯一。

音轨ISRC（国际标准录音代码）为12位字母数字代码，详见[ISRC手册]。可用12个ASCII 0x00字符表示无ISRC。

除引出轨外，提示单中每条音轨**必须**包含至少一个索引点（引出轨**必须**为零索引点）。对于CD-DA，索引点数量**不应**超过100。

### 8.7.1.1. 提示单音轨索引点
| 数据 | 描述 |
|---|---|
u(64) | 索引点相对于音轨偏移量的样本偏移量。
u(8) | 音轨索引点编号。
u(3 * 8) | 保留区域。所有位**必须**设置为0。

对于CD-DA，音轨索引点偏移量**必须**能被588个样本整除（588样本 = 44100样本/秒 × 1/75秒）。需注意此偏移量是从音轨起始位置计算，而非音频数据起始位置。

对于CD-DA，索引点编号0对应轨道预间隙（pre-gap）。音轨中的第一个索引点编号**必须**为0或1，后续索引点编号**必须**依次递增1。索引点编号在音轨内**必须**保持唯一。
### 8.8. 图片
图片元数据块包含与FLAC文件中音频相关联的图像数据。其格式派生自ID3v2规范中的附加图片（APIC）帧，详见[ID3v2]。但与ID3v2的APIC帧不同，媒体类型和描述字段前增加了4字节长度字段，而非以0x00分隔的字符串。一个FLAC文件**可**包含一个或多个图片元数据块。

需注意：尽管媒体类型、描述和图片数据的长度字段为4字节（理论上可编码最大4 GiB），但元数据块总大小**不可**超过元数据块头部规定的限制（即16 MiB）。

图片元数据块也可包含[RFC3986]中定义的URI以替代图片数据。

图片元数据块的结构如下表所示：

| 数据 | 描述 |
|---|---|
u(32) | 根据表13定义的图片类型。
u(32) | 媒体类型字符串的字节长度。
u(n*8) | 符合[RFC2046]的媒体类型字符串，或文本字符串`-->`（表示数据部分是图片URI而非图片数据本身）。该字段**必须**为可打印ASCII字符（0x20-0x7E）。
u(32) | 描述字符串的字节长度。
u(n*8) | 图片的UTF-8格式描述。
u(32) | 图片宽度（像素）。
u(32) | 图片高度（像素）。
u(32) | 图片色深（每像素位数）。
u(32) | 对索引色图片（如GIF）为使用的颜色数；非索引色图片为0。
u(32) | 图片数据的字节长度。
u(n*8) | 二进制图片数据。

高度、宽度、色深和"颜色数量"字段仅用于信息展示。应用程序**不可**将这些字段用于解码图片或显示决策，但**可以**用于判断是否处理该区块（例如选择不同图片区块时），也**可以**向用户展示。若图片不包含这些字段的概念（如矢量图可能无像素尺寸）或字段内容未知，相关字段**必须**设置为零。

下表列出了所有定义的图片类型。表中未列出的值均为保留值。一个文件中**只能**存在一个类型1和类型2的图片。通常实践中，多数FLAC播放设备和软件在播放时会显示类型3（封面）的图片元数据块内容（若存在）。

| 值 | 图片类型 |
|---|---|
0 | 其他
1 | 32x32像素PNG文件图标（参见[RFC2083]）
2 | 通用文件图标
3 | 封面
4 | 封底
5 | 内页说明
6 | 媒体标签（如CD、黑胶或卡带标签）
7 | 主唱/主奏/独奏者
8 | 艺术家/表演者
9 | 指挥
10 | 乐队/乐团
11 | 作曲者
12 | 词作者/文本作者
13 | 录音地点
14 | 录音过程
15 | 演出过程
16 | 电影/视频画面捕捉
17 | 亮色鱼类图案
18 | 插画
19 | 乐队/艺术家标识
20 | 发行商/工作室标识

数值 17（"一条色彩鲜艳的鱼"）的起源和用途尚不明确。该数值的保留是为了保持与 ID3v2 的兼容性。<br>应用程序在嵌入图片时**不应**向用户提供该选项。

若该区块包含 URI（非图片），则适用以下条款：

- URI 可采用绝对或相对形式。若为相对形式 URI，其路径相对于被处理 FLAC 内容的 URI 路径。<br>
- 应用程序**必须**在以下情形获取用户的明确授权：通过远程协议获取图像时，或获取与被处理 FLAC 文件不同目录的本地图像时。<br>
- 支持链接图像的应用程序**必须**优雅处理 URI 不可用的情况，并**可以**向用户报告该不可用状态。<br>
- 应用程序**可以**基于任何理由（特别是出于安全或隐私考虑）拒绝处理 URI。

## 9. 帧结构
在最后一个元数据块之后直接跟随一个或多个帧。每个帧由帧头、一个或多个子帧、用于实现字节对齐的填充零位以及帧尾组成。每个帧中的子帧数量等于音频声道数。

每个帧头独立于流信息元数据块和其他帧头存储音频采样率、每样本比特数和声道数。这样设计是为了允许FLAC文件的多播传输，但也允许这些属性在流中发生变化。由于并非所有使用FLAC解码器的环境都能在播放时适应这些属性的变化，解码器**可以**选择在此类变化发生时停止解码。不检查此类变化的解码器可能容易受到缓冲区溢出的攻击。另见第11节。

需要注意的是，在FLAC中存储具有变化音频属性的音频会导致各种实际问题。例如，音频属性的变化必须发生在帧边界处，否则处理过程将无法无损。当选择可变块大小来适应这种情况时，需注意小于16样本的块是不允许的；因此，无法存储那些在文件起始或上次变化后16个样本内发生属性变化的音频流。此外，由于流信息元数据块只能容纳单一属性集，它仅对此类音频流的部分有效。因此，建议将具有变化属性的音频流存储在能够处理此类变化的容器封装的FLAC中，因为这类容器不存在上述限制。详见第10节。

### 9.1. 帧头
每个帧必须在字节边界开始，并以15位帧同步码0b111111111111100开头。同步码之后是分块策略位，该位**不得**在音频流中改变。对于固定块大小流，分块策略位为0；对于可变块大小流则为1。如果已知分块策略，解码器在搜索帧起始时可以利用该位来减少误报可能性，因为帧的前两个字节对于固定块大小流是0xFFF8，对于可变块大小流是0xFFF9。

### 9.1.1. 块大小位
在帧同步码和分块策略位之后是4位（每帧第三个字节的前4位），称为块大小位。它们的值根据下表与块大小相关联，其中v是这4位作为无符号数的值。如果块大小位编码了非常见块大小，该值会在编码后的数字之后存储；详见第9.1.6节。

|值| 块大小|
|---|---|
|0b0000|保留|
|0b0001|192|
|0b0010 - 0b0101|144 * (2v)，即576、1152、2304或4608|
|0b0110|非常见块大小减1，存储为8位数字|
|0b0111|非常见块大小减1，存储为16位数字|
|0b1000 - 0b1111|2v，即256、512、1024、2048、4096、8192、16384或32768|

### 9.1.2. 采样率位
接下来的4位（每帧第三个字节的后4位）称为采样率位，其包含的音频采样率根据下表确定。如果采样率位编码了不常见采样率，该值会在不常见块大小之后存储；若未使用不常见块大小，则在编码后的数字之后存储。详见第9.1.7节。

| 值       | 采样率                                                                 |
|----------|-----------------------------------------------------------------------|
| 0b0000   | 仅在流信息元数据块中存储采样率                                        |
| 0b0001   | 88.2 kHz                                                             |
| 0b0010   | 176.4 kHz                                                            |
| 0b0011   | 192 kHz                                                              |
| 0b0100   | 8 kHz                                                                |
| 0b0101   | 16 kHz                                                               |
| 0b0110   | 22.05 kHz                                                            |
| 0b0111   | 24 kHz                                                               |
| 0b1000   | 32 kHz                                                               |
| 0b1001   | 44.1 kHz                                                             |
| 0b1010   | 48 kHz                                                               |
| 0b1011   | 96 kHz                                                               |
| 0b1100   | 不常见采样率（单位为kHz），存储为8位数字                               |
| 0b1101   | 不常见采样率（单位为Hz），存储为16位数字                              |
| 0b1110   | 不常见采样率（单位为Hz除以10），存储为16位数字                        |
| 0b1111   | 禁用                                                                |

### 9.1.3. 声道位
接下来的4位（每帧第四个字节的前4位）称为声道位，其包含音频的声道数量以及使用的立体声去相关方式（根据下表确定）。

若使用与下表中不同的通道布局，可通过Vorbis注释元数据块中的WAVEFORMATEXTENSIBLE_CHANNEL_MASK标签进行标记（详见第8.6.2节）。需注意：即使通过WAVEFORMATEXTENSIBLE_CHANNEL_MASK指定了不同的通道布局并覆盖了下表中的通道顺序，声道位仍包含帧中实际编码的声道数量。关于左-侧、侧-右和中-侧立体声编码方式的详细信息，请参见第4.2节。

| 值| 声道配置|
|---|---|
| 0b0000   | 1声道：单声道|
| 0b0001   | 2声道：左、右|
| 0b0010   | 3声道：左、右、中置|
| 0b0011   | 4声道：前左、前右、后左、后右|
| 0b0100   | 5声道：前左、前右、前中置、后/环绕左、后/环绕右|
| 0b0101   | 6声道：前左、前右、前中置、低频效果（LFE）、后/环绕左、后/环绕右|
| 0b0110   | 7声道：前左、前右、前中置、低频效果（LFE）、后中置、侧左、侧右|
| 0b0111   | 8声道：前左、前右、前中置、低频效果（LFE）、后左、后右、侧左、侧右|
| 0b1000   | 2声道：左、右；存储为左-侧立体声|
| 0b1001   | 2声道：左、右；存储为侧-右立体声|
| 0b1010   | 2声道：左、右；存储为中-侧立体声|
| 0b1011 - 0b1111 | 保留|

### 9.1.4. 位深度位
接下来的3位（每帧第四个字节的第5、6、7位）根据下表存储音频的位深度。随后的1位为保留位且**必须**为零。

|值| 位深度|
|---|---|
| 0b000  | 仅在流信息元数据块中存储位深度|
| 0b001  | 每样本8比特|
| 0b010  | 每样本12比特|
| 0b011  | 保留|
| 0b100  | 每样本16比特|
| 0b101  | 每样本20比特|
| 0b110  | 每样本24比特|
| 0b111  | 每样本32比特|

### 9.1.5. 编码数字<br>
在保留位（从帧的第五个字节开始）之后存储的是样本编号或帧编号，统称为编码数字。当处理可变块大小流时，此处编码的是帧内第一个样本的样本编号。当文件包含固定块大小流时，此处编码的是帧编号。关于标志流类型（固定块大小流或可变块大小流）的阻塞策略位，请参见第9.1节。另见附录B.1。<br>

编码数字采用类似[RFC3629]定义的UTF-8可变长度编码方案，但扩展支持最大36位未编码值或7字节编码值。<br>

当编码帧编号时，其值**不得**超过31位未编码值或6字节编码值的容量。需注意，由于大多数通用UTF-8编码器/解码器遵循[RFC3629]标准，将无法处理这些扩展编码。此外，虽然UTF-8专门用于字符编码，但FLAC将其用于数字编码。编解码时应遵循[RFC3629]第3章流程，但需用帧/样本编号代替字符编号，并使用下方扩展表格替代[RFC3629]第3章原表。

| 数值范围（十六进制） | 八位组序列（二进制） |
|----------------------|----------------------|
| 0000 0000 0000 -<br>0000 0000 007F | `0xxxxxxx` |
| 0000 0000 0080 -<br>0000 0000 07FF | `110xxxxx 10xxxxxx` |
| 0000 0000 0800 -<br>0000 0000 FFFF | `1110xxxx 10xxxxxx 10xxxxxx` |
| 0000 0001 0000 -<br>0000 001F FFFF | `11110xxx 10xxxxxx 10xxxxxx 10xxxxxx` |
| 0000 0020 0000 -<br>0000 03FF FFFF | `111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx` |
| 0000 0400 0000 -<br>0000 7FFF FFFF | `1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx` |
| 0000 8000 0000 -<br>000F FFFF FFFF | `11111110 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx` |

若编码数字为帧编号，其值**必须**等于当前帧之前的所有帧数。若编码数字为样本编号，其值**必须**等于当前帧之前的所有样本数。若流不满足此要求，则（可靠）定位功能将无法实现。<br>

例如，对于属于可变块大小流且前含510亿样本的帧，其编码数字构建过程如下：<br>

```
字节1-5
0b11111110 0b10101111 0b10011111 0b10110101 0b10100011
               ^^^^^^     ^^^^^^     ^^^^^^     ^^^^^^
                 |          |          |      Bits 18-13
                 |          |      Bits 24-19
                 |      Bits 30-25
             Bits 36-31

字节6-7
0b10111000 0b10000000
    ^^^^^^     ^^^^^^
      |       Bits 6-1
  Bits 12-7
```

### 9.1.6. 非常见块大小<br>
若本节前文定义的块大小位为 `0b0110` 或 `0b0110`（存储`块大小减1`值），则块大小减1值将跟随在编码数字之后，存储为8位或16位大端序无符号数。禁止使用值65535（对应块大小为65536），​**不得**在流中使用此值，因为流信息元数据块无法表示此类块大小。值0至14（对应块大小1至15）仅可在流的最后一帧中使用，​**不得**用于其他帧。另见第8.2节。<br>

### 9.1.7. 非常见采样率<br>
若采样率位为 `0b1100`、`0b1101` 或 `0b1110`（存储非常见采样率值），则采样率值将跟随在非常见块大小之后（若无非常见块大小则直接跟随编码数字），存储为8位或16位大端序无符号数。<br>

当子帧包含音频时，采样率**不得**为0。采样率为0的情况仅可在表示非音频内容时使用。详见第8.2节。<br>

### 9.1.8. 帧头CRC<br>
最后，在帧/样本编号、非常见块大小或非常见采样率之后（根据后两者是否存在）存储8位CRC校验码。该CRC初始值为0，采用多项式$x^8 + x^2 + x + 1$。此CRC覆盖CRC字段前的整个帧头，包括同步码。

## 9.2. 子帧<br>
帧头之后包含与音频通道数量相等的若干子帧。注意子帧包含的比特流不一定以完整字节为单位，因此只有第一个子帧起始于字节边界。<br>

### 9.2.1. 子帧头<br>
每个子帧以头部开始。头部的第一个比特**必须**为0，随后6个比特根据下表描述子帧类型（其中v为这6个比特的无符号数值）：<br>

| 值 | 子帧类型 |
|----|----------|
| 0b000000 | 常量子帧 |
| 0b000001 | 原样子帧 |
| 0b000010 - 0b000111 | 保留 |
| 0b001000 - 0b001100 | 使用(v-8)阶固定预测器的子帧（即阶数0、1、2、3或4） |
| 0b001101 - 0b011111 | 保留 |
| 0b100000 - 0b111111 | 使用(v-31)阶线性预测器的子帧（即阶数1至32，含端点） |

子帧类型比特之后是一个标志位，用于指示该子帧是否使用废弃比特（参见第9.2.2节）。若标志位为0，表示子帧未使用任何废弃比特，此时子帧头结束。若标志位为1，表示子帧使用废弃比特，此时标志位后直接以一元编码形式存储`使用废弃比特数减1`的值。<br>

### 9.2.2. 每样本废弃比特数<br>
大多数未压缩音频文件格式只能存储比特深度为整数字节数的音频样本。当样本的比特深度非整数字节时，通常通过填充最低有效零比特使其达到整数字节位数。例如，将14位样本右移2位可填充为16位样本（此时最低有效位有2个零比特）。本规范中，这些最低有效零比特称为"每样本废弃比特"或简称"废弃比特"。称其为"废弃"是因为它们不携带信息但仍被存储。<br>

FLAC格式可通过信号标记废弃比特的存在，并在编码子帧时将其排除。为此，需将子帧头中的废弃比特标志位置1，并在标志位后以一元编码形式存储`废弃比特数k减1`。例如，若k=3，则后续为`0b001`；若k=0，则废弃比特标志位为0，且无后续一元编码值。本文档中，若子帧头标记了特定数量的废弃比特，则称该子帧"使用"了这些废弃比特。<br>

若子帧使用废弃比特（即k≠0），则样本编码时需忽略k个最低有效位。例如，当未采用立体声去相关的帧在帧头指定每样本16位，且子帧k=3时，该子帧样本实际按每样本13位编码。更多细节参见第9.2.3节关于子帧比特深度计算方式。解码器**必须**在解码子帧样本后通过左移（补零）恢复k个最低有效位。若帧采用左-侧、侧-右或中-侧立体声编码，解码器**必须**在恢复左右声道前对子帧执行补零操作。每样本废弃比特数**必须**确保最终每样本有效比特数（计算方法见第9.2.3节）大于零。<br>

除整文件固定废弃比特数的音频文件外，还存在废弃比特数可变的音频文件。某些DVD-Audio光盘会选择性清零样本块的最低有效位以提升Meridian无损打包编解码器的压缩率（参见[MLP]）。另有如lossyWAV（参见[lossyWAV]）等音频处理器会对样本块清零若干最低有效位，以非无损方式提升压缩率。因此，废弃比特数k**允许**在帧间变化，也**允许**在子帧间不同。若子帧内废弃比特数中途变化（如前半部分2位废弃，后半部分4位废弃），则该子帧使用最低的废弃比特数，否则非零比特将被丢弃，处理过程将不再无损。

### 9.2.3. 常量子帧
在常量子帧中，仅存储单个样本。该样本以大端序有符号二进制补码整数形式存储。用于存储该样本的比特数取决于当前子帧的位深。子帧的位深等于帧头中编码的位深（见第9.1.4节）减去子帧头中编码的已使用浪费位数量（见第9.2.2节）。如果子帧是边子帧（见第4.2节），则该子帧的位深将增加1比特。

### 9.2.4. 原样子帧
原样子帧按顺序未编码存储所有样本。关于如何未编码存储样本，请参见第9.2.3节。子帧中需要存储的样本数量由帧头中的块大小提供。

### 9.2.5. 固定预测器子帧
下表中定义了五种不同的固定预测器，分别对应预测阶数0到4。该表还包含了解释选择这些固定预测器原理的推导过程。

| 阶数 | 预测 | 推导 |
|---|---|---|
| 0 | $0$ | 不适用 |
| 1 | $a(n-1)$ | 不适用 |
| 2 | $2 \times a(n-1) - a(n-2)$ | $a(n-1) + a'(n-1)$ |
| 3 | $3 \times a(n-1) - 3 \times a(n-2) + a(n-3)$ | $a(n-1) + a'(n-1) + a''(n-1)$ |
| 4 | $4 \times a(n-1) - 6 \times a(n-2) + 4 \times a(n-3) - a(n-4)$ | $a(n-1) + a'(n-1) + a''(n-1) + a'''(n-1)$ |
这里：
- n 表示被预测样本的编号。<br>
- a(n) 表示被预测的样本。<br>
- a(n-1) 表示被预测样本的前一个样本。<br>
- a'(n-1) 表示前一个样本与其前前样本的差值，即 $a(n-1) - a(n-2)$。这是可用的最近一阶离散导 数。<br>
- a''(n-1) 表示 $a'(n-1) - a'(n-2)$，即可用的最近二阶离散导数。<br>
- a'''(n-1) 表示 $a''(n-1) - a''(n-2)$，即可用的最近三阶离散导数。


由于预测器需要使用被预测样本之前的样本进行预测，因此只有在已知足够数量的样本时才能使用。由于FLAC中每个子帧都是完全独立编码的，每个子帧的前几个样本无法被预测。因此需要存储数量等于预测器阶数的所谓预热样本。这些样本未经编码直接存储，绕过预测器和残差编码阶段。关于如何未编码存储样本，请参见第9.2.3节。下表定义了固定预测器子帧在位元流中的呈现方式。

| 数据 | 描述 |
|---|---|
| s(n) | 未编码的预热样本（n = 子帧的每样本比特数 × 预测器阶数） |
| 编码残差 | 按第9.2.7节定义的编码残差 |

由于固定预测器已预先定义，因此无需存储其参数。存储在子帧头中的固定预测器阶数指定了所采用的预测器类型。

当使用固定预测器编码信号时，需从每个样本中减去对应的预测值并将结果送入残差编码器。当解码使用固定预测器的信号时，需先解码残差值，随后为每个样本加上对应的预测值。这意味着在子帧内部，解码必须是一个顺序处理过程，因为每个样本都需要足够数量的已完全解码的前序样本来计算预测值。

对于阶数0的固定预测器，其预测值恒为0，因此每个残差样本等于其对应的输入样本或解码样本。阶数0的固定预测器与原样子帧的区别在于：原样子帧直接未编码存储所有样本，而阶数0的固定预测器会将其所有样本送入残差编码器进行处理。

一阶固定预测器的工作机制与差分脉冲编码调制（DPCM）编码类似，其产生的残差样本是当前样本与前一个样本的差值。更高阶的固定预测器可理解为对前序样本进行多项式拟合的预测模型。


### 9.2.6. 线性预测器子帧
虽然固定预测器非常适合简单信号，但对更复杂的信号使用（非固定）线性预测器可以通过进一步缩小残差样本来提升压缩率。但需要权衡的是，存储预测器系数也会占用空间。

在FLAC格式中，预测器由最多32个预测器系数和一个位移量定义。预测值的计算方式是：将每个系数与其对应的历史样本相乘，求和后再进行位移。当使用线性预测器编码信号时，需从每个样本中减去对应的预测值并将结果送入残差编码器。当解码使用线性预测器的信号时，需先解码残差值，随后为每个样本加上对应的预测值。这意味着在子帧内部，解码必须是一个顺序处理过程，因为需要足够数量的已解码样本来计算每个样本的预测值。

下表定义了线性预测器子帧在位元流中的呈现方式。

表22  
| 数据 | 描述 |
|---|---|
| s(n) | 未编码的预热样本（n = 子帧的每样本比特数 × LPC阶数） |
| u(4) | (预测器系数精度（以比特计）)-1（注：0b1111为禁用值） |
| s(5) | 预测所需的右移位量（以比特计） |
| s(n) | 预测器系数（n = 预测器系数精度 × LPC阶数） |
| 编码残差 | 按第9.2.7节定义的编码残差 |

关于如何未编码存储预热样本，请参见第9.2.3节。预测器系数以大端序有符号二进制补码整数形式存储，每个系数所需的比特数由预测器系数精度定义。虽然预测右移位量以有符号二进制补码形式存储，但该数值必须为非负数（原因解释见附录B.4）。

请注意预测器系数在位元流中的出现顺序与其对应的历史样本位置相关。具体而言，预测器系数的排列顺序与样本的时间顺序相反。因此，第一个预测器系数需与预测目标样本的直接前序样本相乘，第二个预测器系数需与该样本的更早前序样本相乘，依此类推。

### 9.2.7. 编码残差
编码残差的前两位比特表示使用的编码方法。参见下表。

|值|描述|
|---|---|
|0b00|使用4比特参数的划分式Rice编码|
|0b01|使用5比特参数的划分式Rice编码|
|0b10 - 0b11|保留值|

两种已定义的编码方法工作原理相同，但Rice参数使用的比特数不同。紧接编码方法比特后的4个比特构成分区阶数（无符号数）。编码残差的剩余部分由$2^{\text{分区阶数}}$个分区组成。例如，如果这4个比特是0b1000，则分区阶数为8，残差将被分割为$2^8 = 256$个分区。

每个分区包含一定数量的残差样本。第一个分区的残差样本数等于（块大小 >> 分区阶数）- 预测器阶数，即块大小除以分区数再减去预测器阶数。其他所有分区的残差样本数等于（块大小 >> 分区阶数）。

分区阶数**必须**满足块大小能被分区数整除。例如，这意味着对于所有奇数块大小，仅允许分区阶数0。分区阶数还**必须**满足（块大小 >> 分区阶数）大于预测器阶数。例如，当块大小为4096且预测器阶数为4时，分区阶数不能大于9。

每个分区以一个参数开头。如果子帧的编码残差使用4比特Rice参数（见表23），则每个分区的前4个比特要么是Rice参数，要么是转义码。若这4个比特为0b1111则表示转义码；否则，它们包含一个无符号数形式的Rice参数。如果当前子帧的编码残差使用5比特Rice参数，则每个分区的前5个比特若为0b11111则表示转义码；否则，它们同样包含一个无符号数形式的Rice参数。

### 9.2.7.1. 转义分区
若使用转义码，则该分区不包含变长Rice编码残差，而是包含定长未编码残差。紧接转义码后的5个比特表示每个残差样本的存储比特数（无符号数）。残差样本本身以有符号二进制补码形式存储。例如，当某分区被转义且每个残差样本用3比特存储时，数值-1表示为0b111。

需注意，存储样本的比特数可能为0，这意味着该分区中所有残差样本的值为0且无需存储任何比特。此时，该分区仅包含转义码和0b00000。

### 9.2.7.2. Rice编码
若某分区提供了Rice参数，则该分区包含Rice编码残差。作为有符号数的残差样本，在Rice编码中通过无符号数表示：<br>
- 正数：数值乘以2<br>
- 负数：数值乘以-2后减1<br>
这种有符号数表示方法称为zigzag编码。经zigzag编码的残差称为折叠残差。

每个折叠残差样本随后被拆分为两部分：高位部分（MSB）和低位部分（LSB）。每个分区的Rice参数决定拆分位置：即低位部分的比特数。每个残差样本以一元编码存储高位部分，后接二进制编码存储低位部分。

例如，某分区的Rice参数为3，折叠残差样本值为38（二进制0b100110）：<br>
- 高位部分为0b100（十进制4），以一元编码0b00001存储<br>
- 低位部分为0b110（十进制6），直接存储为二进制<br>
最终Rice码字为0b00001110。分区的所有残差样本码字按顺序连续存储。

解码Rice码字时需执行以下步骤：<br>
1. 统计连续零比特的数量直至遇到1比特<br>
2. 读取Rice参数指定数量的后续比特<br>
3. 零比特数量左移Rice参数位（即乘以$2^{\text{Rice参数}}$），与读取值进行位或运算（即相加）得到折叠残差值<br>
4. 若折叠残差值为偶数：右移1位（即除以2）得到原始残差值<br>
5. 若折叠残差值为奇数：右移1位后取反（加1并除以-2）得到原始残差值（需考虑解码机器的有符号二进制补码表示）

附录D展示了完整编码残差的解码过程示例。

### 9.2.7.3. 残差样本值限制
所有残差样本值**必须**可用32位有符号原码整数范围表示，或等效地**必须**落在32位有符号补码整数范围内（但排除该范围内最小的负数值）。这意味着残差样本值的绝对值**必须**小于$2^{31}$。FLAC编码器**必须**确保此条件成立。若FLAC编码器对某个子帧无法找到满足所有残差样本均处于上述范围的预测器，则**必须**默认写入逐字子帧（verbatim subframe）。附录A解释了何种情况下残差样本已隐式满足该范围要求，因此无需额外校验。

设定此限制的原因在于确保解码器处理残差时可采用32位整数简化计算。特别排除32位补码最小负数值的原因在于：该值无法在32位有符号整数范围内取反，且多数计算绝对值的库函数对此值的处理行为未定义，因此避免解码器需专门处理该值。

### 9.3. 帧尾部
最后一个子帧之后是帧尾部。若最后一个子帧未字节对齐（即存储所有子帧所需总比特数非8的倍数），则填充零比特直至字节对齐。随后附加16位CRC校验码，其生成多项式为$x^{16} + x^{15} + x^{2} + x^{0}$，初始值为0。此CRC覆盖整个帧（含同步码但不含16位CRC自身）。

## 10. 容器映射
FLAC格式可以在不使用任何容器的情况下使用，因为它已经提供了通常与容器相关的最基本功能。然而，这种基础容器提供的功能相当有限，对于更高级的功能（例如将FLAC音频与视频结合），需要由功能更强大的容器进行封装。这带来了一个问题：由于这些容器功能的存在，FLAC格式将属于编码数据的数据（如块大小和采样率）与属于容器的数据（如校验和时间码）混合在了一起。选择直接封装FLAC帧的做法意味着部分数据将被重复存储，并可能导致FLAC帧与封装容器之间的数据不一致。

由于FLAC帧彼此完全独立，因此不需要使用处理依赖关系的容器格式功能。例如，嵌入Matroska容器中的所有FLAC帧在存储为SimpleBlock时都被标记为关键帧，而仅包含FLAC帧的MP4文件轨道则不需要同步样本框（sync sample box）。

### 10.1. Ogg 映射
Ogg容器格式定义于[RFC3533]。携带FLAC数据的逻辑比特流的首个数据包结构如下表所示：

| 数据 | 描述 |
|-----|-----|
| 5字节 | 字节序列0x7F 0x46 0x4C 0x41 0x43（同[RFC5334]定义） |
| 2字节 | FLAC-in-Ogg映射的版本号。该字节序列为0x01 0x00，表示映射版本1.0 |
| 2字节 | 头部数据包数量（不包含首个头部数据包），以大端序编码的无符号数表示 |
| 4字节 | fLaC签名标识 |
| 4字节 | 流信息元数据块的元数据块头 |
| 34字节 | 流信息元数据块内容 |

### 10.1. Ogg 映射
头部数据包数量**可以**为0，这意味着后续数据包数量未知。首个数据包**不得**与其他数据包共享Ogg页面，这意味着FLAC-in-Ogg逻辑流的首个页面始终为79字节。

首个数据包之后是一个或多个头部数据包，每个头部数据包包含单个元数据块。出于历史原因，第一个头部数据包**应当**是Vorbis注释元数据块。这与未封装的FLAC流不同：在未封装FLAC流中，元数据块的顺序无关紧要（流信息元数据块除外），且Vorbis注释元数据块是可选的。

头部数据包之后是音频数据包。每个音频数据包包含单个FLAC帧。首个音频数据包**必须**起始于新的Ogg页面，即最后一个元数据块**必须**在封装任何音频数据包前完成其所在页面。

所有包含头部数据包的页面的颗粒位置（granule position）​**必须**为0。对于包含音频数据包的页面，颗粒位置是帧中最后一个完整数据包所包含的最后一个样本的编号。样本编号考虑声道间样本。如果页面不包含任何数据包结束（例如仅包含延续到下一页的大数据包起始部分），则颗粒位置设为最大可能值（即0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF）。

首个包含完整数据包的音频数据页面的颗粒位置**可以**大于该页面上完成的数据包所包含的样本数量。换句话说，根据颗粒位置和音频数据推算出的流中首个样本的编号**可以**大于0。例如，这使得服务器能够将实时流广播给不同时间加入的多个客户端，而无需为每个客户端重写颗粒位置。

如果音频流在编码过程中发生音频属性（采样率、声道数或位深）的变化，应当通过结束当前Ogg流编码并开始与前一流串联的新Ogg流来处理。这在Ogg中称为链接（chaining）。详细信息请参阅Ogg规范[RFC3533]。

### 10.2. Matroska 映射
Matroska容器格式定义于[RFC9559]。用于承载FLAC数据的音轨编解码器ID（EBML路径 \Segment\Tracks\TrackEntry\CodecID）为ASCII编码的A_FLAC。首个音频帧之前的所有FLAC数据（即fLaC ASCII签名及所有元数据块）存储为编解码器私有数据（CodecPrivate，EBML路径 \Segment\Tracks\TrackEntry\CodecPrivate）。

在Matroska语境中，每个FLAC帧（包括其所有子帧）被视为单个帧。

若音频流在编码过程中发生音频属性（采样率、声道数或位深）的变化，应当通过结束当前Matroska片段并创建具有新属性的新片段来处理。

### 10.3. ISO 基础媒体文件格式（MP4）映射
由于FLAC音频在MP4文件中的完整封装定义过于广泛，本文档未予收录。具体定义文档请参阅[FLAC-in-MP4-specification]。

## 11. 安全考量
与其他编解码器（如[RFC6716]）类似，FLAC不应与不安全的密码或易受已知明文攻击的密码模式一起使用。部分头部比特及填充内容具有高度可预测性。

FLAC编解码器的实现需要考虑适当的安全问题。[RFC4732]第2.1节提供了关于终端系统遭受DoS攻击的通用信息，并描述了一些缓解策略。以下是与FLAC相关的特定关注领域。

解码器必须具备对畸形载荷的强健性。不符合本规范的载荷**不得**导致解码器内存越界或消耗过多解码资源。内存越界可能使攻击者执行任意代码。该原则同样适用于编码器，尽管编码器问题通常较为罕见。畸形音频流**不得**导致编码器异常行为，因为这可能使攻击者利用转码网关实施攻击。

与所有压缩算法相同，编码和解码都可能产生远大于输入的输出。解码时最极端的情况是包含八个块大小为65535的恒定子帧、采用32位PCM编码的帧。该帧仅有49字节，但可解码超过2MB的非压缩PCM数据。编码时可能存在更大的尺寸膨胀，尽管此类行为通常视为故障。当编码器选择的Rice参数与待编码残差不匹配时，可能出现极长的一元编码符号（最极端情况下每个样本超过4GB）。建议编解码器实现者采取预防措施以避免此类情况下的资源过度消耗。

在处理元数据时，建议实现者彻底测试极端情况处理机制，或在本规范限制之外施加合理限制。例如单个Vorbis注释元数据块可包含数百万有效字段。除潜在恶意文件外，此类限制几乎不会被触及。类似地，图片元数据块的媒体类型和描述可能长达数百万字符，尽管此类内容并无合理用途。超长字符串的一个可能用例是歌词存储（可通过Vorbis注释元数据块字段实现）。

多种元数据块包含长度字段或字段计数。在根据这些长度或计数读取块时，解码器**必须**确保不超出上层长度或计数（最重要的是元数据块自身的长度字段）。由于部分长度字段编码字符串长度且需分配内存，解析器**必须**在根据内容分配内存前验证块的有效性，除非明确要求从畸形文件中恢复数据。

元数据块可能包含引用（如图片元数据块可包含URI）。处理URI时需遵循[RFC3986]的安全考量。应用程序**必须**获得用户明确授权才能通过远程协议获取资源。遵循外部URI会引入路径观察者和URI托管服务运营商的追踪风险。若未受https等保护，方案选择也可能导致路径观察者的完整性攻击。恶意URI托管服务运营商可能返回解析器将读取的任意内容。此外，当URI指向潜在受害者时，此类检索可能用于DDoS攻击。因此，应用程序需为每次检索单独申请用户授权，在解析检索数据时采取额外预防措施，并缓存检索资源。应用程序**必须**获得用户明确授权才能检索与处理中FLAC文件不同目录的本地资源。由于允许相对URI，应用程序**必须**防范目录遍历攻击，并确保不违反同源策略（若已实施该策略）。

在未封装容器中的FLAC流中进行定位依赖于帧头的编码数值及可选的定位表元数据块。解析器**必须**对发现的编码数值或定位点实施全面检查（例如是否在有效范围内，且不与定位过程依赖的其他编码数值或定位点直接矛盾）。缺乏此类检查时，当帧中数值非连续或无效时，定位可能陷入无限循环（可能被用于DoS攻击）。

建议实现者在FLAC解码器中结合模糊测试与不同净化器来发现安全问题。忽略CRC校验结果可提升解码器模糊测试效率。

[FLAC-decoder-testbench]列出了部分具有极端配置的FLAC文件案例集（这些文件会导致某些已知实现崩溃或重启）。该案例集不仅为安全测试提供起点，也可用于测试对本规范的符合性。

FLAC文件可能包含可执行代码，尽管FLAC格式未设计此用途且较为罕见。FLAC偶尔用于存储可执行代码的一个用例是压缩混合模式CD镜像（包含音频与非音频数据，后者可能含可执行代码）。此时可执行代码以音频形式存储且可能被混淆。当然，也可通过二进制文本编码将可执行代码存为元数据（例如Vorbis注释），或直接存入应用元数据块。应用程序**不得**执行FLAC文件中的代码或将FLAC文件部分内容作为可执行代码呈现给用户，除非应用程序具有明确目的（例如将FLAC文件作为光盘镜像读取并呈现为虚拟光驱的应用程序）。

## 12. IANA考虑事项
根据本文档，IANA已注册一个新的媒体类型("audio/flac")并创建了新的IANA注册表，具体如下所述。

### 12.1 媒体类型注册
IANA已按以下方式注册"audio/flac"媒体类型。该媒体类型适用于未按第10章所述封装在容器中的FLAC音频。封装在此类容器中的FLAC音频将采用该容器的媒体类型，例如：封装在Ogg容器中时采用"audio/ogg"类型，或与视频轨道共同封装在MP4容器中时采用"video/mp4"类型。

**类型名称**:  
*audio*

**子类型名称**:  
*flac*

**必需参数**:  
*无*

**可选参数**:  
*无*

**编码考虑事项**:  
*遵循RFC 9639*

**安全考量**:  
*参见RFC 9639第11节的安全考量内容*

**互操作性考虑**:  
*参见RFC 9639附录B中关于历史格式变更的描述*

**发布规范**:  
*RFC 9639*

**使用此媒体类型的应用程序**:  
*FFmpeg、Apache、Firefox*

**片段标识符考虑**:  
*无*

**附加信息**:  

**已弃用别名**:  
*audio/x-flac*

**魔数**:  
*fLaC*

**文件扩展名**:  
*.flac*

**Macintosh文件类型代码**:  
*无*

**统一类型标识符**:  
*org.xiph.flac*（符合public.audio标准）

**Windows剪贴板格式名称**:  
*audio/flac*

**联系人及邮箱**:  
*IETF CELLAR工作组 (cellar@ietf.org)*

**预期用途**:  
*通用*

**使用限制**:  
*无*

**作者**:  
*IETF CELLAR工作组*

**变更控制方**:  
*互联网工程任务组 (iesg@ietf.org)*

### 12.2. FLAC 应用元数据块 ID 注册表<br>
IANA 已创建名为"FLAC 应用元数据块 ID"的新注册表。其对应值对应于第 8.4 节中描述的 32 位标识符。<br>

要在本注册表中注册新应用 ID，需提供以下信息：应用 ID、描述、描述该应用 ID 的文档参考（可选）及变更控制者（IETF 或注册者邮箱）。应用 ID 的分配遵循"先到先得"政策 [RFC8126]，以便 FLAC 社区遇到的任何应用 ID 都能无障碍注册，特别是那些已在音频文件中使用但编码时未注册的 ID。应用 ID 可以是任意 32 位值，但通常由人类可读的 4 个 ASCII 字符组成。<br>

"FLAC 应用元数据块 ID"注册表的初始内容如下表所示。这些初始值取自 xiph.org 的注册页面（参见 [ID-registration-page]），由于该页面已被本注册表取代，现已停止维护。

| 应用名称        | ID (十六进制) | ASCII 表示（如有） | 描述                              | 参考文档                          | 变更控制者 |
|-----------------|---------------|--------------------|-----------------------------------|-----------------------------------|------------|
| 0x41544348      | ATCH          | FlacFile           | [FlacFile], RFC 9639              | IETF                             |
| 0x42534F4C      | BSOL          | beSolo             | RFC 9639                          | IETF                             |
| 0x42554753      | BUGS          | Bugs Player        | RFC 9639                          | IETF                             |
| 0x43756573      | Cues          | GoldWave cue points| RFC 9639                          | IETF                             |
| 0x46696361      | Fica          | CUE Splitter       | RFC 9639                          | IETF                             |
| 0x46746F6C      | Ftol          | flac-tools         | RFC 9639                          | IETF                             |
| 0x4D4F5442      | MOTB          | MOTB MetaCzar      | RFC 9639                          | IETF                             |
| 0x4D505345      | MPSE          | MP3 Stream Editor  | RFC 9639                          | IETF                             |
| 0x4D754D4C      | MuML          | MusicML: Music Metadata Language | RFC 9639           | IETF                             |
| 0x52494646      | RIFF          | Sound Devices RIFF chunk storage | RFC 9639            | IETF                             |
| 0x5346464C      | SFFL          | Sound Font FLAC    | RFC 9639                          | IETF                             |
| 0x534F4E59      | SONY          | Sony Creative Software | RFC 9639                      | IETF                             |
| 0x5351455A      | SQEZ          | flacsqueeze        | RFC 9639                          | IETF                             |
| 0x54745776      | TtWv          | TwistedWave        | RFC 9639                          | IETF                             |
| 0x55495453      | UITS          | UITS Embedding tools | RFC 9639                        | IETF                             |
| 0x61696666      | aiff          | FLAC AIFF chunk storage | [Foreign-metadata], RFC 9639  | IETF                             |
| 0x696D6167      | imag          | flac-image         | RFC 9639                          | IETF                             |
| 0x7065656D      | peem          | Parseable Embedded Extensible Metadata | RFC 9639 | IETF                             |
| 0x71667374      | qfst          | QFLAC Studio       | RFC 9639                          | IETF                             |
| 0x72696666      | riff          | FLAC RIFF chunk storage | [Foreign-metadata], RFC 9639   | IETF                             |
| 0x74756E65      | tune          | TagTuner           | RFC 9639                          | IETF                             |
| 0x77363420      | w64           | FLAC Wave64 chunk storage | [Foreign-metadata], RFC 9639 | IETF                             |
| 0x78626174      | xbat          | XBAT               | RFC 9639                          | IETF                             |
| 0x786D6364      | xmcd          | xmcd               | RFC 9639                          | IETF                             |

## 13. 参考文献<br>
### 13.1 规范性参考文献<br>
[ISRC-handbook]<br>
国际ISRC注册局，《国际标准录音代码（ISRC）手册》（第四版），2021年，<https://www.ifpi.org/isrc_handbook/>。<br>

[RFC1321]<br>
Rivest, R., "MD5消息摘要算法"，RFC 1321，DOI 10.17487/RFC1321，1992年4月，<https://www.rfc-editor.org/info/rfc1321>。<br>

[RFC2046]<br>
Freed, N. 和 N. Borenstein，"多用途互联网邮件扩展（MIME）第二部分：媒体类型"，RFC 2046，DOI 10.17487/RFC2046，1996年11月，<https://www.rfc-editor.org/info/rfc2046>。<br>

[RFC2083]<br>
Boutell, T., "PNG（便携式网络图形）规范1.0版"，RFC 2083，DOI 10.17487/RFC2083，1997年3月，<https://www.rfc-editor.org/info/rfc2083>。<br>

[RFC2119]<br>
Bradner, S., "用于RFC表示要求层级的关键词"，BCP 14，RFC 2119，DOI 10.17487/RFC2119，1997年3月，<https://www.rfc-editor.org/info/rfc2119>。<br>

[RFC3533]<br>
Pfeiffer, S., "Ogg封装格式版本0"，RFC 3533，DOI 10.17487/RFC3533，2003年5月，<https://www.rfc-editor.org/info/rfc3533>。<br>

[RFC3629]<br>
Yergeau, F., "UTF-8，ISO 10646的转换格式"，STD 63，RFC 3629，DOI 10.17487/RFC3629，2003年11月，<https://www.rfc-editor.org/info/rfc3629>。<br>

[RFC3986]<br>
Berners-Lee, T., Fielding, R., 和 L. Masinter，"统一资源标识符（URI）：通用语法"，STD 66，RFC 3986，DOI 10.17487/RFC3986，2005年1月，<https://www.rfc-editor.org/info/rfc3986>。<br>

[RFC8174]<br>
Leiba, B., "RFC 2119关键词中大小写的歧义性"，BCP 14，RFC 8174，DOI 10.17487/RFC8174，2017年5月，<https://www.rfc-editor.org/info/rfc8174>。<br>

[RFC9559]<br>
Lhomme, S., Bunkus, M., 和 D. Rice，"Matroska媒体容器格式规范"，RFC 9559，DOI 10.17487/RFC9559，2024年10月，<https://www.rfc-editor.org/info/rfc9559>。

### 13.2 资料性参考文献<br>
[Durbin]<br>
Durbin, J., "时间序列模型的拟合"，国际统计研究所杂志，第28卷第3期，第233-244页，DOI 10.2307/1401322，1960年，<https://www.jstor.org/stable/1401322>。<br>

[FIR]<br>
维基百科，"有限冲激响应"，2024年8月，<https://en.wikipedia.org/w/index.php?title=Finite_impulse_response&oldid=1240945295>。<br>

[FLAC-decoder-testbench]<br>
"自由无损音频编解码器（FLAC）测试文件"，提交记录aa7b0c6，2023年8月，<https://github.com/ietf-wg-cellar/flac-test-files>。<br>

[FLAC-implementation]<br>
"FLAC"，<https://xiph.org/flac/>。<br>

[FLAC-in-MP4-specification]<br>
"FLAC在ISO基础媒体文件格式中的封装"，提交记录78d85dd，2022年7月，<https://github.com/xiph/flac/blob/master/doc/isoflac.txt>。<br>

[FLAC-specification-github]<br>
"自由无损音频编解码器（FLAC）规范"，<https://github.com/ietf-wg-cellar/flac-specification>。<br>

[FLAC-wiki-interoperability]<br>
"互操作性注意事项"，提交记录58a06d6，<https://github.com/ietf-wg-cellar/flac-specification/wiki/Interoperability-considerations>。<br>

[FlacFile]<br>
"FlacFile"，互联网档案馆存档，2007年10月，<https://web.archive.org/web/20071023070305/http://firestuff.org:80/flacfile/>。<br>

[Foreign-metadata]<br>
"FLAC中外来元数据存储规范"，提交记录72787c3，2023年11月，<https://github.com/xiph/flac/blob/master/doc/foreign_metadata_storage.md>。<br>

[ID-registration-page]<br>
Xiph.Org，"ID注册表"，<https://xiph.org/flac/id.html>。<br>

[ID3v2]<br>
Nilsson, M., "ID3标签版本2.4.0 - 原生帧结构"，互联网档案馆存档，2000年11月，<https://web.archive.org/web/20220903174949/https://id3.org/id3v2.4.0-frames>。<br>

[IEC.60908.1999]<br>
国际电工委员会，"音频录制 - 光盘数字音频系统"，IEC 60908:1999-02，1999年，<https://webstore.iec.ch/publication/3885>。<br>

[LinearPrediction]<br>
维基百科，"线性预测"，2023年8月，<https://en.wikipedia.org/w/index.php?title=Linear_prediction&oldid=1169015573>。<br>

[Lossless-Compression]<br>
Hans, M. 和 R. W. Schafer，"数字音频的无损压缩"，IEEE信号处理杂志，第18卷第4期，第21-32页，DOI 10.1109/79.939834，2001年7月，<https://ieeexplore.ieee.org/document/939834>。<br>

[lossyWAV]<br>
Hydrogenaudio知识库，"lossyWAV"，2021年7月，<https://wiki.hydrogenaud.io/index.php?title=LossyWAV&oldid=32877>。<br>

[MLP]<br>
Gerzon, M. A., Craven, P. G., Stuart, J. R., Law, M. J., 和 R. J. Wilson，"MLP无损压缩系统"，音频工程协会会议：第17届国际高质量音频编码会议，1999年9月，<https://www.aes.org/e-lib/online/browse.cfm?elib=8082>。<br>

[MusicBrainz]<br>
MusicBrainz，"标签与变量"，MusicBrainz Picard v2.10文档，<https://picard-docs.musicbrainz.org/en/variables/variables.html>。<br>

[RFC4732]<br>
Handley, M. (编), Rescorla, E. (编), 和 IAB，"互联网拒绝服务考虑因素"，RFC 4732，DOI 10.17487/RFC4732，2006年12月，<https://www.rfc-editor.org/info/rfc4732>。<br>

[RFC5334]<br>
Goncalves, I., Pfeiffer, S., 和 C. Montgomery，"Ogg媒体类型"，RFC 5334，DOI 10.17487/RFC5334，2008年9月，<https://www.rfc-editor.org/info/rfc5334>。<br>

[RFC6716]<br>
Valin, JM., Vos, K., 和 T. Terriberry，"Opus音频编解码器定义"，RFC 6716，DOI 10.17487/RFC6716，2012年9月，<https://www.rfc-editor.org/info/rfc6716>。<br>

[RFC8126]<br>
Cotton, M., Leiba, B., 和 T. Narten，"RFC中IANA注意事项章节编写指南"，BCP 26，RFC 8126，DOI 10.17487/RFC8126，2017年6月，<https://www.rfc-editor.org/info/rfc8126>。<br>

[Rice]<br>
Rice, R. F. 和 J. R. Plaunt，"航天器电视数据的自适应变长编码"，IEEE通信技术汇刊，第19卷第6期，第889-897页，DOI 10.1109/TCOM.1971.1090789，1971年12月，<https://ieeexplore.ieee.org/document/1090789>。<br>

[Robinson-TR156]<br>
Robinson, T., "SHORTEN：简单无损/近无损波形压缩"，剑桥大学工程系技术报告CUED/F-INFENG/TR.156，1994年12月，<https://mi.eng.cam.ac.uk/reports/svr-ftp/auto-pdf/robinson_tr156.pdf>。<br>

[Shannon]<br>
Shannon, C. E., "噪声环境下的通信"，IRE会刊，第37卷第1期，第10-21页，DOI 10.1109/JRPROC.1949.232969，1949年1月，<https://ieeexplore.ieee.org/document/1697831>。<br>

[VarLengthCode]<br>
维基百科，"可变长度编码"，2024年4月，<https://en.wikipedia.org/w/index.php?title=Variable-length_code&oldid=1220260423>。<br>

[Vorbis]<br>
Xiph.Org，"Ogg Vorbis I格式规范：注释字段与头信息规范"，<https://xiph.org/vorbis/doc/v-comment.html>。

附录 A. 数值考量<br>
为了保持无损行为，编码和解码采样值时使用的所有算术必须使用整数数据类型完成，以消除引入与浮点算术相关的舍入误差的可能性。只要在使用找到的预测器（predictor）和Rice参数对音频采样进行编码的过程中仅使用整数运算，在分析时（例如寻找合适的预测器或Rice参数）使用浮点表示则无需担忧。<br>

此外，通过使用足够大的数据类型可以消除整数溢出的可能性。对涉及采样值的所有算术选择64位有符号数据类型将确保消除溢出的可能性，但通常选择较小的数据类型以提高性能，特别是在嵌入式设备中。本附录为FLAC文件编码和解码各步骤选择适当数据类型提供了指导原则。<br>

在本附录中，有符号数据类型均采用二进制补码表示。<br>

### A.1. 确定必要的数据类型大小<br>
要找到保证特定算术操作序列不会溢出的最小数据类型大小，应考虑能产生最大可能结果的数值组合。<br>

例如，若将两个16位有符号整数相加，当两个值均为16位有符号整数能表示的最大数值时，会产生最大可能结果。要存储该结果，需要至少17位的有符号整数数据类型。类似地，当添加4个这样的值时需要18位；添加8个时需要19位，依此类推。一般而言，当将多个数值相加时，所需位数会随着数值数量以2为底的对数向上取整后增加。因此，当添加18个存储为8位有符号整数的未知值时，我们需要至少13位的有符号整数数据类型来存储结果，因为18以2为底的对数向上取整后为5（$\log_2{18}$向上取整为5）。<br>

当两个数字相乘时，结果所需的位数等于第一个数字的位数加上第二个数字的位数。例如，若将16位有符号整数与另一个16位有符号整数相乘，结果需要至少32位才能存储而不溢出。通过实例说明：4位能存储的最大有符号值为-8。$(-8) \times (-8) = 64$，这需要至少8位（有符号）来存储。<br>

### A.2. 立体声去相关<br>
当使用立体声去相关时，边通道（side channel）将具有额外1位的位深度；参见第4.2节。<br>

这意味着虽然16位有符号整数具有足够的范围来存储位深度为16位的完全解码FLAC帧中的采样，但在撤销立体声去相关之前，对此类文件中的边子帧（side subframe）进行解码时，将需要至少17位的数据类型来存储解码后的子帧采样。<br>

大多数FLAC解码器将解码后的（子帧）采样存储为32位值，这对于位深最高至（含）31位的文件已足够。<br>


### A.3. 预测<br>
预测（用于编码时计算残差，或解码时与残差相加以计算采样值）通过乘法和累加先前采样值形成。为了消除整数溢出的可能性，应考虑先前采样值与预测器系数组合可能产生的最大值。<br>

要确定固定预测器子帧中计算残差采样（编码时）或音频采样值（解码时）所需的数据类型大小，需按照附录A.1和下方表格所述方式计算这些值的最大可能值。例如，若某帧编码16位音频并采用某种立体声去相关形式，当使用三阶固定预测器时，边通道的子帧编码将需要16+1+3位。<br>

| 阶数 | 残差计算公式                                                                 | 采样值求和次数 | 额外位数 |
|------|-----------------------------------------------------------------------------|----------------|----------|
| 0    | $a(n)$                                                                     | 1              | 0        |
| 1    | $a(n) - a(n-1)$                                                            | 2              | 1        |
| 2    | $a(n) - 2a(n-1) + a(n-2)$                                                  | 4              | 2        |
| 3    | $a(n) - 3a(n-1) + 3a(n-2) - a(n-3)$                                        | 8              | 3        |
| 4    | $a(n) - 4a(n-1) + 6a(n-2) - 4a(n-3) + a(n-4)$                              | 16             | 4        |

其中：<br>
- $n$ 表示被预测采样的编号<br>
- $a(n)$ 是被预测的采样<br>
- $a(n-1)$ 表示被预测采样前一个位置的采样，$a(n-2)$ 表示更前一个位置的采样，依此类推

对于采用线性预测器的子帧，计算会略微复杂。每个预测值是多个乘积项的总和。每个乘积项都是将采样值与预测器系数相乘得到。所需额外位数可通过将预测器系数精度（以位为单位）与音频采样的位深度相加，并加上预测器阶数以2为底的对数值向上取整来计算。<br>

例如，若源采样位深度为24，当前子帧编码边通道（参见第4.2节），预测器阶数为12，且预测器系数精度为15位，则所用有符号整数数据类型的最小要求位数为$(24 + 1) + 15 + \lceil \log_2{12} \rceil = 44$位。另一示例中，当边通道子帧位深度为16，预测器阶数为8，且预测器系数精度为12位时，所用有符号整数数据类型的最小要求位数为$(16 + 1) + 12 + \lceil \log_2{8} \rceil = 32$位。

### A.4. 残差<br>
如第9.2.7节所述，编码器必须确保残差采样可以用32位有符号二进制补码整数表示（排除最小负值）。如前一节所述，可以计算残差采样是否已隐式满足该条件，或是否需要额外检查。当残差符合理论31位有符号整数范围时即可实现隐式满足，因为这同时满足上述两个标准。若无法实现隐式满足，则必须单独计算并检查所有残差值。<br>

对于固定预测器的残差，其最大残差采样大小已在前一节计算。但对于线性预测器，预测值会通过右移若干位进行调整。残差所需位数等于前一节计算的位数减去预测右移位数，并额外增加1位以考虑编码时从当前采样中减去预测值的操作。<br>

取前一节的最后一个示例（预测需要32位），当右移10位时，残差采样所需数据类型大小为$32 - 10 + 1 = 23$位，这意味着无需执行前述检查。<br>

另一示例中，当使用固定预测器编码32位PCM时，必须检查所有预测器阶数。虽然零阶固定预测器可保证残差采样符合32位有符号整数范围，但可能产生32位有符号整数的最小可表示负值作为残差采样值。<br>

需注意在解码过程中，虽然残差采样值被限制在上述范围内，但预测值不受此限制。这意味着尽管残差采样的解码可完全在32位有符号整数中进行，解码器必须确保将每个残差采样与其对应预测值相加时使用足够宽度的有符号整数数据类型（与编码要求相同）。<br>

### A.5. Rice编码<br>
当对残差采样值进行折叠（即Z形编码）时，若先将每个残差采样的绝对值存入与前一阶段位数相同的无符号数据类型，再根据残差采样正负性进行双倍减一操作，则无需额外位数。然而，许多实现选择要求数据类型增加1位，以便Z形编码可通过单步操作完成（无需类型转换），而无需采用前句描述的多步流程。<br>

附录 B. 历史格式变更<br>
本信息性附录记录了FLAC格式多年来的变更历史。当遇到使用本附录所述变更前规范生成的FLAC文件时，这些信息可能具有参考价值。<br>

FLAC格式最初于2000年12月制定，其比特流格式在2001年7月FLAC 1.0（参考编码器/解码器）发布后即视为冻结。本附录仅考虑自首个稳定版本发布后的变更，不涉及FLAC流式子集定义（见第7节）的修改。<br>

### B.1. 块策略位的添加<br>
规范中最大的向后不兼容变更发布于2007年7月。在此变更前，可变块大小流未通过帧头中的标志位显式标记。解码器有两种方式检测可变块大小流：通过比较流信息元数据块中的最小和最大块大小（固定块大小流中二者相等）实现，或在解码器未收到流信息元数据块时（理论上不可能发生）通过检测流中块大小的变化实现。由于帧头中编码数值的含义取决于流是否采用可变块大小，这导致了问题：编码数值的含义无法可靠确定。为解决此问题，将一个保留位改为块策略位使用。另见第9.1节。<br>

伴随新标志位的添加，块大小位的含义（见第9.1.1节）也进行了细微调整。最初，块大小位模式0b0001-0b0101和0b1000-0b1111仅用于固定块大小流，而0b0110和0b0111可用于固定块大小流和可变块大小流。此变更后，这些限制被取消，模式0b0001-0b1111现可用于可变块大小流和固定块大小流。<br>

### B.2. 编码残差采样的限制<br>
在IETF CELLAR工作组标准化过程中，认为有必要对规范进行另一项变更。如第9.2.7节所述，现对残差采样施加了限制。在IETF标准化工作前，该限制未被明确规定。但据工作组所知，当时没有FLAC编码器会生成超出此限制的残差采样。这主要是因为编码24位PCM时几乎不可能遇到超出此限制的残差采样，且更高位深PCM的编码在当时任何已知编码器中尚未实现。实际上，当被触发生成此类残差采样时，这些FLAC编码器会产生损坏文件，且即使在处理人工构造素材时，非实验性编码器也不太可能产生此类情况。因此，此变更预计不会导致现有实现不符合规范。<br>

### B.3. 5位Rice参数的添加<br>
格式的重要新增内容是使用5位Rice参数的残差编码方法。在2007年7月发布此新增内容前，规范中仅定义了使用4位Rice参数的分区Rice编码。当编码24位PCM时，该方法提供的范围被证实过小，因此新增了与前者相同但使用5位Rice参数的第二残差编码方法。<br>

### B.4. LPC移位限制为非负值<br>
如第9.2.6节所述，预测器右移值采用二进制补码表示且必须为非负数。这是因为在C语言标准中，对数值进行负位移位的右移操作属于未定义行为。原本预期正数表示右移，负数表示左移。2007年FLAC参考编码器被修改为不再生成含负预测器右移的LPC子帧，因为实际使用此类子帧几乎无法带来任何优势，且当时已广泛使用的解码器无法处理此类子帧。<br>

## 附录 C. 互操作性考量

如附录 B 所述，FLAC 格式经历了一些变更与增补。此外，FLAC 格式某些功能的实现耗费了多年时间，这意味着早期的解码器实现无法针对包含这些功能的文件进行测试。最后，许多低质量的 FLAC 解码器仅实现了播放最常见 FLAC 文件所需的最低限度功能。<br>
本附录为旨在创建高兼容性文件的编码器实现提供了一些考量。由于该主题可能在本文件发布后发生变化，请参阅 [FLAC-wiki-interoperability] 以获取最新信息。

### C.1. 可流化子集之外的功能

如第 7 节所述，FLAC 将其部分能力指定为 ​**FLAC 可流化子集**。某些解码器可能选择仅解码符合可流化子集所施加限制的 FLAC 文件。因此，在创建 FLAC 文件时遵循 FLAC 可流化子集的限制，可实现与解码器的最大兼容性。

### C.2. 可变块大小

由于通常难以找到实现最大压缩的最佳块大小排列，大多数编码器选择创建具有**固定块大小**的文件。因此，许多解码器实现在处理可变块大小流时极少被使用，这可能暴露出错误或揭示实现完全无法解码此类流。此外，如附录 B.1 所述，可变块大小流的编码方式发生了一些变更。因此，当使用**固定块大小流**创建 FLAC 文件时，可实现与解码器的最大兼容性。

### C.3. 5位Rice参数

如附录 B.3 所述，采用 ​**5位Rice参数** 的编码方法是在 FLAC 格式首次引入多年后才新增的，因此某些早期解码器可能无法解码包含此类 Rice 参数的文件。引入该功能的主要目的是改善 24 位 PCM 音频的压缩，而 16 位 PCM 音频的压缩极少受益于使用 5 位 Rice 参数。因此，当创建包含 16 位或更低位深音频的 FLAC 文件时，​**完全不使用 5位Rice参数** 可实现与解码器的最大兼容性。

### C.4. Rice 转义码

经实践证明，使用**转义 Rice 分区**仅能带来极小的压缩率提升，因此这类分区极少被使用。由于许多编码器默认不使用此类分区，或完全无法生成它们，很可能许多解码器实现无法正确解码这些分区。因此，当创建 FLAC 文件时**完全不使用转义 Rice 分区**，可实现与解码器的最大兼容性。

### C.5. 非常见块大小

出于未知原因，某些解码器选择仅支持对音频流中除最后一个块外的所有块使用常见块大小。因此，当创建 FLAC 文件时，对音频流中除最后一个块外的所有块使用第9.1.1节列出的**常见块大小**，可实现与解码器的最大兼容性。

### C.6. 非常见位深

大多数音频采用整数字节位深（例如 8、16 或 24 位）存储。但存在使用不同位深的音频，例如：
- DSD（1 位）音频<br>
- DVD-Audio 中的 20 位或 22 位音频<br>
- ADPCM 编码的 4 位音频<br>
- Nintendo 64 游戏机的 5 位音频<br>
由于某些解码器可能无法正确处理非整数字节位深的音频，建议将此类音频转换为整数字节位深（例如将 20 位音频补零为 24 位），以提高解码器兼容性。

### C.6. 非常见位深

大多数音频采用整数字节位深（例如 8、16 或 24 位）存储。但存在使用不同位深的音频，例如：
- DVD-Audio 支持存储 20 位 PCM 音频<br>
- DAT 和 DV 可存储 12 位 PCM 音频<br>
- NICAM-728 以 14 位采样，随后通过压扩处理缩减为 10 位<br>
- 8 位 µ-law 编码可无损转换为 14 位（线性）PCM<br>
- 8 位 A-law 编码可无损转换为 13 位（线性）PCM<br>
由于某些解码器可能无法正确处理非整数字节位深的音频，建议将此类音频转换为整数字节位深（例如将 20 位音频补零为 24 位），以提高解码器兼容性。

FLAC格式可以直接包含这些比特深度，但由于它们并不常见，某些解码器可能无法正确处理生成的文件。可以通过向每个样本填充零位至整数字节的比特深度，将这些格式存储在FLAC文件中，而无需牺牲压缩率。<br>FLAC格式可以高效压缩这些填充的冗余位。详见第9.2.2节。
因此，当通过向此类音频样本填充零位至下一个整数字节的比特深度来创建FLAC文件时，可实现与解码器的最大兼容性。
若原始信号本身已包含填充位，则在未知原始比特深度的情况下无法无损还原该操作。为避免歧义，需要存储原始比特深度，例如存储在Vorbis注释字段中或通过保留原始文件的文件头。具体实现方法由开发者自行选择。
除"非整数字节"比特深度的音频外，部分解码器实现仅接受编码16比特PCM音频的FLAC文件。许多实现支持最高24比特的深度，但不支持更高比特深度。最新兼容性信息请参考[FLAC-wiki-interoperability]。

### C.7. 多声道音频与非标准采样率
多数FLAC音频播放器无法渲染多声道音频或采用非标准采样率的音频。虽然这不属于FLAC格式特有的问题，但在需要最大程度兼容解码器时仍需注意。与前述兼容性考量不同，此类兼容性问题无法通过牺牲FLAC的无损特性来改善。

根据非穷尽性调查，不可忽视数量的播放器（特别是硬件播放器）不支持3个及以上声道或非常用采样率的音频，详见第9.1.2节。

对于支持多声道音频渲染的播放器，许多不会解析和使用WAVEFORMATEXTENSIBLE_CHANNEL_MASK标签（见第8.6.2节）。这同样属于兼容性考量，因为改善兼容性需要以牺牲FLAC的无损特性为代价。

### C.8. 流内音频属性变更
每个FLAC帧头部独立于流信息元数据块和其他帧头部存储音频采样率、每样本比特数和声道数。此设计初衷是允许FLAC文件的多播，但也支持在流内变更这些属性。然而多数FLAC解码器无法处理此类变更，因为其他格式鲜少能容纳这种流，且播放过程中变更播放属性通常会导致播放中断。如第9章所述，使用此FLAC特性还会引发诸多实际问题。

即便按照第9章建议，将属性变化的音频流封装在支持此类变更的容器中存储，多数解码器仍无法正确解码此类流。因此，当FLAC文件采用单一音频属性集创建（即流信息元数据块编码的属性（见第8.2节）与所有帧头部编码的属性（见第9.1节）完全一致）时，可实现与解码器的最大兼容性。可通过在音频属性变更点将输入流分割为独立流或文件的方式实现该要求。

## 附录 D. 示例
本资料性附录包含分步解码的FLAC文件简短示例。相较于正式规范，这些示例提供了更生动的理解FLAC格式的方式。对示例的讲解假定读者至少粗略阅读过规范，并会参考规范来理解所用术语。这些示例主要聚焦于若干元数据块的布局、子帧类型，以及某些特性(如浪费位和立体声去相关)对此布局的影响。

示例文件由不同FLAC编码器生成。它们以十六进制或二进制格式呈现，后附表格和文本，通过起始比特位置指出这些表示中的各种特征。每个起始位置(表中简写为"start")由十六进制字节位置和该字节内的起始比特组成，以加号分隔。计数从零开始。例如，起始于第17字节第3位的特征记为起始于0x10+2。本附录分析的示例文件可在[FLAC规范github仓库]找到。

本附录所有数据均经过严格验证。但由于本附录属于资料性内容，若其中信息与正式规范存在冲突，以规范描述为准。

### D.1 解码示例1
这个极简FLAC示例文件编码了包含两个通道的PCM音频，每个通道各含一个样本。本示例重点展示FLAC文件的核心组成部分。

#### D.1.1 示例文件1的十六进制表示

```
          0 1  2 3  4 5  6 7  8 9  A B 
00000000: 664c 6143 8000 0022 1000 1000  fLaC..."....
0000000c: 0000 0f00 000f 0ac4 42f0 0000  ........B...
00000018: 0001 3e84 b418 07dc 6903 0758  ..>.....i..X
00000024: 6a3d ad1a 2e0f fff8 6918 0000  j=......i...
00000030: bf03 58fd 0312 8baa 9a         ..X......
```
#### D.1.1 示例文件1的二进制表示
```
00000000: 01100110 01001100 01100001 01000011  fLaC
00000004: 10000000 00000000 00000000 00100010  ..."
00000008: 00010000 00000000 00010000 00000000  ....
0000000c: 00000000 00000000 00001111 00000000  ....
00000010: 00000000 00001111 00001010 11000100  ....
00000014: 01000010 11110000 00000000 00000000  B...
00000018: 00000000 00000001 00111110 10000100  ..>.
0000001c: 10110100 00011000 00000111 11011100  ....
00000020: 01101001 00000011 00000111 01011000  i..X
00000024: 01101010 00111101 10101101 00011010  j=..
00000028: 00101110 00001111 11111111 11111000  ....
0000002c: 01101001 00011000 00000000 00000000  i...
00000030: 10111111 00000011 01011000 11111101  ..X.
00000034: 00000011 00010010 10001011 10101010  ....
00000038: 10011010
```


#### D.1.3. 签名与流信息
文件的前4字节包含fLaC文件签名。紧随其后的是元数据块。签名和第一个元数据块头的解析如下表所示：

|起始位|长度|内容|描述|
|-----|----|----|---|
|0x00+0|4 字节|0x664C6143|fLaC|
|0x04+0|1 比特|0b1|最后一个元数据块|
|0x04+1|7 比特|0b0000000|Streaminfo元数据块|
|0x05+0|3 字节|0x000022|34字节长度|

由于头信息表明这是最后一个元数据块，第一个音频帧的位置可计算为元数据块头后的首字节位置+块长度，即8+34=42或0x2a。因此0x2a处确实包含固定块大小流的帧同步码——0xfff8。

流信息元数据块内容解析如下表：

|起始位|长度|内容|描述|
|-----|----|----|---|
|0x08+0|2 字节|0x1000|最小块大小4096|
|0x0a+0|2 字节|0x1000|最大块大小4096|
|0x0c+0|3 字节|0x00000f|最小帧大小15字节|
|0x0f+0|3 字节|0x00000f|最大帧大小15字节|
|0x12+0|20 比特|0x0ac4, 0b0100|采样率44100赫兹|
|0x14+4|3 比特|0b001|2声道|
|0x14+7|5 比特|0b01111|采样位深16|
|0x15+4|36 比特|0b0000, 0x00000001|总样本数1|
|0x1a|16 字节|(...)|MD5校验和|

最小和最大块大小均为4096。这显然是编码器计划使用的块大小，但由于只提供了1个声道间样本，文件中实际上并不存在包含4096样本的帧。

注意：所有涉及样本数量的参数（块大小、总样本数、采样率）均指声道间样本。

MD5校验和（起始于0x1a）为0x3e84 b418 07dc 6903 0758 6a3d ad1a 2e0f。该值将在解码样本后进行验证。

### D.1.4. 音频帧
帧头起始于位置0x2a，解析如下表：

|起始位|长度|内容|描述|
|---|---|---|---|
|0x2a+0|15 比特|0xff, 0b1111100|帧同步码|
|0x2b+7|1 比特|0b0|阻塞策略|
|0x2c+0|4 比特|0b0110|下方定义的8位块大小|
|0x2c+4|4 比特|0b1001|44.1 kHz采样率|
|0x2d+0|4 比特|0b0001|立体声，无去相关|
|0x2d+4|3 比特|0b100|16位比特深度|
|0x2d+7|1 比特|0b0|强制0比特|
|0x2e+0|1 字节|0x00|帧编号0|
|0x2f+0|1 字节|0x00|块大小1|
|0x30+0|1 字节|0xbf|帧头CRC|

由于是固定块大小流，0x2e处的数值包含帧编号。因该值小于128，仅使用1字节编码。

在字节0x31处，第一个子帧开始，解析如下表：

|起始位|长度|内容|描述|
|---|---|---|---|
|0x31+0|1 比特|0b0|强制0比特|
|0x31+1|6 比特|0b000001|原样子帧|
|0x31+7|1 比特|0b1|使用废弃比特|
|0x32+0|2 比特|0b01|使用2个废弃比特|
|0x32+2|14 比特|0b011000, 0xfd|14位未编码样本|

因该子帧的废弃比特标志为1，后续为一元编码数值。从0x32开始的0b01表示一元编码数值1，即该子帧使用2个废弃比特。

作为原样子帧，仅包含未编码样本值。块大小为1时仅含单个样本。音频比特深度为16位，但因子帧头表明使用2个废弃比特，实际存储14位。无立体声去相关时，侧声道比特深度扩展不适用。接下来的14位（起始于0x32+2）以大端序有符号补码形式存储未编码样本，值为0b011000 11111101（即6397）。需左移2位补偿废弃比特，得到0b011000 11111101 00（即25588）。

第二个子帧起始于0x34，解析如下表：

|起始位|长度|内容|描述|
|---|---|---|---|
|0x34+0|1 比特|0b0|强制0比特|
|0x34+1|6 比特|0b000001|原样子帧|
|0x34+7|1 比特|0b1|使用废弃比特|
|0x35+0|4 比特|0b0001|使用4个废弃比特|
|0x35+4|12 比特|0b0010, 0x8b|12位未编码样本|

废弃比特标志同样为1，但后续一元编码数值为4位，表明使用4个废弃比特。样本存储为12位，值为0b0010 10001011（即651）。左移4位后得0b0010 10001011 0000（即10416）。

若存在立体声去相关，此处需进行逆处理。

因最后一个子帧以字节对齐结束，无填充比特。后续2字节（起始于0x38）包含帧CRC。作为文件中唯一帧，文件以CRC结束。

验证MD5校验和时，需将样本按声道间交错、小端序、有符号补码、字节对齐排列。第一样本25588对应0xf463，第二样本10416对应0xb028。以0xf463b028为输入计算MD5校验和，结果与文件头一致，表明解码无损。

### D.2. 解码示例2
此FLAC文件比第一个示例更大，但仍包含极少音频数据。本示例重点在于解码具有固定预测器和编码残差的子帧，同时包含极短的寻址表、Vorbis注释元数据块和填充元数据块。

#### D.2.1. 示例文件2的十六进制表示

```
00000000: 664c 6143 0000 0022 0010 0010  fLaC..."....
0000000c: 0000 1700 0044 0ac4 42f0 0000  .....D..B...
00000018: 0013 d5b0 5649 75e9 8b8d 8b93  ....VIu.....
00000024: 0422 757b 8103 0300 0012 0000  ."u{........
00000030: 0000 0000 0000 0000 0000 0000  ............
0000003c: 0000 0010 0400 003a 2000 0000  .......: ...
00000048: 7265 6665 7265 6e63 6520 6c69  reference li
00000054: 6246 4c41 4320 312e 332e 3320  bFLAC 1.3.3
00000060: 3230 3139 3038 3034 0100 0000  20190804....
0000006c: 0e00 0000 5449 544c 453d d7a9  ....TITLE=..
00000078: d79c d795 d79d 8100 0006 0000  ............
00000084: 0000 0000 fff8 6998 000f 9912  ......i.....
00000090: 0867 0162 3d14 4299 8f5d f70d  .g.b=.B..]..
0000009c: 6fe0 0c17 caeb 2100 0ee7 a77a  o.....!....z
000000a8: 24a1 590c 1217 b603 097b 784f  $.Y......{xO
000000b4: aa9a 33d2 85e0 70ad 5b1b 4851  ..3...p.[.HQ
000000c0: b401 0d99 d2cd 1a68 f1e6 b810  .......h....
000000cc: fff8 6918 0102 a402 c382 c40b  ..i.........
000000d8: c14a 03ee 48dd 03b6 7c13 30    .J..H...|.0
```

#### D.2.1. 示例文件2的二进制表示（只有音频帧）

```
00000088: 11111111 11111000 01101001 10011000  ..i.
0000008c: 00000000 00001111 10011001 00010010  ....
00000090: 00001000 01100111 00000001 01100010  .g.b
00000094: 00111101 00010100 01000010 10011001  =.B.
00000098: 10001111 01011101 11110111 00001101  .]..
0000009c: 01101111 11100000 00001100 00010111  o...
000000a0: 11001010 11101011 00100001 00000000  ..!.
000000a4: 00001110 11100111 10100111 01111010  ...z
000000a8: 00100100 10100001 01011001 00001100  $.Y.
000000ac: 00010010 00010111 10110110 00000011  ....
000000b0: 00001001 01111011 01111000 01001111  .{xO
000000b4: 10101010 10011010 00110011 11010010  ..3.
000000b8: 10000101 11100000 01110000 10101101  ..p.
000000bc: 01011011 00011011 01001000 01010001  [.HQ
000000c0: 10110100 00000001 00001101 10011001  ....
000000c4: 11010010 11001101 00011010 01101000  ...h
000000c8: 11110001 11100110 10111000 00010000  ....
000000cc: 11111111 11111000 01101001 00011000  ..i.
000000d0: 00000001 00000010 10100100 00000010  ....
000000d4: 11000011 10000010 11000100 00001011  ....
000000d8: 11000001 01001010 00000011 11101110  .J..
000000dc: 01001000 11011101 00000011 10110110  H...
000000e0: 01111100 00010011 00110000           |.0
```

### D.2.3. Streaminfo 元数据块
流信息元数据块的大部分内容（包括其头部）与示例1相同，因此下表中仅列出不同的部分。

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x04+0|1 bit|0b0|不是最后一个元数据块|
|0x08+0|2 bytes|0x0010|最小块大小16|
|0x0a+0|2 bytes|0x0010|最大块大小16|
|0x0c+0|3 bytes|0x000017|最小帧大小23字节|
|0x0f+0|3 bytes|0x000044|最大帧大小68字节|
|0x15+4|36 bits|0b0000, 0x00000013|总样本数19|
|0x1a|16 bytes|(...)|MD5校验和|

此次最小和最大块大小在文件中体现为：存在一个16样本的块，最后一个块（含3样本）不计入最小块大小。MD5校验和为 `0xd5b0 5649 75e9 8b8d 8b93 0422 757b 8103`，将在本示例末尾验证。

<br>

### D.2.4. 搜索表
搜索表元数据块仅包含一个条目。此处它指向第一帧，虽不实用但足以满足示例需求。其分解如下表：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x2a+0|1 bit|0b0|不是最后一个元数据块|
|0x2a+1|7 bits|0b0000011|搜索表元数据块|
|0x2b+0|3 bytes|0x000012|长度18字节|
|0x2e+0|8 bytes|0x0000000000000000|指向样本0的搜索点|
|0x36+0|8 bytes|0x0000000000000000|指向偏移0的搜索点|
|0x3e+0|2 bytes|0x0010|指向块大小16的搜索点|

<br>

### D.2.5. Vorbis 注释
Vorbis注释元数据块包含供应商字符串和单个注释，分解如下表：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x40+0|1 bit|0b0|不是最后一个元数据块|
|0x40+1|7 bits|0b0000100|Vorbis注释元数据块|
|0x41+0|3 bytes|0x00003a|长度58字节|
|0x44+0|4 bytes|0x20000000|供应商字符串长度32字节|
|0x48+0|32 bytes|(...)|供应商字符串|
|0x68+0|4 bytes|0x01000000|字段数量1|
|0x6c+0|4 bytes|0x0e000000|字段长度14字节|
|0x70+0|14 bytes|(...)|字段内容|

供应商字符串为 `reference libFLAC 1.3.3 20190804`，唯一字段的内容为：

TITLE=שלום


按阅读方向，组成该字段内容的字符序列为：  
"ש"（希伯来字母Shin，U+05E9）、  
"ל"（希伯来字母Lamed，U+05DC）、  
"ו"（希伯来字母Vav，U+05D5）、  
"ם"（希伯来字母Final Mem，U+05DD）。  

Vorbis注释字段为14字节但仅包含10字符，因其包含4个2字节字符。

### D.2.6. 填充
最后一个元数据块是（极短的）填充块。

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x7e+0|1 bit|0b1|最后一个元数据块|
|0x7e+1|7 bits|0b0000001|填充元数据块|
|0x7f+0|3 bytes|0x000006|长度6字节|
|0x82+0|6 bytes|0x000000000000|填充字节|

<br>

### D.2.7. 第一音频帧
帧头起始于0x88位置，分解如下表：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x88+0|15 bits|0xff, 0b1111100|帧同步|
|0x89+7|1 bit|0b0|分块策略|
|0x8a+0|4 bits|0b0110|下方定义的8位块大小|
|0x8a+4|4 bits|0b1001|采样率44.1 kHz|
|0x8b+0|4 bits|0b1001|左-右立体声|
|0x8b+4|3 bits|0b100|位深度16位|
|0x8b+7|1 bit|0b0|强制0位|
|0x8c+0|1 byte|0x00|帧编号0|
|0x8d+0|1 byte|0x0f|块大小16|
|0x8e+0|1 byte|0x99|帧头CRC|

第一子帧起始于字节0x8f（编码残差部分未在下表列出）。由于此子帧编码侧声道，位深度从16位增至17位，此特性在未编码预热样本中表现最明显。

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x8f+0|1 bit|0b0|强制0位|
|0x8f+1|6 bits|0b001001|固定子帧，一阶|
|0x8f+7|1 bit|0b0|未使用浪费位|
|0x90+0|17 bits|0x0867, 0b0|未编码预热样本|

编码残差分解如下表所示。所有商数采用一元编码，余数均以Rice参数指定的位数进行未编码存储。

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x92+1|2 bits|0b00|4位参数的Rice编码|
|0x92+3|4 bits|0b0000|分区阶数0|
|0x92+7|4 bits|0b1011|Rice参数11|
|0x93+3|4 bits|0b0001|商数3|
|0x93+7|11 bits|0b00011110100|余数244|
|0x95+2|2 bits|0b01|商数1|
|0x95+4|11 bits|0b01000100001|余数545|
|0x96+7|2 bits|0b01|商数1|
|0x97+1|11 bits|0b00110011000|余数408|
|0x98+4|1 bit|0b1|商数0|
|0x98+5|11 bits|0b11101011101|余数1885|
|0x9a+0|1 bit|0b1|商数0|
|0x9a+1|11 bits|0b11101110000|余数1904|
|0x9b+4|1 bit|0b1|商数0|
|0x9b+5|11 bits|0b10101101111|余数1391|
|0x9d+0|1 bit|0b1|商数0|
|0x9d+1|11 bits|0b11000000000|余数1536|
|0x9e+4|1 bit|0b1|商数0|
|0x9e+5|11 bits|0b10000010111|余数1047|
|0xa0+0|1 bit|0b1|商数0|
|0xa0+1|11 bits|0b10010101110|余数1198|
|0xa1+4|1 bit|0b1|商数0|
|0xa1+5|11 bits|0b01100100001|余数801|
|0xa3+0|13 bits|0b0000000000001|商数12|
|0xa4+5|11 bits|0b11011100111|余数1767|
|0xa6+0|1 bit|0b1|商数0|
|0xa6+1|11 bits|0b01001110111|余数631|
|0xa7+4|1 bit|0b1|商数0|
|0xa7+5|11 bits|0b01000100100|余数548|
|0xa9+0|1 bit|0b1|商数0|
|0xa9+1|11 bits|0b01000010101|余数533|
|0xaa+4|1 bit|0b1|商数0|
|0xaa+5|11 bits|0b00100001100|余数268|

此时解码器应已完成编码残差的解码，共接收16个样本：1个预热样本和15个残差样本。每个残差样本可通过商数、余数及反锯齿编码计算得出。例如，第一个锯齿编码残差样本的值为 $3 \times 2^{11} + 244 = 6388$。由于该值为偶数，通过除以2还原反锯齿编码，得到残差样本值3194。下表展示所有残差样本的计算过程：

| 商数 | 余数 | 锯齿编码值 | 残差样本值  |
|------|------|------------|------------|
| 3    | 244  | 6388       | 3194       |
| 1    | 545  | 2593       | -1297      |
| 1    | 408  | 2456       | 1228       |
| 0    | 1885 | 1885       | -943       |
| 0    | 1904 | 1904       | 952        |
| 0    | 1391 | 1391       | -696       |
| 0    | 1536 | 1536       | 768        |
| 0    | 1047 | 1047       | -524       |
| 0    | 1198 | 1198       | 599        |
| 0    | 801  | 801        | -401       |
| 12   | 1767 | 26343      | -13172     |
| 0    | 631  | 631        | -316       |
| 0    | 548  | 548        | 274        |
| 0    | 533  | 533        | -267       |
| 0    | 268  | 268        | 134        |


在此案例中，使用Rice编码比未编码存储数值更高效。Rice编码（不含分区阶数和参数）的总长度为199比特。若采用未编码存储，最大残差值（-13172）需要15比特存储空间，因此15个样本以15比特存储将产生225比特的序列。

<br>

下一步是通过预测器和残差恢复样本值。由于此子帧使用一阶固定预测器，残差值将与前一个样本值相加：

| 残差      | 样本值      |
|----------|------------|
|（预热样本）| 4302       |
| 3194     | 7496       |
| -1297    | 6199       |
| 1228     | 7427       |
| -943     | 6484       |
| 952      | 7436       |
| -696     | 6740       |
| 768      | 7508       |
| -524     | 6984       |
| 599      | 7583       |
| -401     | 7182       |
| -13172   | -5990      |
| -316     | -6306      |
| 274      | -6032      |
| -267     | -6299      |
| 134      | -6165      |

至此，第一个子帧的解码已完成。第二个子帧的解码过程与此高度相似（同样使用一阶固定预测器），具体过程留作读者练习，结果见下表。下一步是撤销立体声去相关处理，如下表所示。由于立体声去相关方式为"侧-右"模式，右声道样本直接来自第二个子帧，而左声道样本通过两个子帧对应样本值相加获得。

| 子帧1  | 子帧2  | 左声道 | 右声道 |
|--------|--------|--------|--------|
| 4302   | 6070   | 10372  | 6070   |
| 7496   | 10545  | 18041  | 10545  |
| 6199   | 8743   | 14942  | 8743   |
| 7427   | 10449  | 17876  | 10449  |
| 6484   | 9143   | 15627  | 9143   |
| 7436   | 10463  | 17899  | 10463  |
| 6740   | 9502   | 16242  | 9502   |
| 7508   | 10569  | 18077  | 10569  |
| 6984   | 9840   | 16824  | 9840   |
| 7583   | 10680  | 18263  | 10680  |
| 7182   | 10113  | 17295  | 10113  |
| -5990  | -8428  | -14418 | -8428  |
| -6306  | -8895  | -15201 | -8895  |
| -6032  | -8476  | -14508 | -8476  |
| -6299  | -8896  | -15195 | -8896  |
| -6165  | -8653  | -14818 | -8653  |

由于第二个子帧结尾已字节对齐，无需填充比特。最终，帧的最后2个字节包含帧CRC校验码。

### D.2.8. 第二音频帧
第二音频帧与第一个示例中解码的帧结构相似，但此次包含3个样本（而非1个）。

帧头起始于0xcc位置，分解如下表：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0xcc+0|15 bits|0xff, 0b1111100|帧同步|
|0xcd+7|1 bit|0b0|分块策略|
|0xce+0|4 bits|0b0110|下方定义的8位块大小|
|0xce+4|4 bits|0b1001|采样率44.1 kHz|
|0xcf+0|4 bits|0b0001|立体声（无去相关）|
|0xcf+4|3 bits|0b100|位深度16位|
|0xcf+7|1 bit|0b0|强制0位|
|0xd0+0|1 byte|0x01|帧编号1|
|0xd1+0|1 byte|0x02|块大小3|
|0xd2+0|1 byte|0xa4|帧头CRC|

第一子帧起始于0xd3+0，分解如下表：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0xd3+0|1 bit|0b0|强制0位|
|0xd3+1|6 bits|0b000001|原样子帧|
|0xd3+7|1 bit|0b0|未使用浪费位|
|0xd4+0|16 bits|0xc382|16位未编码样本|
|0xd6+0|16 bits|0xc40b|16位未编码样本|
|0xd8+0|16 bits|0xc14a|16位未编码样本|

第二子帧起始于0xda+0，分解如下表：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0xda+0|1 bit|0b0|强制0位|
|0xda+1|6 bits|0b000001|原样子帧|
|0xda+7|1 bit|0b1|使用浪费位|
|0xdb+0|1 bit|0b1|使用1个浪费位|
|0xdb+1|15 bits|0b110111001001000|15位未编码样本|
|0xdd+0|15 bits|0b110111010000001|15位未编码样本|
|0xde+7|15 bits|0b110110110011111|15位未编码样本|

由于此子帧使用浪费位，15位未编码样本需左移1位。例如，样本1存储为-4536，左移1位后变为-9072。

因最后一个子帧未字节对齐，在2字节的帧CRC（位于0xe1+0）前需添加2个填充位。

<br>

### D.2.9. MD5校验和验证
文件内所有样本已解码完成，现可验证MD5校验和。所有样本值需以小端序有符号格式交叉存储，结果按每组12样本（即6个跨声道样本）分行展示：
```
0x8428 B617 7946 3129 5E3A 2722 D445 D128 0B3D B723 EB45 DF28
0x723f 1E25 9D46 4929 B841 7026 5747 B829 8F43 8127 AEC7 14DF
0x9FC4 41DD 54C7 E4DE A5C4 40DD 1EC6 33DE 82C3 90DC 0BC4 02DD
0x4AC1 3EDB
```

此数据的MD5校验和与流信息元数据块中的校验和完全一致。

## D.3. 解码示例3
本示例同样是一个极短的FLAC文件，重点在于解码包含线性预测器和多分区编码残差的子帧。

<br>

### D.3.1. 示例文件3的十六进制表示

```
00000000: 664c 6143 8000 0022 1000 1000  fLaC..."....
0000000c: 0000 1f00 001f 07d0 0070 0000  .........p..
00000018: 0018 f8f9 e396 f5cb cfc6 dc80  ............
00000024: 7f99 7790 6b32 fff8 6802 0017  ..w.k2..h...
00000030: e944 004f 6f31 3d10 47d2 27cb  .D.Oo1=.G.'.
0000003c: 6d09 0831 452b dc28 2222 8057  m..1E+.("".W
00000048: a3                             .
```
### D.3.1. 示例文件3的二进制表示（只有音频帧）
```
0000002a: 11111111 11111000 01101000 00000010  ..h.
0000002e: 00000000 00010111 11101001 01000100  ...D
00000032: 00000000 01001111 01101111 00110001  .Oo1
00000036: 00111101 00010000 01000111 11010010  =.G.
0000003a: 00100111 11001011 01101101 00001001  '.m.
0000003e: 00001000 00110001 01000101 00101011  .1E+
00000042: 11011100 00101000 00100010 00100010  .(""
00000046: 10000000 01010111 10100011           .W.
```

### D.3.3. Streaminfo 元数据块
流信息元数据块的大部分内容（包括其头部）与示例1相同，因此下表中仅列出差异部分。

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x0c+0|3 bytes|0x00001f|最小帧大小31字节|
|0x0f+0|3 bytes|0x00001f|最大帧大小31字节|
|0x12+0|20 bits|0x07d0, 0x0000|采样率32000赫兹|
|0x14+4|3 bits|0b000|1声道|
|0x14+7|5 bits|0b00111|采样位深度8位|
|0x15+4|36 bits|0b0000, 0x00000018|总样本数24|
|0x1a|16 bytes|(...)|MD5校验和|

### D.3.4. 音频帧
帧头起始于0x2a位置，分解如下表：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x2a+0|15 bits|0xff, 0b1111100|帧同步|
|0x2b+7|1 bit|0b0|分块策略|
|0x2c+0|4 bits|0b0110|下方定义的8位块大小|
|0x2c+4|4 bits|0b1000|采样率32 kHz|
|0x2d+0|4 bits|0b0000|单声道音频（1声道）|
|0x2d+4|3 bits|0b001|位深度8位|
|0x2d+7|1 bit|0b0|强制0位|
|0x2e+0|1 byte|0x00|帧编号0|
|0x2f+0|1 byte|0x17|块大小24|
|0x30+0|1 byte|0xe9|帧头CRC|

唯一子帧起始于字节0x31（编码残差部分未在下表列出），分解如下表：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x31+0|1 bit|0b0|强制0位|
|0x31+1|6 bits|0b100010|线性预测子帧，三阶|
|0x31+7|1 bit|0b0|未使用浪费位|
|0x32+0|8 bits|0x00|未编码预热样本0|
|0x33+0|8 bits|0x4f|未编码预热样本79|
|0x34+0|8 bits|0x6f|未编码预热样本111|
|0x35+0|4 bits|0b0011|系数精度4位|
|0x35+4|5 bits|0b00010|预测右移2|
|0x36+1|4 bits|0b0111|预测器系数7|
|0x36+5|4 bits|0b1010|预测器系数-6|
|0x37+1|4 bits|0b0010|预测器系数2|


### D.3.4. 编码残差与解码过程
数据流继续包含编码残差，分解如下表（第三、四分区留作读者练习）：

|起始位址|长度|内容|描述|
|---|---|---|---|
|0x37+5|2 bits|0b00|Rice编码残差，4位参数|
|0x37+7|4 bits|0b0010|分区阶数2|
|0x38+3|4 bits|0b0011|Rice参数3|
|0x38+7|1 bit|0b1|商数0|
|0x39+0|3 bits|0b110|余数6|
|0x39+3|1 bit|0b1|商数0|
|0x39+4|3 bits|0b001|余数1|
|0x39+7|4 bits|0b0001|商数3|
|0x3a+3|3 bits|0b001|余数1|
|0x3a+6|4 bits|0b1111|无Rice参数（转义码）|
|0x3b+2|5 bits|0b00101|5位编码的分区|
|0x3b+7|5 bits|0b10110|残差-10|
|0x3c+4|5 bits|0b11010|残差-6|
|0x3d+1|5 bits|0b00010|残差2|
|0x3d+6|5 bits|0b01000|残差8|
|0x3e+3|5 bits|0b01000|残差8|
|0x3f+0|5 bits|0b00110|残差6|
|0x3f+5|4 bits|0b0010|Rice参数2|
|0x40+1|22 bits|(...)|残差分区3|
|0x42+7|4 bits|0b0001|Rice参数1|
|0x43+3|23 bits|(...)|残差分区4|

帧结尾包含6个填充位和2字节的帧CRC。

<br>

### 样本计算过程
需通过21次预测计算与残差叠加完成解码。由于预测计算依赖前序样本，此过程必须顺序执行。下表展示典型样本（第4行）的计算示例：

预测器未移位值：  
$7 \times 111 - 6 \times 79 + 2 \times 0 = 303$  
右移2位后：  
$303 \gg 2 = 75$  
叠加残差：  
$75 + 3 = 78$

| 残差 | 未移位预测值 | 移位后预测值 | 样本值 |
|------|-------------|-------------|--------|
| (预热) | N/A         | N/A         | 0      |
| (预热) | N/A         | N/A         | 79     |
| (预热) | N/A         | N/A         | 111    |
| 3    | 303         | 75          | 78     |
| -1   | 38          | 9           | 8      |
| -13  | -190        | -48         | -61    |
| -10  | -319        | -80         | -90    |
| -6   | -248        | -62         | -68    |
| 2    | -58         | -15         | -13    |
| 8    | 137         | 34          | 42     |
| 8    | 236         | 59          | 67     |
| 6    | 191         | 47          | 53     |
| 0    | 53          | 13          | 13     |
| -3   | -93         | -24         | -27    |
| -5   | -161        | -41         | -46    |
| -4   | -134        | -34         | -38    |
| -1   | -44         | -11         | -12    |
| 1    | 52          | 13          | 14     |
| 1    | 94          | 23          | 24     |
| 4    | 60          | 15          | 19     |
| 2    | 17          | 4           | 6      |
| 2    | -24         | -6          | -4     |
| 2    | -26         | -7          | -5     |
| 0    | 1           | 0           | 0      |

<br>

### MD5校验和输入
最终样本序列的十六进制表示为：
0x004F 6F4E 08C3 A6BC F32A 4335 0DE5 D2DA F40E 1813 06FC FB00

该序列的MD5校验和与流信息元数据块中的值完全一致。

## 致谢
FLAC 的发展深受音频压缩领域众多先驱者的启发，特别感谢以下贡献者：

- ​**Tony Robinson**：其开发的Shorten编解码器及相关论文（参见[Robinson-TR156]）为FLAC的基础方法提供了重要参考。FLAC在Shorten的基础上对固定预测器、线性预测系数（LPC）量化及Rice编码进行了改进与扩展。

- ​**Solomon W. Golomb 与 Robert F. Rice**：FLAC的熵编码器采用了他们提出的通用编码方案（参见[Rice]）。

- ​**Norman Levinson 与 James Durbin**：FLAC参考编码器使用由他们开发并优化的算法，通过自相关系数计算LPC系数（参见[Durbin]）。

- ​**Claude Shannon**：信息论基础研究者（参见[Shannon]）。

FLAC格式规范、参考实现[FLAC-implementation]及本文档初版由Josh Coalson主导完成，其开创性工作奠定了FLAC的基础，我们深表感谢。

<br>

## 作者信息
**Martijn van Beurden**  
荷兰  
邮箱：mvanb1@gmail.com  

**Andrew Weaver**  
邮箱：theandrewjw@gmail.com