1. 简介
FLAC是受支持最快且最广泛支持的无损音频编解码器,唯一一种是非专有的,不受专利影响,具有 开源 参考实现,具有良好的文档格式和API,并具有几种其他独立实现。
2. 技术特点
- 无损压缩:被编码的音频(PCM)数据没有任何信息损失,解码输出的音频与编码器的输入的每一个字节都是一样的。每个数据帧都有一个当前帧的16-bit CRC校验码,用于监测数据传输错误。对整段音频数据,在文件头中还保存有一个针对原始未压缩音频数据的MD5标记,用于在解码和测试时对数据进行校验。
- 灵活的压缩策略:与libflac使用是“质量”的参数,该参数变化从0(最快)至8(最小)。虽然在压缩过程(压缩文件总是完美的“无损”表示的原始数据)。涉及速度和容量之间的折衷,解码过程中始终是相当快的,而不是非常依赖于压缩
- 快速:FLAC更看重解码的速度。解码只需要整数运算,并且相对于大多数编码方式而言,对计算速度要求很低。在很普通的硬件上就可以轻松实现实时解码。
- 硬件支持:由于FLAC提供了免费的解码范例,而且解码的复杂程度低,所以FLAC是目前少数获得硬件支持的无损压缩编码之一。(APE格式也有少数硬件支持)
- 可以流化:FLAC的每个数据帧都包含了解码所需的全部信息。解码当前帧无需参照它前面或后面的数据帧。FLAC使用了同步代码和CRC(类似于MPEG等编码格式),这样解码器在数据流中跳跃定位时可以有最小的时间延迟。
- 可以定位:FLAC支持快速采样精确定位。这不仅对于播放有益,更使得FLAC文件便于编辑。
- 富于弹性的metadata:可以定义和实现新类型的metadata数据块,而不会影响旧的数据流和解码器的使用。目前已有的metadata类型包括tag,cue表,和定位表。已经注册的应用程序可以定义自己专用的metadata类型(这一点与MIDI标准相似)。
- 非常适合于存档应用:FLAC是一个开放的编码格式,并且没有任何数据的损失,你可以将它转换为你需要的任何其他格式。除了每个数据帧的CRC和MD5标记对数据完整性的保障,flac(FLAC项目提供的命令行方式编码工具)还提供了一个verify(校验)选项,当使用该选项进行编码的时候,编码的同时就会立即对已编码数据进行解码并与原始输入数据进行比较,一旦发现不同就会退出并且报警提示。
- 便于对CD进行备份:FLAC有一个cue表,表内的metadata数据块用于保存CD的内容列表和所有音轨的索引点。你可以将一张CD保存到一个单一文件,并导入CD的cue表格,这样一个FLAC文件就可以完整地记录整张CD的全部信息。当你的原来的CD损坏的时候,你就可以用这个文件恢复出与原来一模一样的CD副本。
- 抗损伤:由于FLAC的帧结构,当数据流损坏时,数据损失会被限制在受损的数据帧之内。一般只会丢失很短的一个片段。而很多其他无损音频压缩格式在遇到损坏时,一个损坏就会造成后面所有数据丢失。
3. 解码原理
解码器主要由五个模块组成,如下图所示。
一、解码头信息,码流输入解码器,解码出码流中的比特率、采样率等信息,并将残差信号编码码流输入到下一步的嫡解码器
二、嫡解码,嫡解码器依据上级传来的码流信息以解码残差信号
三、解码,由残差信号和预测系数恢复原始音频信号
四、立体声处理,由码流中的声道设置信息恢复立体声的左右声道信号
五、格式化输出,将左右声道按需求格式输出。
3.1 LPC
线性预测(linear prediction)是指用P个已知的样值的某种线性组合来预测未知的样值。多用于语音信号处理中,用前面的采样值的线性组合来估计离散时间域信号。在数字语音处理中,线性预测经常成为线性预测编码(LPC),可以作为滤波器理论的一部分。
假设已知n时刻前p个样点的语音信号值为x(n-1), x(n-2)…, x(n-p), 则x(n)的估计值为:
3.2 Golomb
对于任一待编码的非负正整数N,Golomb编码将其分为两个部分:所在组的编号GroupID以及分组后余下的部分,GroupID实际是待编码数字N和参数m的商,余下的部分则是其商的余数,具体计算如下:
q=N/m
r=N%m
对于得到的组号q使用一元编码(Unary code),余下部分r则使用固定长度的二进制编码(binary encoding)。
一元编码(Unarycoding)是一种简单的只能对非负整数进行编码的方法,对于任意非负整数num,它的一元编码就是num个1后面紧跟着一个0。例如:
num | Unary coding |
0 | 0 |
1 | 10 |
2 | 110 |
3 | 1110 |
4 | 11110 |
5 | 111110 |
使用一元编码编码组号也就是商q后,对于余下的部分r则有根据编码数字大小的不同有不同的处理方法。
- 如果参数m是2的次幂(这也是下面将要介绍的Golomb-Rice编码),则使用取r的二进制表示的低log2(m)位,作为r的码字
- 如果参数m不是2的次幂,如果m不是2的次幂,设b=⌈log2(m)⌉
- 如果r<2b−m,则使用b-1位的二进制编码r。
- 如果r≧2b−m,则使用b位二进制对r+2b−m进行编码
FLAC takes advantage of the fact that the error signal generally has a Laplacian (two-sided geometric) distribution, and that there are a set of special Huffman codes called Rice codes that can be used to efficiently encode these kind of signals quickly and without needing a dictionary。
1. FLAC 编码设置只对编码时间有较大影响而对解码影响不大;因为等级越高,编码器就会花越多的时间去寻找最佳的压缩算法,而解码器则根据给定的压缩算法直接解压。
2. FLAC简介
基本结构:
4byte 字符“flaC”:flac标志,用于识别flac数据流
STREAMINFO 文STREAMINFO 件信息描述块(metadata block):包含必须的信息(采样率、声道数…)
可选的其他描述信息块:(解码是可以不用识别)
一个以上的音频帧(frame)
3. 编码的过程
Flac把未压缩的音频流划分为块(block),并独立压缩,压缩后的数据块形成数据帧(frame),把数据帧连接形成压缩后的flac数据流(stream)
分块(blocking) flac分块大小是可变的。分块大小应适当选择,太小影响压缩率(太多帧头信息),太大难以得到高效的压缩模型。一般44.1k线性采样,分块大小2~6k较合适(默认4096)
声道内解相关性? 立体声的左右声道数据之间有许多相关性,可以利用这种相关性压缩数据。Flac有四种方式表示声道数据。
独立模式:左右声道独立编码;
Mid-side模式:转换表达式:mid = (left + right) / 2, side = left - right.。
Left-side:Left不变,s
Right-side:
建模(modeling)编码器尝试使用一个数学方法(近似)描述原始信号,这种描述信息一般来说比原始信息小得多,这些数学方法是编码器和解码器都已知的(flac现在有4个种类的预测方法,并可以加入更多方法)flac运行在各个块中使用不同的预测算法。大多时候不能完全精确的描述原始信息,此时还会剩下少量数据残渣(residual, residue, or error)。Flac有两种产生近似值的方法:1)为信号找个合适的多项式。2)简单线性预测(LPC)。前者更快但不精确。
数据残渣编码 对建模后剩余的数据进行编码,保证数据的无损。目前flac只使用一种编码方法。
帧 (framing)一个音频帧被一个帧头(frameheader)和帧脚(frame footer)包围。帧头以同步字开始,包含了解码这帧的最小信息如采样率,采样位数等,同时包含了这帧里的分块数或采样数及一个8位CRC校验码。帧头可以用来进行再同步。帧尾包含一个16位CRC校验码。如果解码器检测到CRC错误将产生一个silent block。
4. 定义
(block、subblock 指没有被编码的原始数据;frame、subframe指编码后的数据)
Block:一组或多组跨所有声道的采样点(flac采样组数范围16~65535)。
Subblock:一个或多个单声道的采样点,一个Block包含几个声道就有几个subblock,同个block内subblock的采样点数相同。
Blocksize:一个block中任意subblock的采样点个数(与声道数无关)。
Frame:一个frame帧头加一个或多个Subframe
Subframe:一个subframe帧头加某一声道上一个或多个编码后的采样点,一个frame中的所有subframe包含的采样点数一样。
(每次一个subblock被编码成一个subframe,多个subframe组成一个frame)
5. Flac格式(format)
Flac中所有数值都是整形,大端模式,除非特别指出,否则数值都是unsigned的。
一些概述:
Flac比特流以“flaC”开始,接着是必须的metadata块(STREAMINFO),然后是其他可选的metadata块,接着是音频帧。
Flac做多可以支持到128类metadata,已经定义的包括下面几种:
A. STREAMINFO:包含整个比特流的一些信息,如采样率、声道数、采样总数等。他一定是第一个metadata而且必须有。之后可以接其他metadata,这些metadata可以不用识别直接跳过。
B. APPLICATION:包含第三方应用软件信息,这个段里的32位识别码是flac维护组织提供的,是唯一的。
C. PADDING:没有意义的东西,主要用来后期添加其他metadata。
D. SEEKTABLE:保存快速定位点,一个点由18bytes组成(2k就可以精确到1%的定位),表里可以有任意多个定位点。
E. VORBIS_COMMENT:存储了一系列可读的“名/值”的键值对,使用UTF-8编码。这是flac唯一官方支持的标签段。
F. CUESHEET:存储用在cue sheet中的各种信息。可以用来划分音轨,在备份CD时十分有用。
G. PICTURE:保存相关图片,同时还有url、分辨率等信息,可以有不止一个picture block。
音频数据由一个或多个音频帧组成,每一帧包含一个帧头:同步字,块大小,采样率,声道数…然后是8bitCRC校验码;同时帧头还包含本帧第一个采样点的采样序号(blocksize变长的文件)或本帧的序号(blocksize定长的文件),他们用于精确定位。接着是编码后的subframes,每个subframe代表一个声道。最后是一些有0填充的边界。每个subframe有他自己的帧头用于指出他是怎样被编码的。
当从一个文件中间开始解码时需要知道一个帧的起始点。可以通过一个14bit的同步字来判断。但是他可能会出现在subframe里面,此时可以通过检测剩余数据(没有无效数据)和CRC8.
同样当从中间某帧开始解码时,没有读取STREAMINFO,为了得到采样率和声道数等信息,需要再帧头里加入相关信息,为了减少数据,使用了查表的方法来定义常用的采样率。
格式:
长度 | 名称 | 说明 | ||
<32> | “flaC” | 0x66 0x41 0x61 0x43 固定标签 | ||
<1> | METADATA BLOCK | HEADER |
| 最后一个metadata为’1’,其他为’0’ |
<7> | 块信息类型 | 0 : STREAMINFO 1 : PADDING 2 : APPLICATION 3 : SEEKTABLE 4 : VORBIS_COMMENT 5 : CUESHEET 6 : PICTURE 7-126 : reserved 127 : 无效 | ||
<24> | 后面跟的数据长度 | 单位是byte,不包括此头的长度 | ||
| DATA | 数据,与头中的类型要相符 | 参加metadata data | |
| FRAME | HEADER | 头 | 见FRAME HEADER |
| SubFrame | 子帧 | 包含一个通道的数据,见SUBFRAME | |
| ? |
| 填充0用于对齐 | |
16 | FOOTER | 尾 | CRC-16 |
Metadata block DATA:
Metadata类型 | 长度 | 说明 | ||
STREAMINFO | 16 | blocksize最小的中的采样数 | ||
16 | Blocksize中最大的采样数 | |||
24 | 最小帧大小(byte),0表示未知 | |||
24 | 最大帧大小(byte),0表示未知 | |||
20 | 采样率(Hz) 最大655350Hz,0无效 | |||
3 | 声道数减一,flac支持1~8个声道 | |||
5 | 采样位数减一,flac支持4~32位采样位数 | |||
36 | 一个声道的总采样数,0表示未知 | |||
128 | 未编码时的原始信号的MD5信息 | |||
PADDING | N | ‘0’ N必须是8的倍数 | ||
APPLICATION | 32 | 应用程序ID | ||
N | 应用程序数据,必须是8的倍数 | |||
SEEKTABLE | SEEKPOINT | 64 | 目标帧中第一个采样点的序号 | |
64 | 相对于第一帧开始的偏移(byte) | |||
16 | 目标帧中的采样数 | |||
SEEKPOINT | 同上 | SEEKPOINT的个数等于DTAT段长度/18 | ||
CUESHEET | 64 | 音轨偏移量(单位是采样数) | ||
8 | 音轨数目 | |||
12*8 | 音轨ISRC | |||
1 | 轨迹类型:0 音乐 1非音乐 | |||
1 | pre-emphasis标记 | |||
6+13*8 | 保留 ‘0’ | |||
8 | 应该的索引数目 | |||
INDEXn(有多个) | 64 | 偏移(单位是采样点) | ||
8 | 索引号 | |||
3*8 | 保留 | |||
PICTURE | 32 | 图片类型(同ID3v2 APIC) 0 - Other 1 - 32x32 pixels 'file icon' (PNG only) 2 - Other file icon 3 - Cover (front) 4 - Cover (back) 5 - Leaflet page 6 - Media (e.g. label side of CD) 7 - Lead artist/lead performer/soloist 8 - Artist/performer 9 - Conductor 10 - Band/Orchestra 11 - Composer 12 - Lyricist/text writer 13 - Recording Location 14 - During recording 15 - During performance 16 - Movie/video screen capture 17 - A bright coloured fish 18 - Illustration 19 - Band/artist logotype 20 - Publisher/Studio logotype | ||
32 | MIME 类型说明字符长度(byte) | |||
N*8 | MIME类型说明字符 | |||
32 | 描述符长度(byte) | |||
N*8 | 描述符UTF-8 | |||
32 | 图片宽度 | |||
32 | 图片高度 | |||
32 | 图片颜色深度 | |||
32 | 索引图使用的颜色数目,0非索引图 | |||
32 | 图片数据长度 | |||
N*8 | 图片二进制文件 |
Frame Header:
长度 | 说明 | 说明 |
14 | 同步字 | '11111111111110' |
1 | 保留 | 0 : 强制值 1 : 保留未来使用 |
1 | 分块策略 | 0:固定块大小,帧头包含帧的序号 1:块大小可变,帧头包含采样点序号 |
4 | 块内的采样数 | 0000 : reserved 0001 : 192 samples 0010-0101 : 576 * (2^(n-2)) samples, i.e. 576/1152/2304/4608 0110 : get 8 bit (blocksize-1) from end of header 0111 : get 16 bit (blocksize-1) from end of header 1000-1111:256 * (2^(n-8)) 采样点 |
4 | 采样率 | 0000 : get from STREAMINFO metadata block 0001 : 88.2kHz 0010 : 176.4kHz 0011 : 192kHz 0100 : 8kHz 0101 : 16kHz 0110 : 22.05kHz 0111 : 24kHz 1000 : 32kHz 1001 : 44.1kHz 1010 : 48kHz 1011 : 96kHz 1100 : get 8 bit sample rate (in kHz) from end of header 1101 : get 16 bit sample rate (in Hz) from end of header 1110 : get 16 bit sample rate (in tens of Hz) from end of header 1111 : invalid, to prevent sync-fooling string of 1s |
4 | 声道分配 | 0000-0111 :独立声道减一,分配如下: 1 channel: mono 2 channels: left, right 3 channels: left, right, center 4 channels: left, right, back left, back right 5 channels: left, right, center, back/surround left, back/surround right 6 channels: left, right, center, LFE, back/surround left, back/surround right 7 channels、8 channels: not defined 1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel 1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel 1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel 1011-1111 : reserved |
3 | 采样深度 | 000 : get from STREAMINFO metadata block 001 : 8 bits per sample 010 : 12 bits per sample 011 : reserved 100 : 16 bits per sample 101 : 20 bits per sample 110 : 24 bits per sample 111 : reserved |
1 | 保留 | 0 : mandatory value 1 : reserved for future use |
? |
| if(variable blocksize) <8-56>:"UTF-8" coded sample number (decoded number is 36 bits) else <8-48>:"UTF-8" coded frame number (decoded number is 31 bits) |
? |
| if(blocksize bits == 011x) 8/16 bit (blocksize-1) |
? |
| if(sample rate bits == 11xx) 8/16 bit sample rate |
8 |
| CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) of everything before the crc, including the sync code |
SubFrame:
长度 | 域 | 说明 |
1 | 填充0 | prevent sync-fooling string of 1s |
6 | Subframe类型 | 000000 : SUBFRAME_CONSTANT 000001 : SUBFRAME_VERBATIM 00001x : reserved 0001xx : reserved 001xxx : if(xxx <= 4) SUBFRAME_FIXED, xxx=order ; else reserved 01xxxx : reserved 1xxxxx : SUBFRAME_LPC, xxxxx=order-1 |
1+k | 'Wasted bits-per-sample' flag | 0 : no wasted bits-per-sample in source subblock, k=0 1 : k wasted bits-per-sample in source subblock, k-1 follows, unary coded; e.g. k=3 => 001 follows, k=7 => 0000001 follows. |