代码之家  ›  专栏  ›  技术社区  ›  lornova

通过截断减少采样位深度

  •  0
  • lornova  · 技术社区  · 14 年前

    只取每个样本的16个最高有效位(即截断)相当于进行比例计算(out=in*0xFFFF/0xFFFFFF)?

    4 回复  |  直到 14 年前
        1
  •  1
  •   andrewmu    14 年前

    我想你是说 (in * 0xFFFF) / 0xFFFFFF ,在这种情况下,是的。

        2
  •  3
  •   tdammers    14 年前

    在截断(也就是抖动)之前,在原始信号中加入一个精心设计的噪声信号,刚好低于截断阈值,这样可以获得更好的探测效果。

        3
  •  1
  •   Nick Haddad    14 年前

    Dithering pow-r 抖动算法有一种特殊的形状,在许多数字音频工作站应用中非常流行(Cakewalk的声纳、逻辑等)。

    noise 在相当低的振幅,并混入你的信号。你会发现这掩盖了一些量化效应。

        4
  •  1
  •   sh1    11 年前

    x * 0xffff / 0xffffff 太迂腐了,但是如果你的样品有签名的话,就不是一个好的方法——而且一般来说可能不是一个好的方法。

    是的,您希望源区域中的最大值与目标区域中的最大值匹配,但其中使用的值仅适用于无符号区域,并且量化步骤的分布意味着使用最大可能输出值的情况非常少见。

    如果对样本进行签名,则峰值正值为0x7fff和0x7fffff,而峰值负值为-0x8000和-0x800000。第一个问题是确定+1是否等于0x7fff,或者-1是否等于-0x8000。如果你选择后者,那就是一个简单的移位操作。如果你试着两者都有,那么零就不再是零了。

    在那之后,你有一个问题,就是除法向零方向循环。这意味着与其他值相比,有太多的值被舍入为零。这会导致失真。

    如果要根据峰值正值进行缩放,正确的形式是:

    out = rint((float)in * 0x7fff / 0x7fffff);
    

    对于任何给定的输入,这个表单应该正确地四舍五入到最接近的可用输出值,并且它应该将最大可能的输入值映射到最大可能的输出值,但是它将有一个分布在整个范围内的量化步骤的丑陋分布。

    大多数人更喜欢:

    out = (in + 128) >> 8;
    if (out > 0x7fff) out = 0x7fff;
    

    你加128是因为右移向负无穷大。这个 平均的

    学究们可以在关于右转和除法行为的假设上挖洞,但为了清晰起见,我忽略了这些假设。

    然而,正如其他人指出的那样,你通常不应该在不抖动的情况下减少音频的位深度,最好是噪声整形。TPDF抖动如下:

    out = (in + (rand() & 255) - (rand() & 255)) >> 8;
    if (out < -0x8000) out = -0x8000;
    if (out > 0x7fff) out = 0x7fff;
    

    同样,使用 rand()