使用 add + 将 pcm16 转换为 pcm14转移

发布于 2024-09-08 02:07:02 字数 213 浏览 0 评论 0原文

我正在研究一种声音转换算法,其中接收一系列签名短裤。
在算法中的给定点,它将样本从 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦年海沫深 2024-09-15 02:07:02

向下移动会丢失最低有效两位。如果您只是移位,那么即使底部两位都已设置,它也将始终向下舍入。如果设置了丢失的较大位,则将 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!)

请止步禁区 2024-09-15 02:07:02

我猜它是为了产生四舍五入的效果?我只是希望他们考虑 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 than MAX_INT16 - 2. Otherwise there might be issues when it overflows.

醉殇 2024-09-15 02:07:02

正如其他人所指出的,+2 是试图使右移执行四舍五入到最近的除法。但是,存在两个问题:

  • 输入样本 32766 或 32767 在加 2 时可能会溢出 intint 只保证能够表示最多可达32767);

  • 负数右移的行为是实现定义的。

为了避免这些问题,它应该是:(

int16_t sample = (old_sample > 0 ? old_sample + 2L : old_sample - 2L) / 4;

与移位运算符不同,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:

int16_t sample = (old_sample > 0 ? old_sample + 2L : old_sample - 2L) / 4;

(Unlike the shift operator, the division operator in C99 is defined to round-towards-zero).

空城旧梦 2024-09-15 02:07:02

该代码的意图可能是四舍五入,如其他答复中所示。但这无疑是一个非常糟糕的例子。这里发生了两件事,最初的程序员可能没有想到:

  • 提升为 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:

  • promotion to int and re-assignment to int16_t
  • right shift of a signed value

Promotion to int (because of the +2 which is just an int) is bad here because you don't know what the precision of int 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文