将16位pcm转换为8位

时间:2011-04-19 13:52:49

标签: java algorithm audio bit pcm

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

有人能建议一个好的算法吗?

我没有提到比特率,因为我认为这对算法并不重要 - 对吗?

4 个答案:

答案 0 :(得分: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,这将是不好的。

答案 1 :(得分:6)

16位采样通常是有符号的,8位采样通常是无符号的,因此最简单的答案是需要转换带有符号的16位采样(16位采样几乎总是存储为-32768到+32767)到无符号然后取结果的前8位。在C中,这可以表示为output =(unsigned char)((unsigned short)(输入+ 32768)&gt;&gt; 8)。这是一个良好的开端,可能足以满足您的需求,但听起来不是很好。由于“量化噪声”,它听起来很粗糙。

量化噪声是原始输入和算法输出之间的差异。无论你做什么,你都会有噪音,平均噪音会“半点”。你无能为力,但有办法让噪音不那么明显。

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

要获得听起来不错的结果,您需要添加抖动。抖动是一种试图平滑量化噪声的技术。最简单的抖动只是从噪声中去除了模式,因此噪声模式不会分散实际的信号模式。更好的抖动可以更进一步,并采取措施通过将多个样本的误差值加在一起来减少噪声,然后在总误差变得足够大以便进行校正时添加校正。

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

答案 2 :(得分:1)

对16位样本进行归一化,然后按8位样本的最大值重新缩放。

这样可以获得更准确的转换,因为每个样本的低8位都没有被丢弃。但是,我的解决方案在计算上比选择的答案更昂贵。

答案 3 :(得分:1)

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

这对我有用。