我必须将数字音频信号的位深度从24位减少到16位。
只取每个样本的16个最高有效位(即截断)相当于进行比例计算(out = in * 0xFFFF / 0xFFFFFF)?
发布于 2010-10-26 18:45:38
我猜你指的是(in * 0xFFFF) / 0xFFFFFF,在这种情况下,是的。
发布于 2010-10-26 18:43:14
在截断之前,将精心制作的噪声信号添加到原始信号中,略低于截断阈值,将获得更好的探测结果。抖动)。
发布于 2014-04-15 02:51:51
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是因为右移向负无穷大进行舍入。平均量化误差为-128,您可以添加128来校正它,以使0精确地保持为0。溢出测试是必要的,因为输入值0x7fffff会给出0x8000的结果,并且当您将其存储在16位字中时,它会返回一个负值峰值。
学究可以在关于右移位和除法行为的假设中戳出漏洞,但为了清楚起见,我忽略了这些假设。
然而,正如其他人指出的那样,你通常不应该在没有抖动的情况下减少音频的比特深度,最好是噪声整形。TPDF抖动如下:
out = (in + (rand() & 255) - (rand() & 255)) >> 8;
if (out < -0x8000) out = -0x8000;
if (out > 0x7fff) out = 0x7fff;同样,为了清晰起见,我将忽略rand()的使用方面的大问题。
https://stackoverflow.com/questions/4022838
复制相似问题