java将16位pcm转换为8位 4 月,3 周 Questions & Answers 12770 我将pcm音频存储在字节数组中。每个样本16位。我想让它每样音频8位 有谁能提出一个好的算法来做到这一点吗 我没有提到比特率,因为我认为它对算法不重要——对吧
# 1 楼答案 16位样本通常是有符号的,8位样本通常是无符号的,因此最简单的答案是,您需要将16位样本从有符号(16位样本几乎总是以-32768到+32767的范围存储)转换为无符号,然后获取结果的前8位。在C语言中,这可以表示为输出=(无符号字符)((无符号短)(输入+32768)>>;8). 这是一个很好的开始,可能足以满足您的需求,但听起来不太好。这听起来很粗糙,因为“量化噪声” 量化噪声是原始输入和算法输出之间的差异。无论你做什么,你都会有噪音,而噪音平均为“半点”。对此你无能为力,但有办法让噪音变得不那么明显 量化噪声的主要问题是它容易形成图案。如果输入和输出之间的差异是完全随机的,实际上听起来很好,但是相反,对于波形的某一部分,输出会重复地太高,而对于下一部分,输出会太低。你的耳朵听到了这个图案 要获得听起来不错的结果,需要添加抖动。抖动是一种试图消除量化噪声的技术。最简单的抖动只是从噪声中去除模式,这样噪声模式就不会偏离实际的信号模式。更好的抖动可以更进一步,采取措施减少噪声,方法是将多个样本的误差值相加,然后在总误差大到值得校正时加入校正 你可以在网上找到各种抖动算法的解释和代码示例。一个好的研究领域可能是SoX工具http://en.wikipedia.org/wiki/SoX。检查声源的抖动效果,并尝试在启用和不启用抖动的情况下将各种声音从16位转换为8位。当转换为8位声音时,抖动会产生不同的质量,你会感到惊讶
# 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,这将是不好的
# 1 楼答案
16位样本通常是有符号的,8位样本通常是无符号的,因此最简单的答案是,您需要将16位样本从有符号(16位样本几乎总是以-32768到+32767的范围存储)转换为无符号,然后获取结果的前8位。在C语言中,这可以表示为输出=(无符号字符)((无符号短)(输入+32768)>>;8). 这是一个很好的开始,可能足以满足您的需求,但听起来不太好。这听起来很粗糙,因为“量化噪声”
量化噪声是原始输入和算法输出之间的差异。无论你做什么,你都会有噪音,而噪音平均为“半点”。对此你无能为力,但有办法让噪音变得不那么明显
量化噪声的主要问题是它容易形成图案。如果输入和输出之间的差异是完全随机的,实际上听起来很好,但是相反,对于波形的某一部分,输出会重复地太高,而对于下一部分,输出会太低。你的耳朵听到了这个图案
要获得听起来不错的结果,需要添加抖动。抖动是一种试图消除量化噪声的技术。最简单的抖动只是从噪声中去除模式,这样噪声模式就不会偏离实际的信号模式。更好的抖动可以更进一步,采取措施减少噪声,方法是将多个样本的误差值相加,然后在总误差大到值得校正时加入校正
你可以在网上找到各种抖动算法的解释和代码示例。一个好的研究领域可能是SoX工具http://en.wikipedia.org/wiki/SoX。检查声源的抖动效果,并尝试在启用和不启用抖动的情况下将各种声音从16位转换为8位。当转换为8位声音时,抖动会产生不同的质量,你会感到惊讶
# 2 楼答案
标准化16位样本,然后按8位样本的最大值重新缩放
这会产生更精确的转换,因为每个样本的低8位不会被丢弃。然而,我的解决方案在计算上比选择的答案更昂贵
# 3 楼答案
我现在不明白为什么只取高位字节是不够的,即丢弃每个样本的低位8位
当然,假设样本是线性的;如果它们不是这样的话,也许你需要做一些事情来线性化它们,然后再丢弃比特
正如AShelly在一篇评论中所建议的,四舍五入可能是一个好主意,即如果我们要丢弃的字节高于其最大值的一半,则添加1:
针对0xff的测试实现了钳制,所以我们不需要冒险将1添加到0xff,并将其包装到0x00,这将是不好的