wavfile.write:相同的数组,但只有一个有效

wavfile.write: Identical arrays but only one works

我有两个相同的数组(设计使然,因为我通过执行 FFT 然后对第一个进行逆 FFT 获得了第二个)。但是,当我将第一个写入 .wav 文件时,我得到了发声文件,而不是当我对第二个文件执行相同操作时却没有。我听不到声音。这是我的代码:

fs, data = wavfile.read(filename)
a = data.T[0]
c = fft(a)
y2 = fftp.ifft(c)
y2 = np.array([int(round(i)) for i in y2.real])

现在当我尝试时:

sum(y2==a)==len(a)

我得到 True,这意味着两个数组是相同的。唯一的区别是一个有 "dtype=int16":

In [322]: a
Out[322]: array([ 1,  1,  1, ..., 21, 20, 21], dtype=int16)
In [321]: y2
Out[321]: array([ 1,  1,  1, ..., 21, 20, 21])

如何将第二个数组转换为可生成有效 .wav 文件的格式?

"only difference" 差别很大。

The WAV format,默认情况下,将样本存储为带符号的 little-endian 16 位整数。因此,当您将 int16 值的数组作为原始数据写入时,您将获得一个可播放的 WAV 文件(至少在 little-endian 系统上)。

但是当你写一个 int32 值的数组时,你会得到废话——每个数字变成 2 个样本,其中一个是数据的高位字,下一个是低位字。因此,您以一半的速度获得了原始音频样本,并与有效的随机噪声交织。


或者,您也可以使用 non-default WAV 格式。你没有展示足够多的代码来展示你是如何处理这个的,但是你可以用各种不同的格式编写 WAV 文件,从 8 位无符号整数到 32 位浮点数,而 32 位有符号整数是一个有效的格式。 WAV 文件甚至可以处理压缩(包括 MP3)。

但是 less-common 格式可能并不适用于所有工具;许多程序假定 WAV 是 16 位整数,并且不知道如何处理其他任何东西。

所以,您最好写 16 位整数。


或者,也许您已经在这样做了——用正确的方式编写 32 位 int 值 header——也许您的播放器正在正确处理它们。

但是您正在写入介于 -32768 和 32767 之间的 32 位 int 值。这意味着您只使用了动态范围的 1/65536,因此一切都将非常安静。如果要写入 32 位 int 值,则需要将它们规范化为 32 位 int 范围,而不是 16 位 int 范围。


解决所有这些问题的最简单方法是:在写入之前将值转换回 int16

y3 = y2.astype(np.int16)