有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java将16位pcm转换为8位

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

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

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


共 (3) 个答案

  1. # 1 楼答案

    16位样本通常是有符号的,8位样本通常是无符号的,因此最简单的答案是,您需要将16位样本从有符号(16位样本几乎总是以-32768到+32767的范围存储)转换为无符号,然后获取结果的前8位。在C语言中,这可以表示为输出=(无符号字符)((无符号短)(输入+32768)>>;8). 这是一个很好的开始,可能足以满足您的需求,但听起来不太好。这听起来很粗糙,因为“量化噪声”

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

    量化噪声的主要问题是它容易形成图案。如果输入和输出之间的差异是完全随机的,实际上听起来很好,但是相反,对于波形的某一部分,输出会重复地太高,而对于下一部分,输出会太低。你的耳朵听到了这个图案

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

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

  2. # 2 楼答案

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

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

  3. # 3 楼答案

    我现在不明白为什么只取高位字节是不够的,即丢弃每个样本的低位8位

    当然,假设样本是线性的;如果它们不是这样的话,也许你需要做一些事情来线性化它们,然后再丢弃比特

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

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

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

    针对0xff的测试实现了钳制,所以我们不需要冒险将1添加到0xff,并将其包装到0x00,这将是不好的