java - 16+ 位音频格式如何工作?

标签 java audio arrays wav

我正在尝试用 Java 编写一些基本的声音编辑程序,但我在使用 16 位 WAVE 文件格式时遇到了很多麻烦。

当我询问 Java 它认为我的声音文件有多少样本时,它给了我一个两倍于我预期的数字。当我告诉 Java 生成 80000 字节样本的正弦波时,它播放了 1 秒而不是 2 秒(尽管采样率大约是每秒 40000)。

经过更多的搜索,我意识到我的文件的“帧大小”是 2,“样本”实际上是 2 个字节而不是一个字节,这被称为 16 位音频文件。作为实验,我将声音文件写入一个字节数组,将每隔一个字节设置为 0,然后播放结果。当我只保留奇数样本时,播放的声音文件带有一点点静态噪音。当我只保留偶数时,静态噪音会在没有声音文件的情况下自行播放。这让我认为偶数字节包含奇数字节中静态的精确反转,其中包含要播放的实际声音。当一起播放时,偶数字节会消除奇数字节中的静电,从而提高声音保真度。

This website对 16 位声音编码的基础知识有很好的解释。但是,这还不足以让我继续并开始逐字节编辑文件。如何对 16 位(或更大)的声音文件进行逐字节编辑,同时仍保持其较高的保真度?用每个样本 16 位而不是 8 位编码声音的公式是什么?

最佳答案

How can I do byte-by-byte editing of a 16-bit (or larger) sound file...?

这个问题没有任何意义。当你说“逐字节编辑”时,你真的应该说“逐个样本”。在这种情况下,每个样本都是 16 位(或两个字节),将样本分开是没有意义的。这就像试图在文本编辑器中只编辑每个字母的上半部分。

数字音频流的单个 channel 是数字序列(也称为样本)。每个样本都代表了声波在某个时刻施加在麦克风振膜上的压力。在一个八位的声音文件中,只有 256 个可能的值,而在一个 16 位的声音文件中,有 65536 个可能的值。 16 位文件的分辨率要高得多。

This makes me think that the even bytes contain the exact inverse of the static in the odd bytes, which contain the actual sound to be played.

这有一定的道理。信号处理中“噪声”的定义是你听到的和你想听到的之间的差异。当您将所有奇数字节清零时,您踩到了每个样本的低位部分。通过更改样本,您引入了一些您不想听到的东西(即噪音)。当您将偶数字节置零时,您杀死了所有高阶位,因此也杀死了大部分信号。保留在低位字节中的正是您在第一个实验中引入的噪声的倒数。 (您的耳朵无法分辨给定声波和同一声波的逆波之间的区别。)

样本值和压力之间没有绝对映射关系,但您应该了解以下几点:

1) 样本是签名还是未签名?每个样本都有一个值,该值必须介于某个最小值和某个最大值之间。如果(16 位)样本是有符号的,则最小值为 -32768(0x8000),最大值为 32767(0x7FFF),0 正好在中间。如果样本是无符号的,则最小值为 0,最大值为 65535 (0xFFFF)。弄错了,您会立即知道,因为您听到的只是巨大噪音。

2) 样本是线性的吗?样本值总是与某些东西成正比。如果它们与声压级成正比,则称为“线性编码”。但它们可能与声压的对数或与声压的某些其他函数成正比。非线性编码几乎都是 8 位的,它们通常只在电话等专门应用中遇到。如果您处理的是 16 位或更大的样本,那么它们几乎肯定是线性的。

关于java - 16+ 位音频格式如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14187799/

相关文章:

java - 如何启动已经在播放的声音?

c++ - 使用 Memcpy 扩大指针数组的大小

java套接字输入流,PrintWriter不工作

java - 组合和聚合有什么区别?

java - DataBase(数据模型)构建文件夹结构

python - 从if [Python]退出

audio - 我们如何通过SCPlayer移除视频中的声音?

javascript - 从嵌套对象数组中删除重复项并保留其顺序 : javascript

java - 检测数组中最近的元素

java - Java 快速排序的 StackOverFlowError