3

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

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

  • 标准化 16 位值。即找到最大的并以此划分。
  • 使用 M=8 的 Q(x) 公式。

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

很多爱,路易丝

4

3 回答 3

3

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

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

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

于 2009-12-27T19:27:47.307 回答
3

这听起来像波形音频处理,您的输入是 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 数据,那么有符号字符是不正确的,但由于问题没有特别要求,所以我把它省略了。

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

于 2009-12-27T19:37:54.667 回答
1

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

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

unsigned char s8 = s * 255 ;

如果范围不是 0.0 <= s <= 1.0,而是 0.0 <= s <= max,则:

unsigned char s8 = s / max * 255 ;

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

于 2009-12-27T20:18:20.280 回答