6

I have pcm audio stored in a byte array. It is 16 bits per sample. I want to make it 8 bit per sample audio.

Can anyone suggest a good algorithm to do that?

I haven't mentioned the bitrate because I think it isn't important for the algorithm - right?

4

4 回答 4

10

I can't see right now why it's not enough to just take the upper byte, i.e. discard the lower 8 bits of each sample.

That of course assumes that the samples are linear; if they're not then maybe you need to do something to linearize them before dropping bits.

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

As suggested by AShelly in a comment, it might be a good idea to round, i.e. add 1 if the byte we're discarding is higher than half its maximum:

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

The test against 0xff implements clamping, so we don't risk adding 1 to 0xff and wrapping that to 0x00 which would be bad.

于 2011-04-19T13:55:12.233 回答
8

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 位声音时抖动可以产生的质量差异。

于 2013-09-13T02:51:45.240 回答
2
byteData = (byte) (((shortData +32768)>>8)& 0xFF) 

这对我有用。

于 2015-12-09T13:11:50.733 回答
1

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

这会产生更准确的转换,因为每个样本的低 8 位不会被丢弃。但是,我的解决方案在计算上比选择的答案更昂贵。

于 2012-11-12T15:53:56.633 回答