将16位pcm转换为8位

gos*_*vka 5 java algorithm audio pcm bit

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

谁能建议一个好的算法来做到这一点?

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

unw*_*ind 8

我现在无法看到为什么只取高位字节是不够的,即丢弃每个样本的低8位.

那当然假设样品是线性的; 如果它们不是那么可能你需要做一些事情来线性化它们然后丢弃位.

short sixteenBit = 0xfeed;
byte eightBit = sixteenBit >> 8;
// eightBit is now 0xfe.
Run Code Online (Sandbox Code Playgroud)

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

eightBit += eightBit < 0xff && ((sixteenBit & 0xff) > 0x80);
Run Code Online (Sandbox Code Playgroud)

针对0xff的测试实现了钳位,因此我们不会冒险添加1到0xff并将其包装到0x00,这将是不好的.


小智 6

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

量化噪声是原始输入和算法输出之间的差异.无论你做什么,你都会产生噪音,平均噪音将是"半个小时".你无能为力,但有办法让噪音不那么明显.

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

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

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