我正在尝试使用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
答案 0 :(得分:2)
看起来你有两个错误:
您正在为FFT长度标准化两次
您没有考虑到您的数据是24位整数的事实,因此存在隐式缩放因子2 ^ 23
我们可以插入数字,看看这个假设是否与您所看到的一致 - 错误应该是:
20 * log10(2^23 / 48000) = 44.8 dB
这可能足够接近。
因此,您需要将输入样本除以2 ^ 23以使它们进入-1.0到+1.0的范围,并且还删除第二个标准化(除以data_size
)。