将16位pcm转换为8位



我有pcm音频存储在字节数组中。每个样本是16位。我想让它每个样本音频8位。

谁能提出一个好的算法来做到这一点?

我没有提到比特率因为我认为它对算法不重要,对吧?

我现在看不出为什么只取上字节是不够的,即丢弃每个样本的低8位。

这当然是假设样本是线性的;如果它们不是,那么也许你需要在掉位之前做一些事情来线性化它们。

short sixteenBit = 0xfeed;
byte eightBit = sixteenBit >> 8;
// eightBit is now 0xfe.

正如AShelly在评论中建议的那样,舍入可能是一个好主意,即如果我们丢弃的字节高于其最大值的一半,则加1:

eightBit += eightBit < 0xff && ((sixteenBit & 0xff) > 0x80);

针对0xff的测试实现了夹紧,所以我们不会冒险将1添加到0xff并将其包装到0x00,这将是不好的。

16位样本通常是有符号的,而8位样本通常是无符号的,所以最简单的答案是你需要将16位样本从有符号的(16位样本几乎总是存储为-32768到+32767的范围)转换为无符号的,然后取结果的前8位。在C中,这可以表示为output = (unsigned char)((unsigned short)(input + 32768)>> 8)。这是一个很好的开始,可能足以满足您的需求,但听起来不太好。因为"量化噪声",听起来很粗糙。

量化噪声是原始输入和算法输出之间的差异。无论你做什么,你都会有噪音,噪音平均会是"半点"。你对此无能为力,但有一些方法可以使噪音不那么明显。

量化噪声的主要问题是它倾向于形成模式。如果输入和输出之间的差异完全是随机的,事情听起来会很好,但相反,输出会反复地对波形的某一部分太高,对下一部分太低。你的耳朵能听到这种模式。

要得到听起来不错的结果,你需要添加抖动。抖动是一种试图消除量化噪声的技术。最简单的抖动只是去除噪声中的模式,这样噪声模式就不会分散实际的信号模式。更好的抖动可以更进一步,通过将多个样本的误差值加在一起,然后在总误差大到值得校正时加入校正,从而采取措施减少噪声。

您可以在线找到各种抖动算法的解释和代码示例。SoX工具http://en.wikipedia.org/wiki/SoX可能是一个很好的研究领域。检查源的抖动效果,并尝试将各种声音从16位转换为8位,并启用或不启用抖动。当转换为8位声音时,抖动所产生的质量差异会让你感到惊讶。

byteData = (byte) (((shortData +32768)>>8)& 0xFF) 

正常化16位样本,然后按8位样本的最大值重新缩放。

这会产生更精确的转换,因为每个样本的低8位不会被丢弃。然而,我的解决方案比选择的答案计算成本更高。

最新更新