计算FFT频率分量的功率

时间:2014-10-22 19:07:35

标签: python audio numpy signal-processing fft

我正在尝试使用numpy计算48000个音频数据样本的FFT频率分量以dB为单位测量的功率,采样率为48000 Hz。我正在测试的文件具有1000 Hz的全功率(0 dB)正弦波。当我计算具有最多能量的能带的均方根值时,我期待0 dB的结果,但是,我得到以下结果:

1000.0Hz 41.8387130383 dB

有人会解释为什么我会得到不同的结果吗?我的代码如下。

'data'是48000个样本的numpy数组,具有32位精度。据我了解,我需要通过数据样本的长度来标准化fft结果。

p = np.fft.fft(data)
uniquePts = math.ceil(len(data)+1/2.0)
p = p[0:uniquePts]
freqs = np.fft.fftfreq(len(p))

将fft结果标准化为数据样本的长度

p = np.divide(p,float(len(data)))
p = np.abs(p)
p = np.power(p,2)

将FFT结果乘以2,以说明我们将返回FFT数组中的元素总数减半的事实

if len(data) % 2 > 0:
  p[1:len(p)] = np.multiply(p[1:len(p)], 2)
else:
  p[1:len(p) - 1] = np.multiply(p[1:len(p) -1], 2)

此时,我发现具有idx所代表的最多能量的FFT分量:

data_size=48000 #1 second of audio
idx=np.argmax(np.abs(p)**2) 
rms = math.sqrt(p[idx])
dbRep = 20 * math.log10((1.0 * rms)/data_size)
print abs(freqs[i] * frate), dbRep

1 个答案:

答案 0 :(得分:2)

看起来你有两个错误:

  • 您正在为FFT长度标准化两次

  • 您没有考虑到您的数据是24位整数的事实,因此存在隐式缩放因子2 ^ 23

我们可以插入数字,看看这个假设是否与您所看到的一致 - 错误应该是:

20 * log10(2^23 / 48000) = 44.8 dB

这可能足够接近。

因此,您需要将输入样本除以2 ^ 23以使它们进入-1.0到+1.0的范围,并且还删除第二个标准化(除以data_size)。