我有一个包含许多正 16 位值(存储为双精度值)的缓冲区,我想将其量化为 8 位(0-255 值)。

根据 维基百科 该过程将是:

  • 标准化 16 位值。IE。找到最大的并除以它。
  • 使用 M=8 的 Q(x) 公式。

所以我想知道,C 是否有一个可以进行这种量化的函数,或者有人知道我可以使用的 C 实现吗?

爱意满满 路易丝

有帮助吗?

解决方案

假设值 d 是在区间内 [0.0, max]:

unsigned char quantize(double d, double max)
{
    return (unsigned char)((d / max) * 255.0);
}

我不确定你说的 "16 位值 "是什么意思;在任何使用 IEEE-754 的系统上,双精度值都是 64 位的。但是,如果您有其他数字类型的值,则过程实际上是相同的。

其他提示

这听起来像波形音频处理,其中输入是 16 位 PCM 数据,输出是 8 位 PCM 数据,并且使用双精度数作为中间值。

然而,8 位 PCM 波形数据不仅仅是量化的,其表示形式是超过 128 个符号的无符号值。(就像指数以浮点数存储的方式一样)

首先找到最大值不仅是量化,也是缩放。所以在伪代码中

double dMax = max_of_all_values(); // 
...
foreach (dValue in array_of_doubles)
{
   signed char bValue = (signed char)((dValue / dMax)*127.0);
}

如果您想要更高的准确性,您可以舍入而不是截断,但在音频处理中,通常最好随机化截断顺序,甚至通过本质上运行过滤算法作为从双精度到有符号字符截断的一部分来整形它。

笔记:如果输出是 8 位 PCM 数据,则signed char 是不正确的,但由于问题没有具体要求,所以我将其省略。

编辑:如果要将其用作像素数据,那么您需要无符号值。我看到当输入无符号时,詹姆斯已经给出了无符号值的正确答案(归一化数据的 dB 值实际上应该都是负数)

从您的问题中不清楚编码是什么,因为“正 16 位值(存储为双精度值)“没有任何实际意义;它们要么是 16 位,要么是双精度,不能两者都是。

然而,假设这是标准化为 1.0 的 16 位无符号数据(因此值范围为 0.0 <= s <= 1.0),那么将它们扩展为 8 位整数值所需要做的就是将每个样本乘以 255。

unsigned char s8 = s * 255 ;

如果范围不是 0.0 <= s <= 1.0,但 0.0 <= s <= 最大限度 然后:

unsigned char s8 = s / max * 255 ;

无论哪种方式,除了您自己编写的函数之外,没有任何“量化”函数;但必要的变换无疑是一个简单的算术表达式(尽管如果数据被压缩的话可能就不那么简单了 - 即例如,μ-lay 或 A-law 编码)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top