使用 add + 将 pcm16 转换为 pcm14转移
我正在研究一种声音转换算法,其中接收一系列签名短裤。
在算法中的给定点,它将样本从 16 位转换为 14 位,它是这样进行的:
int16_t sample = (old_sample + 2) >> 2;
对我来说,很明显需要进行移位,因为我们想要去掉至少 2 个有效位,但是呢? +2
在那里?
I am studying a sound converting algorithm where an array of signed shorts is received.
At a given point in the algorithm it converts the samples from 16 bits to 14 bits, and it does it like this:
int16_t sample = (old_sample + 2) >> 2;
For me its clear that the shifting is needed as we want to get rid of the least 2 significant bits, but what about the +2
there?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
向下移动会丢失最低有效两位。如果您只是移位,那么即使底部两位都已设置,它也将始终向下舍入。如果设置了丢失的较大位,则将 2 舍入相加。
(还值得注意的是,减少位数的更好方法是使用抖动,即在减少样本大小之前添加随机(且非常少量)的噪声,这可以避免以下问题:由于声音是周期性的,因此对于特定频率,舍入通常会持续上升或持续下降,从而导致可察觉的结果;声音失真。链接的维基百科文章比我解释得更好!)
Shifting down loses the least significant two bits. If you just shift, then that will always round down, even if the bottom two bits are both set. Adding the 2 rounds up if the bigger of the bits being lost is set.
(Also worth noting that a better method of reducing the number of bits is to use dithering, i.e. adding a random (and very small) amount of noise before the reduction in sample size; this avoids the problem that, since the sounds are periodic, the rounding can often end up going consistently up or consistently down for a particular frequency, resulting in perceptible distortion in the sound. The wikipedia article linked explains it better than I can!)
我猜它是为了产生四舍五入的效果?我只是希望他们考虑
old_sample
大于MAX_INT16 - 2
的情况。否则溢出时可能会出现问题。I guess its intended to have the effect of rounding? I just hope that they conisdered the case of
old_sample
being more thanMAX_INT16 - 2
. Otherwise there might be issues when it overflows.正如其他人所指出的,+2 是试图使右移执行四舍五入到最近的除法。但是,存在两个问题:
输入样本 32766 或 32767 在加 2 时可能会溢出
int
(int
只保证能够表示最多可达32767);负数右移的行为是实现定义的。
为了避免这些问题,它应该是:(
与移位运算符不同,C99 中的除法运算符被定义为向零舍入)。
As others have noted, the +2 is an attempt to make the right shift perform a round-to-nearest division. However, there are two problems:
input samples of 32766 or 32767 may overflow
int
when 2 is added (int
is only guaranteed to be able to represent numbers up to 32767);The behaviour of a right shift of a negative number is implementation-defined.
To avoid these issues, it should be:
(Unlike the shift operator, the division operator in C99 is defined to round-towards-zero).
该代码的意图可能是四舍五入,如其他答复中所示。但这无疑是一个非常糟糕的例子。这里发生了两件事,最初的程序员可能没有想到:
int
和重新分配给int16_t
signed
code> 值提升为
int
(因为+2
只是一个int
)在这里是不好的,因为你不知道什么是int
在任何随机平台上的精度是您碰巧登陆的。如果值为负,有符号值的右移取决于编译器,因此结果也可能因平台而异。
The intent of that code is probably rounding as is indicated in the other replies. But this is certainly a very bad example of it. There are two things going on here that the original programmer probably didn't intend:
int
and re-assignment toint16_t
signed
valuePromotion to
int
(because of the+2
which is just anint
) is bad here because you don't know what the precision ofint
on any random platform is that you happen to land on.Right shift of
signed
values is compiler dependent if the value is negative, so the outcome may vary from platform to platform, too.