【问题标题】:Fft windowing in Python, choice and optimisationPython中的Fft窗口,选择和优化
【发布时间】:2014-07-18 09:17:58
【问题描述】:

我目前正在尝试计算 THD、本底噪声和其他音频测量值(IMD、使用 Python 的频率响应)。为此,我将 wave 文件导入 numpy 数组,然后使用 scipy 模块计算 fft。为避免混叠,我需要在执行 fft 之前对数据进行窗口化。所以我尝试比较不同的窗口,这是一些结果(997 kHz 正弦波,32 位,adobe 试听生成的 192 kHz):

我正在寻找精度:本底噪声应尽可能低,峰值外的响应应尽可能平坦。所以我的问题是:Rife-Vincent 真的是我最好的选择吗?我是否错过了其他我不知道且未测试的“秘密”窗口?

如果我决定保留 Rife-Vincent 窗口,问题在于时间计算!其他窗口在 scipy 模块中实现,计算速度非常快。我这样计算 Rife-Vincent 系数:

w = np.empty(M,dtype=np.float64)
a = 2*np.pi/M
for i in np.arange(0, M):
    w[i] = (35 - 56*np.cos(a*i) + 28*np.cos(2*a*i) - 8*np.cos(3*a*i) + np.cos(4*a*i))/128

其中 M 是我的数据长度,可能会很长。这非常耗时,有人可以帮我优化吗?

【问题讨论】:

  • “997 kHz 正弦波,192 kHz”是什么意思?
  • 纯正弦 @ 997 Hz(这是个错误,对此感到抱歉;))以 192 kHz 采样。

标签: python fft windowing


【解决方案1】:

回答如何计算窗口:

a = 2*np.pi/M
x = np.arange(0, M)
w = (35 - 56 * np.cos(a * x) + 28 * np.cos(2 * a * x) - 8 * np.cos(3 * a * x) + np.cos(4 * a * x))/128

应该很快。您可以通过这样做为自己节省一些临时变量:

w = 35 - 56 * np.cos(a * x)
w +=  28 * np.cos(2 * a * x)
w -= 8 * np.cos(3 * a * x)
w += np.cos(4 * a * x)
w /= 128.

但对于 3e7 点,它只会在大约 7 中为您节省 1 秒。

如果你想要更快,你应该使用 numexpr:

w = ne.evaluate('(35 - 56 * cos(a * x) + 28 * cos(2 * a * x) - 8 * cos(3 * a * x) + cos(4 * a * x))/128')

这将并行编译和计算它;在我的电脑上,时间从 7 秒变为 2 秒。

【讨论】:

  • 非常感谢,这是一个非常好的改进!是否也可以减少matplotlib(~2s)和Scipy等模块的加载时间?
  • @NessyW。那是另一个问题。但事实是,它不应该花这么长时间。在我的机器上,MPL 在 250 毫秒内加载,scipy 在 80 毫秒内加载。不要忘记在您的问题中添加您的操作系统以及它们是如何安装的。
  • 我承认我的问题表述得不好。我实际上想问,需要这么长时间是否正常(我正在研究 Raspberry Pi :))?顺便说一句,我测试你的 numepxr 方法太快了:它更快,但它没有给我相同的结果^^我正在研究它,当我找到原因时会回来......
  • 哦,那么除了修补您自己的 numpy 并减少您在导入时所做的事情之外,您几乎无能为力。例如,您可以禁用测试模块。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 1970-01-01
  • 2012-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多