常见音频编码格式解析

版权声明:版权声明:本文为博主原创文章,转载请把文章链接一并转载。 https://blog.csdn.net/houxiaoni01/article/details/78810674

常见音频编码格式解析

1.MP3编码格式

1.1.MP3概述

  MPEG-1 or MPEG-2 Audio Layer III是一种音频压缩技术,其全称是动态影像专家压缩标准音频层面3(Moving Picture Experts Group Audio Layer III),简称为MP3,是目前最流行的音频编码格式。
  MP3文件是由帧(frame)构成的,帧是MP3文件最小的组成单位。MPEG音频文件是MPEG1标准中的声音部分,也叫MPEG音频层,它根据压缩质量和编码复杂程度划分为三层,即 Layer-1、Layer2、Layer3,且分别对应MP1、MP2、MP3这三种声音文件,并根据不同的用途,使用不同层次的编码。MPEG音频编码的层次越高,编码器越复杂,压缩率也越高,MP1和MP2的压缩率分别为4:1和6:1-8:1,而MP3的压缩率则高达10:1-12:1,也就是说,一分钟CD音质的音乐,未经压缩需要10MB的存储空间,而经过MP3压缩编码后只有1MB左右。不过MP3对音频信号采用的是有损压缩方式,为了降低声音失真度,MP3采取了“感官编码技术”,即编码时先对音频文件进行频谱分析,然后用过滤器滤掉噪音电平,接着通过量化的方式将剩下的每一位打散排列,最后形成具有较高压缩比的MP3文件,并使压缩后的文件在回放时能够达到比较接近原音源的声音效果。根据MPEG规范的说法,MPEG-4中的AAC(Advanced audio coding)将是MP3格式的下一代。

1.2.MPEG音频压缩基础

  在众多音频压缩方法中,这些方法在保持声音质量的同时尽量压缩数字音频使之占用更小的存储空间。MPEG压缩是该领域中效果最好的一个。这种压缩是有损压缩,这意味着,当运用这一方法压缩时肯定会丢失一部分音频信息。但是,由于压缩方法的控制很难发现这种损失。使用几个非常复杂和苛刻的数学算法,使得只有原始音频中几乎听不到的部分损失掉。这就给重要的信息剩下了更多的空间。通过这种方法可以将音频压缩12倍(可以选择压缩率),效果显著。正是应为他的质量,MPEG音频变得流行起来。
  MPEG-1,MPEG-2和MPEG-4都是人们熟悉的MPEG标准,MP3只涉及到前两中,另外还有一个非官方标准MPEG-2.5用于扩展MPEG-2/LSF到更低的采样率。
  MPEG-1音频(ISO/IEC 11172-3)描述了具有如下属性的三层音频编码:
- 1或2个声道;
- 采样频率为32kHz,44.1kHz或48kHz;
- 位率从32kbps到448kbps;

  每一层都有自己的优点。
  MPEG-2音频(ISO/IEC 13818-3)有两个MPEG-1的扩展,通常叫做MPEG-2/LSF和MPEG-2/Multichannel。
  MPEG-2/LSF有如下特点:
- 1或2个声道;
- 采样频率为MPEG-1的一半;
- 波特率从8kbps256kbps;

  MPEG-2/Mutichannel有如下特点:
- 多达5个声道和1个LFE-通道(低频增强 不是重低音);
- 同MPEG-1一样的采样频率;
- 5.1的最高波特率可能达到1Mbps;

1.3.MPEG Layer3编/解码的基本原理

  音乐CD具有44.1KHz 16Bits立体声的音频质量,一张CD可以存储74分钟的歌曲(大约15首左右)。如何将这些歌曲无损或基本无损地进行压缩,以使在同样的媒体上存储更多的歌曲,一直困扰着软件业。当MPEG协会提出MPEG Audio Layer1~Layer3后,机会产生了。通过使用MPEG1 Layer3编码技术,制作者得以用大约12∶1的压缩率记录16KHz带宽的有损音乐信号。不过,同CD原声区别不大。人的听力系统具有非常优越的性能,其动态范围超过96dB。你既可以听到扣子掉在地上这样小的声音,也可以听到波音747的强大的轰鸣声。但当我们站在飞机场听着波音747的轰鸣时,你还能分辨出扣子掉在地上的声音吗?不可能。人的听力系统适应声音的动态变化,人们对这种适应及屏蔽特性音质研究后得出对声音压缩非常有用的理论。人们很早以前就知道利用这种特性来为磁带录音降低噪音了(当没有音乐时嘶嘶声很容易听到,而当音乐信号电平很高时嘶嘶声不容易听到)。当声音较强时产生屏蔽效应。在阈值曲线下的噪音或小信号声音无法被人耳听到。在较强信号出现时,允许通过更多的信号。在此时增加被量化过的小信号数据(使用无用的位来携带更多的信息)可以达到一定程度的压缩的目的。通常情况下,MP3压缩器将原始声音通过FFT(快速傅立叶变换)变化到频域,然后通过一定的算法算出何种频率声音可以携带更多的信息。而在还原时解码器所需要做的仅仅是将其从频域再变换回来。

1.4.整个MP3文件结构

MP3文件大体分为三部分:TAG_V2(ID3V2),音频数据,TAG_V1(ID3V1)

                     表格 1-1

section description
ID3V2 在文件开始的位置,包含了作者,作曲,专辑等信息,长度不固定,扩展了ID3V1的信息量
Frame
.
.
.
Frame
一系列的帧,在文件的中间位置,个数由文件大小和帧长决定;
每个FRAME的长度可能不固定,也可能固定,由位率bitrate决定;
每个FRAME又分为帧头和数据实体两部分;
帧头记录了mp3的位率,采样率,版本等信息,每个帧之间相互独立。

1.4.1.ID3V2

  ID3V2到现在一共有4个版本,但流行的播放软件一般只支持第3版,即ID3v2.3。由于ID3V1记录在MP3文件的末尾,ID3V2就只好记录在MP3文件的首部了(如果有一天发布ID3V3,真不知道该记录在哪里)。也正是由于这个原因,对ID3V2的操作比ID3V1要慢。而且ID3V2结构比ID3V1的结构要复杂得多,但比前者全面且可以伸缩和扩展。
  下面就介绍一下ID3V2.3:
  每个ID3V2.3的标签都由一个标签头和若干个标签帧或一个扩展标签头组成。关于曲目的信息如标题、作者等都存放在不同的标签帧中,扩展标签头和标签帧并不是必要的,但每个标签至少要有一个标签帧。标签头和标签帧一起顺序存放在MP3文件的首部。
(一)标签头
  在文件的首部顺序记录10个字节的ID3V2.3的头部。数据结构如下:
  char Header[3];     //必须为”ID3”否则认为标签不存在
  char Ver;       //版本号 ID3V2.3就记录3
  char Revision;     //副版本号 此版本记录为0
  char Flag;       //存放标志的字节,这个版本只定义了三位,稍后详细解说
  char Size[4];      //标签大小,包括标签头的10 个字节和所有的标签帧的大小
  ==注:对这里我有疑惑,因为在实际寻找首帧的过程中,我发现有的mp3文件的标签大小是不包含标签头的,但有的又是包含的,可能是某些mp3编码器写标签的BUG,所以为了兼容只好认为其是包含的,如果按大小找不到,再向后搜索,直到找到首帧为止。==

这里写图片描述
                  图 1-1
蓝色部分即为ID3V2.3的头部:前4个字节就是ID30x03(第3版)
第5个字节:副版本号,为0
注:文中关于mp3文件数据截图均为“紫藤花.mp3”文件中的数据截图。
(1)标志字节
标志字节一般为0,定义如下:
abc00000
a – 表示是否使用Unsynchronisation(一般不设置)
b – 表示是否有扩展头部,一般没有(至少Winamp 没有记录),所以一般也不设置
c – 表示是否为测试标签(99.99%的标签都不是测试用的啦,所以一般也不设置)
上图蓝色部分第6个字节:存放标志的字节,只定义了三位,这里值为0。
(2)标签大小
一共四个字节,但每个字节只用7位,最高位不使用恒为0。所以格式如下:
0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx
计算大小时要将0去掉,得到一个28位的二进制数,就是标签大小,计算公式如下:
int total_size;
total_size = (Size[0]&0x7F)*0x200000 + (Size[1]&0x7F)*0x4000 + (Size[2]&0x7F)*0x80 + (Size[3]&0x7F)

上图蓝色部分第7到10字节:表示ID3标签的大小,这里为
total_size =(0x00&0x7F)*0x200000 + (0x00&0x7F)*0x4000 + (0x10&0x7F)*0x80 + (0x72 &0x7F) = 0x872 = 2162

(二)标签帧
  每个标签帧都由一个10个字节的帧头和至少一个字节的不固定长度的内容组成。它们也是顺序存放在文件中,和标签头及其他的标签帧也没有特殊的字符分隔。得到一个完整的帧的内容只有从帧头中得到内容大小后才能读出,读取时要注意大小,不要将其他帧的内容或帧头读入。

  帧头的定义如下:
  char ID[4];    /用四个字符标识一个帧,说明其内容,稍后有常用的标识对照表/
  char Size[4];   /帧内容的大小,不包括帧头,不得小于1/
  char Flags[2];   /存放标志,只定义了6位,稍后详细解说/

这里写图片描述
                  图 1-2
蓝色部分是一个歌曲标题的标签帧
(1)帧标识
  用四个字符标识一个帧,说明一个帧的内容含义,常用的对照如下:
  TIT2 = 标题   //表示内容为这首歌的标题,下同
  TPE1=作者
  TALB=专集
  TRCK=音轨    //格式:N/M其中N 为专集中的第N首,M为专集中共M首,N和M为ASCII码表示的数字
  TYER=年代   //是用ASCII 码表示的数字
  TCON=类型   //直接用字符串表示
  COMM=备注   //格式:”eng\0备注内容”,其中eng表示备注所使用的自然语言
  注:前4个字节为帧标识,这里是54 49 54 32(TIT2)是标题的标签帧。

             表1-2 标签帧的标识以及其意义对照表

index content index content
AENC [Audio encryption] TKEY [Initial key]
APIC [Attached picture] TLAN [Language(s)]
COMM [Comments] TLEN [Length]
COMR [Commercial frame] TMED [Media type]
ENCR [Encryption method registration] TOAL [Original album/movie/show title]
EQUA [Equalization] TOFN [Original filename]
ETCO [Event timing codes] TOLY [Original lyricist(s)/text writer(s)]
GEOB [General encapsulated object] TOPE [Original artist(s)/performer(s)]
GRID [Group identification registration] TORY [Original release year]
IPLS [Involved people list] TOWN [File owner/licensee]
LINK [Linked information] TPE1 [Lead performer(s)/Soloist(s)]
MCDI [Music CD identifier] TPE2 [Band/orchestra/accompaniment]
MLLT [MPEG location lookup table] TPE3 [Conductor/performer refinement]
OWNE [Ownership frame] TPE4 [Interpreted, remixed, or otherwise modified by]
PRIV [Private frame] TPOS [Part of a set]
PCNT [Play counter] TPUB [Publisher]
POPM [Popularimeter] TRCK [Track number/Position in set]
POSS [Position synchronisation frame] TRDA [Recording dates]
RBUF [Recommended buffer size] TRSN [Internet radio station name]
RVAD [Relative volume adjustment] TRSO [Internet radio station owner]
RVRB [Reverb] TSIZ [Size]
SYL [Synchronized lyric/text] TSRC [ISRC (international standard recording code)]
SYTC [Synchronized tempo codes] TSSE [Software/Hardware and settings used for]
TALB [Album/Movie/Show title] TYER [Year]
TBPM [BPM (beats per minute)] TXXX [User defined text information frame]
TCOM [Composer] UFID [Unique file identifier]
TCON [Content type] USER [Terms of use]
TCOP [Copyright message] USLT [Unsychronized lyric/text transcription]
TDAT [Date] WCOM [Commercial information]
TDLY [Playlist delay] WCOP [Copyright/Legal information]
TENC [Encoded by] WOAF [Official audio file webpage]
TEXT [Lyricist/Text writer] WOAR [Official artist/performer webpage]
TFLT [File type] WOAS [Official audio source webpage]
TIME [Time] WORS [Official internet radio station homepage]
TIT1 [Content group description] WPAY [Payment]
TIT2 [Title/songname/content description] WPUB [Publishers official webpage]
TIT3 [Subtitle/Description refinement] WXXX [User defined URL link frame]

(2)大小
  这个可没有标签头的算法那么麻烦,每个字节的8 位全用,格式如下
  xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
  算法如下:
  int FSize;
  FSize = Size[0]*0x100000000 + Size[1]*0x10000+ Size[2]*0x100 + Size[3];
  第5到8字节为标签帧的大小,这里为
  FSize = 0x00*0x100000000+ 0x00*0x10000 + 0x00*0x100 + 0x24 = 0x24 = 36
  注意:这里的帧大小,并不包含帧头的10个字节,只表示帧内容的大小。
(3)标志
  只定义了6位,另外的10位为0,但大部分的情况下16位都为0就可以了。格式如下:abc00000ijk00000
- a – 标签保护标志,设置时认为此帧作废
- b – 文件保护标志,设置时认为此帧作废
- c – 只读标志,设置时认为此帧不能修改
- i – 压缩标志,设置时一个字节存放两个BCD码表示数字
- j – 加密标志
- k – 组标志,设置时说明此帧和其他的某帧是一组

  值得一提的是winamp在保存和读取帧内容的时候会在内容前面加个”\0”,并把这个字节计算在帧内容的大小中。
  第9到10字节为标签帧的标记,如上所述,这里为00。

  帧内容是歌曲标题,标题的36个字节的内容为:紫藤花☆ゞ忍音.地带[renyin.12u.cn]。

1.4.2.音频数据帧

  每个帧都有一个帧头Header,长度是4Byte(32bit),帧头后面可能有两个字节的CRC 校验值,这两个字节的校验值是否存在决定于Header信息的第16bit,为0则帧头后面无校验,为1则有校验,校验值长度为2个字节,紧跟在Header后面的就是帧的实体数据,也就是压缩的声音数据,当解码器读到此处时就进行解码了。格式如下:
(1)帧头格式
  帧头长4字节,对于固定位率的MP3文件,所有帧的帧头(即CBR帧头)格式一样,其数据结构如下(注:此结构要自己定义):

typedef struct frameHeader
{
    unsigned int sync: 11;                  //同步信息
    unsigned int version: 2;                  //版本
    unsigned int layer: 2;                  //层
    unsigned int error protection: 1;        // CRC校验
    unsigned int bitrate_index: 4;          //位率
    unsigned int sampling_frequency: 2;    //采样频率
    unsigned int padding: 1;                  //帧长调节
    unsigned int private: 1;                  //保留字
    unsigned int mode: 2;                    //声道模式
    unsigned int mode extension: 2;        //扩充模式
    unsigned int copyright: 1;              //版权
    unsigned int original: 1;                //原版标志
    unsigned int emphasis: 2;                //强调模式
}FHEADER, *LPHEADER;

                 表1-3 MP3帧头字节使用说明

 
名字 位长 说明
同步信息 11 第1、2字节 所有位均为1,第1字节恒为FF。
版本 2 00-MPEG2.5 01-未定义  10-MPEG 2  11-MPEG 1
2 00-未定义  01-Layer 3  10-Layer 2  11-Layer 1
CRC校验 1 0-校验  1-不校验
位率 4 第3字节 取样率,单位是kbps,例如采用MPEG-1 Layer 3,64kbps是,值为0101。 
bits V1,L1 V1,L2 V1,L3 V2,L1 V2,L2 V2,L3
0000 free free free free free free
0001 32 32 32 32(32) 32(8) 8(8)
0010 64 48 40 64(48) 48(16) 16(16)
0011 96 56 48 96(56) 56(24) 24(24)
0100 128 64 56 128(64) 64(32) 32(32)
0101 160 80 64 160(80) 80(40) 60(40)
0110 192 96 80 192(96) 96(48) 80(48)
0111 224 112 96 224(112) 112(56) 56(56)
1000 256 128 112 256(128) 128(64) 64(64)
1001 288 160 128 288(144) 160(80) 128(80)
1010 320 192 160 320(160) 192(96) 160(96)
1011 352 224 192 352(176) 224(112) 112(112)
1100 384 256 224 384(192) 256(128) 128(128)
1101 416 320 256 416(224) 320(114) 256(114)
1110 448 384 320 448(256) 384(160) 320(160)
1111 bad bad bad bad bad bad
V1 - MPEG 1  V2 - MPEG 2 and MPEG 2.5 L1 - Layer 1   L2 - Layer 2  L3 - Layer 3 “free” 表示位率可变   “bad” 表示不允许值
采样率 2 采样频率,对于MPEG-1: 00-44.1kHz 01-48kHz 10-32kHz 11-未定义 对于MPEG-2: 00-22.05kHz 01-24kHz 10-16kHz 11-未定义 对于MPEG-2.5: 00-11.025kHz 01-12kHz 10-8kHz 11-未定义
帧长调节 1 用来调整文件头长度,0-无需调整,1-调整,具体调整计算方法见下文。
保留字 1 没有使用。
声道模式 2 第4字节 表示声道, 00-立体声Stereo 01-Joint Stereo      10-双声道Dual channel 11-单声道Single channel 
扩充模式 2 当声道模式为01是才使用。
Value 强度立体声 MS立体声
00 off off
01 on off
10 off on
11 on on
版权 1 文件是否合法,0-不合法 1-合法
原版标志 1 是否原版,0-非原版 1-原版
强调方式 2 用于声音经降噪压缩后再补偿的分类,很少用到,今后也可能不会用。 00-未定义 01-50/15ms 10-保留 11-CCITT J.17

注意:关于读取帧头也可以使用下面的方法

定义一个结构体

typedef struct frameHeader
{
unsigned int sync1:8;               //同步信息1

unsigned int error_protection:1;        //CRC校验
unsigned int layer:2;               //层
unsigned int version:2;                 //版本
unsigned int sync2:3;               //同步信息2

unsigned int extension:1;           //版权
unsigned int padding:1;              //填充空白字
unsigned int sample_rate_index:2;   //采样率索引
unsigned int bit_rate_index:4;      //位率索引

unsigned int emphasis:2;            //强调方式
unsigned int original:1;                //原始媒体
unsigned int copyright:1;           //版权标志
unsigned int mode_extension:2;      //扩展模式,仅用于联合立体声
unsigned int channel_mode:2;        //声道模式

}FHEADER, *pFHEADER;

  请注意该结构体将同步信息分成了两个部分,而且其他的位的顺序也和上表列出的有所差别,这个主要是因为c语言在存取数据时总是从低位开始,而这个帧头是需要从高位来读取的。
读取方式如下:
FHEADER header;
fread( &header, sizeof( FHEADER ), 1, streams );  //这里假设文件已打开,读取位置已经指向帧头所在的位置
这样一次就可以读入帧头的所有信息了。

这里写图片描述
                  图 1-3

第1帧数据:帧头为FF FB 90 04
11111111 11111011 10010000 00000010
前11位:同步信息
第12到13位:版本,其值为11 ->MPEG 1
第14到15位:层,其值为01->Layer 3
第16位:CRC检验标识,其值为1 ->不校验
第17到20位:位率,其值为1001,从前面可知本帧为V1,L3类型, ->128K
第21到22位:采样率,其值为00,从前面知本帧为 MPEG 1-> 44.1K
第23位:帧长调节,其值为0 ->无需调整
第24位:未使用
第25到26位:声道模式,其值为00->立体声Stereo
第27到28位:扩充模式,当声道模式为01(联合立体声)时才使用,此处未使用
第29位:版权,其值为0->无版权
第30位:原版标志,其值为1->是原版文件
第31到32位:强调方式,其值为00->未定义
(2)计算帧长度
  我们首先区分两个术语:帧大小和帧长度。帧大小即每帧采样数表示一帧中采样的个数,这是恒定值。其值如下表所示

MPEG1 MPEG2(LSF) MPEG2.5(LSF)
Layer1 384 384
Layer2 1152 1152
Layer3 1152 576

  帧长度是压缩时每一帧的长度,包括帧头。它将填充的空位也计算在内。LayerI的一个空位长4字节,LayerII和LayerIII的空位是1字节。当读取MPEG文件时必须计算该值以便找到相邻的帧。注意:因为有填充和比特率变换,帧长度可能变化。
  从头中读取比特率,采样频率和填充的值后可以进行计算,
LyaerI使用公式:
            帧长度(字节) = (( 每帧采样数/ 8 * 比特率 ) / 采样频率 ) + 填充 * 4
LyerII和LyaerIII使用公式:
             帧长度(字节)= (( 每帧采样数/ 8 * 比特率 ) / 采样频率 ) + 填充
例如图1-3中,比特率为128K,采样率为44.1K,填充0,则其帧长度为:
                  (1152 / 8 * 128K)/44.1K = 417 (字节)
(3)每帧的持续时间
  每帧的持续时间可以通过计算获得,下面给出计算公式
               每帧持续时间(毫秒) = 每帧采样数 / 采样频率 * 1000ms
  如图1-3中,其每帧时间为:
                 1152 / 44.1K * 1000 = 26.12 (约等于26ms)
  如果是MPEG2 Layer III 采样率为16KHz的话那一帧要持续36毫秒,这个相差还是蛮大的,所以还是应该通过计算来获的。
(4)CRC校验
  如果帧头的校验位为0,则帧头后就有一个16位的CRC值,这个值是big-endian的值,把这个值和该帧通过计算得出的CRC值进行比较就可以得知该帧是否有效。
(5)帧数据
  在帧头后边是Side Info(姑且称之为通道信息)。对标准的立体声MP3文件来说其长度为32字节。通道信息后面是Scale factor(增益因子)信息。当解码器在读到上述信息后,就可以进行解码了。对应图1-3中地址0x880到0x89F(含),此处数据全为0。当MP3文件被打开后,播放器首先试图对帧进行同步,然后分别读取通道信息及增益因子等数据,再进行霍夫曼解码,至此我们已经获得解压后的数据。但这些数据仍然不能进行播放,它们还处于频域,要想听到歌曲还要将它由频域通过特定的手段转换到时域。接下来的处理分别为立体化处理;抗锯齿处理;IMDCT变换;IDCT变换及窗口化滑动处理。
  对于mp3来说现在有两种编码方式:一种是CBR,也就是固定位率,固定位率的帧的大小在整个文件中都是固定的(公式如上所述),只要知道文件总长度,和从第一帧帧头读出的信息,就可以通过计算得出这个mp3文件的信息,比如总的帧数,总的播放时间等等,要定位到某一帧或某个时间点也很方便,这种编码方式不需要文件头,第一帧开始就是音频数据;另一种是VBR,就是可变位率,VBR是XING公司推出的算法,所以在MP3的FRAME里会有“Xing”这个关键字(也有用“Info”来标识的,现在很多流行的小软件也可以进行VBR压缩,它们是否遵守这个约定,那就不得而知了),它存放在MP3文件中的第一个有效帧的数据区里,它标识了这个MP3文件是VBR的。同时第一个帧里存放了MP3文件的帧的总个数,这就很容易获得播放总时间,同时还有100个字节存放了播放总时间的100个时间分段的帧索引,假设4分钟的MP3歌曲,240s,分成100段,每两个相邻INDEX的时间差就是2.4s,所以通过这个INDEX,只要前后处理少数的FRAME,就能快速找出我们需要快进的帧头。其实这第一帧就相当于文件头了。不过现在有些编码器在编码CBR文件时也像VBR那样将信息记入第一帧,比如著名的lame,它使用“Info”来做CBR的标记。
  CBR总播放时长计算公式:
                   播放时长 = (文件大小 – ID3标签大小) * 8 / 比特率
  VBR总播放时长计算公式:
                  播放时长 = 有效数据帧总帧数 * 每帧采样数 / 采样率
(6)VBR头
  这里列出VBR的第一帧存储文件信息的头的格式。有两种格式,一种是常见的XINGHeader(头部包含字符‘Xing’),另一种是VBRIHeader(头部包含字符‘VBRI’)鉴于VBRIHeader不常见,下面只说XINGHeader。VBR的第一帧不包含声音数据,其长度是156个字节,用来存放标准的声音帧头(4字节)、VBR文件标识、帧数、文件字节数等信息,具体结构说明见表1-4。

                         表1-4 VBR文件第一帧结构

字节 说明
0 - 3 与CBR相同的标准声音帧头
4 - x 存放VBR文件标识“Xing”(58 69 6E 67),此标识具体位置视采用的MPEG标准和声道模式而定。标识的前后字节没有使用。
36 - 39 MPEG-1和非单声道(常见)
21 - 24 MPEG-1和单声道
21 - 24 MPEG-2和非单声道
13 - 16 MPEG-2和非单声道
40 - 43 指示VBR头具体内容的标志, 组合方式为逻辑或。区域是强制的,说明是否存储了帧数、文件长度、目录表和VBR规模信息,如果存储了,则分别为0x0001、0x0002、0x0004、0x0008。 如0x0007(意味总帧数,文件长度,目录表的存储区有效)
44 - 47 帧数(包括第一帧),存储总帧数的Big-Endian值
48 - 51 文件长度,存储文件长度Big-Endian值,单位为字节
52 - 151 目录表,用来按时间进行字节定位。 100字节的 TOC 索引,用于快速定位。 对于这个区域的存储内容,我认为可有可无,因为用1个字节来索引一个几兆文件的一帧是不可能做到准确定位的,就我所见基本上所有的VBR的mp3文件的 TOC都几乎是相同的,就是把256平均分成100份然后填进去,其实和正确的值差不到哪里去,如果懒的话这么做也成吧,反正也是不准确的定位。 TCO索引的计算方式如下 `(TOC[i] / 256) * 文件长度` 比如文件持续240秒,我需要跳到60秒,文件长度为5000000字节 计算如下 `TOC[(60/240)*100] = TOC[25]` 然后相对于文件中的位置大约是在 `(TOC[25]/256) * 5000000` 如果要自己重建的话,基本是把这个步骤反过来做就可以了。要求准确的话,就需要根据时间点找到正确帧的位置然后再计算,我定位帧的做法都是从第一帧开始搜索,这样偏差我认为不会超过1帧,也比较准确,不过计算出来的TOC的值还是和偷懒的做法大同小异。
152 -155 VBR规模,用于位率变动

  在VBR格式的第一帧中,XING Header包括帧头一共最多只需要156个字节就够了,当然也可以在XING Header后面存储编码器的信息,比如lame在其后就是存储其版本,这需要给第一帧留足够的空间才行。
至于mp3的信息用从XING Header读出的信息就可以计算,比如:
总持续时间 = 总帧数 * 每帧采样数 / 采样率 (结果为秒)
平均位率 = 文件长度 / 总持续时间 * 8

1.4.3.ID3v1

  ID3V1标准并不周全,存放的信息少,无法存放歌词,无法录入专辑封面、图片等。ID3V2是一个相当完备的标准,但给编写软件带来困难,虽然赞成此格式的人很多,在软件中绝大多数MP3仍在使用ID3V1标准。ID3v1标签包含艺术家,标题,唱片集,发布年代和流派。另外还有额外的注释空间。位于音频文件的最后固定为128字节。可以读取该文件的最后这128字节获得标签。
ID3V1结构如下:
AAABBBBB BBBBBBBB BBBBBBBB BBBBBBBB BCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDEEE EFFFFFFF FFFFFFFF FFFFFFFF FFFFFGHI
            表1-5 ID3V1.0文件尾说明

字节 长度(字节) 说明
1-3(A) 3 存放“TAG”字符,表示ID3 V1.0标准,紧接其后的是歌曲信息。
4-33(B) 30 歌名
34-63(C) 30 作者
64-93(D) 30 专辑名
94-97(E) 4 年份
98-125(F) 28 附注
126(G) 1 保留位
127(H) 1 音轨号
128(I) 1 MP3音乐类别(即流派),共147种

  ID3V1的各项信息都是顺序存放,没有任何标识将其分开,比如标题信息不足30个字节,则使用”\0”填充,数据结构定义如下:

typedef struct tagID3V1
{
    charHeader[3];          /*标签头必须是"TAG"否则认为没有标签*/
    charTitle[30];          /*标题*/
    charArtist[30];         /*作者*/
    charAlbum[30];          /*专集*/
    charYear[4];             /*出品年代*/
    charComment[28];         /*备注*/
    charreserve;             /*保留*/
    chartrack;              /*音轨*/
    charGenre;              /*类型*/
}ID3V1, *pID3V1;

            表1-6 MP3音乐类别(红色为Winamp扩充,蓝色为其他扩充)

num 类别 num 类别 num 类别 num 类别
0 ‘Blues’ 37 ‘Sound Clip’ 74 ‘Acid Jazz’ 111 “SlowJam”
1 ‘Classic Rock’ 38 ‘Gospel’ 75 ‘Polka’ 112 “Club”
2 ‘Country’ 39 ‘Noise’ 76 ‘Retro’ 113 “Tango”
3 ‘Dance’ 40 ‘AlternRock’ 77 ‘Musical’ 114 “Samba”
4 ‘Disco’ 41 ‘Bass’ 78 ‘Rock & Roll’ 115 “Folklore”
5 ‘Funk’ 42 ‘Soul’ 79 ‘Hard Rock’ 116 “Ballad”
6 ‘Grunge’ 43 ‘Punk’ 80 “Folk” 117 “PowerBallad”
7 ‘Hip-Hop’ 44 ‘Space’ 81 “Folk-Rock” 118 “RhythmicSoul”
8 ‘Jazz’ 45 ‘Meditative’ 82 “NationalFolk” 119 “Freestyle”
9 ‘Metal’ 46 ‘Instrumental Pop’ 83 “Swing” 120 “Duet”
10 ‘New Age’ 47 ‘Instrumental Rock’ 84 “FastFusion” 121 “PunkRock”
11 ‘Oldies’ 48 ‘Ethnic’ 85 “Bebob” 122 “DrumSolo”
12 ‘Other’ 49 ‘Gothic’ 86 “Latin” 123 “Acapella”
13 ‘Pop’ 50 ‘Darkwave’ 87 “Revival” 124 “Euro-House”
14 ‘R&B’ 51 ‘Techno-Industrial’ 88 “Celtic” 125 “DanceHall”
15 ‘Rap’ 52 ‘Electronic’ 89 “Bluegrass” 126 “Goa”
16 ‘Reggae’ 53 ‘Pop-Folk’ 90 “Avantgarde” 127 “Drum&Bass”
17 ‘Rock’ 54 ‘Eurodance’ 91 “GothicRock” 128 “Club-House”
18 ‘Techno’ 55 ‘Dream’ 92 “ProgessiveRock” 129 “Hardcore”
19 ‘Industrial’ 56 ‘Southern Rock’ 93 “PsychedelicRock” 130 “Terror”
20 ‘Alternative’ 57 ‘Comedy’ 94 “SymphonicRock” 131 “Indie”
21 ‘Ska’ 58 ‘Cult’ 95 “SlowRock” 132 “BritPop”
22 ‘Death Metal’ 59 ‘Gangsta’ 96 “BigBand” 133 “Negerpunk”
23 ‘Pranks’ 60 ‘Top 40’ 97 “Chorus” 134 “PolskPunk”
24 ‘Soundtrack’ 61 ‘Christian Rap’ 98 “EasyListening” 135 “Beat”
25 ‘Euro-Techno’ 62 ‘Pop/Funk’ 99 “Acoustic” 136 “ChristianGangstaRap”
26 ‘Ambient’ 63 ‘Jungle’ 100 “Humour” 137 “Heavyl”
27 ‘Trip-Hop’ 64 ‘Native American’ 101 “Speech” 138 “Blackl”
28 ‘Vocal’ 65 ‘Cabaret’ 102 “Chanson” 139 “Crossover”
29 ‘Jazz+Funk’ 66 ‘New Wave’ 103 “Opera” 140 “ContemporaryChristian”
30 ‘Fusion’ 67 ‘Psychadelic’ 104 “ChamberMusic” 141 “ChristianRock”
31 ‘Trance’ 68 ‘Rave’ 105 “Sonata” 142 “Merengue”
32 ‘Classical’ 69 ‘Showtunes’ 106 “Symphony” 143 “Salsa”
33 ‘Instrumental’ 70 ‘Trailer’ 107 “BootyBass” 144 “Trashl”
34 ‘Acid’ 71 ‘Lo-Fi’ 108 “Primus” 145 “Anime”
35 ‘House’ 72 ‘Tribal’ 109 “PornGroove” 146 “JPop”
36 ‘Game’ 73 ‘Acid Punk’ 110 “Satire” 147 “Synthpop”

其他任何的数值都认为是“unknown”

==补充:==
APEV2:一般存在于ID3V1之前,
标签头:

headerID[8];        //固定为“APETAGEX”
version[4];      //表示版版本
size[4];            //所有标签帧和尾标签的总长度,低位在前。
Count[4];          //标签帧的个数,低位在前。
Flags[4];          //
Reserved[8];        //保留位

标签尾:与标签头一样.
标签结构:

Size 4个字节大小   //帧内容的长度,低位在前
Flags 4个字节大小     //
Id                  //真标识,长度不固定
Pre                //恒为0
Value                //

Lyrics3v2:这个帧结构是用来保存歌词的。如果它存在的话,一般就是放在APEV2与ID3V1之间。结构如下:

开始标志 25字节   //“LYRICSBEGININD000003110LYR”,固定的。
歌词大小  5字节   //歌词的长度
歌词内容  x字节   //歌词的内容,长度肯定不固定。
帧大小    6字节  //前3项的长度,也就是25+5+歌词内容长度
结尾标识 9字节     //“LYRICS200”固定的

  这个标签很有用,在我们计算帧大小的时候就很有必要了,因为比如一个MP3是6M,但是可能歌词就占了1.5M,所以实际的帧只有4.5,所以在计算一些必要的信息时,我们需要把歌词的部分去掉。例如,我们可以从尾部移动137个字节(128+9),然后获取9个字节,判断是否与尾部标识匹配,如果匹配,则再移动6个字节,计算出尾部歌词的大小。我们就可以算出尾部歌词的字节数了。

2.AAC编码格式

2.1.AAC概述

  AAC是高级音频编码(Advanced Audio Coding)的缩写,出现于1997年,最初是基于MPEG-2的音频编码技术。由Fraunhofer IIS、Dolby Laboratories、AT&T、Sony等公司共同开发,目的是取代MP3格式。2000年,MPEG-4标准出台,AAC重新集成了其它技术(PS,SBR),为区别于传统的MPEG-2 AAC,故含有SBR或PS特性的AAC又称为MPEG-4 AAC。
  AAC是新一代的音频有损压缩技术,它通过一些附加的编码技术(比如PS,SBR等),衍生出了LC-AAC,HE-AAC,HE-AACv2三种主要的编码,LC-AAC就是比较传统的AAC,相对而言,主要用于中高码率(>=80Kbps),HE-AAC(相当于AAC+SBR)主要用于中低码率(<=80Kbps),而新近推出的HE-AACv2(相当于AAC+SBR+PS)主要用于低码率(<=48Kbps),事实上大部分编码器设成<=48Kbps自动启用PS技术,而>48Kbps就不加PS,就相当于普通的HE-AAC。

2.2.AAC扩展名

  AAC编码的主要扩展名有三种:
  1).AAC—使用MPEG-2 Audio Transport Stream( ADTS,参见MPEG-2 )容器,区别于使用MPEG-4容器的MP4/M4A格式,属于传统的AAC编码(FAAC默认的封装,但FAAC亦可输出 MPEG-4 封装的AAC)
  2).MP4—使用了MPEG-4 Part 14的简化版即3GPP Media Release 6 Basic (3gp6,参见3GP ) 进行封装的AAC编码(Nero AAC 编码器仅能输出MPEG-4封装的AAC);
  3).M4A - 为了区别纯音频MP4文件和包含视频的MP4文件而由苹果(Apple)公司使用的扩展名,Apple iTunes 对纯音频MP4文件采用了”.M4A”命名。M4A的本质和音频MP4相同,故音频MP4文件亦可直接更改扩展名为M4A。

2.3.AAC规格

  AAC共有9种规格,以适应不同的场合的需要:

            表1 AAC规则

文件 规格
MPEG-2 AAC LC 低复杂度规格(Low Complexity)
MPEG-2 AAC Main 主规格
MPEG-2 AAC SSR 可变采样率规格(Scaleable Sample Rate)
MPEG-4 AAC LC 低复杂度规格(Low Complexity)
MPEG-4 AAC Main 主规格
MPEG-4 AAC SSR 变采样率规格(Scaleable Sample Rate)
MPEG-4 AAC LTP 长时期预测规格(Long Term Predicition)
MPEG-4 AAC LD 低延迟规格(Low Delay)
MPEG-4 AAC HE 高效率规格(High Efficiency)

  其中: MPEG-2 AAC LC 比较简单,无增益控制,但提高了编码效率,在中等码率(96kbps-192kbps)的编码效率以及音质方面,都能找到平衡点。
  MPEG-4 AAC LC常用于MP4文件中的音频编码。
  MPEG-4 AAC Main包含了除增益控制之外的全部功能,其音质最好。
  MPEG-4 AAC HE适合用于低码率(32kbps-96kbps)编码。
  目前使用最多的是LC和HE(适合低码率)。流行的Nero AAC编码程序只支持LC,HE,HEv2这三种规格,编码后的AAC音频,规格显示都是LC。HE其实就是AAC(LC)+SBR技术,HEv2就是AAC(LC)+SBR+PS技术。

这里写图片描述
           图 2-1

  HE:“High Efficiency”(高效性)。HE-AAC v1(又称AACPlusV1,SBR),用容器的方法实现了AAC(LC)+SBR技术。SBR其实代表的是Spectral Band Replication(频段复制)。简要叙述一下,音乐的主要频谱集中在低频段,高频段幅度很小,但很重要,决定了音质。如果对整个频段编码,若是为了保护高频就会造成低频段编码过细以致文件巨大;若是保存了低频的主要成分而失去高频成分就会丧失音质。SBR把频谱切割开来,低频单独编码保存主要成分,高频单独放大编码保存音质,“统筹兼顾”了,在减少文件大小的情况下还保存了音质,完美的化解这一矛盾。
  HEv2:用容器的方法包含了HE-AAC v1和PS技术。PS指“parametric stereo”(参数立体声)。原来的立体声文件文件大小是一个声道的两倍。但是两个声道的声音存在某种相似性,根据香农信息熵编码定理,相关性应该被去掉才能减小文件大小。所以PS技术存储了一个声道的全部信息,然后,花很少的字节用参数描述另一个声道和它不同的地方。

2.4.AAC特点

  1)AAC是一种高压缩比的音频压缩算法,但它的压缩比要远超过较老的音频压缩算法,如AC-3、MP3等。并且其质量可以同未压缩的CD音质相媲美。
  2)同其他类似的音频编码算法一样,AAC也是采用了变换编码算法,但AAC使用了分辨率更高的滤波器组,因此它可以达到更高的压缩比。
  3)AAC使用了临时噪声重整、后向自适应线性预测、联合立体声技术和量化哈夫曼编码等技术,这些技术的使用都使压缩比得到进一步的提高。(压缩比通常为18:1)
  4)AAC支持更多种采样率和比特率、支持1个到48个音轨、支持多达15个低频音轨、具有多种语言的兼容能力、还有多达15个内嵌数据流。
  5)AAC支持更宽的声音频率范围,最高可达到96kHz,最低可达8KHz,远宽于MP3的16KHz-48kHz的范围。
  6)不同于MP3及WMA,AAC几乎不损失声音频率中的甚高、甚低频率成分,并且比WMA在频谱结构上更接近于原始音频,因而声音的保真度更好。
  7)AAC采用优化的算法达到了更高的解码效率,解码时只需较少的处理能力。
  8)不足:属于有损压缩,与APE、FLAC等无损格式相比,音质有“本质上”差距,同时USB3.0和大容量存储空间等技术的普及,AAC的优势不明显。

2.5.AAC音频格式解析

2.5.1.AAC音频格式有ADIF、ADTS、LATM

  • ADIF:Audio Data Interchange Format音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。

  • ADTS:Audio Data Transport Stream音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。

  • LATM 的全称为“Low-overhead MPEG-4 Audio TransportMultiplex”(低开销音频传输复用),是MPEG-4 AAC制定的一种高效率的码流传输方式,MPEG-2 TS流也采用LATM作为AAC音频码流的封装格式之一。

      LATM作为AAC音频码流的封装格式之一。
      LATM格式也以帧为单位,主要由AudioSpecificConfig(音频特定配置单元)与音频负载组成。AudioSpecificConfig描述了一个LATM帧的信息,音频负载主要由PayloadLengthInfo(负载长度信息)和PayloadMux(负载净荷)组成。AudioSpecificConfig结构说明如下:
    The Audio Specific Config is the global header for MPEG-4 Audio:

5 bits: object type
if (object type == 31)
        6 bits + 32: object type
4 bits: frequency index
if (frequency index == 15)
        24 bits: frequency
4 bits: channel configuration
var bits: AOT Specific Config

  AudioSpecificConfig 信息可以是带内传,也可以是带外传。所谓带内传,就是指每一个LATM 帧,都含有一个AudioSpecificConfig 信息;而带外传,则每一个LATM帧都不含有AudioSpecificConfig信息,而通过其他方式把AudioSpecificConfig信息发送到解码端,由于AudioSpecificConfig信息一般是不变的,所以只需发送一次即可。由此可见,AudioSpecificConfig信息采用带内传输可适应音频编码信息不断变化的情况,而采用带外传输,可以节省音频传输码率。带内或带外传,由muxconfigPresent 标志位决定。例如流媒体应用中,muxconfigPresent可设置为0,这样LATM帧中将不含有AudioSpecificConfig信息,LATM帧通过RTP包发送出去,AudioSpecificConfig 可通过SDP文件一次性传送到解码端。

         AudioSpecificConfig 主要参数

参数 含义
numSubFrames 子帧的数目
numProgram 复用的节目数
numLayer 复用的层数
frameLengthType 负载的帧长度类型,包括固定长度与可变长度
audioObjectType 音频对象类型
samplingFrequency 采样率
channelConfiguration 声道配置

  音频负载由若干子帧组成,每个子帧由PayloadLengthInfo和PayloadMux组成,与ADTS帧净荷一样,音频负载主要包含原始帧数据。
  AAC打包成TS流通常有两种方式,分别是先打包成ADTS或LATM。ADTS的每一帧都有个帧头,在每个帧头信息都一样的状况下,会有很大的冗余。LATM格式具有很大的灵活性,每帧的音频配置单元既可以带内传输,又可以带外传输。正因为如此,LATM不仅适用于流传输还可以用于RTP传输,RTP传输时,若音频数据配置信息是保持不变,可以先通过SDP会话先传输StreamMuxConfig(AudioSpecificConfig)信息,由于LATM流由一个包含了一个或多个音频帧的audioMuxElements序列组成。一个完整或部分完整的audioMuxElement可直接映射到一个RTP负载上。
  简单说,ADTS可以在任意帧解码,也就是说它每一帧都有头信息。ADIF只有一个统一的头,所以必须得到所有的数据后解码。且这两种的header的格式也是不同的,目前一般编码后的和抽取出的都是ADTS格式的音频流。两者具体的组织结构如下所示:

AAC的ADIF格式见下图:

header() raw_data_stream()

AAC的ADTS的一般格式见下图:

syncword header() error_check() raw_data_block()

图中表示出了ADTS一帧的简明结构,其两边的空白矩形表示一帧前后的数据。

2.5.2.ADIF和ADTS的header

(1)ADIF的头信息:

这里写图片描述

  ADIF头信息位于AAC文件的起始处,接下来就是连续的raw data blocks。
  组成ADIF头信息的各个域如下所示:

Field name Size(bits) Comment
adif_id 32(bits) Always: “ADIF”
copyright_id_present 1
copyright_id 72 Only if copyright_id_present == 1
original_copy 1
home 1
bitstream_type 1 0: CBR, 1: VBR
bitrate 23 For CBR: bitrate, for VBR: peak bitrate, 0 means unknown
num_program_config_elements 4
The next 2 fields come (num_program_config_elements + 1) times
buffer_fullness 20 Only if bitstream_type == 0
program_config_element VAR

(2)下面分析下ADTS头文件结构和信息:
  AAC音频文件的每一帧由ADTS Header和AAC Audio Data组成。

这里写图片描述

  一般情况下ADTS的头信息都是7个字节,分为2部分:其一为固定头信息,紧接着是可变头信息。固定头信息中的数据每一帧都相同,而可变头信息则在帧与帧之间可变。

adts_fixed_header();
adts_variable_header();

ADTS的固定头信息:

这里写图片描述

  • Syncword:同步字,总是0xFFF,all bits must be 1,代表着一个ADTS帧的开始;解码器可通过0xFFF确定每个ADTS的开始位置,因为它的存在,解码可以在这个流中任何位置开始, 即可以在任意帧解码。
  • ID:MPEG Version: 0 for MPEG-4,1 for MPEG-2
  • Layer:always: ‘00’
  • protection_absent:Warning, set to 1 if there is no CRC and 0 if there is CRC
  • profile:表示使用哪个级别的AAC,如01 Low Complexity(LC) – AAC LC。

      profile的值等于 Audio Object Type的值减1。
      profile = MPEG-4 Audio Object Type - 1

这里写图片描述

在MPEG-2 AAC中定义了3种:

这里写图片描述

  • sampling_frequency_index:表示使用的采样率下标,通过这个下标在Sampling Frequencies[ ]数组中查找得知采样率的值。

There are 13 supported frequencies:

这里写图片描述

  • channel_configuration:表示声道数,比如2表示立体声双声道

这里写图片描述

ADTS的可变头信息:

这里写图片描述

  • aac_frame_length:一个ADTS帧的长度包括ADTS头和AAC原始流。
  • adts_buffer_fullness:0x7FF说明是码率可变的码流。
  • number_of_raw_data_blocks_in_frame:

      表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。所以说number_of_raw_data_blocks_in_frame == 0 表示说ADTS帧中有一个AAC数据块。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
    组成ADTS头信息的各个域如下所示:

序号 长度(bits) 说明
1 Syncword 12 all bits must be 1
2 MPEG version 1 0 for MPEG-4, 1 for MPEG-2
3 Layer 2 always “00”
4 Protection Absent 1 et to 1 if there is no CRC and 0 if there is CRC
5 Profile 2 the MPEG-4 Audio Object Type minus 1
6 MPEG-4 Sampling Frequency Index 4 MPEG-4 Sampling Frequency Index (15 is forbidden)
7 Private Stream 1 set to 0 when encoding, ignore when decoding
8 MPEG-4 Channel Configuration 3 MPEG-4 Channel Configuration (in the case of 0, the channel configuration is sent via an inband PCE)
9 Originality 1 set to 0 when encoding, ignore when decoding
10 Home 1 set to 0 when encoding, ignore when decoding
11 Copyrighted Stream 1 set to 0 when encoding, ignore when decoding
12 Copyrighted Start 1 set to 0 when encoding, ignore when decoding
13 Frame Length 13 this value must include 7 or 9 bytes of header length: FrameLength = (ProtectionAbsent == 1 ? 7 : 9) + size(AACFrame)
14 Buffer Fullness 11 buffer fullness
15 Number of AAC Frames 2 number of AAC frames (RDBs) in ADTS frame minus 1, for maximum compatibility always use 1 AAC frame per ADTS frame
16 CRC 16 CRC if protection absent is 0

2.5.3.ADIF和ADTS数据信息

  在AAC中,原始数据块的组成可能有六种不同的元素:
  SCE:Single Channel Element单通道元素。单通道元素基本上只由一个ICS组成。一个原始数据块最可能由16个SCE组成。
  CPE:Channel Pair Element 双通道元素,由两个可能共享边信息的ICS和一些联合立体声编码信息组成。一个原始数据块最多可能由16个SCE组成。
  CCE:Coupling Channel Element 藕合通道元素。代表一个块的多通道联合立体声信息或者多语种程序的对话信息。
  LFE:Low Frequency Element 低频元素。包含了一个加强低采样频率的通道。
  DSE:Data Stream Element 数据流元素,包含了一些并不属于音频的附加信息。
  PCE:Program Config Element 程序配置元素。包含了声道的配置信息。它可能出现在ADIF 头部信息中。
  FIL:Fill Element 填充元素。包含了一些扩展信息。如SBR,动态范围控制信息等。

2.5.4.将AAC打包成ADTS格式

  如果是通过嵌入式高清解码芯片做产品的话,一般情况的解码工作都是由硬件来完成的。所以大部分的工作是把AAC原始流打包成ADTS的格式,然后丢给硬件就行了。通过对ADTS格式的了解,很容易就能把AAC打包成ADTS。我们只需得到封装格式里面关于音频采样率、声道数、元数据长度、aac格式类型等信息。然后在每个AAC原始流前面加上个ADTS头就OK了。
  贴上ffmpeg中添加ADTS头的代码,就可以很清晰的了解ADTS头的结构:

int ff_adts_write_frame_header(ADTSContext *ctx, uint8_t *buf, int size, int pce_size)
{
    PutBitContext pb;

    init_put_bits(&pb, buf, ADTS_HEADER_SIZE);

    /* adts_fixed_header */
    put_bits(&pb, 12, 0xfff);                      /* syncword */
    put_bits(&pb, 1, 0);                           /* ID */
    put_bits(&pb, 2, 0);                           /* layer */
    put_bits(&pb, 1, 1);                           /* protection_absent */
    put_bits(&pb, 2, ctx->objecttype);             /* profile_objecttype */
    put_bits(&pb, 4, ctx->sample_rate_index);
    put_bits(&pb, 1, 0);                           /* private_bit */
    put_bits(&pb, 3, ctx->channel_conf);           /* channel_configuration */
    put_bits(&pb, 1, 0);                           /* original_copy */
    put_bits(&pb, 1, 0);                           /* home */

    /* adts_variable_header */
    put_bits(&pb, 1, 0);                          /* copyright_identification_bit */
    put_bits(&pb, 1, 0);                          /* copyright_identification_start */
    put_bits(&pb, 13, ADTS_HEADER_SIZE + size + pce_size);     /* aac_frame_length */
    put_bits(&pb, 11, 0x7ff);                     /* adts_buffer_fullness */
    put_bits(&pb, 2, 0);                          /* number_of_raw_data_blocks_in_frame */

    flush_put_bits(&pb);
    return 0;
}

2.5.5.AAC文件处理流程

  (1)判断文件格式,确定为ADIF或ADTS;
  (2)若为ADIF,解ADIF头信息,跳至第6步;
  (3)若为ADTS,寻找同步头;
  (4)解ADTS帧头信息;
  (5)若有错误检测,进行错误检测;
  (6)解块信息;
  (7)解元素信息。

2.6.AAC解码流程

  语音系统对实时性要求较高,基本是这样一个流程,采集音频数据,本地编码,数据上传,服务器处理,数据下发,本地解码。
  ADTS是帧序列,本身具备流特征,在音频流的传输与处理方面更加合适。
  下面是AAC解码流程图:

这里写图片描述
          图2-2 AAC解码流程图

  在主控模块开始运行后,主控模块将AAC比特流的一部分放入输入缓冲区,通过查找同步字得到一帧的起始,找到后,根据ISO/IEC 13818-7所述的语法开始进行Noisless Decoding(无噪解码),无噪解码实际上就是哈夫曼解码,通过反量化(Dequantize)、联合立体声(Joint Stereo),知觉噪声替换(PNS),瞬时噪声整形(TNS),反离散余弦变换(IMDCT),频段复制(SBR)这几个模块之后,得出左右声道的PCM码流,再由主控模块将其放入输出缓冲区输出到声音播放设备。

==技术解析:==
1、主控模块:
  所谓的主控模块,它的主要任务是操作输入输出缓冲区,调用其它各模块协同工作。其中,输入输出缓冲区均由DSP控制模块提供接口。输出缓冲区中将存放的数据为解码出来的PCM数据,代表了声音的振幅。它由一块固定长度的缓冲区构成,通过调用DSP控制模块的接口函数,得到头指针,在完成输出缓冲区的填充后,调用中断处理输出至I2S接口所连接的音频ADC芯片(立体声音频DAC和DirectDrive耳机放大器)输出模拟声音。

3.WMA 编码格式

3.1.WMA概述

  WMA(Windows Media Audio),它是微软公司推出的与MP3格式齐名的一种新的音频格式。由于WMA在压缩比和音质方面都超过了MP3,更是远胜于RA(Real Audio),即使在较低的采样频率下也能产生较好的音质。一般使用Windows Media Audio编码格式的文件以WMA作为扩展名,一些使用Windows Media Audio编码格式编码其所有内容的纯音频ASF文件也使用WMA作为扩展名。
  WMA格式是以减少数据流量但保持音质的方法来达到更高的压缩率目的,其压缩率一般可以达到1:18,生成的文件大小只有相应MP3文件的一半。
  所需频宽:320~112kbps(压缩10~12倍)
  特性:当Bitrate小于128K时,WMA几乎在同级别的所有有损编码格式中表现得最出色,但似乎128k是WMA一个槛,当Bitrate再往上提升时,不会有太多的音质改变。
  优点:当Bitrate小于128K时,WMA最为出色且编码后得到的音频文件很小。
  缺点:当Bitrate大于128K时,WMA音质损失过大。WMA标准不开放,由微软掌握。
  应用领域:voip

3.2.WMA音频格式解析

  WMA是微软定义的一种媒体文件格式,它是一种流媒体。由于WMA协议是不公开的,所以我们就只能通过大量的文件来做分析,简单的分析网上一般都可以找到,下边我就引用别人的一些:

这里写图片描述
               WMA 文件结构示意图

  如图1,每一个WMA文件,它的头16个字节是固定的,为十六进制的“30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”,用来标识这个是否为WMA文件。接下来的8个字节为一个整数(高位存在后面),表示整个WMA文件头部的大小,这个头部里面包含了Tag信息等所有非音频信息,头部后面的是音频信息,我们在这里就不深入了解了。那个整数接下来的6个字节还没搞清楚是什么用的,不过不影响我们对Tag信息的读写。
  也就是说从文件开始偏移量为31开始,里面存放了很多帧,有我们需要的标准Tag信息,扩展Tag信息,WMA文件控制信息等等。每个帧不是等长的,但是帧头是固定的24个字节,其中前16字节是用来标识这个帧的名字,后8个字节是用来表示这个帧(包括帧头)的大小。这一点和MP3文件的ID3V2信息比较像。
  由于我们只需要读写Tag信息,而Tag信息又分别保存在两个帧里,分别为标准Tag帧和扩展Tag帧,所以我们只需要处理这两个帧,其他帧完全可以根据获得的帧长度来跳过。
  如图2,标准Tag帧只包含歌曲标题,艺术家,版权,备注四个内容。它的帧名是十六进制的“33 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”,在24个字节的帧头后紧跟着5个分别为2个字节的整数,前四个分别表示歌曲标题,艺术家,版权,备注的大小,第五个还不清楚有什么用的,大部分情况下是不使用的,即它的大小为0。在这10个字节后,这五个信息的内容就按顺序存放了。记住,在WMA文件里,所有的文字都是按Unicode宽字符的编码方式储存的,而且每个字符串后面都有一个0结束字符的。
  如图3,再看扩展Tag帧,这里就比较麻烦了,里面包含的信息的个数是不确定的,每个信息也是按照像帧一样的方式组织起来的。扩展Tag帧的帧名是十六进制的“40 A4 D0 D2 07 E3 D2 11 97 F0 00 A0 C9 5E A8 50”,在24字节的帧头(HeadFlag:16,HeadSize:8)后先有一个两个字节的整数表示这个帧里一共有的扩展信息个数(ExNo)。紧接着是扩展信息。
  如图4,每一个扩展信息包含扩展信息名字和对应的值。先有一个2个字节的整数来表示扩展信息名字的大小,接着是扩展信息名称,然后有一个2个字节的整数标志(Flag),这个后面再讲。然后又是一个2个字节的整数,表示值的大小,接着就是这个值。
  当扩展信息名字为WMFSDKVersion时,这个值表示的是这个WMA文件的版本;当扩展信息名字为WM/AlbumTitle时,这个值代表的就是专辑名;当扩展信息名字为WM/Genre时,这个值代表的就是流派;同理,很容易从扩展信息的名字看出这个值的用途的。这些扩展信息的名字和值几乎都是用Unicode的字符串来存储的,到现在为止只发现对下面两个情况例外。(关于所有扩展信息的名字可以从很多地方查到,比如SDK帮助,MSDN)
  下面再来看看那个标志Flag,这个基本上是没什么用的(通常值为0),只对WM/TrackNumber和WM/Track这两个扩展信息名字有用,当Flag为3的时候后面的值(也就是曲目信息)是以4个字节的整数的形式表示,当Flag为0的时候,曲目信息是以普通的字符串形式表示的。

4.WAV编码格式

4.1.WAV概述

  WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持MSADPCM,CCITTALAW等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几。WAV打开工具是WINDOWS的媒体播放器。
  通常使用三个参数来表示声音:量化位数、取样频率和采样点振幅。量化位数分为8位、16位、24位三种,声道有单声道和立体声之分,取样频率一般有11025Hz(11kHz)、22050Hz(22kHz)和44100Hz(44kHz)三种,不过尽管音质出色,但在压缩后的文件体积过大!相对其他音频格式而言是一个缺点,其文件大小的计算方式为:WAV格式文件所占容量(B) = (取样频率 量化位数 声道) * 时间 / 8 (1字节= 8bit) 每一分钟WAV格式的音频文件的大小为10MB,其大小不随音量大小及清晰度的变化而变化。
  WAV是最接近无损的音乐格式,所以文件大小相对也比较大。

4.2.WAV特点

  WAV音频格式的优点包括:简单的编/解码(几乎直接存储来自模/数转换器(ADC)的信号)、普遍的认同/支持以及无损耗存储。WAV格式的主要缺点是需要音频存储空间。对于小的存储限制或小带宽应用而言,这可能是一个重要的问题。WAV格式的另外一个潜在缺陷是在32位WAV文件中的2G限制,这种限制已在为SoundForge开发的W64格式中得到了改善。
  常见的WAV文件使用PCM无压缩编码,这使WAV文件的质量极高,体积也出奇大,对于PCM WAV,恐怕也只有无损压缩的音频才能和其有相同的质量,平时我们见的什么mp3,wma(不含wmalossless)和wav的质量都是差很远的!这点可以通过频谱看出,即使320kbps的mp3和wav一比,也要自卑了!

4.3.剖析WAV

  WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为“WAV”,数据本身的格式为PCM或压缩型,属于无损音乐格式的一种。
  符合RIFF(Resource Interchange File Format资源互换文件格式)规范,RIFF文件是windows环境下大部分多媒体文件遵循的一种文件结构,RIFF文件所包含的数据类型由该文件的扩展名来标识,能以RIFF文件存储的数据包括:音频视频交错格式数据(.AVI)波形格式数据(.WAV)位图格式数据(.RDI)MIDI格式数据(.RMI)调色板格式(.PAL)多媒体电影(.RMN)动画光标(.ANI)其它RIFF文件(.BND)。每个WAV文件的头四个字节便是“RIFF”。
  WAV文件由文件头和数据体两大部分组成。其中文件头又分为RIFF/WAV文件标识段和声音数据格式说明段两部分。WAV文件各部分内容及格式见下表。常见的声音文件主要有两种,分别对应于单声道(11.025KHz采样率、8Bit的采样值)和双声道(44.1KHz采样率、16Bit的采样值)。采样率是指:声音信号在“模→数”转换过程中单位时间内采样的次数。采样值是指每一次采样周期内声音模拟信号的积分值。对于单声道声音文件,采样数据为八位的短整数(short int 00H-FFH);而对于双声道立体声声音文件,每次采样数据为一个16位的整数(int),高八位和低八位分别代表左右两个声道。WAV文件数据块包含以脉冲编码调制(PCM)格式表示的样本。WAV文件是由样本组织而成的。在单声道WAV文件中,声道0代表左声道,声道1代表右声道。在多声道WAV文件中,样本是交替出现的。WAV对音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以为WAV的音频流进行编码。数据块的记录方式是little-endian字节顺序,标志符并不是字符串而是单独的符号。

这里写图片描述
            图4-1 WAV音频文件格式

  • 文件头
    • RIFF/WAV文件标识段
    • 声音数据格式说明段
  • 数据体:由PCM(脉冲编码调制)格式表示的样本组成。

      WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:
      RIFF WAVE Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。具体见下表(图4-1无Fact Chunk):

                               表4-1 WAV文件的组成

偏移地址 大小字节 数据块类型 内容
00H~03H 4 char 资源交换文件标志(RIFF)
04H~07H 4 long 从下个地址开始到文件尾的总字节数(little-endian 32-bit 正整数,整个档案的大小,扣掉辨识字符和长度,共8个字节。)
08H~0BH 4 char WAV文件标志(WAVE)
0CH~0FH 4 char 波形格式标志(fmt),最后一位空格。
10H~13H 4 不定 过滤字节(一般为00000010H),若为00000012H则说明数据头携带附加信息(见“附加信息”)。
14H~15H 2 int 格式种类(值为1时表示数据为线性PCM编码,大于1时表示有压缩的编码)
16H~17H 2 int 通道数,单声道为1,双声道为2
18H~1BH 4 long 采样频率
1CH~1FH 4 long 波形数据传输速率(每秒平均字节数):Byte率=采样频率音频通道数每次采样得到的样本位数/8
20H~21H 2 int DATA数据块长度,字节。块对齐=通道数*每次采样得到的样本位数/8
22H~23H 2 int PCM位宽,即样本数据位数
随后2字节 2 int 附加信息(可选,由上方过滤字节确定)
随后 不定长度字符 “fact”,该部分是可选部分,一般当WAV文件是由某些软件转换而来时,包含该部分。若包含该部分:(1)该部分的前4字节为数据头,一般为4个字母。(2)随后4个字节表示长度,即除去头(4字节)和长度(4字节)之后,数据本身的长度。(3)最后的字节为数据本身。例如:“66 61 73 74 04 00 00 00F8 2F 14 00” 。“66 61 73 74”是fact字段的数据头,“04 00 00 00”是数据本身的长度,“F8 2F 14 00”是数据本身。(注意是little-endian字节顺序)
随后4字节 4 char 数据标志符(data)
随后4字节 4 int DATA总数据长度 字节
随后 不定 DATA数据块

  WAV文件作为最经典的Windows多媒体音频格式,应用非常广泛,它使用三个参数来表示声音:采样位数、采样频率和声道数。
举例:我们使用UE打开这个音频文件

这里写图片描述

注意,我们的PC都是小端模式,所以注意读取数据的真实内容。
我们解读一下这个wav文件
  00H ~ 03H 52 49 46 46 对应的是RIFF
  04H ~ 07H 48 10 03 00 对应的是后面文件的大小,小端模式所以是00031048 ,换算为十进制的200776
  08H ~ 0BH 57 41 56 45 对应的是标示符WAVE
  0CH ~ 0FH 66 6d 74 20 对应是波形格式标示符fmt
  10H ~ 13H 12 00 00 00 对应的是过滤字节,不知道是什么作用,由于本文件不是标准的采样率,所以可能和上面的不一致
  14H ~ 15H 01 00 对应的十进制是1 线性的PCM编码,我们这里只探讨PCM编码
  16H ~ 17H 01 00 对应的十进制是1 表示单声道,MONO
  18H ~ 1BH 80 3E 00 00 对应的十进制是16000.表示采样率是16000的
  1CH ~ 1FH 00 7D 00 00 对应的十进制是32000,波形数据传输率,每秒多少个字节,可以用(200776 -72)/32000 = 6.272s
  20H ~ 21H 02 00 对应的十进制是2,数据的调整数
  22H ~ 23H 10 00 对应的十进制是16,样本数据的位数,表示用16位表示一个样本

  我们的和表4-1之间有一些差距,是ffmpeg转码的数据,所以中间夹着了一些ffmpeg的信息
  48H ~ 4BH 64 61 74 71 对应的ACSCII码是data
  4CH ~ 4FH 00 10 03 00 对应的十进制是200704,表示采样数据的总数
  从50H开始就是真正的数据部分

  在使用ffmpeg解包的时候总共是有49个包,每个包的大小为4096, 49*4096 =200704,
  怎么计算出来包的大小,需要进一步的分析。

对于Data块,根据声道数和采样率的不同情况,布局如下(每列代表8bits):

采样率和声道数 采样1 采样2
8 Bit 单声道 数据1 数据2
8 Bit 双声道 声道1数据1 声道2数据1 声道1数据2 声道2数据2
16 Bit 单声道 数据1低字节 数据1高字节 数据1低字节 数据1高字节
16 Bit 双声道 声道1数据1低字节 声道1数据1高字节 声道2数据1低字节 声道2数据1高字节 声道1数据2低字节 声道1数据2高字节 声道2数据2低字节 声道2数据2高字节

PCM数据的存放方式:
  WAV文件的每个样本值包含在一个整数i中,i的长度为容纳指定样本长度所需的最小字节数。首先存储低有效字节,表示样本幅度的位放在i的高有效位上,剩下的位置为0,这样8位和16位的PCM波形样本的数据格式如下所示。

样本大小 数据格式 最大值 最小值
8位PCM Unsigned int 225 0
16位PCM int 32767 -32767

下面我们看一个具体的例子,wav音频文件如下:(十六进制的形式)

这里写图片描述

对应的分析如下图所示:

这里写图片描述

==补充:RIFF概念==
  在Windows环境下,大部分的多媒体文件都依循着一种结构来存放信息,这种结构称为“资源互换文件格式”(Resources lnterchange File Format),简称RIFF。例如声音的WAV文件、视频的AVI文件等等均是由此结构衍生出来的。RIFF可以看做是一种树状结构,其基本构成单位为chunk,犹如树状结构中的节点,每个chunk由“辨别码”、“数据大小”及“数据”所组成。

块的标志符(4BYTES)
数据大小 (4BYTES)
数据

 图一、 块的结构示意图

  辨别码由4个ASCII码所构成,数据大小则标示出紧跟其后数据的长度(单位为Byte),而数据大小本身也用掉4个Byte,所以事实上一个chunk的长度为数据大小加8。一般而言,chunk本身并不允许内部再包含chunk,但有两种例外,分别为以“RIFF”及“LIST”为辨别码的chunk。而针对此两种chunk,RIFF又从原先的“数据”中切出4个Byte。 此4个Byte称为“格式辨别码”,然而RIFF又规定文件中仅能有一个以“RIFF”为辨别码的chunk。

RIFF/LIST标志符(4BYTES)
数据1大小 (4BYTES)
数据1 格式/列表类型
数据

 图二、RIFF/LIST块结构

  只要依循此一结构的文件,我们均称之为RIFF档。此种结构提供了一种系统化的分类。如果和MS-DOS文件系统作比较,“RIFF”chunk就好比是一台硬盘的根目录,其格式辨别码便是此硬盘的逻辑代码(C:或D:),而“LIST”chunk即为其下的子目录,其他的chunk则为一般的文件。至于在RIFF文件的处理方面,微软提供了相关的函数。视窗下的各种多媒体文件格式就如同在磁盘机下规定仅能放怎样的目录,而在该目录下仅能放何种数据。

5.ALAC编码格式

  ALAC(Apple Lossless Audio Codec)苹果的无损音频压缩编码格式,ALAC与MP3的主要分别在于编码过程中,MP3会取消小部分高频及低频部分的音频数据,而ALAC则会如实记录,不会删除音频中任何细节数据。由于资料无损,ALAC音频文件大小会比MP3大,通常每片音乐CD(约70至80分钟)经ALAC编码后,音频文件大小约300MB。
  常见ALAC编码音频文件同AAC编码音频均采用m4a容器封装,需注意查看编码信息可区分它们。

6.AC-3编码格式

6.1.AC-3概述

  AC-3(Digital Audio Compression Standard)音频编码格式,传说中的杜比实验室的杰作,著名的有损数据压缩的多媒体储存格式。可以包括多达6个独立的声道。最知名的是5.1声道技术。在5.1声道技术中,5代表着5个基本声道,独立连接至五个不同的喇叭(20至20,000 Hz),分别是右前(RF),中(C),左前(LF),右后(RR),左后(LR);而1则代表1个低频声效,连接至低音辅助喇叭(20至120 Hz)每个AC-3 的音频帧都是以0x0B77为同步头。开源解码库liba52。
  AC-3是一种灵活的音频数据压缩技术,它具有将多种声轨格式编码为一种低码率比特流的能力。支持8种不同的声道配置方式,从传统的单声道、立体声到拥有6个分离声道的环绕声格式(左声道、中置声道、右声道、左环绕声道、右环绕声道及低音效果声道)。AC-3的比特流所允许的采样频率可以为48 kHz、44.1 kHz、或32 kHz中的任何一种,并且所支持的码率从32 kbps(千比特位/秒)到640 kbps不等。

6.2.AC-3比特流的特征

  AC-3的比特流是由帧(Frame)构成的(详见图6-1),在恒定的时间间隔内,其所有编码的声道所包含的信息就能体现在1536个PCM采样值的信息。每一个AC-3的帧(Frame)都具有固定的尺寸,只由采样频率及编码数据率决定。同时,每个帧(Frame)都是独立的实体而且并不与前一个帧(Frame)分享数据,除了在MDCT所固有的去交迭变换。

SYNC CRC#1 SI BSI AUDIO BLOCK 0 AUDIO BLOCK 1 AUDIO BLOCK 2 AUDIO BLOCK 3 AUDIO BLOCK 4 AUDIO BLOCK 5 AUX DATA CRC#2

                           图6-1 AC-3帧结构

Block Switch Flags Dither Flags Dynamic Range Control Coupling Strategy Coupling Coordinates Exponent Strategy Exponents Bit Allocation Parameters Mantissas

                          图6-2 AC-3声音块结构

  在每个AC-3帧(Frame)的开头是SI域(同步信息Sync Information)及BSI域(比特流信息)。SI域及BSI域描述了比特流的结构,包括采样频率、数据码率、编码声道的数目及其他一些系统描述的元素。每个帧用两个CRC(循环冗余码校验字)字来提供侦错手段,一个位于帧的起始处,另一个位于帧的结尾。每个帧有6个声音块,每个块表示为每个编码声道包含256个PCM取样(sample)(详见图6-2)。声音块中所含内容包括块转换标志,耦合坐标、指数、位分配参数、尾数。允许在帧的内部进行数据分享,比如在声音块0中的数据可以被同一帧内的后续块所使用。在每个帧的结尾处有一个可选的辅助数据域,在这个区域内允许系统设计者在AC-3比特流中嵌入可在整个系统内传递的、自有的控制字及状态字信息。AC-3的编/解码器被设计成一个完整的音频子系统的解决方案,它拥有普通的低码率编/解码所没有的许多特性。这些特性包括适用于消费类音频回放系统的动态范围压缩特性(Dynamic Range Compression)、对话归一(Dialog Normalization)以及缩混特性(Downmixing),缩混特性可以将多声道音频进行转换为特定数目的声道输出。动态范围控制(Dynamic Range Control)的控制字是嵌入在AC-3比特流内,并被解码器应用,可以使同一个比特流源在不同模式下进行还音。

7.APE编码格式

7.1.APE简单介绍

  APE是Monkey’s Audio提供的一种无损压缩音频格式。与mp3、ogg有损压缩方式不同,庞大的WAV音频文件通过Monkey’s Audio软件进行“瘦身”压缩,压缩比大约为2:1(为源文件的60%左右)。由于采用特殊算法,保证音质不受损失,通过解压缩可以得到与源文件一致的品质,即通过Monkey’还原成WAV,还可把APE音频格式刻录成CD保存。而还原后的音乐文件与压缩前一模一样,没有任何音质损失,因此可以用它来保存、复制CD。因为被压缩后的APE文件容量要比WAV源文件小一半多,如用于网络音频文件传输,可以节约传输所用的时间且能保持音质。其特点如下所示:
  (1)Monkey’s Audio是高优化和高效率的;
  (2)无损压缩,没有质量损失;
  (3)可以被大多数的流行players和rippers支持,如Media Center、Foobar、WMP、Winamp等;
  (4)完全免费和开源。

7.2.APE文件结构

7.2.1.Header句法结构

  Header的内容包括:文件的属性、sound的参数(如声道数、采样率等)、内部结构(如帧数、Seek Table,甚至可能包括WAV的header)。Header的句法结构如下图所示:

这里写图片描述
这里写图片描述
这里写图片描述

7.2.2.Header句法元素含义

  (1)tag:此元素的值为四个字符“MAC”,是APE文件的标志。可以通过该标志来判断一个媒体文件是否为APE文件。
  (2)compression_level:压缩等级,对应的等级如下所示:

这里写图片描述

  (3)format_flags:APE文件标记,标记了APE文件以及APE编码格式的一些属性,如sample的位数、是否含有CRC校验、是否含有WAVE Header等等。ffmpeg对format_flags值的定义如下所示,这也是在句法结构图中的那些数字的含义。

#define MAC_FORMAT_FLAG_8_BIT               1   // is 8-bit [OBSOLETE]
#define MAC_FORMAT_FLAG_CRC               2     // uses the new CRC32 error detection [OBSOLETE]
#define MAC_FORMAT_FLAG_HAS_PEAK_LEVEL      4   // uint32 nPeakLevel after the header [OBSOLETE]
#define MAC_FORMAT_FLAG_24_BIT              8   // is 24-bit [OBSOLETE]
#define MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS   16  // has the number of seek elements after the peak level
#define MAC_FORMAT_FLAG_CREATE_WAV_HEADER   32  // create the wave header on decompression (not stored)

  (4)seek_table_length:标识了seek_table的长度。在file_version大于等于3980的版本中,seek_table_length是seek_table所占用的字节数;而在file_version小于3980的版本中,seek_table_length是seek_table包含的数组元素个数,与seek_table包含字节数为四倍的关系。
  (5)seek_table:seek_table中存放的是每个frame在APE文件中的position。但是,在真正去读取frame的时候,需要考虑四字节对齐的问题。
  (6)total_frames:包含frame的个数。
  (7)blocks_per_frame:标识每个frame包含的block的个数,这只对前total _frames - 1的frame有效。对于最后一个frame,它所包含的block的个数由句法元素final_frame_blocks的值来指定。
  (8)final_frame_blocks:最后一个frame包含的block的个数。

7.2.3.APE Tag结构

  APE tag用来存放metadata数据,比如歌名、演唱者、专辑名等等,这些信息就称为tag(标签)信息。APE tag有两个版本,即APEV1与APEV2。APEV1一般放在文件的末尾,而APEV2具有与ID3v2一样的灵活性和可括展性,字段名可自定义,字段长度可扩展,同时格式定义又不像ID3v2那么繁琐。APEV2的格式很简单,实现起来也很方便,tag存放位置是可选的,既可以在文件头也可以在文件尾。APEV1与APEV2的区别主要有两个方面:
  (a)APEV1使用的是ACSII编码,而APEV2使用的是UTF-8编码,使得可以实现unicode支持。
  (b)APEV2标准里增加了一个APE Tags Header,APEV1里面没有。
APEV1与APEV2的结构分别如下图所示:

这里写图片描述

(1)APE Tags Header
  APE Tags Header只在APEV2中才有,其内容包括整个tag的长度、item的个数等。最开始是固定的8个字符“APETAGEX”,用来标识tag header的开始。APE Tags Header与APE Tags Footer的结构相似,唯一的不同就是Tags Flag中的一个bit,这也是用于区分APE Tags Header与APE Tags Footer的一个标记。APE Tags Header的结构如下所示:

Preamble 64 bits {‘A’, ‘P’, ‘E’, ‘T’, ‘A’, ‘G’, ‘E’, ‘X’}
Version Number, Bits 0…7 Version Number, Bits 8…15 Version Number, Bits 16…23 Version Number, Bits 24…31 32 bits 1000 = Version 1.000 (old) 2000 = Version 2.000 (new)
Tag Size, Bits 0…7 Tag Size, Bits 8…15 Tag Size, Bits 16…23 Tag Size, Bits 24…31 32 bits Tag size in bytes including footer and all tag items excluding the header to be as compatible as possible with APE Tags 1.000
Item Count, Bits 0…7 Item Count, Bits 8…15 Item Count, Bits 16…23 Item Count, Bits 24…31 32 bits Number of items in the Tag (n)
Tags Flags, Bits 0…7 Tags Flags, Bits 8…15 Tags Flags, Bits 16…23 Tags Flags, Bits 24…31 32 bits Global flags of all items (there are also private flags for every item)
Reserved 64 bits Must be zero

(2)APE Tag Item
  APE Tag Item存在于APEV1和APEV2中,其结构如下所示:

Size of the Item Value, Bits 0…7 Size of the Item Value, Bits 8…15 Size of the Item Value, Bits 16…23 Size of the Item Value, Bits 24…31 32 bits Length len of the assigned value in bytes
Tags Flags, Bits 0…7 Tags Flags, Bits 8…15 Tags Flags, Bits 16…23 Tags Flags, Bits 24…31 32 bits Item flags
Item Key m bytes Item key, can contain ASCII characters from 0x20 (Space) up to 0x7E (Tilde)
0x00 1 byte Item key terminator
Item Value len bytes Item value, can be binary data or UTF-8 string

(3)APE Tags Footer
  APE Tags Footer与APE Tags Header的结构相似,但它可以存在于APEV1和APEV2中。唯一的不同就是Tags Flag中的一个bit位,这也是用于区分APE Tags Header与APE Tags Footer的一个标记。最开始是固定的8个字符“APETAGEX”,用来标识tag footer的开始。APE Tags Footer的结构如下所示:

Preamble 64 bits {‘A’, ‘P’, ‘E’, ‘T’, ‘A’, ‘G’, ‘E’, ‘X’}
Version Number, Bits 0…7 Version Number, Bits 8…15 Version Number, Bits 16…23 Version Number, Bits 24…31 32 bits 1000 = Version 1.000 (old) 2000 = Version 2.000 (new)
Tag Size, Bits 0…7 Tag Size, Bits 8…15 Tag Size, Bits 16…23 Tag Size, Bits 24…31 32 bits Tag size in bytes including footer and all tag items excluding the header to be as compatible as possible with APE Tags 1.000
Item Count, Bits 0…7 Item Count, Bits 8…15 Item Count, Bits 16…23 Item Count, Bits 24…31 32 bits Number of items in the Tag (n)
Tags Flags, Bits 0…7 Tags Flags, Bits 8…15 Tags Flags, Bits 16…23 Tags Flags, Bits 24…31 32 bits Global flags of all items (there are also private flags for every item)
Reserved 64 bits Must be zero

(4)一个简单的示例
  上面的几个图来自wiki,可能有点抽象。我们以一个简单的示例来说明一下,这样比较直观。如下图所示,图为在Linux平台用ghex打开的一个APE文件。

这里写图片描述

从图中可以看出,该tag为APEV2 tag。
a、APE Tags Header
  首先是APE Tags Header,从图中可以很容易的找到,以“APTTAGEX”开始,然后是4个字节的version,0x00 00 07 D0,即version为2000。
  然后是四个字节的tag size,为0x00 00 00 72,即整个APE tag包括114个字节,其中不包括APE Tags Header的长度。可以从图中数一下,确实是114个字节。
  在然后的四个字节是item的个数,0x00 00 00 03,即包括三个item。
  紧接着是4个字节的flags,为0xA0 00 00 00。
  最后是reserved的8个字节,全部为0。
b、APE Tag Item
  由对APE Tags Header的分析可以知道,该tag中包括了三个item,从图中也可以看的出来,分别为Title、Artist和Album。我们可以以Title这个item为例进行分析。APE Tags Header为固定的32个字节,因此,跳过32个字节之后便是Title这个item的内容。
  首先是四个字节的length,0x00 00 00 0C,即为12个字节。这个12表示该item的value占12个字节。
  然后是四个字节的flags,这里为0x00 00 00 00。
  接着是item的key,这里为Title,是ASCII编码。item的key后面是一个字节的标志位,为0x00,用于标识item的key结束。
  最后是item的value,由上面的分析可以知道为12个字节。
c、APE Tags Footer
  APE Tags Footer的结构和APE Tags Header的结构是一样的,而且内容几乎一样,唯一的区别就在于flag。APE Tags Header的flag为0xA0 00 00 00,而APE Tags Footer的flag为0x80 00 00 00。查看了几个APE文件,APE Tags Header的flag都为0xA0 00 00 00,而APE Tags Footer的flag都为0x80 00 00 00,这两个flag的值可能是固定的值(个人猜测),以此来区分APE Tags Footer与APE Tags Header。

8.FLAC编码格式

8.1.FLAC概述

  FLAC(Free Lossless Audio Codec)中文可解释为无损音频压缩编码。FLAC是一套著名的自由音频压缩编码,其特点是无损压缩。不同于其他有损压缩编码如MP3 及AAC,它不会破坏任何原有的音频资讯,所以可以还原音乐光盘音质。2012年以来它已被很多软件及硬件音频产品(如CD等)所支持。
  **解析区别:**FLAC与MP3不同,MP3是有损音频压缩编码,但FLAC是无损压缩,也就是说音频以FLAC编码压缩后不会丢失任何信息,将FLAC文件还原为WAV文件后,与压缩前的WAV文件内容相同。这种压缩与ZIP的方式类似,但FLAC的压缩比率大于ZIP和RAR,因为FLAC是专门针对PCM音频的特点设计的压缩方式。而且可以使用播放器直接播放FLAC压缩的文件,就像通常播放你的MP3文件一样(近几年已经有许多汽车播放器和家用音响设备支持FLAC,在FLAC的网站上你可以找到这些设备厂家的链接)。

8.2.FLAC编码过程及相关定义

8.2.1.FLAC编码过程

  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:Right不变

  建模(modeling):编码器尝试使用一个数学方法(近似)描述原始信号,这种描述信息一般来说比原始信息小得多,这些数学方法是编码器和解码器都已知的(flac现在有4个种类的预测方法,并可以加入更多方法)flac运行在各个块中使用不同的预测算法。大多时候不能完全精确的描述原始信息,此时还会剩下少量数据残渣(residual, residue, or error)。Flac有两种产生近似值的方法:1)为信号找个合适的多项式。2)简单线性预测(LPC)。前者更快但不精确。
  数据残渣编码:对建模后剩余的数据进行编码,保证数据的无损。目前flac只使用一种编码方法。
  帧(framing):一个音频帧被一个帧头(frame header)和帧脚(frame footer)包围。帧头以同步字开始,包含了解码这帧的最小信息如采样率,采样位数等,同时包含了这帧里的分块数或采样数及一个8位CRC校验码。帧头可以用来进行再同步。帧尾包含一个16位CRC校验码。如果解码器检测到CRC错误将产生一个silent block。

8.2.2.定义

(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)

8.3.FLAC格式解析

8.3.1.FLAC文件结构

                      表8-1 FLAC文件结构

Field Name Length(bit) Description
文件标记“fLaC” 32 “fLaC”标志,用于识别flac数据流 0x66 0x41 0x61 0x43
METADATA BLOCK 34*8 STREAMINFO,必选的metadata block,说明Stream的基本特性(采样率、声道数…)。
METADATA BLOCK 一个或者多个metadata block,可选。(解码时可以不用识别)
AUDIO FRAMES 一个或者多个Audio Frame

8.3.2.FLAC格式

  Flac中所有数值都是整形,大端模式,除非特别指出,否则数值都是unsigned的。
(1)概述
  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,为了得到采样率和声道数等信息,需要再帧头里加入相关信息,为了减少数据,使用了查表的方法来定义常用的采样率。
(2)格式

这里写图片描述

这里写图片描述
这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述
这里写图片描述

9.AMR编码格式

9.1.AMR概述

  AMR(Adaptive Multi-Rate)自适应多速率音频压缩音频编码格式,是一个使语音编码最优化的专利,专用于有效地压缩语音频率。
  AMR音频主要用于移动设备的音频压缩,压缩比非常高,但是音质比较差,主要用于语音类的音频压缩,不适合对音质要求较高的音乐类音频的压缩。AMR被标准语音编码 3GPP在1998年10月选用,现在广泛在GSM和UMTS中使用。它使用1-8个不同的位速编码。之前的手机里有很多amr的音频文件,可分成:
- AMR-NB(AMR-NarrowBind),语音带宽范围:300-3700Hz,8KHz采样频率,每20ms编码一帧,每个帧中包含160个语音样点;
- AMR-WB(Adaptive Multi-Rate - Wideband Speech Codec),语音带宽范围50-7000Hz,16KHz采样频率。但考虑语音的短时相关性,每帧长度均为20ms;
- AMR-WB+(Extended Adaptive Multi-Rate - Wideband Speech Codec):amr-nb和amr-wb都属于speech codec,对audio的编码效果并不好,为了提高对audio的编码效果,出现了amr-wb+。amr-wb+可以支持更高的采样率,对speech和audio采用不同的编码算法,对speech采用ACELP编码,对audio采用变换编码。amr-wb+在低比特率上对audio的编码效果与he aac+相当。amr-wb+包含amr-wb,但复杂度更高。

9.2.AMR编码方式

  (1)AMR-NB一共有16种编码方式。0-7对应8种不同的编码方式,每种编码方式的采样频率不同;8-15 用于噪音或者保留用。

这里写图片描述

说明:
  比特率是指将数字声音由模拟格式转化成数字格式的采样率,采样率越高,还原后的音质就越好。
  比特率值与现实音频对照:
- 16kbps=电话音质
- 24kbps=增加电话音质,短波广播,长波广播,欧洲制式中波广播
- 40kbps=美国制式中波广播
- 56kbps=话音
- 64kbps=增加话音(手机铃声最佳比特率设定值,手机单声道MP3播放器最佳设定值)
- 112kbps=FM调频立体声广播
- 128kbps=磁带(手机立体声MP3播放器最佳设定值,低档MP3播放器最佳设定值)
- 160kbps=HIFI高保真(中高档MP3播放器最佳设定值)
- 192kbps=CD(高档MP3播放器最佳设定值)
- 256kbps=Studio音乐工作室(音乐发烧友适用)

  (2)AMR-WB全称为“Adaptive Multi-rate–Wideband”,即“自适应多速率宽带编码”,采样频率为16kHz,是一种同时被国际标准化组织ITU-T和3GPP采用的宽带语音编码标准,也称为G722.2标准。
  AMR-WB支持9种不同的编码方式:6.6kb/s、8.85kb/s、12.65kb/s、14.25kb/s、15.85kb/s、18.25kb/s、19.85kb/s、23.05kb/s、23.85kb,提供的语音带宽范围达到50~7000Hz,人声感觉比以前更加自然、舒适和易于分辨。

这里写图片描述

9.3.AMR文件结构解析

  下面我们来看一个实际的AMR文件(http://download.csdn.net/detail/ce123/6701049):

这里写图片描述

  从图中可以看出,所有AMR文件头标志是6个字节(最后一个字节是换行符”/n”)。帧头为0x2C,后面就紧跟的是音频帧。这个文件是每帧21字节。

文件头
语音帧1
语音帧2

文件头:
  单声道和多声道情况下文件的头部是不一致的,单声道情况下的文件头只包括一个Magic number,而多声道情况下文件头既包含Magic number,在其之后还包含一个32位的Chanel description field。多声道情况下的32位通道描述字符,前28位都是保留字符,必须设置成0,最后4位说明使用的声道个数。
语音数据:
  文件头之后就是时间上连续的语音帧块了,每个帧块包含若干个8位组对齐的语音帧,相对于若干个声道,从第一个声道开始依次排列。每一个语音帧都是从一个8位的帧头开始,其中P为填充位必须设为0,每个帧都是8位组对齐的。
  对于不同的编码模式,它的音频帧的大小是不同的,比特率也是不同的;如下图所示:

这里写图片描述

  音频数据帧大小的计算:amr一帧对应20ms,那么一秒有50帧的音频数据。由于比特率不同,每帧的数据大小也不同。如果比特率是12.2kbs,那么每秒采样的音频数据位数为:12200 / 50 = 244bit = 30.5byte,取整为31字节。取整要四舍五入,再加上一个字节的帧头,这样数据帧的大小为32字节。

9.4.AMR帧格式解析

  AMR语音帧格式为帧头和语音数据组成;并且分为两种类型的帧格式:AMR IF1和 AMR IF2。

帧头 语音数据

具体如下:
这里写图片描述

(1)AMR IF1的帧格式如下图:

这里写图片描述

a . AMR语音帧头Header占1个字节,如下图所示:

这里写图片描述

其中:
  P = 0;
  FT:Frame Type,对应不同编码模式,占4bits。(参见“9.2. AMR编码方式”表格中说明)
  Q:帧质量指示器,0表示为坏帧;占1bits;
  后面的2个P补0。
b. 帧头后面就是辅助信息。此辅助信息针对自适应模式及差错检测。
c. 辅助信息后面就是语音数据。每一帧的数据有分为三个部分:Class A ,Class B ,Class C;
- Class A:是一帧中最敏感、最重要的数据。这部分数据如有损坏,整个帧将无法解码。所以,一般在无线传输的时候要使用各种冗余的方式对这部分数据加以保护。
- Class B:相对而言,比Class A不重要的数据。
- Class C:比Class B还不重要的数据。

(2)AMR IF2的帧格式如下图所示:

这里写图片描述

  相对于IF1格式,IF2省去了Frame Quality Indicator,Mode Indication,Mode Request和CRC校验。但是增加了bit填充。因为AMR帧中数据的长度并不是字节(8bit)的整数倍,所以在有些帧的末尾需要增加bit填充,以使整个帧的长度达到字节的整数倍。

9.5.异常帧分析

  下图是一个出现异常帧的示例:(zbc1217.amr)

这里写图片描述

  从上图可以看见,本amr音频帧头都是0x3C,但是在0x000091e6处,帧头字节为0x44。与0x3C不一致。而在0x00009243处,才恢复到0x3C。
  对异常帧的简单处理办法是,遇到异常帧就跳过异常帧。后面的读帧算法有描述。

9.6.AMR帧读取算法

  因为可能存在异常帧,所以不一定所有的语音帧大小一致,对于跟正常帧大小不一致的,或者帧头跟正常帧头不一致的,就不交给解码器,直接抛弃该坏帧。下面是算法描述流程图:

这里写图片描述

9.7.AMR解码流程

  AMR Payload Decode原理分析如图中Payload Parse模块—–解码出编码语音数据;
  AMR Speech Decode原理分析如图中Speech Decode模块—-解码语音帧;
  AMR DTX decode原理分析如图中DTX Decode模块—–解码噪音帧;
  AMR Post-Processing原理分析如图中的Post-Processing模块—–语音后处理;

这里写图片描述

9.8.AMR模式选择的自适应机制

  自适应的基本概念是以更加智能的方式解决信源和信道编码的速率分配问题,使得无线资源的配置和利用更加灵活和高效。实际的语音编码速率取决于信道的条件,它是信道质量的函数。而这部分的工作是解码器根据噪声等测量参数协助基站来完成,选择模式,决定速率快慢。原则上在信道很差的时候采用速率比较低的编码器,这样就能分配给信道编码更多的比特数来实现纠错,实现更可靠的差错控制,从而有效地抑制错误发生,提高话音质量。

这里写图片描述
          自适应过程实现框图

10.ATRAC编码格式

  ATRAC(Adaptive Transform Acoustic Coding)是Sony 公司开发的一种相对老的音频编码格式,又细分成ATRAC1、ATRAC2、ATRAC3、ATRAC3plus,这些都是独立的技术,后来Sony把这些技术统称为ATRAC。在rmvb的封装格式中也能看到这种音频编码格式。

11.DTS编码格式

  DTS(Digital Theater Systems)大名鼎鼎的DTS(数码影院系统)是由DTS公司开发,一种多通道的音频技术,低损,环绕立体声,被广泛的应用在DVD等高清片源上。同样也需要授权,与杜比公司是竞争对手。最常见的是DTS 5.1:保存5条音频通道的数据用于环绕立体声,分别是center,left-front,right-front,left-rear,and right-rear。除此之外DTS公司还开发了DTS 70 mm、DTS 70 ES、DTS NEO:6、DTS 96/24、DTS-HD Master Audio、DTS-HD High Resolution Audio、DTS Connect、DTS Surround Sensation等技术。由于版权比较严格,而且文档很难从网上找到。

12.OGG编码格式

12.1.OGG概述

  OGG是一个自由且开放标准的容器格式,由Xiph.Org 基金会所维护,“Ogg”意指一种文件格式,可以纳入各式各样自由和开放源代码的编解码器,包含音效、视频、文字(像字幕)与元数据的处理。
  一般说到OGG,都是指Ogg_Vorbis,这就是咱们常见的.ogg结尾的音频文件,Vorbis是一种有损音讯压缩格式,由Xiph.Org基金会所领导并开放源代码。Vorbis通常以Ogg作为容器格式,所以常合称为Ogg Vorbis。其实,OGG不仅仅只能包含Vorbis格式,它可以包含视频格式。因此,为了区分只包含音频格式的文件格式,产生了一种新的文件格式OGV,这种格式既包含音频格式,也包含视频格式。但是OGV文件格式的压缩方法和OGG是一样的,可以采用同一种方式进行解析。
  为了说明简单,下面统称OGG。
优点与缺点:
  优点:① Ogg Vorbis的音质和MP3不相上下,但无法和FLAC比。
     ② Ogg Vorbis支持类似于MP3的ID3信息;
     ③ Ogg Vorbis格式支持流式播放;
     ④ Ogg Vorbis避免了像MP3文件的ID3标记那样烦琐的操作(有很多针对MP3的ID3修改软件标记早已不繁琐)。
  缺点:① 播放兼容性差。mp3已经成了便携随身听的代名词。绝大多数播放器、包括手机、pad等设备都支持mp3格式(其实mp3专利芯片授权费极低),而支持ogg格式的播放器很少。
     ② mp3是1997年以前就已经诞生,将近20年垄断了消费机市场。ogg音频普及性非常差,相对于mp3而言音质也没有竞争力,普及的可能性极低。
     ③ 相对于已经普及的微软WMA格式,ogg没有任何优势。不管是播放软件兼容性,码率,流媒体等方面。
     ④ 多声道系统已经由DOLBY、DTS两家公司垄断,他们都有完整的制作发行体系。大型多声道电影、电视、音乐制作都是基于这两家公司的技术和标准。ogg只能望洋兴叹了。
     ⑤ 很多专业音频制作软件不支持ogg文件格式。
     ⑥ 现今HIFI已经被HIRES(高解析)代替,随着存储、网速等限制,用户的聆听设备已经上了一个台阶,有损格式已经渐渐失去市场。

12.2.OGG/OGV文件结构

  首先介绍一下几个相关的概念:
  (1)Packet:Packet一个解码单元,或者是一帧数据。
  (2)Segment:Segment是由Packet分割而成,一个Segment最多只包含255格式bytes。Segment没有Header。
  (3)Page:Page是OGG/OGV文件格式的基本组成单元,是对Segment的封装。给一个或者几个连续的Segments添加一个Page Header就构成了一个Page。
  OGG文件解码后,按应用要求的时序关系合成若干物理流,一个物理流由若干逻辑流组成,一个逻辑流由若干包(Packet)组成。
  但OG文件本身是由页(page)组成的,这样,在形成OGG文件的时候,就要将逻辑流的各个包分割为若干区段(segment)后再进行页封装,每页都加上页头。一个区段的长度最多为255字节,一页最多封装255个区段。如果几个包的总长度≤255个区段,那么这几个包的区段可以封装在一页;如果一个包长度>255个区段,那么就会被被封装成两页或多页,下一个包必须用新的页开始封装。每个页之间相互独立,都包含了各自应有的信息,页的大小是可变的,通常为4K-8KB,最大值不能超过65307 bytes(27+255+255*255=65307)。

下面看一下OGG/OGV的文件格式,如下图所示:
这里写图片描述

  OGG/OGV文件就是由一个个的Page组成的。在解析的时候,通过Page的Header标记(“OggS”)将Page解析出来。下面看一些Page的Header结构,如下图所示。

               表12-1 Page的Header结构
这里写图片描述

(1)页标识Page Starter:“OggS”ASCII字符分别为0x4f ‘O’ 0x67 ‘g’ 0x67 ‘g’ 0x53 ‘S’,4个字节大小,它标识着一个页的开始。其作用是分离Ogg封装格式还原媒体编码时识别新页的作用。
(2)版本ID:一般当前版本默认为0,1个字节。
(3)Header Type:这个变量用来标识一个Page的类型。可以设置3种数值。
- 0x01:设置,说明该page和前面的一个page属于同一个packet;如果不设置,说明该page属于一个新的packet。
- 0x02:设置,说明该page是该stream的第一个page,如果不设置,说明不是。
- 0x04:设置,说明该page是该stream的最后一个page,如果不设置,说明不是。

(4)Granule Position:媒体编码相关的参数信息,8个字节,对于音频流来说,它存储着到本页为止逻辑流在PCM输出中采样码的数目,可以由它来算得时间戳。对于视频流来说,它存储着到本页为止视频帧编码的数目。若此值为-1,说明,该page不是当前packet的最后一个page。
  一个Page Header占用的字节数是不固定的,主要是因为Segment Table的长度不固定。因此我们可以得到页头的长度和整个页的长度:


Header_size = 27 + Seg Numbers; (byte)


Page_size = Header_size + Segment_table中每个segment的大小;

  OGG/OGV的封装格式比较简单。不过到这里,会有一个疑问,解码的时候是以packet为单位的,那么解析出pages之后,该如何获得packets呢?了解了OGG/OGV文件格式的封装过程之后,这个问题就比较简单了。

12.3.OGG/OGV文件封装过程

  OGG/OGV文件格式的封装主要分为四个过程:
  第一、从编码器获得Packets;
  第二:将Packets分割成Segments;
  第三:将Segments打包成Pages;
  第四:将不同stream的pages组合在一起从而获得OGG/OGV文件。对于只含有一个stream的文件,这个过程可以没有。

封装过程如下图所示:
这里写图片描述

  Packets分割成Segments之后,由于Segment的最大长度只能为255,而且一个Segment不能包含两个Packet中的数据,因此,如果某个Segment的长度小于255,这个Segment就是Packet的最后一个Segment。有一种特殊的情况,那就是Segment的长度为0。如果一个Packet的长度正好是255的整数倍,那么就会用一个长度为0的Segment作为与下一个Packet的分界。以图中的seg_5为例,它是packet_1和packet_2的分界,它的长度必须小于255,包括0。
  图中只是给出了一个比较简单的情况。在真正深入到OGG/OGV文件中去之后才发现,Packets和Pages的关系还是比较复杂的。图中的情况是一个Packet包含在一个或者多个Pages中,而一个Page只涉及到一个Packet的数据。实际的情况是,一个Page可能涉及到多个Packets的数据,而且还有可能不是整个Packet的数据。举个例子,还是上图中的Packets和Segments,只是Pages重新打包。例如:
  page_1:packet_1的seg_1、seg_2、seg_3、seg_4
  page_2:packet_1的seg_5和packet_2的seg_1
  page_3:packet_2的seg_2、seg_3和packet_3的seg_1、seg_2
  因此,在解析OGG/OGV文件的时候,就需要做相应的处理。

12.4.OGG/OGV文件Header信息

  OGG/OGV文件是由Pages组成的,因此,与文件、stream有关的信息,也是保存在Pages中的,这些Pages一般放在文件的开始位置。那么,如何判断Pages中放的Header信息呢?这个其实比较简单,可以通过Page的Header之后的几个字节来判断。这几个字节不仅可以判断Page中的数据是否为Header信息,还可以判断Header信息的类型。这几个字节是以ASCII的形式存在的,比如:“\001virbis、“\200theora”、“fishead”等等。OGG/OGV文件包含的Header的信息类型比较多,关于各个Header的类型、结构、解析方法等,可以去参考一下ffmpeg。
  对于只包含vorbis音频格式的OGG文件,包含的Header一般比较少。而在OGV文件中,就比较多了。

12.5.OGG Vorbis 比特流的结构

  Ogg文件解码后形成比特流,比特流最前面是三个包头,按照在文件中的顺序依次是:标识头(identification header)、注释头(comment header)和装备头(Setup Header)。标识头设置了版本和流的简单音频特性(如采样率和声道数目等),注释头包括用户文本注释和供应商以及封装软件产生的字符串,装备头包括所需的解码器装备信息,以及完整的VQ和译码本。通常情况下,标识头分割在ogg文件第1页,注释头和装备头分割在ogg文件第2页,这些包头数据也就是所在页的页数据。从第3页开始的页数据才是真正的媒体流的压缩数据。三个包头的结构分别见表12-2、表12-3、表12-5。

               表12-2 标识头结构

域名称 占用字节 描述
header_type_flag 1 =1:包头类型为标识包
packet_pattern 6 =76 6F 72 62 69 73,包头标识,vorbis的Ascii码
vorbis_version 4 版本
audio_channels 1 声道数目,必须>0
audio_sample_rate 4 音频采样率,必须>0
bitrate_maximum 4 最大比特率
bitrate_nominal 4 标称比特率
bitrate_minimum 4 最小比特率
blocksize_0 块大小0: 占用4位,与blocksize_1共占用1字节
blocksize_1 块大小1: 占用4位,必须≥blocksize_0
framing_flag 1 =1,边界标志,表示标识头结束

说明:
  ①比特率域仅作为提示。尤其是标称比特率,是纯粹VBR流,只有>0,该域才是有意义的。如果三个比特率域设置为相同的值,意味着固定速率比特流,或者有严格边界但接近固定速率的比特流。仅设置标称比特率意味着只有一个 VBR(可变位速率) 或 ABR(平均位速率) 流。设置最大或最小比特率意味着一个 VBR 比特流,遵守比特率限制。没有设置表明由编码器自行处理。
  ②块大小域不知为何意

              12-3 注释头的结构

域名称 占用字节 描述
header_type_flag 1 =3:包头类型为注释包
packet_pattern 6 =76 6F 72 62 69 73,包头标识,vorbis 的Ascii码
companyinfolength 4 制作软件信息所占用的字节数
companyinfo 制作软件信息
retention_byte 4 保留字节
comment[1]_length 4 注释[1]字符串所占用的字节数
comment[1] 注释[1]内容
……
comment[N]_length 4 注释[N]字符串所占用的字节数
framing_flag 1 =1,边界标志,表示注释头结束

说明:
  ①注释名称后面用等号连接注释内容。
  ②常用的注释名称见表5。
  ③注释名称是可以重复的。例如:如果一个曲目由三个艺术家共同演唱,那么以下情况是允许的:
  ARTIST=张三
  ARTIST=李四
  ARTIST=王五

    表12-4 常用注释名称

注释名称 中译义
ALBUM 专辑
ARTIST 艺术家
COPYRIGHT 版权
DATE 日期
DESCRIPTION 描述
GENRE 风格
CONTACT 联系人
ISRC 国际标准记录代码
LICENSE 许可证
LOCATION 声道位置
ORGANIZATION 公司名
PERFORMER 表演者
TITLE 标题
TRACKNUMBER 曲目号
YEAR 年代
VERSION 版本

说明:
  用户也可以自己创新注释名称。

                 表12-5 装备头的结构

域名称 占用字 描述
header_type_flag 1 =5:包头类型为装备包
packet_pattern 6 =76 6F 72 62 69 73,包头标识,vorbis的Ascii码
lists of codebook configurations 码本结构表
time-domain transform configurations 时间戳转换配置
floor configurations 底层配置
residue configurations 剩余配置
channel mapping configurations 信道映射配置
mode configurations 模式配置

说明:
  装备头后面紧接着的就是真正的媒体压缩数据流了。

12.6.实例解析

下面是我手机里的 Lock.ogg 的部分数据:

-----------------------------------------------------------------------------------------
0000: 4F 67 67 53 00 02 00 00 00 00 00 00 00 00 82 78   OggS..........0010: 00 00 00 00 00 00 12 85 4E 81 01 1E 01 76 6F 72   ...........vor
0020: 62 69 73 00 00 00 00 01 44 AC 00 00 FF FF FF FF   bis.....D.......
0030: 00 F4 01 00 FF FF FF FF B8 01 4F 67 67 53 00 00   ..........OggS..
0040: 00 00 00 00 00 00 00 00 82 78 00 00 01 00 00 00   ..............
0050: CC 63 C9 DB 0F 4D FF FF FF FF FF FF FF FF FF FF   蘡邵.M..........
0060: FF FF FF E8 03 76 6F 72 62 69 73 1D 00 00 00 58   .....vorbis....X
0070: 69 70 68 2E 4F 72 67 20 6C 69 62 56 6F 72 62 69   iph.Org libVorbi
0080: 73 20 49 20 32 30 30 34 30 36 32 39 01 00 00 00   s I 20040629....
0090: 1C 00 00 00 45 4E 43 4F 44 45 52 3D 41 64 6F 62   ....ENCODER=Adob
00A0: 65 28 52 29 20 41 75 64 69 74 69 6F 6E 28 52 29   e(R) Audition(R)
00B0: 01 05 76 6F 72 62 69 73 29 42 43 56 01 00 08 00   ..vorbis)BCV....
……
------------------------------------------------------------------------------------------

解析:
0000-0039:第一页
 0000-001B:页头部
  0000-0003=4F 67 67 53:页标识,OggS的Ascii字符
  0004=00:版本号为0
  0005=02:页头部类型:本页为逻辑流的第一页bos
  0006-000D=0:区段位置为0
  000E-0011=82 78 00 00:逻辑流ID
  0012-0015=0:本页在逻辑流中的序号为0
  0016-0019=12 85 4E 81:循环冗余校验码校验和
  001A=01:区段表中有1个区段
  001B=1E:区段表中的区段长度为 1E
 001C-0039:页数据(0039=1C+1E-1)
  001C=01:包头类型为标识包,包长度为1E(001C-0039),是区段表中区段的长度
  001D-0022=76 6F 72 62 69 73:包头标识,vorbis的Ascii码
  0023-0026=0:版本号为0
  0027=01:单声道
  0028-002B=44 AC 00 00:音频采样率为44.1KHZ(&HAC44=44100)
  002C-002F=FF FF FF FF:最大比特率未设置
  0030-0033=00 F4 01 00:标称比特率
  0034-0037=FF FF FF FF:最小比特率未设置
  0038=B8:块大小0为二进制的1011,块大小1为二进制的1000
  0039=01:标识包结束
003A-0E8B:第二页
 003A-0063:页头部
  003A-003D=4F 67 67 53:页标识,OggS的Ascii字符
  003E=00:版本号为0
  003F=00:页头部类型:本页为新包,不是逻辑流的第一页,也不是最后一页
  0040-0047=0:区段位置为0
  0048-004B=82 78 00 00:逻辑流ID
  004C-004F=01 00 00 00:本页在逻辑流中的序号为1
  0050-0053=CC 63 C9 DB:循环冗余校验码校验和
  0054=0F:区段表中有15个区段
  0055-0063=4D FF FF FF FF FF FF FF FF FF FF FF FF FF E8:区段表中15个区段的长度
 0064-0E8B:页数据(0E8B=64+4D+FF*D+E8-1)
  0064=03:包头类型为注释包,包长度为4D(0064-00B0),是区段表中第1个区段的长度
  0065-006A=76 6F 72 62 69 73:包头标识,vorbis的Ascii码
  006B-006E=1D 00 00 00:制作软件信息]的长度为29字节
  006F-008B=制作软件信息字符串:Xiph.Org libVorbis I 20040629
  008C-008F=01 00 00 00:保留字节
  0094-00AF=注释[1]字符串:ENCODER=Adobe(R) Audition(R)
  00B0=01:注释包结束
  00B1=05:包头类型为装备包
  00B2-00B7=76 6F 72 62 69 73:包头标识,vorbis的Ascii码
  ……

13.PCM编码格式

13.1.PCM概述

  PCM (Pulse Code Modulated Audio)也被称为脉冲编码调制,是目前计算机应用中最高保真水平的音频编码格式。PCM音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准的数字音频数据。PCM约定俗成了无损编码,能做到最大程度的无限接近绝对保真。被广泛用于素材保存及音乐欣赏,CD、DVD以及我们常见的WAV文件中均有应用,优点是音质好,缺点是体积大。
  做嵌入式音视频产品时,一般情况的音视频都是芯片负责解码。如果遇到版权问题,例如AC3、DTS,有些时候芯片厂商要求很严格,用户会采取软解的方法,软解也就是把AC3 DTS等音频解成PCM,然后在送给芯片。
  PCM编码方式:

这里写图片描述

13.2.PCM数据格式

  如果是单声道的音频文件,采样数据按时间的先后顺序依次存入(有的时候也会采用LRLRLR方式存储,只是另一个声道的数据为0),如果是双声道的话就按照LRLRLR的方式存储,存储的时候还和机器的大小端有关。大端模式如下图所示:

这里写图片描述

14.RealAudio

  Real Audio是Real networks推出的一种音乐压缩格式,它的压缩比可达到1:96,因此在网上比较流行。经过压缩的音乐文件可以在通过速率为14.4kbps的 Modem上网的计算机中流畅回放,其最大特点是可以实现网上实时回访,也就是说边下载边播放。
  网络中非常常见,在rmvb、rm封装格式中,或者是.ra 、.ram音频文件,由RealNetworks发展的一种多媒体音频文件格式,目前已有很多版本:
  lpcJ, 14_4: IS-54 VSELP (RealAudio 1)
  28_8: G.728 LD-CELP (RealAudio 2)
  dnet: Dolby AC3 (RealAudio 3)
  sipr: Sipro Lab Telecom ACELP-NET (RealAudio 4/5)
  cook: G2/Cook Codec (RealAudio 6)
  atrc: Sony ATRAC3 (RealAudio 8)
  raac: MPEG-4 LC-AAC (RealAudio 9)
  racp: MPEG-4 HE-AAC (RealAudio 10)
  ralf: RealAudio Lossless Format (RealAudio 10)

没有更多推荐了,返回首页