【问题标题】:What would be a good (de)compression routine for this scenario对于这种情况,什么是好的(解)压缩程序
【发布时间】:2009-08-28 17:51:41
【问题描述】:

我需要一个针对受限资源环境(例如基于二进制(十六进制数据)的嵌入式系统)优化的 FAST 解压缩例程,具有以下特点:

  1. 数据面向 8 位(字节)(数据总线为 8 位宽)。
  2. 字节值在 0 到 0xFF 的范围内并不统一,但在每个 DataSet 中都有泊松分布(钟形曲线)。
  3. 数据集是高级固定的(要刻录到 Flash 中),每个集很少 > 1 - 2MB

压缩可能需要尽可能多的时间,但在内存占用最少的最坏情况下,一个字节的解压缩应该需要 23uS,因为它将在嵌入式系统(3Mhz - 12Mhz 内核,2k)等受限资源环境中完成字节 RAM)。

什么是好的减压程序?

基本的运行长度编码似乎太浪费了——我可以立即看到,将标头集添加到压缩数据以使用未使用的字节值来表示经常重复的模式会带来惊人的性能!

对于只投入了几分钟的我来说,肯定已经存在来自热爱这些东西的人的更好的算法吗?

我想要一些“准备就绪”的示例在 PC 上试用,以便我可以将性能与基本 RLE 进行比较。

【问题讨论】:

  • 你真的是指 256 字节的 RAM 吗?那么,如果一个压缩字节可以扩展到 >256 个未压缩字节,它们就没有空间了?
  • 连续字节之间是否存在相关性?压缩可以有损吗?
  • 如果这类似于 6502 或 z80,大多数(全部?)指令都需要几个时钟周期,并且在 2mhz 时会花费超过一微秒的时间。
  • 1 uSec 只有 2 个时钟周期 @ 2 Mhz。在您施加的约束下,您将很难实现均匀的运行长度编码。
  • 好点 Jim.. 我将重新审视时序约束并更新本文。时钟频率不过可以提高到 12Mhz。

标签: embedded compression run-length-encoding


【解决方案1】:

当性能是唯一关注点时我使用的两种解决方案:

  • LZO 拥有 GPL 许可证。
  • liblzf 拥有 BSD 许可证。
  • miniLZO.tar.gz 这是LZO,只是重新打包成更适合嵌入式开发的“缩小”版本。

解压时,两者都非常快。我发现LZO 在大多数情况下会创建比liblzf 稍小的压缩数据。您需要对速度进行自己的基准测试,但我认为它们“基本相同”。两者都比 zlib 快几光年,但两者都没有压缩(如您所料)。

LZO,尤其是miniLZOliblzf 都非常适合嵌入式目标。

【讨论】:

    【解决方案2】:

    如果您有预设的值分布,这意味着每个值的概率在所有数据集上都是固定的,您可以使用固定代码创建霍夫曼编码(代码树不必嵌入到数据中)。

    根据数据,我会尝试使用固定代码或 lz77 的 huffman(请参阅 Brian 的链接)。

    【讨论】:

      【解决方案3】:

      嗯,我想到的主要两种算法是HuffmanLZ

      第一个基本上只是创建一个字典。如果你充分限制字典的大小,它应该会很快……但不要指望很好的压缩。

      后者通过向输出文件的重复部分添加反向引用来工作。这可能只需要很少的内存即可运行,除非您需要使用文件 i/o 来读取反向引用或将最近读取的数据块存储在 RAM 中。

      如果重复的部分往往彼此靠近,我怀疑 LZ 是您的最佳选择。正如您所提到的,霍夫曼的工作原理是拥有一本包含经常重复的元素的字典。

      【讨论】:

      • 如果PoorLuzer 有更多的RAM 和CPU 周期可以使用,那么任何一个都可能是可行的,但如果限制确实如所述,我认为他是在问不可能的问题。
      • 我在“听到”时犯了一些错误,来自一位将进行实际编程的朋友,我上次发布的值并更新了帖子以反映更准确的值。这种东西对我来说是新的,因为我一直为操作系统编程。
      【解决方案4】:

      由于这似乎是音频,我会查看差分 PCM 或 ADPCM,或类似的东西,这会将其减少到 4 位/样本而不会造成太大的质量损失。

      使用最基本的差分 PCM 实现,您只需存储当前样本和累加器之间的 4 位有符号差,然后将该差添加到累加器并移动到下一个样本。如果差异超出 [-8,7],则必须限制该值,并且累加器可能需要几个样本才能赶上。解码速度非常快,几乎不需要内存,只需将每个值添加到累加器并将累加器作为下一个样本输出即可。

      对基本 DPCM 的一个小改进是使用查找表将 4 位值解码为更大的非线性范围,以帮助累加器在信号变得更大声和更高音调时更快地赶上,其中它们仍然是 1相隔接近零,但以更大的增量向极限增加。和/或您可以保留其中一个值来切换乘数。决定何时使用它由编码器决定。通过这些改进,您可以获得更好的质量,或者每个样本 3 位而不是 4 位。

      如果您的设备具有非线性 μ-law 或 A-law ADC,您可以获得与 11-12 位相当的质量和 8 位样本。或者你可以在你的解码器中自己做。 http://en.wikipedia.org/wiki/M-law_algorithm

      可能有便宜的芯片已经为您完成了所有这些工作,具体取决于您正在制作的内容。我没看过。

      【讨论】:

      • 这不适用于音频 :-) 它实际上是使用经典的 UART 通过“位敲击”字节中的每个位来发送预定义的曼彻斯特编码数据集。此过程继续进行,没有剩余字节。
      • 我假设是因为正态分布并且因为 23uS 与 44.1khz 匹配。
      【解决方案5】:

      您应该使用带有命令行开关的压缩软件工具或可以尝试不同算法的压缩库来尝试不同的压缩算法。 为您的应用使用典型数据。 然后您就知道哪种算法最适合您的需求。

      【讨论】:

      • 是的,但问题是大多数软件压缩工具都是针对 PC 而不是嵌入式系统,因此对可用资源量有不同的假设。
      【解决方案6】:

      我在嵌入式系统中使用了 zlib 作为引导加载程序,它在启动时将应用程序映像解压缩到 RAM。许可证非常宽松,没有 GPL 废话。它确实进行了一次 malloc 调用,但在我的情况下,我只是用一个返回指向静态块的指针的存根和相应的 free() 存根替换了它。我通过监视它的内存分配使用来获得正确的大小来做到这一点。如果你的系统可以支持动态内存分配,那就简单多了。

      http://www.zlib.net/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-08
        • 2013-04-23
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多