2010-10-26 56 views
0

我必须将数字音频信号的位深度从24位降低到16位。通过截断减少采样位深

以仅16个最高位显著每个样本(即截断)等效于做一个比例运算(OUT =在*为0xFFFF/0XFFFFFF)?

回答

1

我假定你的意思(in * 0xFFFF)/0xFFFFFF,在这种情况下,是的。

+0

当然,遗憾的错字... – Wizard79 2010-10-26 11:24:29

+0

当然,你可以简单地位上下移动:'OUT =在>> 8'(未签名样本)。 – andrewmu 2010-10-26 11:27:07

+0

为什么只适用于未签名的样本? – Wizard79 2010-10-26 20:15:21

3

你会加入一个精心制作的噪声信号与原始信号,略低于截断门槛,截断(又名抖动)之前获得更好的探测结果。

+0

我知道,通过减少比特深度我引入量化噪声(因此减少的24比特信号听起来比16位大师最差),但我怎么能“精心推敲”的抖动噪声? – Wizard79 2010-10-26 11:45:49

+0

抖动的目标是分配舍入误差,但是您希望最小化所引入的可听工件的数量。白噪声是一个很好的起点,但根据应用的不同,平衡噪声的频谱可能会带来更好的结果。 – tdammers 2010-10-26 19:11:23

1

Dithering加入噪声一般会给你更好的结果。关键是噪音的形状。人口众多的数字音频工作站应用(Cakewalk的SONAR,Logic等)中,抖动算法具有特定的形状,非常流行。

如果您不需要pow-r的保真度,您可以简单地生成一些幅度相当低的noise,并将其混合到您的信号中。你会发现这掩盖了一些量化效应。

0

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()这我要忽视为清晰起见,使用大的问题。