【问题标题】:Calculate power of FFT Frequency component计算 FFT 频率分量的功率
【发布时间】:2014-12-18 08:38:58
【问题描述】:

我正在尝试使用 numpy 计算以 48000 Hz 的采样率为 48000 个音频数据样本的 FFT 频率分量的 dB 测量功率。我正在测试的文件具有 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

【问题讨论】:

  • data 的取值范围是多少?
  • 'data' 包含来自 24 位波形文件的 32 位有符号整数,我对其有符号整数值进行了符号扩展。我可以从音频文件中导出正确的数据库表示,所以我认为“数据”没有问题。
  • OK - 那么data 的数字范围是多少?是 32 位有符号整数的全范围,即 -2e9 到 +2e9,还是 24 位 PCM 的全范围,还是什么?
  • 全范围 24 位 PCM,-8388607 到 8388608
  • 好的 - data_size 是什么?

标签: python audio numpy signal-processing fft


【解决方案1】:

看起来你有两个错误:

  • 您对 FFT 长度进行了两次标准化

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

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

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

这可能已经足够接近了。

因此,您需要将输入样本除以 2^23 以使它们进入 -1.0 到 +1.0 的范围内,并移除第二次归一化(除以 data_size)。

【讨论】:

  • 那么这将是我用来校准计算的最大比例吗?
  • 好吧,如果您希望 0 dB 对应于满量程(-1 到 +1)信号,那么是的,您需要将整数样本转换为其等效的定点。请记住,虽然 0 dB 本身没有任何意义 - 它是一个相对测量值,因此您需要定义 0 dB 对您的意义。
  • 完美。很好的解释。
猜你喜欢
  • 2021-03-09
  • 1970-01-01
  • 2017-06-06
  • 2020-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
  • 2017-08-11
相关资源
最近更新 更多