0

我正在研究一种声音转换算法,其中接收到一系列签名短裤。
在算法的给定点,它将样本从 16 位转换为 14 位,它是这样进行的:

int16_t sample = (old_sample + 2) >> 2;

对我来说,很明显需要进行移位,因为我们想要摆脱至少 2 个有效位,但是+2那里呢?

4

4 回答 4

8

向下移动会丢失最低有效的两位。如果您只是移位,那么即使底部两位都已设置,它也将始终向下舍入。如果设置了较大的丢失位,则将 2 轮向上添加。

(另外值得注意的是,减少比特数的更好方法是使用抖动,即在减少样本大小之前添加随机(并且非常小)量的噪声;这避免了由于声音是周期性的问题,对于特定频率,舍入通常最终会持续上升或持续下降,从而导致声音出现明显的失真。链接的维基百科文章比我能更好地解释它!)

于 2010-07-06T17:05:27.837 回答
1

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

  • 32766 或 32767 的输入样本在int添加 2 时可能会溢出(int仅保证能够表示最多 32767 的数字);

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

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

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

(与移位运算符不同,C99 中的除法运算符被定义为向零舍入)。

于 2010-07-07T01:19:59.767 回答
1

我猜它打算有四舍五入的效果?我只是希望他们考虑到的情况old_sample超过MAX_INT16 - 2. 否则溢出时可能会出现问题。

于 2010-07-06T17:11:01.830 回答
0

如其他回复中所示,该代码的意图可能是四舍五入。但这肯定是一个非常糟糕的例子。这里发生了两件事,最初的程序员可能并不打算这样做:

  • 晋升int和重新分配到int16_t
  • signed值的右移

提升到int(因为+2which 只是一个int)在这里很糟糕,因为您不知道int您碰巧登陆的任何随机平台上的精度是多少。

如果值为负,则值的右移signed取决于编译器,因此结果也可能因平台而异。

于 2010-07-06T18:47:26.783 回答