`
lfp001
  • 浏览: 100616 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MP3解码之哈夫曼解码快速算法

阅读更多

      哈夫曼(huffman)解码用查表法,数据组织采用树形结构,若采用二叉树,一次处理一位(bit),效率是比较低的。从一些杂志上看到关于哈夫曼(huffman)解码的快速算法介绍,直接用位流索引一次处理N(4<N<=32)位,这种方法实际上是不可行的,原因是构造出的码表很长,如果一次处理8位,可以编写程序构造出码表,不过可以肯定的是码表的长度会超过我们事先的想象,以至于没有多大的实用价值。一次处理多位(一位以上)码表中冗余度很大导致码表很长。

      MP3解码处理主数据(main_data)的第一步就是对主数据进行哈夫曼解码。MP3编解码用到的哈夫曼表由ISO/IEC 11172-3 的附录B中给出,大值区用到31张码表(其中第0、4、14号码表未使用),小值区用到两张码表。从ISO/IEC 11172-3复制出两张原始的码表来分析,解码大值区的码表:

Huffman code table 7
 x  y hlen hcod
 0  0   1   1
 0  1   3   010
 0  2   6   001010
 0  3   8   00010011
 0  4   8   00010000
 0  5   9   000001010
 1  0   3   011
 1  1   4   0011
 1  2   6   000111
 1  3   7   0001010
 1  4   7   0000101
 1  5   8   00000011
 2  0   6   001011
 2  1   5   00100
 2  2   7   0001101
 2  3   8   00010001
 2  4   8   00001000
 2  5   9   000000100
 3  0   7   0001100
 3  1   7   0001011
 3  2   8   00010010
 3  3   9   000001111
 3  4   9   000001011
 3  5   9   000000010
 4  0   7   0000111
 4  1   7   0000110
 4  2   8   00001001
 4  3   9   000001110
 4  4   9   000000011
 4  5  10   0000000001
 5  0   8   00000110
 5  1   8   00000100
 5  2   9   000000101
 5  3  10   0000000011
 5  4  10   0000000010
 5  5  10   0000000000

 

解码小值区的码表:

Huffman code table 17
 x  y hlen hcod
 0  0  1   1
 0  1  4   0101
 0  2  4   0100
 0  3  5   00101
 0  4  4   0110
 0  5  6   000101
 0  6  5   00100
 0  7  6   000100
 0  8  4   0111
 0  9  5   00011
 0  10 5   00110
 0  11 6   000000
 0  12 5   00111
 0  13 6   000010
 0  14 6   000011
 0  15 6   000001

 

所有码表中,大值区的x=0..15,y=0..15,码长hlen=1..19。

 

一次处理多位应该如何实现呢?首先构造出码表,如果每次处理2比特,构造码表暂存数据时用4叉树;如果一次处理3比特,则用8叉树,以此类推。编程从一个文本文件中读入如上所示的原始的哈夫曼表数据,将其插入到N叉树中相应的位置。假如一次处理2位而码字(hcod)是5位(hlen=5),那么在hcod最后分别补上0和1凑足2的整数倍位数,这就导致了构造出的哈夫曼表冗余度,即一个码字对应多个码表中元素。一次处理的位数越多,构造出的码表的冗余度越大。

 

根据自己解码设计构造出码比较费事,解码过程挺简单。

 

实际编程中,可以用数组来存储N叉树,只需要将指针域的值改为元素在数组中的下标值。以大值区解码一次处理2比特为例,x和y取值范围为0..15,只需占用4比特;码长hlen取值范围为1..19,存储hlen只需5比特。存储一个码值只需要13比特,可以将一个码值存储在16位整数中,低4位是y,接下来的4位是x,再接下来的5位是hlen。高3位全为零表示该数组元素存储的是一个码值,最高位为1(表示负数)则其绝对什表示该数组元素存储的是数组的下标值。经过这样处理后解码大值区的码表“Huffman code table 7”:

static short htbv7[72] = {
  -4, -68, 256, 256,  -8, -48, -64,1041, -12, -28, -40, -44, -16, -20, -24,2069,
2645,2629,2644,2643,2357,2357,2372,2372,2341,2341,2386,2386,2129, -32,2128, -36,
2309,2309,2356,2356,2371,2371,2355,2355,2084,2114,1812,1812,1857,1857,1856,1856,
 -52, -56, -60,1554,2052,2083,2098,2051,1811,1811,1841,1841,1840,1840,1826,1826,
1313,1313,1538,1568, 769, 769, 784, 784};

 

解码小值区的码表“Huffman code table 17”一次处理4比特:

static short htc0[80] = {
 -16, -32, -48, -64,1026,1025,1028,1032, 256, 256, 256, 256, 256, 256, 256, 256,
1547,1547,1547,1547,1551,1551,1551,1551,1549,1549,1549,1549,1550,1550,1550,1550,
1543,1543,1543,1543,1541,1541,1541,1541,1289,1289,1289,1289,1289,1289,1289,1289,
1286,1286,1286,1286,1286,1286,1286,1286,1283,1283,1283,1283,1283,1283,1283,1283,
1290,1290,1290,1290,1290,1290,1290,1290,1292,1292,1292,1292,1292,1292,1292,1292};

 

码表构造好了,如何解码呢?从码流中读入4字节暂存到unsigned int umask,解码大值区得到x和y:

y = ptab[umask >> 30];	// 一次处理2比特,ptab指向码表(如ptab=htbv7)
while (y < 0) {
	umask <<= 2;
	y = ptab[(umask >> 30) - y];
}
x = y >> 8;		// hlen
num -= x;			// num为umask中剩余的比特数
umask <<= x;
x = (y >> 4) & 0xf;		// 得到x值
y &= 0xf;			// 得到y值

 

解码小值区得到y值的代码:

y = ptab[umask >> 28];		// 一次处理4比特
while (y < 0) {
	umask <<= 4;
	y = ptab[(umask >> 28) - y];
}
x = y >> 8;	// hlen
num -= x;
umask <<= x;

y &= 0xf;		// 得到y值

 

每解码完一个码字,重新刷新umask和num。以上解码方法正确与否可以用“Huffman code table 7”或“Huffman code table 17”内的数据去检查。

 

一次处理N比特肯定比一次处理1比特效率高。兼顾效率和存储空间开销,解码大值区采用一次处理2位到4位,解码小值区一次处理4位,这样比较好。

0
0
分享到:
评论

相关推荐

    mp3解码算法原理——具体解码算法

    ### MP3解码算法原理详解 #### 一、概述 MP3作为一种广泛使用的音频压缩格式,其高效的数据压缩技术使其成为数字音乐领域的标准之一。本文将深入探讨MP3解码的具体算法及其工作原理,帮助读者更好地理解MP3格式的...

    哈夫曼编解码_哈夫曼_C语言_哈夫曼编码_哈夫曼编解码_数字图像处理_

    相反,将编码还原成原始数据的过程被称为哈夫曼解码。 在C语言中实现哈夫曼编码和解码,通常包括以下步骤: 1. **构建哈夫曼树**:首先统计字符的出现频率,然后根据频率创建一个优先队列(通常用最小堆实现)。...

    哈夫曼matlab编解码

    哈夫曼编码是一种高效的数据压缩方法,由大卫·哈夫曼在...MATLAB作为强大的科学计算工具,提供了丰富的函数支持,使得在其中实现哈夫曼编解码变得相对简单。通过学习和实践,你可以更好地掌握这一重要的数据压缩算法。

    MP3的解码程序,包括哈夫曼编码

    它可能调用了其他子函数,如解析MP3帧头、解密音频数据块、执行哈夫曼解码等。 `common.c`:通用功能模块,通常包含了跨文件使用的辅助函数,比如内存管理、错误处理或数据类型转换等。 `musicout.c`:这个名字...

    利用C++实现哈夫曼算法

    利用C++实现哈夫曼算法 哈夫曼算法是数据压缩的一种重要算法,它的主要思想是构造一棵哈夫曼树(二叉树),其基本思路是,每次从字符中挑出两个...同时,哈夫曼算法也可以应用于其他领域,如数据压缩、编码和解码等。

    C++ 哈夫曼编码解码程序

    3. **哈夫曼解码** - 给定一个已编码的字符串,从根节点开始,根据遇到的0和1沿着哈夫曼树向下移动。当到达叶子节点时,读取对应的符号,然后返回根节点,继续解码剩余的编码。 在C++中实现哈夫曼编码和解码,需要...

    Haffman 哈夫曼编解码 matlab版和C语言版

    - MATLAB是一种强大的数学计算和数据可视化工具,它的优点在于能够快速原型开发和实验。在MATLAB中,可以使用内置的数据结构和函数来实现哈夫曼树的构建和编码过程。例如,可以使用队列和树节点结构来表示哈夫曼树...

    huffcode.rar_huffman 解码_哈夫曼_哈夫曼编 译码_哈夫曼编/译码器_曼 数据 结构

    总结起来,这个压缩包提供了哈夫曼编码和解码的实现,对于学习数据结构和算法,尤其是理解和应用变长编码技术,是非常有价值的资源。通过对它的研究,不仅可以掌握哈夫曼编码的基本原理,还能了解如何将理论知识应用...

    哈夫曼编码与解码的程序

    在C语言中实现哈夫曼编码与解码的过程包括几个关键步骤:构造哈夫曼树、生成哈夫曼编码、编码文件和解码文件。 1. 构造哈夫曼树: - 首先,统计输入文本中每个字符出现的频率。 - 然后,创建一个最小堆(优先队列...

    哈夫曼编码解码器 c++源代码

    例如,哈夫曼树的构建和遍历应尽可能快,哈夫曼编码和解码的过程也要避免不必要的计算。 通过以上步骤,我们可以构建出一个完整的哈夫曼编码解码器。在实际应用中,这个工具可以用于压缩文本、图像等数据,减少存储...

    C#哈夫曼树编码/解码程序

    哈夫曼树(Huffman Tree),也称为最优二叉树,是数据压缩中的一种关键算法。在C#中实现哈夫曼编码和解码程序,主要是为了高效地进行数据的压缩与解压缩操作。哈夫曼编码利用了字符出现频率的不同,为频率高的字符...

    哈夫曼树的编码跟解码

    哈夫曼解码则相反,它是从编码反向推导出原始字符的过程: 1. **读取编码**:按照编码的位序列,从根节点出发,根据遇到的0和1选择相应的分支。 2. **到达叶节点**:当所有编码位都被读取,或者到达叶节点时,识别出...

    哈夫曼编解码程序 基于mfc

    3. **构造哈夫曼树**:根据频率数组,使用贪心算法构建哈夫曼树。可以维护两个优先队列,一个用于存储待合并的节点,另一个用于存储已生成的节点。每次从队列中取出频率最小的两个节点合并,然后将新生成的节点加入...

    哈夫曼编码以及解码实现

    在给定的“哈弗曼编码”文件中,可能包含了实现哈夫曼编码和解码的具体算法和源代码。这些代码可能包括了创建哈夫曼树的函数、生成编码表的函数、解码函数,以及与用户交互的界面逻辑。通过阅读和理解这些代码,可以...

    C语言 哈夫曼树的编码解码

    C语言 哈夫曼树的编码解码

    数据结构实验哈夫曼算法实验报告

    但是,哈夫曼算法也存在一些缺点,例如编码和解码的时间复杂度较高,且不适合实时处理的大数据量。 本实验报告展示了哈夫曼算法的设计和实现,并对其进行了分析。哈夫曼算法是数据压缩领域中的一个重要算法,具有...

    数据结构课程设计_哈夫曼编解码(代码+实验报告)

    - 实验目的:理解哈夫曼编码的原理,掌握编码和解码算法。 - 设计思路:如何设计数据结构(如优先队列、哈夫曼树)来实现编码和解码。 - 模块解释:各个函数的作用和工作流程。 - 结果分析:编码前后的文件大小比较...

    基于哈夫曼算法的图像压缩

    这个程序包括了编码和解码两个过程,可以从`in.bmp`输入图像,通过`Compressor.cpp`中的算法进行压缩,将结果保存到`encode.dat`文件中,然后通过解码过程生成`out.bmp`。让我们详细探讨一下这个过程。 1. **哈夫曼...

    霍夫曼树实现编码解码C语言实现

    在编码过程中,会读取这些文本文件,计算每个字符的频率,构建霍夫曼树,生成编码表,并将文本转换为霍夫曼编码的二进制流。解码时,则会读取这个二进制流,按照霍夫曼树进行反向操作,恢复出原始文本。 在实际应用...

    哈夫曼算法的实现源码

    在本文中,我们将深入探讨哈夫曼算法的原理、编码与解码过程,并结合提供的源代码文件`Huffman.cpp`和`Huffman.h`进行分析。 **哈夫曼编码原理** 哈夫曼编码是基于频率的变长编码,它通过构建一个二叉树来为每个...

Global site tag (gtag.js) - Google Analytics