一、简介
1.1 音频相关术语
ID3:
一般位于一个mp3文件的开头或末尾的若干字节内,记录该mp3文件的歌手、标题、专辑名称、年代、风格等信息,ID3分位两个版本,V1版ID3在文件末尾的固定128字节,以TAG字符开头,若没有则认为无ID3V1信息,V2版ID3位于mp3的开头,长度可变。
采样率:
每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示,采样率是指将模拟信号转换成数字信号时的采样频率,也就是单位时间内采样多少点,采样频率越高声音的还原就越真实越自然,在当今的主流采集卡上,采样频率一般共分为22.05KHz、44.1KHz、48KHz三个等级,22.05KHz只能达到FM广播的声音品质,44.1KHz则是理论上的CD音质界限,48KHz则更加精确一些。
比特率:
比特率是指每秒传送的比特(bit)数。单位为bps(Bit Per Second),比特率越高,传送的数据越大。在音频、视频领域,比特率常翻译为码率,比特率表示经过编码(压缩)后的音、视频数据每秒钟需要用多少个比特来表示,而比特就是二进制里面最小的单位,要么是0,要么是1。比特率与音、视频压缩的关系,简单的说就是比特率越高,音频、视频的质量就越好,但编码后的文件就越大;如果比特率越少则情况刚好相反。
比特率=采样率 * 采样位数 * 声道数,(文件总大小 - 头信息)/ (采样率 * 采样位数 * 通道数 / 8) [也就是比特率(字节)] ≈ 文件时长
码率/码流/位率:
是指音频、视频文件在单位时间内使用的数据流量,通俗一点的理解就是取样率,是音频、视频编码中质量控制中最重要的部分,一般我们用的单位是Kb/s、Mb/s。一般来说码流越大,压缩比就越小,质量就越高。码流越大,说明单位时间内取样率越大,数据流,精度就越高,处理出来的文件就越接近原始文件
编码:
从信息论的观点来看,描述信源的数据是信息和数据冗余之和,即:数据=信息+数据冗余。音频信号在时域和频域上具有相关性,也即存在数据冗余。将音频作为一个信源,音频编码的实质是减少音频中的冗余。
自然界中的声音非常复杂,波形极其复杂,通常我们采用的是脉冲代码调制编码,即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码
解码:
编码的逆过程
1.2MP3简述
MP3全称为MPEG Audio Layer 3,它是一种高效的计算机音频编码方案,它以较大的压缩比将音频文件转换成较小的扩展名为.mp3的文件,基本保持源文件的音质,MP3是ISO/MPEG标准的一部分,ISO/MPEG标准描述了使用高性能感知编码方案的音频压缩,此标准一直在不断更新以满足“质高量小”的追求,现已形成MPEG Layer1、Layer2、Layer3三种音频编解码方案,分别对应MP1、MP2、MP3 这三种声音文件。MPEG 音频编码的层次越高,编码器越复杂,压缩率也越高。MP3 是利用人耳对高频声音信号不敏感的特性,将时域波形信号转换成频域信号,并划分成多个频段,对不同的频段使用不同的压缩率,对高频加大压缩比(甚至忽略信号)对低频信号使用小压缩比,保证信号不失真。这样一来就相当于抛弃人耳基本听不到的高频声音,只保留能听到的低频部分,这样可得到很高的压缩率。
音频压缩由编码和解码两个部分组成。把波形文件里的数字音频数据转换为高度压缩的形式(称为比特流)即为编码;要解码则把比特流重建为波形文件。
音频压缩可以分为无损(lossless)压缩和有损压缩。无损压缩就是尽量降低音频数据的冗余度,以减小其体积。音频信号经过编码和解码之后,必须要 和原来的信号一致。无损压缩的压缩率是比较有限的,不过现在比较出色的APE能做到50%的压缩率(本人用Monkey’s Audio 3.97,Extra High压缩模式下压缩WAV,压缩率最低能达到52%);有损压缩就是用尽一切手段,包括无损压缩用到的方法,丢掉一切能丢掉的数据,以减小体积。而音 频压缩后解码听起来起码是要跟原来差不多的,有损压缩的压缩比能大幅提高,MP3就是属于有损压缩,压缩比是12:1(128kbps)。
MPEG(Moving Picture Expert Group)是ISO下的一个动态图像专家组,它指定的MPEG标准广泛的应用于各种多媒体中,MPEG标准包括视频和音频标准,其中音频标准已制定出MPEG-1、MPEG-2、MPEG-2 ACC、MPEG-4。MPEG-1和MPEG-2标准使用同一个音频编解码族Layer1、2、3,MP3绝大多数使用的是MPEG1标准
MP3音频压缩包含编码和解码两部分,编码是将原始信号转换成电平信号的过程,解码即是逆过程,MP3 采用了感知音频编码(PerceptualAudio Coding)这一失真算法。人耳感受声音的频率范围是20Hz-20kHz,MP3截掉了大量的冗余信号和无关的信号,编码器通过混合滤波器组将原始声音变换到频率域,利用心理声学模型,估算刚好能被察觉到的噪声水平,再经过量化,转换成Huffman编码,形成MP3位流。解码器要简单得多,它的任务是从编码后的谱线成分中,经过反量化和逆变换,提取出声音信号。
MP3文件数据由多个帧组成,帧是MP3文件最小组成单位。每个帧又由帧头和帧数据组成,帧头记录着该帧的基本信息,包括位率索引和采样率索引(这对理解ABR和VBR编码方式很重要)。帧数据,顾名思义就是记录着主体音频数据。每个帧播放时间是0.026秒,其长度随位率的不同而不等。有些MP3文件末尾有些额外字节存放非声音数据的说明信息。不同的连续画面切换以达到动态效果,每幅画面就是一个“帧”,不同的是MP3里面的帧记录的是音频数据而不是图形数据。MP3的帧速度大概是30帧/秒。
MP3的全称为MPEG1 Layer-3音频文件, MPEG音频文件是MPEG1标准中的声音部分,也叫MPEG音频层,它根据压缩质量和编码复杂程度划分为三层,即Layer1、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文件,并使压缩后的文件在回放时能够达到比较接近原音源的声音效果。
以下是MP3算法的主要步骤:
**1.采样率转换:**将输入音频信号的采样率转换为固定的值,通常为44.1 kHz。这是因为人耳对于音频的感知范围大约在20 Hz到20 kHz之间,因此高于该范围的频率可以被削弱或删除。
**2.分帧:**将音频信号分成一系列短时窗口,通常为23.2 ms至46.4 ms的长度。每个窗口内的音频数据被视为一个帧。通常使用重叠窗口技术来减少帧之间的不连续性。
**3.快速傅里叶变换(FFT):**对每个帧应用FFT变换,将时域中的音频信号转换为频域中的频谱表示。通过FFT,可以得到每个频率成分的幅度和相位信息。
**4.声学模型:**基于人耳的听觉特性,使用心理声学模型来确定哪些频率成分对人耳更重要,并且哪些可以被舍弃或减少精度。这样可以将高频部分进行更多的压缩。
**5.量化和编码:**对于每个频率成分,使用掩蔽模型来确定对应的量化器(Quantizer)步长。然后将量化后的频谱系数进行熵编码,通常使用霍夫曼编码等方法。
**6.帧间预测:**为了进一步提高压缩效率,MP3还使用帧间预测技术,通过利用相邻帧之间的冗余性来减小数据量。差异信号被编码并存储。
**7.解码:**解码过程与压缩过程相反,包括熵解码、逆量化、FFT逆变换、帧间预测恢复等步骤。最终得到恢复的音频信号。
MP3算法是一种有损压缩算法,压缩过程中丢失了一些音频细节。但在合理的比特率下,MP3能够提供高质量的音频,并成为广泛应用的音频压缩格式。
请注意,上述是MP3算法的基本概述,实际的MP3编码器和解码器实现会涉及更多细节和参数设置,如窗口函数选择、码率控制、声道处理等。
1.优点
1.广泛兼容性:
MP3是最普遍使用的音频格式,几乎所有设备和软件都可以支持。这使得文件的分享和播放变得更加方便。
2.成熟的技术:
MP3技术已经存在多年,其算法经过广泛的测试和应用,可靠性高。
3.适中的音质与文件大小:
MP3在适中的比特率下(如128kbps到192kbps)能够提供相对良好的音质,对于日常听音需求来说,具备良好的音质与文件大小的平衡。
4.灵活的比特率选项:
MP3支持固定比特率(CBR)和可变比特率(VBR)编码,用户能自由选择合适的比特率以平衡质量与文件体积。
2.缺点
1.音质损失:
MP3采用有损压缩,音频信息在压缩过程中会丢失,尤其是在低比特率(低于128kbps)设置下,可能导致音质明显下降。
2.相对较低的压缩效率:
相比于新一代的压缩算法(如AAC或OGG Vorbis),MP3在相同比特率下,通常音质较差。这些新算法使用更先进的编码技术,可以在更低文件大小下提供更好的音质。
3.动态范围压缩问题:
MP3可能会压缩音频的动态范围,这在音量变化较大的音频中可能导致细节损失,特别是对于经典音乐或电影配乐等需要广泛动态范围的场合。
4.不支持新特性:
相较于某些现代格式(如AAC),MP3不支持多声道音频、环绕声等特点,限制了其在一些应用中的使用。
二、格式解析
MP3文件是由帧(frame)构成的,帧是MP3 文件最小的组成单位。MP3 的全称应为MPEG1 Layer-3 音频文件。
MPEG(MovingPicture Experts Group),MPGE音频层指MPGE文件中的声音部分,根据编码质量和复杂程度分为3层,即Layer-1、Layer2、Layer3,对应MP1、MP2、MP3三种格式文件。
2.1 MP3文件结构
MP3主要由多个数据帧组成,一个数据帧包括帧头与数据块。在MP3文件的开头,可能包括ID3V2元数据,而文件末尾可能包括128字节的ID3V1元数据MP3最开始只有数据帧,对于应用者而言,无从得知该mp3文件的相关信息,包括演唱者,作曲家,专辑名等,因此产生了ID3V1标签,固定128个字节,放在文件最后,该标签可以提供如上的信息。然而,固定的128个字节ID3V1标签所能提供的信息实在有限,越来越不满足应用的需要,ID3V2应运而生,该标签存在于文件首部,作为ID3V1的补充。毕竟,文件尾部已经被占用了。
其中ID3v2,APEv2,ID3v1这三部分是可选项,是存放文件的一些其他信息,例如:作者,专辑等,与编解码没有任何关系。解码的时候,如果有这部分内容,需要跳过这些数据。
2.2 ID3V1
ID3v1是第一个版本的音频标签,长度为固定的 128 字节,位置在 MP3 文件的尾部,各项信息都顺序存放,不足部分使用’\0’补足,可使用UltraEdit打开查看。
typedef struct tagID3V1
{
char Header[3]; /*标签头必须是"TAG"否则认为没有标签*/
char Title[30]; /*标题*/
char Artist[30]; /*作者*/
char Album[30]; /*专集*/
char Year[4]; /*出品年代*/
char Comment[28]; /*备注*/
char reserve; /*保留*/
char track;; /*音轨*/
char Genre; /*类型*/
}ID3V1,*pID3V1;
其中,歌名是固定分配为 30 个字节,如果歌名太短则以 0 填充完整,太长则被截断,其他信息类似情况存储。MP3 音乐类别总共有 147 种,每一种对应一个数组,比如 0 对应“Blues”、1 对应“Classic Rock”、2 对应“Country”等等。
注释:
1.如果MP3的注释=30字节,那么就要占用 Reserved 和 Track 两个字节,这要看 Reserved 是否=0,如果=0,那么注释有 28 个字节。如果不是,那么注释有 30 个字节。当注释!=30 个字节的时候,那就没有 Track 了。
2.如果 MP3 文件后面虽然有“TAG”三个字母,但字母后面全是0,那就不是一个合法的 ID3V1 信息,应该认为没有 ID3V1 信息。
3.ID3V1 的各项信息都是顺序存放,没有任何标识将其分开,一般用 0补足规定的长度。比如歌曲名有 20 个字节,则在歌曲名后要补足 10 个 0,否则将造成信息错误。
4.歌曲风格共 148 种,用编号表示,详情可上网查询。其数据存放按照顺序一个个存放,如果长度不足则补 0,ID3v1 应该已经比较少用了。
2.3 ID3V2
ID3V2一共有四个版本,ID3V2.1/2.2/2.3/2.4,目前流行的播放软件一般只支持第三版即ID3V2.3,由于ID3V1记录在文件的末尾处,ID3V2就只能记录在文件的首部了,也是因为这个原因,对ID3V2的操作比ID3V1要慢,而且ID3V2的结构比ID3V1的结构复杂的多,但是ID3V2可以记录更多的信息,长度可变
ID3V2.3由一个标签头和若干个标签帧或者一个扩展标签头组成,至少要有一个标签帧,每一个标签帧记录一种信息,例如作曲、标题等
ID3V2由10个字节的标签头与多个标签帧组成,标签帧不固定长度,包括10个字节的帧头与至少1字节的帧内容。
2.3.1 ID3V2标签头内容
ID3V2存放在MP3文件的首部,由1个标签头和若干标签帧组成。
标签头为10个字节,
char Header[3]; /*必须为"ID3"否则认为标签不存在*/
char Ver; /*版本号ID3V2.3 就记录3*/
char Revision; /*副版本号此版本记录为0*/
char Flag; /*存放标志的字节,这个版本只定义了三位,稍后详细解说*/
char Size[4]; /*标签大小,包括标签头的10 个字节和所有的标签帧的大小*/
每个标签帧都有一个10个字节的帧头和至少一个字节的不固定长度的内容组成为,帧头的定义如下:
char FrameID[4]; /*用四个字符标识一个帧,说明其内容,稍后有常用的标识对照表*/
char Size[4]; /*帧内容的大小,不包括帧头,不得小于1*/
char Flags[2]; /*存放标志,只定义了6 位,稍后详细解说*/
注释
1.Size 字段的计算公式如下(从左至右):
size =字节1的值0x200000+字节2的值0x4000+字节3的值*0x80+字节4的值(每个字节只用7位,最高位不使用,恒为0)
2.如果所有标签帧的总长度<标签内容长度,则须用0填满。
位于文件开始处,长度为10字节,结构如下:
char Header[3]; /必须为“ID3”否则认为标签不存在/
char Ver; /版本号ID3V2.3 就记录3/
char Revision; /副版本号此版本记录为0/
char Flag; /*标志字节,只使用高三位,其它位为0 */
char Size[4]; /标签大小/
注:标签大小,不能确定具体包括哪些内容,解析歌曲文件后,发现没有哪些字节之和会等于该值,详见下面的实例分析
标志字节一般为0,定义如下(abc000000B)
a:表示是否使用Unsynchronisation
b:表示是否有扩展头部,一般没有,所以一般也不设置
c:表示是否为测试标签,99.99%的标签都不是测试标签,不设置
标签大小共四个字节,每个字节只使用低7位,最高位不使用恒为0,计算时将最高位去掉,得到28bit的数据,计算公式如下:
Size=(Size[0]&0x7F)*0x200000+(Size[1]&0x7F)*0x400+(Size[2]&0x7F)*0x80+(Size[3]&0x7F)
以《金南玲 - 逆流成河.mp3》为例,使用WinHex工具打开如下,读者可自己对照上述结构,本章结束会给出详细的结构分析
2.3.2 ID3V2标签帧结构
每个标签帧都有10个字节的帧头(和标签头不是一个东西,虽然他们刚好都是10字节,标签头只有一个,每个标签帧都有一个帧头)和至少一个字节的内容构成,在文件中是连续存放的。标签帧头由三个部分组成,即 Frame[4]、Size[4] 和 Flags[2]。标签帧与标签头/其他标签帧无特殊字节分割,只能通过帧头信息来确定帧内容的大小。
ID3V2长度不固定,尾部可能有补空数据。
注释
1.标签帧大小计算公式:Size = Size[0]*0x1000000+Size[1]*0x10000+Size[2]*0x100+Size[3]。
2.标签帧之间没有特殊的分隔符,要得到一个完整的标签帧内容必须先从帧头中得到帧内容长度。
3.帧内容均为字符串,常以 00 开头。
4.Flags一般没用,通常为0.
帧头长度10字节,定义如下:
char ID[4]; /标识帧,说明其内容,例如作者/标题等/
char Size[4]; /帧内容的大小,不包括帧头,不得小于1/
char Flags[2]; /标志帧,只定义了6 位/
Frame 是用四个字符表示帧内容含义,比如 TIT2 为标题、TPE1 为作者、TALB 为专辑、TRCK 为音轨、TYER 为年代等等信息。Size用四个字节组成 32bit 数表示帧大小。Flags 是标签帧的标志位,一般为 0 即可。
标识帧,常见的内容如下:
TIT2=标题
TPE1=作者
TALB=专集
TRCK=音轨格式:N/M 其中N为专集中的第N首,M为专集中共M首,N和M 为ASCII 码表示的数字.
TYER=年代是用ASCII 码表示的数字
TCON=类型直接用字符串表示
COMM=备注格式:“eng\0备注内容”,其中eng 表示备注所使用的自然语言
帧内容大小,计算公式如下:
Size = Size[0]*0x100000000 + Size[1]*0x10000+ Size[2]*0x100 +Size[3];
**标志帧,**使用每个字节的高三位,其他位均为0(abc00000B xyz00000B)
a – 标签保护标志,设置时认为此帧作废
b – 文件保护标志,设置时认为此帧作废
c – 只读标志,设置时认为此帧不能修改
x – 压缩标志,设置时一个字节存放两个BCD 码表示数字
y-- 加密标志
z-- 组标志,设置时说明此帧和其他的某帧是一组
2.3.3 标签帧标识符
注释
1.帧内容是数字的,都用 Ascii 字符表示。
2.有的 TCON(风格、流派)的帧内容是直接用字符串表示的,如“genre”,而有的则是用编号表示的,如“28 31 32 29”就是用字符串“(12)”表示 12 号风格,我们在解析的时候要注意。
3.TRCK(音轨)的帧内容格式是:N/M。其中,分母表示专辑中共有 M 首歌曲,分子表示专辑中的第 N 首曲。
2.4 音频数据解析
2.4.1 编码方式:CBR与VBR
MP3有两种编码方式,一种是CBR,一种是VBR,前者是恒定码率,后者是可变码率。
CBR
CBR,也就是固定位率,固定位率的帧的大小在整个文件中都是是固定的,只要知道文件总长度,和从第一帧帧头读出的信息,就都可以通过计算得出这个mp3文件的信息,比如总的帧数,总的播放时间等等,要定位到某一帧或某个时间点也很方便,这种编码方式不需要文件头,第一帧开始就是音频数据。
恒定码率的帧大小是固定的,除去ID3V1与ID3V2,有效数据帧总长度为帧大小与帧数据的乘积,从而可算得MP3播放时长,跳播容易。一般有效数据帧第一帧即为音频数据,但也有例外,有些编码器在编码CBR文件时也像VBR那样将信息记入第一帧,比如著名的lame,它使用"Info"来做CBR的标记。
CBR相关计算公式:
LayerII 与 LayerII
帧长 = (每帧采样次数 * 比特率 / 8 / 采样率) + 补白
LayerI
帧长 = (每帧采样次数 * 比特率 / 8 / 采样率) + 补白 * 4
CBR 总播放时长计算公式:
播放时长 = (文件大小 – ID3标签大小) * 8 / 比特率
VBR
VBR是XING公司推出的算法,所以在MP3的FRAME里会有“Xing"这个关键字(也有用"Info"来标识的,现在很多流行的小软件也可以进行VBR压缩,它们是否遵守这个约定,那就不得而知了),它存放在MP3文件中的第一个有效帧的数据区里,它标识了这个MP3文件是VBR的,也就是说,MP3数据帧如果是VBR编码,则第一帧是VBR帧。同时第一个帧里存放了MP3文件的帧的总个数,这就很容易获得了播放总时间,同时还有100个字节存放了播放总时间的100个时间分段的帧索引,假设4分钟的MP3歌曲,240S,分成100段,每两个相邻INDEX的时间差就是2.4S,所以通过这个INDEX,只要前后处理少数的FRAME,就能快速找出我们需要快进的帧头。其实这第一帧就相当于文件头了 。
MP3是由帧构成的,MP3能象动画那样读到哪放到哪, 播放器不必预读整个文件的内容,即使部分数据损坏也不会对播放效果有太大影响(实际上这就是流媒体所具有的特性)。而每个帧的帧头里都包含这该帧的码率 (bitrate,单位是kbps)等信息,所以,我们可以对每一段音乐甚至每一个帧定义独立的码率,这就是VBR(Variable bitrate,动态码率)技术。
与VBR向对应的是CBR(Constant bitrate)。一支交响曲,合奏大动态部分的数据量显然大于引子部分,如果用128kbps的CBR编码方式来编码,在引子部分可能有多余的数据流 量,而在合奏部分却又不够,VBR就是解决这个问题的。把在不影响音质的情况下,对流量需求小的部分分配较小的码率,把冗余字节缓存起来留给有需要的部 分,在短时间内提供更高的码率,以保证音乐的质量。所以说,VBR的作用是更合理的分配流量,在不增大文件体积的条件下提高声音的质量。
不过VBR在应用初期带给过MP3随生听不少麻烦。因为早期大多数MP3播放器都是针对CBR设计的,其根据文件大小来获得时长的算法对VBR失效了, 因为VBR MP3的bitrate可能每时每刻都在变化。不过现在这个问题基本上不用担心了,市场上的播放器基本上都解决这问题了。
不过现在有些编码器在编码CBR文件时也像VBR那样将信息记入第一帧,比如著名的lame,它使用"Info"来做CBR的标记。
VBR相关计算公式:
VBR 总播放时长计算公式:
播放时长 = 有效数据帧总帧数 * 每帧采样数 / 采样率
每一帧的播放时长计算公式:
帧播放时长 = 采样数 / 采样频率 * 1000 毫秒
2.4.2 有效音频数据帧
1. 数据帧帧头
每个帧都有一个帧头,长度是四个字节,帧后面可能有2字节的CRC校验,取决于帧头的第16位,为0则无校验,为1则有校验,后面是可变长度的附加信息,对于标准的MP3文件来说,其长度是32字节,紧接其后的是压缩的声音数据,当解码器读到此处时就进行解码了。
MP3数据是按照一帧一帧的方式存储的:Frame1 Frame2 … FrameN,每个Frame如下表所示:
其长度为 4 字节,数据结构如下:
typedef 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; //强调模式
}HEADER;
各bit位排列如下:
AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
具体数据结构含义如下:
帧头信息
帧头信息如下表所示。
帧边信息(通道信息)
Mpeg1 layer 3 的Side information格式如下:
在帧头后边是Side Info(姑且称之为通道信息)。对标准的立体声MP3文件来说其长度为32字节。当解码器在读到上述信息后,就可以进行解码了。帧边信息解码的主要目的在于找出解这帧的各个参数,包括主数据开始位置,尺度因子长度等。帧边信息如下图所示。
main_data_begin: 表示一帧数据main_data开始的位置。表示main data相对于该帧同步头的负偏移。这里涉及到bit reservior技术:即把当前帧未使用完的bit数,留给后面需要的帧使用,这就导致每一帧的main data开始的位置,可能在它的Header和side information之前。这种技术就叫做bit reservoir。
Private_bits:留作私用。
Scfsi:表明两个granule是否使用相同的缩放因子。
scalefac_compress:被编码的缩放因子所占的比特数。
Part_2_3_length:表示main data中scalefactor和Huffman数据所占的比特数。
Global_gain:全局量化步长。
window_switching_flag、 block_bype和mixed_block_type:当window_switching_flag未置位时,block_type为0;当其置位时, block_type由mixed_block_type[gr][ch]指定,如下图所示:
当block_type为0、1、3时,为长块;为2时,为短块。mixed_block_flag[gr][ch]为1时,为混合块。
Table_select、Big_value、count1_table_select、Region0_count和region1_count:参考Huffman码表选择。
subblock_gain:短窗量化时所用的增益偏移量。
preflag和scalefac_scale:反量化时用到的变量。
Main data
main data的结构如下图所示:
其中 granule0 和 granule1 表示在一帧里面的粒度组 1 和粒度组 2,channel0 和 channel1 表示在一个粒度组里面的两个通道,scalefactor 为尺度因子 ,quantized value 为量化后的哈夫曼编码值,它分为 big values 大值区和 count1 1 值区.
CRC 校验:表达式为 X16+X15+X2+1
2. 帧长度与真大小
3. 帧持续时间
计算公式:
每帧持续时间(毫秒) = 每帧采样数 / 采样频率 * 1000
例:1152/441000*1000=26ms
三、编码原理
3.1 功能模块说明
MP3编码主要由3大功能模块组成,包括混合滤波器组(子带滤波器和MDCT),心理声学模型,量化编码(比特和比特因子分配和哈夫曼编码)。
3.1.1 混合滤波器组
这部分包括子带滤波器组和MDCT两部分。子带滤波器组编码完成样本信号从时域到频域的映射,并将规定的音频信号通过带通滤波器组分解成32个子带输出。子带滤波器组输出的32个子带是等带宽的,而由心理声学模型得出的临界带宽则不是等带宽的,所以为了使得进行编码的各个比例因子带与临界频带相匹配,需要对每个子带信号做MDCT变换。将子带滤波器组的输出送到MDCT滤波器组后,每组将细分为18条频线,共产生576条频线。然后利用心理声学模型中计算出来的子带信号的信掩比,决定分配给576条谱线的比特数。
数字音频信号以脉冲的形式送进编码器,首先会经过一滤波器段(filterbank),它由两个串联的滤波器段组成:一个多相分析滤波器段和一个MDCT(Modified Discrete Cosine Transform,经改良的离散余弦转换),前者也应用到layer-1和layer-2中,后者是MP3独有的。
输入的音频信号在20Hz-20k Hz的频率范围内,通过第一个滤波器段后,把信号按频率分成32个小频带,称为子带(Subband)。20000Hz/32=625Hz,那么每个子带 的宽度就是625Hz。人耳对不同频段的灵敏度是不同的,编码器可对不同的子带进行不同的量化分层。
不过等宽的子 带并没有准确反映人耳的听觉特性,这样进行等宽划分并没有考虑到不同信号的临界宽度,也就是该信号的影响范围,以及不同信号的相互影响,所以这样会产生大 量的信号重叠。MDCT转换就是为了解决这问题,它能对子带进行细分,清楚重叠部分,得到更高的频谱解析度。
3.1.2 心理声学模型
心理声学模型利用了人耳听觉系统的遮蔽效应特性,移除大量的不相关信号,从而达到压缩音频数据的效果。为了精确地计算遮蔽阈值,要求信号有更好的频域解析度,因此在使用心理声学模型前先对信号进行傅立叶变换。MPEG-I提供了两种心理声学模型,第一种模型计算简单,在高比特率编码时提供适当精度,第二种模型比较复杂,一般在较低比特率编码时使用。MP3编码中一般使用心理声学模型二。心理声学模型的目的就是求出各个子带的掩蔽域值,并以此控制量化过程。心理声学模型实现过程一般是先用FFT求出信号的频谱特性,根据频谱特性找出各频率点上的音调成分(有些称为音乐成分)和非音调成分(或称噪音成分);根据掩蔽域曲线确定各个音调成分和非音调成分在其它频率点的掩蔽域值;最后求出各频率点的总体掩蔽域,并折算到编码子带中。对于子带滤波器组输出的谱值量化后产生的噪声,如果能够被控制在掩蔽域值以下,则最终的压缩数据被解码后的结果与原始信号可以不加区分。一个给定信号的掩蔽能力取决于它的频率和响度,所以心理声学模型的最终输出是信掩比SMR(signal-to-maskradio),即信号强度与掩蔽阈值的比率。
研究声音心理学模型用途有:
(1)研究模型的PE值决定做MDCT变换时使用长窗框还是短窗框
(2)研究模型的SMR值决定量化编码时的比特数分配
1) 最小听觉门槛判定 (The minimal audition threshold)
人耳的听力范围是20Hz-20k Hz的频率范围,但是人耳对不同的频率声音的灵敏度是不同的,不同频率的声音要达到能被人耳听到的水平所需要的强度是不一样。那么通过计算,可以把音乐文 件中存在但不能被人耳听到的声音去掉。 通过这原理,我们还可以建立模型,把大部分数据空间分配到人耳最灵敏的2kHz到5kHz范围,其余频率分配比较少的空间;
声音其实是传播在介质中的能量波,人耳对声音能量强弱的直接感受就是听到音量的大小,也就是响度,单位是分贝(dB)。SPL(Sound Pressure Level),表示声音强度的名词,SPL是评价听觉刺激强度的标准,也就是说,我们对外界声音的感觉强度完全由它决定,其单位为dB。下面是人耳可听最小响度曲线:
0dB是听觉灵敏度的极限,而120dB是痛苦灵敏度的极限。人耳在2000Hz到5000Hz范围内的灵敏度最高,两端就迅速下降。所以人耳对中频的灵敏度远高于高低频。
横轴为f(HZ),纵轴为SPL(dB),若声音强度(SPL)低于该曲线的值表示人听不到声音,如下图所示。从图中可以得出几条结论:
第一,人的听觉频率范围大约在10Hz~20KHz之间
第二,大约在3KHz到4KHz时SPL有最小值,也就是所人在该频率范围内的听觉最敏锐
2) 人耳的遮蔽效应 (The Masking effect)
遮蔽效应表现在强信号会遮蔽邻近频率的弱信号。用生活经验来说,在安静的房间中,一根针掉到地上都能听见,可到了大街上,就算手机音量调到最大,来电时也 未必能听见,而手机的声音确确实实是存在的,原因就是被周围更大的声音遮蔽了。有了对遮蔽效应的研究成果,编码器就能根据已建立的数学模型,计算强信号对 附近弱信号的遮蔽,把能引起人们注意的声音才保留。
人耳还有前遮蔽效应和后遮蔽效应:因为人需要一定的时间来处理声音信号,在强信号之前或之后的弱信号,会被遮蔽掉。前遮蔽效应的时间约只有2-5ms,而后遮蔽的时间比较长,大约有100ms。利用这,我们能减小强信号之前和之后的分辨率;
不同频率的声音有不同的遮蔽宽度,这叫临界宽度。可以想象,弱信号越接近强信号的中心,遮蔽效应会越严重。临界宽度跟声音频率成正比。下面是临界宽度列表:
因为人耳对不同频率的敏感程度不同,MPEG1/Audio将22KHz范围内可感知的频率范围划分为23~26个临界频带,如下图。
从表中能得出几条结论:
第一,当当中心频率值在500Hz以内时,不同临界频带的带宽()几乎相同,约100Hz
当中心频率值大于500Hz后,随着f值得上升,临界频带的带宽剧增
第二,从表中也可以看出,人耳对低频的解析度要比高频更好
感受编码机制可以分为两个部分:知觉噪音成型(perceptual noise shaping)和知觉边带/变换编码(perceptual subband / transform coding)。编码器通过分析滤波器段(filterbank)分析音频信号的频谱组成并应用听觉心理学模型来估计仅仅可以注意得到的噪音电平。在后面 的量化和编码阶段,编码器会提高强信号附近的噪音电平,也就是减少量化位数,这样就能达到节省流量,压缩数据的目的。如果所有量化噪音都能控制在屏蔽临界 曲线以下,那么处理后人耳就区别不出哪个才是原音。
3) 人耳的空间响应:
人耳对某些高频的声音的空间感很差,辨别不了声源的方向。联合立体声(Joint Stereo)应运而生:在某些频率上采用“单声道”(事实上并非真正意义上的单声道),以减小流量。
4)频域上的遮蔽效应
SPL较大的信号容易掩盖频率相近的SPL较小的信号,叫声音的遮蔽效应。就比如在机场很难听到打电话的声音。
如上图所示,Masking Threshold将大约在0.7kHz,1.6kHz和2.3kHz的信号遮蔽了,当然0.7kHz信号的SPL在静音门槛曲线之下,不被遮蔽也是听不到的。
在这里,涉及3个重要的量——SMR、SNR和MNR。
SMR(signal-to-maskratio):指在一个临界频带内,从masker到遮噪门槛值的距离。
SNR(signal-to-noiseratio):指信号经过m位元量化后的信噪比,等于量化前信号方差和量化噪声的方差之比,。
MNR(mask-to-noise):用来测量人耳可以感知的失真参数,
如下图所示,展示了3者之间的关系,其中的灰色区域Critial Band指临界频带,Masking Threshold就是遮噪门槛曲线,图中的SMR指在临界频带内最大的SMR值。
值得注意的是,(1)我们上面讨论的SMR、SNR和NMR三者都是基于临界频带的,但遮蔽效应不仅对临界频带有影响,对临近的临界频带也有影响,称为遮噪延展性(2)上图所显示的是一个临界频带内的一条遮噪曲线,实际情况存在多条遮噪曲线,结果是这些曲线的叠加。
5)时域上的遮噪曲线
从上图可以看出,在一段很短的时间内(200ms左右),若出现了两个声音,不管出现的先后顺序,SPL大的声音(masker)会遮蔽SPL小的声音(maskee)。
若maskee出现在前,则遮噪曲线如上图的Pre-Masking;若maskee出现在后,则遮噪曲线如上图中的Post-Masking。由图中很容易看出,Post-Masking要比Pre-Masking在时间轴上要长很多。Pre-Masking能遮蔽前回音,这是选择MDCT窗口的一个依据。
6)感知熵Perceptual Entropy(PE)
最重要的一点,PE能显示特定信号在理论上的压缩极限。PE的单位是bits/sample,代表每个取样在维持CD音质的情况下,能够压缩到的最低位元数。
3.1.3 量化编码
当PCM讯号被分成好几个频段并经过一系列的处理后,最后经过MDCT,将波型转换为一连串的系数。这些系数就由Huffman编码器会选择最 合适的Huffman表来做最后的压缩。 Huffman编码一般是双路工作的,但是在某些需要精密编码的情况下,它会进行四路工作。编码器一般会有很多的Huffman编码表,很多时候为了更好 的声音质量和更有效屏蔽量化噪音,编码器甚至能为每一个频段选择最合适的Huffman编码表。
不过编码不是一次就能成功的,要采取Try and Error的方式循环进行。因为编码器一方面要削减量化噪音,让它在人耳遮蔽曲线以下;另一方面要保证bitrate满足要求。实际上这里就是要确定两个 数值:一个是确定bitrate的步进值(gain value),另一个是削减量化噪音的增益因子(ScaleFactor),这两个系数会在正式编码之前确定下来,确定过程由两个嵌套的迭代回路完成:失 真控制回路(Distortion Control Loop)和量化速率控制回路(Nonuniform Quantization Rate Control Loop)
内部迭代回路 (Rate Loop )
量化以后的数据送进Huffman编码器,当发现比特数大于可用流量时,编码器会返回信息,让Rate Loop调整步进值以增大量化步长,从而让数据流量减小。循环会一直进行,尝试不同的量化步长,直到Huffman编码以后的数据流量足够小。因为这个回 路是用来控制码率的,所以叫做Rate Loop。
外部迭代回路 (noise control loop)
显然,这个回路的作用就是控制量化噪音(quantization noise),让其保持在听觉心理学提供的屏蔽临界线(masking threshold)以下。每一个频段都会有一个增益因子,一开始编码器以1.0作为默认因子,如果量化噪音量超过允许的值,那么回路就会调整增益因子, 来把量化噪音降下来。更少的量化噪音意味着流量增大,码率需要提高,所以增益因子每次改变以后,Rate Loop都要进行调整,让码率符合要求。
所以两个回路是嵌套工作的,互相协调,中止条件是量化噪音降到屏蔽临界线以下而码率也足够小。良好的编码器会让两个回路有条不紊的工作,因为一旦处理不好就很容易陷入死循环。
3.2 编码流程
编码流程图如下:
信号流程
(1)MP3编码输入信号:PCM(Pulse Code modulation)声音信号,有些.wav格式的音频文件为PCM信号。
(2)MP3编码输出信号:MP3格式码流
wav文件头格式
wav数据块
WAV格式文件所占容量= (取样频率X 量化位数X 声道)X 时间/ 8 (字节= 8bit)。
14H~15H的2个字节值为1时表示数据位PCM编码格式,可以作为MP3编码器的输入。
MP3一帧包含1152个声音取样,一帧分为2节(granule)。mp3编码时,首先将原始的PCM数据送入滤波器组,分成32个等频宽的子频带,然后再通过MDCT(modified discrete coding transform),将每个子带,转换成18个次频带。然后根据第二声学模型提供的SMR(signal-to-mask ratio),对每一个子频带信号,做位元分配和编码。
3.2.1 Step 1:prediction
根据第二声学模型做预测,预测结果得到的SMR会作为位元分配的依据。第二声学模型中几个重要依据如下:
静音阈值曲线、时域掩蔽效应、频域掩蔽效应、临界频带。
3.2.2 Step 2:子带分离(Analysis Subband Filter)
首先将原始的PCM数据送入滤波器组,分成32个等频宽的子频带。
为多重相位相位滤波器,将PCM信号输入后,滤波器系统看做线性系统,则有
再将用32点进行下采样,得子带滤波器输出结果为
下图是ISO11172-3标准给出的FIGURE 3-C.1 Analysis subband filter flow chart。其步骤为
【a】输入32个音频samples
【b】建立一个数组x[n], for n=0~511用于保存输入的采样值。将x[n]看做一个最多能容纳512个元素的队列,x[511]为队首,x[0]为队尾, 每次接收新的samples前将队首32个元素移出,将samples放入队尾。
【c】加窗滤波器处理,窗函数系数为C[i],i=0~512,通过实现窗函数滤波器
【d】计算64个Yi值,表达式如流程图中所示
【e】计算32个子带滤波器采样值Si,这里使用到矩阵M[i][k],
M[i][k] = cos [(2i + 1)(k - 16)p/64] ,
for i = 0 to 31, and k = 0 to 63.
实际计算时可以将非线性的运算用查Table的方法以减小运算的复杂度。
3.2.3 Step 3:MDCT
MDCT滤波器将32个子带中每一个子带的的信号在频域上进一步划分,长块进行18点(18个频域采样点)的MDCT变换,短块进行6点(6个频域采样点)的MDCT变换,以窗为单位分3次进行。MDCT包括三部分:MDCT窗框、MDCT、长窗假象处理。
(a)MDCT加窗
4种窗及使用情形如下:
窗框的选择依据第二声学模型,规则通常如下:子频带音频讯号稳定时,采用长窗来提供最细的频谱解析度;子频带变动较大时,采用短窗提供较大的时域解析度。决定好窗框以后,就可以以窗框为单位进行MDCT运算。如果是长窗,需要针对混跌做假象处理。
(b)MDCT
作用:将时域信号转换成频域信号
©长窗假象处理(混叠消除)
什么是长窗假象:使用长窗时,频谱上可见邻近的子频带间有明显的重叠现象,处于重叠区间的讯号将会同时影响两个子频带。
假象处理的方式:将处在相对应位置的频线之能量做一定比例的增减,蝶形运算。
MDCT的表达式为:
可以通过蝶形图运算来提高效率,蝶形运算中最重要的是系数值,使用短窗框的MDCT运算点数为12,长窗框则为36。ISO 11172-3的ANNEX_AB.DOC文档中Table 3-B.9给出了蝶形运算的系数如下
附:Step2和Step3的综合图为:
3.2.4 Step 4: Joint Stereo(联合立体声)
编码依据:2个声道存在相干性,方法有:
Intensity Stereo(IS):Human hearing is predominantly less acute at perceiving the direction of certain audio frequencies
Mid/Side (M/S) stereo :The mid channel is L + R. The side channel is L − R
3.2.5 Step 5:位元分配(bit allocation)
根据第二声学模型的预测结果,进行位元分配;位元分配是一个反复调整的过程。
位元分配目的是使每个频带的MNR达到最大,使音质最佳。过程为:寻找最小的MNR频带,分配位元给该频带以提高MNR,接着重新计算各频带的MNR。重复上述过程,直到位元分配结束。
[a]可编码位元数计算方法,1152指每个编码框的取样个数,
比如,以单声道为例,比特率为128kbps,采样频率为44.1kHz,则每个编码框可编码的位元数为3344。但考虑到挡头的32位,附属资料的136位和可选择的16位CRC,所以最终可用的位元数为3344-32-136-16=3160,实际编码最小单位为grannul,所以每个grannul可用位元数为3160/2=1580。
[b]MNR计算方法,在前面心理学模型中已经提到,
其中SMR由声音心理学模型提供,SNR信噪比则是由量化确定的。
3.2.6 Step 6:量化
以缩放因子频带为单位,进行量化。缩放因子频带内使用相同的缩放因子。
mp3中一帧数据含有1152个PCM数据,分成2节(granual)。每节含有576个PCM数据,这576个值在不同的节类型有不同的定义。如下所述:
(a)该节为长块:这576个值代表576条频率线上的值,是时域上的576个pcm值经过时频变换的结果。这576条频率线从低到高分成32个子带,每个子带含18条频率线。同时,也将这576个数据分成若干个缩放因子带,每个缩放因子带共用一个缩放因子。长块的缩放因子带在44kHz按如下表格划分,其中,418-575不属于任何一个缩放因子带,使用系统提供的默认缩放因子:
**(b)该节为短块:**这576个值代表192条频率线的值,192条频率线分32个子带,每条子带包括6条频率线。每条频率线有3个值,分别属于3个窗 (windows_0,windows_1,windows_2)。192条频率线也被分成若干缩放因子带,在44.1kHz时划分如下图,其中,136-191使用默认缩放因子。
这576个值得排列顺序为,先是按缩放因子带从低到高排列;缩放因子带内,按windows_0,windows_2,windows_3排列;每一个window中,频率线从低到高排列。
(c)该节为混合块: 解出来的值分2个部分,第一部分(前36个值)是长块,代表36条频率线;第二部分(后540个值)为短块,代表180个频率线。2部分的排列方式分别于长块和短块相同。
综上,有:
缩放因子带在逆量化时共用的缩放因子,缩放因子被编码于main_data中,欲解码缩放因子,首先得知道缩放因子所占的比特数,在side information的scale_compress[gr][ch]提供这样的信息,所用的bit数通过查如下表才能得到。slen 1和slen 2针对那些缩放因子带,由块类型决定。
下图为量化器的输入输出曲线,量化器的输入为浮点值频率,输出为整形值的频率。
由图知,量化器将输入的浮点值量化后变为整型值,且量化过程为非线性非均匀的。
3.2.7 Step 7:Huffman编码
Huffman编码广泛应用于无损压缩领域,比如我们常用的WINZIP,WINRAR等压缩软件就是以此为基础的(只能说是基础,因为这些用到的编码方法不只是Huffman编码)。 Huffman编码用途就是降低数据的冗余度,可节省大约20%的空间。用WINZIP来再压缩MP3文件每什么效果就因为MP3编码的时候已经应用到采 用Huffman编码。
(a)Huffman码表选择
当从一个缩放因子频带过渡到另一个缩放因子频带时,Huffman码表可能发生改变;需要进行编码的576个值分为大值区、小值区、零值区:
不同的区域使用不同的Huffman表编码,大值区每2个值一起编码,小值区每4个值一起编码,零值区无需编码,大值区以缩放因子频带为单位,分为3个region。每个region使用不同的Huffman表。一共有32个Huffman表供选择。
(b)huffman编码(略)
注:大值区的Huffman表有一个参数linbits,用来指定Huffman表是否能用来编码大于15的数。
3.2.8 Step 8:生成帧
加上Frame Header和Side Information,生成帧。
四、解码原理
MP3 文件是经过压缩算法压缩而存在的,为得到 PCM 信号,需要对 MP3 文件进行解码,解码过程大致为:比特流分析、霍夫曼编码、逆量化处理、立体声处理、频谱重排列、抗锯齿处理、IMDCT 变换、子带合成、PCM 输出。整个过程涉及很多算法计算,要自己编程实现不是一件现实的事情,还好有很多公司经过长期努力实现了解码库编程。
现在合适在小型嵌入式控制器移植运行的有两个版本的开源 MP3 解码库,分别为 Libmad解码库和 Helix 解码库,Libmad 是一个高精度 MPEG 音频解码库,支持 MPEG-1、MPEG-2以及 MPEG-2.5 标准,它可以提供 24bitPCM 输出,完全是定点计算,更多信息可参考网站:http://www.underbit.com/。
Helix 解码库支持浮点和定点计算实现,将该算法移植到 STM32 控制器运行使用定点计算实现,它支持 MPEG-1、MPEG-2 以及 MPEG-2.5 标准的 Layer3 解码。Helix 解码库支持可变位速率、恒定位速率,以及立体声和单声道音频格式。更多信息可参考网站:https://datatype.helixcommunity.org/Mp3dec。
因为 Helix 解码库需要占用的资源比 Libmad 解码库更少,特别是 RAM 空间的使用,这对 STM32控制器来说是比较重要的,所以在实验工程中我们选择 Helix 解码库实现 MP3 文件解码。这两个解码库都是一帧为解码单位的,一次解码一帧,这在应用解码库时是需要着重注意的。
Helix 解码库涉及算法计算,整个界面过程复杂,有兴趣可以深入探究,这里我们着重讲解 Helix移植和使用方法。Helix 网站有提供解码库代码,经过整理,移植 Helix 解码库需要用到的的文件如图 Helix 解码库文件结构 。有优化解码速度,部分解码过程使用汇编实现。
MP3音频解码可以用下图表示总体流程,具体可参见文档《mp3解码算法原理详解》。
4.1程序系统结构
PCM信号进行MP3压缩时,以1152个PCM采样值为单位,封装成具有固定长度的MP3数据帧,帧是MP3文件的最小组成单位。在解码时,利用数据帧里的信息就可以恢复出1152个PCM采样值。这1152个采样值被分为2个粒度组,每个粒度组包含576个采样值。一个MP3数据帧分为5个部分:帧头、CRC校验值、边信息、主数据、附加数据。
比特流:
比特流是一种内容分发协议。它采用高效的软件分发系统和点对点技术共享大体积文件(如一部电影或电视节目),并使每个用户像网络重新分配结点那样提供上传服务。(因为没有专业学过这方面的内容,我暂且把它理解为一段数据,里面的内容有时间再探讨)。
4.2 主控模块
4.3 同步及差错检测
同步及差错检查:mp3的数据流的传输和同步工作中都是以帧为单位的。帧是MP3最小的格式单元,它不可以再被分割。每一帧头部包含了当前帧的一些基本信息,其中就包括同步信息。同步信息的组成是包含连续的12比特的‘1’。mp3视频解码工作的第一步就是使解码器和输入数据流同步。在启动解码器之后,可以搜索数据中连续12个比特的‘1’来完成。在取得同步信息之后,帧头部后续的信息是:帧头信息,包括采样率、填充位、比特率等信息。
数据流的同步以及帧头信息的读取
MP3数据流的同步以帧为单位,每一帧的帧头都包含同步信息。这个同步信息是连续的12比特的‘1’组成。MP3音频解码过程中的第一步就是使解码器与输入数据流同步。在启动解码器后,可以通过搜索数据流中的12比特长的同步字来完成。在取得同步以后跟着的数据就是帧头信息,包括采样率、填充位、比特率等信息。
主数据的读取
在MP3编码过程中使用了比特池技术,所以当前帧的主数据不一定全部都在当前帧中,在解码过程中,必须结合主数据开始指针的值来确定主数据的开始位置。主数据包含的数据有缩放因子、哈夫曼数据及附加数据。这些字段在主数据中有固定的格式。
4.3.1 帧同步
4.3.2 头信息编码
4.3.3 帧边信息编码
4.3.4 main_data_begin
4.3.5 block_type
4.3.6 big_values,count1
4.3.7 处理流程
4.4缩放因子(scale factor)解码
4.4.1 尺度因子带(scalefactor-band)
4.4.2 scfsi
4.4.3 处理流程
4.5 哈夫曼解码
哈夫曼解码:你可以这样理解,我把不同的数据通过一个表格进行一一对应,用这个对应的码来表示原来的信息,那么出现频率高的数,我用尽可能短的码来表示。出现频率低的数用长一点的码来表示。这样可以减少表示信息的内容量。而且传输过去之后,再按照这个对照码可以进行还原。大概原理就是这个。
哈夫曼解码和反量化
在MP3编码过程中,根据心理声学模型的输出,对离散余弦变换的输出样本以粒度为单位进行的量化和分配,再对量化的结果进行哈夫曼编码。量化和编码主要是通过循环迭代完成的,循环模块分为三层来描述,最高层为帧循环,它调用外层迭代循环,而外层迭代循环又调用内层迭代循环。但在解码过程中,哈夫曼解码和反量化过程是分开实现的。每个粒度组的频率线都是用不同的哈夫曼表来进行编码的,因此在解码过程中,需要采用不同的解码方法。反量化频谱过程就是基于所得到的哈夫曼解码数据,根据逆量化全缩放公式和帧边信息,对于不同的窗类型采用不同的公式以恢复576个频率线的真实值。
4.5.1 处理流程
4.6逆量化
4.7联合立体声转换
4.7.1 强度立体声转换
4.7.2 M_S立体声转换
4.7.3 处理流程
4.8 重排序
重排序和反混叠
反量化过程中得出的频谱值不是按相同顺序排列的。在编码的MDCT过程中,对于长窗产生的频谱值先按子带然后按频率排列;对于短窗,产生的频谱值按子带、窗、频率的顺序排列。为了提供哈夫曼编码效率,短窗中的数据被重新排列,按照子带、频率、窗的顺序排列。解码时,重排序及时将短窗中的频谱值重新排列。同样,在编码的MDCT过程中,为了得到更好的频域特性,对长窗对应每个子带进行了去混叠处理,为了得到正确的音频信号,在解码时必须对长窗对应的子带进行混叠重建。
4.8.1 处理流程
4.9 混淆缩减
4.10 IMDCT覆盖叠加
IMDCT:IMDCT是缩写,全称是:Inverse Modified Discrete Cosine Transform(反向修正离散余弦变换)。在MP3中需要使用此算法将输入数据从频域变换到余弦域,对子带滤波进行补偿运算。使用逆向离散余弦变换的公式,对反量化得出的信号进行变换。IMDCT运算公式大概长这样:
IMDCT运算过程如下图:
逆向离散余弦变换
逆向离散余弦变换主要是使用逆向离散余弦变换的公式,对反量化得出的信号进行变换。逆向离散余弦变换的计算十分复杂,为了提高效率,可以对计算做一些优化。
4.10.1 加窗:
4.10.2 叠加:
4.10.3 Szu-Wei Lee的快速算法
4.11 频率反转
频率反转和子带合成
频率反转是对逆向离散余弦变换的输出值中的奇数号子带(0到31号子带中的1,3,5,…,31)中的奇数号样本值(每个子带中的0到17号样本值的1,3,5,…,17号样本值)进行反相处理,用来补偿编码时为提高离散余弦变换效率而进行的频率反转。子带合成滤波器将32个带宽相等的子带中的频域信号反变换成时域信号。子带合成是逆向离散余弦变换后的一个通道中32个子带的样值,经过一系列的计算还原出32个PCM数字音频信号的过程。子带合成过程先将32个子带样值进行逆向离散余弦变换,生成64个中间值,将这64个中间值转入到一个长为1024点的类似先进先出FIFO的缓存,再在这1024个值中抽取一半,构成一个512个值的矢量,再进行加窗运算,最后将加窗结果进行叠加生成32个时域输出。
4.12 合成多相滤波
Byeong Gi Lee的dct快速算法
在帧头后边是通道信息和增益因子(ScaleFactor),数据以比特流的形式送进编码器,当解码器在读到上述信息后,就可以进行解码了。解码比编 码容易得多,播放器先进行帧同步,然后读取通道信息和增益因子,再进行Huffman解码,这样就得到解压以后的数据。但这些数据仍然不能进行播放,因为 它们还只是一些频段信息,还需要经过特殊手段对他们转换组合,跟时间建立联系(实际上就是频域转时域)。然后进行一系列的逆变换,把音频信号重建出来。
五、常见问题
1.MP3的同步标识是什么?
“FF FA xx xx”或者“FF FB xx xx”
2.采样率有哪些?
在当今的主流采集卡上,采样频率一般共分为22.05KHz、44.1KHz、48KHz三个等级,22.05KHz只能达到FM广播的声音品质,44.1KHz则是理论上的CD音质界限,48KHz则更加精确一些。
3.MP3的编码原理大概是怎样的?
MP3音频压缩包含编码和解码两部分,编码是将原始信号转换成电平信号的过程,解码即是逆过程,MP3 采用了感知音频编码(PerceptualAudio Coding)这一失真算法。人耳感受声音的频率范围是20Hz-20kHz,MP3截掉了大量的冗余信号和无关的信号,编码器通过混合滤波器组将原始声音变换到频率域,利用心理声学模型,估算刚好能被察觉到的噪声水平,再经过量化,转换成Huffman编码,形成MP3位流。解码器要简单得多,它的任务是从编码后的谱线成分中,经过反量化和逆变换,提取出声音信号。
4.MP3一帧的时长是多少秒?一帧大小是多大?
根据公式,帧时长=每帧采样数/采样频率,易知MPEG1 Layer3在44.1kHz的条件下:
帧时长=1152/4=0.026s
一帧数据的采样个数根据音频的Layer与MPEG标准不同而不同。如下表所示:
帧长度是压缩时每一帧的长度,包括帧头的4个字节。它将填充的空位也计算在内。Layer 1的一个空位长4字节,Layer 2和Layer 3的空位是1字节。当读取MPEG文件时必须计算该值以便找到相邻的帧。注意:因为有填充和比特率变换,帧长度可能变化
计算公式如下:
Layer 1:Len(字节) = ((每帧采样数/8比特率)/采样频率)+填充4
Layer2/3:Len(字节) = ((每帧采样数/8*比特率)/采样频率)+填充
例:MPEG1 Layer3 比特率128000,采样率44100,填充0,帧长度为:((1152/8*128K)/44.1K+0=417字节
5.VBR头结构是怎样的?
VBR文件头位于MP3文件中第一个有效帧的数据区 。
6.ID3是怎么来的?
起初MP3并不能保存歌手名称、专辑名称、歌名、备注等附加信息,直到1996年,一个叫做Eric Kemp的人制作了Studio3软件,它可以在MP3文件的最后部分增加固定的128字节小块数据,用来记录音乐的信息。很快,MP3ext的作者Michael Mutschler又将这个标记进行了扩展,并正式将其命名为ID3,而且还使用注释的最后两个字节来记录CD和音乐的来源,其版本被定为ID3v1.1。不过ID3v1版本的限制太多,比如歌曲名长度被限制在30个英文字母,稍长一点的曲名就会被截掉,让人头痛不已。在这种情况下,它的升级版本ID3v2出现了。它首先解除了128个字节的限制,各个字段的长度也是弹性可变的,使可包含的音乐信息更为丰富,除了歌名、专辑名、演唱者外,还可保存歌词、均衡器设置、图片等信息。ID3v2的设计更灵活,扩展性更强,并且支持Unicode,因此歌词信息支持多语言。ID3v2甚至能包含一个文件,所以未来的MP3可能会附带有视频文件,让你不仅能听,还可以看。微软的Windows Midia Player就能很好地支持ID3v2,甚至在Windows XP中,你不需要打开任何播放器,只要进入一个存放MP3的文件夹,系统就能读取ID3v2的信息来对文件分类排列。
六、附录
6.1 VBR帧
标准声音帧头:Mp3时,为“FF FA xx xx”或者“FF FB xx xx”
36-39:Mp3的就是这种情况,第5至36的数据存储的是前面提到过的32字节的边信息,无效边信息时是32字节的“00”
45-48:帧数(包括第一帧)
VBR规模:VBR规模,用于位率变动音频质量指示,最差 0,最好 100,大端[可选]
曲子是:刘德华 - 虹桥机场的咖啡厅.mp3(5,898,130字节,时长3分14秒)
a. 第37至40地址为“58 69 6E 67”,就是“Xing”标志了;
b. 第41至44地址为“00 00 00 0F”,这里是Flag了,表示该帧存储了帧数、文件长度、目录表和VBR规模信息。
c. 第45至48地址为“00 00 1D 11”,这里是文件的总帧数(包括第一帧),是big-endia的,(1163+13162+116+1)帧。
d. 第49至52地址为“00 59 FD DE”,这里是文件的总大小,也是Big-Endian的,(5165+9164+15163+13162+1316+14)=5,897,694(字节)。
e. 第53至152地址,就是100字节的目录表了(称作TOC表),如图蓝色的部分。
TOC (Table of Contents)
TCO 索引的计算方式如下:文件长度 100 比如文件持续 240 秒,我需要跳到 60 秒,文件长度为 5000000 字节 计算如下TOC[(60/240)*100] =TOC[25] 然后相对于文件中的位置大约是在 (TOC[25]/256) * 5000000 如果要自己重建的话,基本是把这个步骤反过来做就可以了。要求准确的话,就需要根据时间点找到正确帧的位置然后再计算, 定位帧的做法都是从第一帧开始搜索。
f. 第153至156字节地址为“00 00 00 64”,,音频质量指示质量指示器,为 0(最好)-100(最差)的 Big-Endian 值,没想到这个文件的音质是最差的100。
g. 接下来是Lame版本的相关信息。
Info 帧
info帧,结构和Xing帧是相同的,从一些网上的资料显示:这种类型的帧有点怪,在CBR文件中的第一个数据帧可以是Info帧,在VBR文件中的第一个数据帧也有可能是Info帧。根据文章xx,第一个数据帧为Info帧的文件大概率是CBR文件,比如Kugoo软件制作的铃声的第一帧都是Info帧,而且是CBR文件。
VBRI帧
据了解,目前此头信息,只有用 Fraunhofer 的编码器生成的 MPEG音频文件,才会用到此头。其和Xing 头不一样,其放在第一个MPEG头的后面,大小正好是 32字节。其位置,长度和示例,都是以字节为单位。下表是 VBRi 头的具体格式及含义,单位为字节:
如下图所示,蓝色部分包括了4个字节的帧头,32个字节的空字节,以及26个字节的不包括TOC表的VBRI帧内容。从地址0x6BC开始,0x6BC–0X6BF为VBRI字符。从0X6D7至0X80A为TOC表内容。文件总大小为0X5F0968字节,不包括ID3与TAG,也就是说,如果用HXD看整个文件的大小,实际上是大于0X5F0968字节的。
6.2 MPEG 音频版本表
6.3 比特率索引表(单位 Kbps)
6.4 采样率索引表
6.5 每帧数据的采样数
6.6 channel 模式表
6.7 标签帧的标识以及其意义对照表
index content
AENC [Audio encryption]
APIC [Attached picture]
COMM [Comments]
COMR [Commercial frame]
ENCR [Encryption method registration]
EQUA [Equalization]
ETCO [Event timing codes]
GEOB [General encapsulated object]
GRID [Group identification registration]
IPLS [Involved people list]
LINK [Linked information]
MCDI [Music CD identifier]
MLLT [MPEG location lookup table]
OWNE [Ownership frame]
PRIV [Private frame]
PCNT [Play counter]
POPM [Popularimeter]
POSS [Position synchronisation frame]
RBUF [Recommended buffer size]
RVAD [Relative volume adjustment]
RVRB [Reverb]
SYLT [Synchronized lyric/text]
SYTC [Synchronized tempo codes]
TALB [Album/Movie/Show title]
TBPM [BPM (beats per minute)]
TCOM [Composer]
TCON [Content type]
TCOP [Copyright message]
TDAT [Date]
TDLY [Playlist delay]
TENC [Encoded by]
TEXT [Lyricist/Text writer]
TFLT [File type]
TIME [Time]
TIT1 [Content group description]
TIT2 [Title/songname/content description]
TIT3 [Subtitle/Description refinement]
TKEY [Initial key]
TLAN [Language(s)]
TLEN [Length]
TMED [Media type]
TOAL [Original album/movie/show title]
TOFN [Original filename]
TOLY [Original lyricist(s)/text writer(s)]
TOPE [Original artist(s)/performer(s)]
TORY [Original release year]
TOWN [File owner/licensee]
TPE1 [Lead performer(s)/Soloist(s)]
TPE2 [Band/orchestra/accompaniment]
TPE3 [Conductor/performer refinement]
TPE4 [Interpreted, remixed, or otherwise modified by]
TPOS [Part of a set]
TPUB [Publisher]
TRCK [Track number/Position in set]
TRDA [Recording dates]
TRSN [Internet radio station name]
TRSO [Internet radio station owner]
TSIZ [Size]
TSRC [ISRC (international standard recording code)]
TSSE [Software/Hardware and settings used for
TYER [Year]
TXXX [User defined text information frame]
UFID [Unique file identifier]
USER [Terms of use]
USLT [Unsychronized lyric/text transcription]
WCOM [Commercial information]
WCOP [Copyright/Legal information]
WOAF [Official audio file webpage]
WOAR [Official artist/performer webpage]
WOAS [Official audio source webpage]
WORS [Official internet radio station homepage]
WPAY [Payment]
WPUB [Publishers official webpage]
WXXX [User defined URL link frame]
6.8 音乐类型
0="Blues";
1="ClassicRock";
2="Country";
3="Dance";
4="Disco";
5="Funk";
6="Grunge";
7="Hip-Hop";
8="Jazz";
9="Metal";
10="NewAge";
11="Oldies";
12="Other";
13="Pop";
14="R&B";
15="Rap";
16="Reggae";
17="Rock";
18="Techno";
19="Industrial";
20="Alternative";
21="Ska";
22="Deathl";
23="Pranks";
24="Soundtrack";
25="Euro-Techno";
26="Ambient";
27="Trip-Hop";
28="Vocal";
29="Jazz+Funk";
30="Fusion";
31="Trance";
32="Classical";
33="Instrumental";
34="Acid";
35="House";
36="Game";
37="SoundClip";
38="Gospel";
39="Noise";
40="AlternRock";
41="Bass";
42="Soul";
43="Punk";
44="Space";
45="Meditative";
46="InstrumentalPop";
47="InstrumentalRock";
48="Ethnic";
49="Gothic";
50="Darkwave";
51="Techno-Industrial";
52="Electronic";
53="Pop-Folk";
54="Eurodance";
55="Dream";
56="SouthernRock";
57="Comedy";
58="Cult";
59="Gangsta";
60="Top40";
61="ChristianRap";
62="Pop/Funk";
63="Jungle";
64="NativeAmerican";
65="Cabaret";
66="NewWave";
67="Psychadelic";
68="Rave";
69="Showtunes";
70="Trailer";
71="Lo-Fi";
72="Tribal";
73="AcidPunk";
74="AcidJazz";
75="Polka";
76="Retro";
77="Musical";
78="Rock&Roll";
79="HardRock";
80="Folk";
81="Folk-Rock";
82="NationalFolk";
83="Swing";
84="FastFusion";
85="Bebob";
86="Latin";
87="Revival";
88="Celtic";
89="Bluegrass";
90="Avantgarde";
91="GothicRock";
92="ProgessiveRock";
93="PsychedelicRock";
94="SymphonicRock";
95="SlowRock";
96="BigBand";
97="Chorus";
98="EasyListening";
99="Acoustic";
100="Humour";
101="Speech";
102="Chanson";
103="Opera";
104="ChamberMusic";
105="Sonata";
106="Symphony";
107="BootyBass";
108="Primus";
109="PornGroove";
110="Satire";
111="SlowJam";
112="Club";
113="Tango";
114="Samba";
115="Folklore";
116="Ballad";
117="PowerBallad";
118="RhythmicSoul";
119="Freestyle";
120="Duet";
121="PunkRock";
122="DrumSolo";
123="Acapella";
124="Euro-House";
125="DanceHall";
126="Goa";
127="Drum&Bass";
128="Club-House";
129="Hardcore";
130="Terror";
131="Indie";
132="BritPop";
133="Negerpunk";
134="PolskPunk";
135="Beat";
136="ChristianGangstaRap";
137="Heavyl";
138="Blackl";
139="Crossover";
140="ContemporaryChristian";
141="ChristianRock";
142="Merengue";
143="Salsa";
144="Trashl";
145="Anime";
146="JPop";
147="Synthpop";
6.9 实例分析
1. 歌曲信息
2. 结构解析
1.标签头
标签头:10字节,00H-09H
标签大小:
Size=(Size[0]&0x7F)*0x200000+(Size[1]&0x7F)*0x400+(Size[2]&0x7F)*0x80+(Size[3]&0x7F)
=(0x07&0x7F)*0x400+(0x34&0x7F)*0x80+(0x60&0x7F)
=0x1C00+0x1A00+0x60
=0x3660=13920
2. TSSE标签帧
3. COMM标签帧
帧内容大小:
Size = Size[0]*0x100000000 + Size[1]*0x10000+ Size[2]0x100 +Size[3]
=0x020x100+0x07
=0x207=519
4. TALB标签帧
5. TIT2标签帧
6. TPE1标签帧
7. TPOS标签帧
8. TRCK标签帧
9. APIC标签帧
此处省略N多字节………
帧内容大小:
Size = Size[0]*0x100000000 + Size[1]0x10000+ Size[2]0x100 +Size[3]
=0x010x10000+0xD30x100+0xD7
=0x10000+0xD300+0xD7
=0x1D3D7=119767
10. 未知数据
不清楚该段数据具体作用,目测是填充字节。
11. 音频数据
篇幅有限,只分析第一帧数据,其他帧与此无异。
帧头解析:
FF=11111111 红色
FB=1111 1011 红色黑色绿色紫色
E0=1110 0000 蓝色橄榄色深红色橙色
00=00000000 白色浅绿色深蓝色褐色粉红色
红色:11位,同步信息,所有位均为1,第一个字节恒为FF
黑色:2位,版本,MPEG1
绿色:2位,层,Layer3
紫色:1位,无CRC校验
蓝色:4位,位率,单位是kbps,320
橄榄色:2位,采样频率,44.1K
深红色:1位,用来调整文件头长度,无需调整
橙色:1位,保留字,未使用
白色:2位,表示声道模式,立体声Stereo
浅绿色:2位,声道模式为Joint Stereo时才使用
深蓝色:1位,文件是否合法,不合法
褐色:1位,是否原版,非原版
粉红色:2位,用于声音经降噪压缩后再补偿的分类,未定义
根据以上信息可计算:
帧长度=帧头+通道信息+帧内容= ((1152/8320)/44.1=1044字节
每帧持续时间=1152/44.11000=26.12ms
因为该歌曲为CBR即固定位率歌曲,所以每帧的数据长度都是1044字节,26ms。
12. 其他数据
该歌曲无ID3V1信息。
七、资料下载
1.代码下载地址:
https://github.com/npc-github-octocat/Helix_Mp3
https://sourceforge.net/projects/lame/files/lame/
MPEG-1 (即ISO/IEC 11172)
MPEG-2(即ISO/IEC 13813)
MPEG-4(即ISO/IEC 14496)
2.参考网址
[1] : MP3文件格式与编码原理解码流程详解
https://blog.csdn.net/yuyin86/article/details/7097933/
[2] :MP3编码技术原理
https://blog.csdn.net/sunnylgz/article/details/7615410
[3] :MP3编码原理概述[转]
https://blog.csdn.net/myleeming/article/details/3318002
[4] :MP3编码分析
https://blog.csdn.net/xiahouzuoxin/article/details/7849249
[5] : Mp3解码算法流程
https://blog.csdn.net/jeffchenbiao/article/details/7332863
[6] : MP3解码算法原理解析
https://www.jianshu.com/p/58df71a19901
[7] : 【2017年整理】mp3解码算法原理详解
https://www.docin.com/p-1913003116.html
八、SHINE程序分析
SHINE是一个C语言编写的MP编码程序,总共由11个源文件构成。将源文件添加到VC新建的控制台应用程序中即可运行,但运行时得使用命令行方式。
1、文件数据结构
在types.h中定义了一个config_t的结构体类型,并用它初始化了一个全局变量config,该变量作用相当于面向对象语言中的“对象”,用于在整个编码流程中对编码数据和参数进行保存和管理。
定义了一个用于存储PCM脉冲格式文件信息的结构体类型wave_t,并且用wave_t在config_t中定义了wave变量,该变量保存了MP3编码的源的信息,作为MP3编码器的输入。
定义了一个用于存储MP3编码后信息的结构体类型mpeg_t,同样用mpeg_t在config_t中定义了mpeg变量,该变量存储的信息作为编码后的MP3参数信息输出。
typedefstruct {
time_t start_time; /*记录编码起始时间*/
char* infile; /*编码输入文件*/
wave_t wave; /*PCM文件头信息*/
char* outfile; /*编码输出码流文件*/
mpeg_t mpeg; /*MP3文件头信息*/
} config_t;
以上的结构体主要用于保存“头”信息,编码输出后的字节流实体信息保存在bs结构体(bitstream.h文件中定义)中,bs结构体定义为
staticstruct
{
FILE *f; /* bitstream output file handle */
unsigned int i; /*file buffer index */
unsigned char *b; /* buffer pointer */
} bs;
结构体中的文件指针与指向同一个输出文件,b指向编码后的码流,编码结束后写入文件中。
2、编码前化工作
包括初始化config.mpeg结构体变量的默认值,打开wave类型文件(SHINE程序中此时只读取了文件头信息,没读取实体信息),根据读取的信息对mpeg输出信息进行配置。
3、MP3编码
MP3编码主要由3步组成,分析子频带滤波器组,MDCT变换到频域,位元分配与量化。每次的操作对象为输入PCM的一帧。
MP3编码核心调用
/* polyphase filtering */
for(gr=0; gr<config.mpeg.granules; gr++)
for(ch=0; ch<config.mpeg.channels; ch++)
for(i=0;i<18;i++)
L3_window_filter_subband(&buffer[ch],&l3_sb_sample[ch][gr+1][i][0] ,ch);
/* applymdct to the polyphase output */
L3_mdct_sub(l3_sb_sample, mdct_freq);
/* bit andnoise allocation */
L3_iteration_loop(mdct_freq, &side_info, l3_enc,mean_bits);
/* writethe frame to the bitstream */
L3_format_bitstream(l3_enc, &side_info);
(1)子频带滤波器
下图是ISO11172-3标准给出的Analysis subband filter flow chart。其步骤为
【a】输入32个音频samples
【b】建立一个数组x[n], for n=0~511用于保存输入的采样值。将x[n]看做一个最多能容纳512个元素的队列,x[511]为队首,x[0]为队尾, 每次接收新的samples前将队首32个元素移出,将samples放入队尾。
【c】加窗滤波器处理,窗函数系数为C[i],i=0~512,通过实现窗函数滤波器
【d】计算64个Yi值,表达式如流程图中所示
【e】计算32个子带滤波器采样值Si,这里使用到矩阵M[i][k],
M[i][k] = cos [(2i + 1)(k - 16)p/64] ,
for i = 0 to 31, and k = 0 to 63.
实际计算时可以将非线性的运算用查Table的方法以减小运算的复杂度。
当然,在SHINE程序中,作者对M[i][k]×Y[k]的运算做了简化,主要从两方面:
第一,cos函数在k=16和k=48处的对称性;第二,从各滤波器的相关性考虑,即cos(2i+1)的对称性考虑。
(2)MDCT实现
DCT(离散余弦变换)的原始表达式为
DCT可以通过蝶形运算提高运算效率,具体内容可参考数字信号处理教材的内容。
DCT运算的蝶形图
MDCT的表达式为
MDCT快速算法蝶形图
计算一样可以通过蝶形图运算来提高效率,蝶形运算中最重要的是系数值,使用短窗框的MDCT运算点数为12,长窗框则为36。
ISO 11172-3的ANNEX_AB.DOC文档中Table 3-B.9给出了蝶形运算的系数如下
Table 3-B.9 Layer III coefficients for aliasingreduction:
蝶形系数csi和cai通过下面2个式子计算
带假象处理的MDCT/IMDCT编解码图
32个频带每个频带的蝶形运算都需要8次,SHINE中蝶形运算的程序如下
for(band=31; band--; )
for(k=8;k--; )
{
/* must left justifyresult of multiplication here because the centre
* two values in eachblock are not touched.
*/
bu = muls(mdct_enc[band][17-k],cs[k])+ muls(mdct_enc[band+1][k],ca[k]);
bd =muls(mdct_enc[band+1][k],cs[k]) - muls(mdct_enc[band][17-k],ca[k]);
mdct_enc[band][17-k] = bu;
mdct_enc[band+1][k] = bd;
}
(3)Huffman编码与位元分配
在经过声音心理模型和分析滤波器排之后提供信息之后,就可以对Audio进行位元分配和量化编码了。SHINE程序在该部分做了很多工作,位元分配和量化编码通过3个回圈实现:[a]Iteration Loop [b]Outer Loop [c]Inner Loop。且[a]包含[b],[b]包含[c]。
[c]主要完成量化工作,[b]计算量化后失真大小以决定是否需要重新量化,[a]计算剩余位元数并放在储存处。
位元分配与量化是整个编码过程中计算量最大的部分,是整个编码过程的核心。
【1】外部回圈分析
根据下面的公式计算失真度大小
对于量化误差大于人耳所能能最大可容忍失真的情况,则需将最大的可容忍失真度放大并且将每个未量化前的频带xr[i]放大。
【2】内部回圈分析
首先,根据下面公式进行量化
若出现溢位或者位元数不够分配的情况,则按+1逐渐增大stepsize,直到前述情况不存在。
接着,计算编码所需位元数,通过位元数选择Huffman码表。
4、后处理
将结果写入比特流中,关闭PCM文件和码流存储文件。计算整个编码过程算法运行时间end_time -=config.start_time。