为什么我要丢弃 FFT returns 的一半?

Why should I discard half of what a FFT returns?

查看此答案: Python Scipy FFT wav files

技术部分很明显并且可以工作,但是我有两个理论问题(下面提到的代码):

1) 为什么我必须标准化 (b=...) 帧?如果我使用原始数据会发生什么?

2) 为什么我应该只使用一半的 FFT 结果 (d=...)?

3) 为什么我要 abs(c) FFT 结果?

也许由于对 WAV 格式或 FFT 的理解不足,我遗漏了一些东西,但是虽然这段代码工作得很好,但我很乐意了解它为什么工作以及如何充分利用它。

编辑: 回应@Trilarion 的评论:

我正在尝试写一个简单的,不是 100% 准确但更像是概念验证 Speaker Diarisation in Python. That means taking a wav file (right now I am using this one 用于我的测试)并且每秒(或任何其他分辨率)说如果说话者是人#1 或人#2。我事先知道这是 2 个人,我并没有试图 link 他们到任何已知的语音签名,只是为了分开。现在花每一秒,对它进行 FFT(从而得到一个频率列表),然后使用 KMeans 对它们进行聚类,聚类数在 2 到 4 之间(A,B [,Silence [,A + B]])。

我对一般分析 wav 文件和音频还是陌生的。

import matplotlib.pyplot as plt
from scipy.io import wavfile # get the api
fs, data = wavfile.read('test.wav') # load the data
a = data.T[0] # this is a two channel soundtrack, I get the first track
b=[(ele/2**8.)*2-1 for ele in a] # this is 8-bit track, b is now normalized on [-1,1)
c = sfft.fft(b) # create a list of complex number
d = len(c)/2  # you only need half of the fft list
plt.plot(abs(c[:(d-1)]),'r') 
plt.show()

这取决于您要做什么。看来您只是想绘制光谱密度图,然后就可以了。

一般来说,DFT 中的系数取决于每个频率的相位,因此如果您想保留相位信息,则必须保留复数的自变量。

只有当输入是实数序列 (IIRC) 时才能保证您看到的对称性。如果频率高于奈奎斯特频率(采样频率的一半),它与镜像失真有关,原始频率显示在 DFT 中,但也显示镜像频率。

如果您要反演 DFT,您应该保留完整数据并保留 DFT 系数的自变量。

按顺序解决这些问题:

1) 您不需要归一化,但输入归一化接近数字化波形的原始结构,因此数字不直观。例如,67 的值有多大?将其规范化到 -1 到 1 的范围内来解释这些值会更容易。 (但是如果你想实现一个滤波器,例如,你做了一个 FFT,修改了 FFT 值,然后是一个 IFFT,归一化将是一个不必要的麻烦。)

2) 和 3) 的相似之处在于它们都与主要存在于复数 space 中的数学有关。也就是说,FFT 将一个复数波形(例如,[.5+.1j, .4+.7j, .4+.6j, ...])转换为另一个复数序列。

那么详细:

2) 事实证明,如果输入波形是实数而不是复数,则 FFT 具有关于 0 的对称性,因此只有频率 >=0 的值才是唯一有趣的。

3) FFT输出的值是复数,所以有Re和Im部分,但也可以表示为幅度和相位。对于音频信号,通常是最有趣的幅度,因为这主要是我们听到的。因此,人们经常使用 abs(即幅度),但相位对于不同的问题也很重要。