我想尝试使用FFT而不是在时域中计算y=filter(b,a,x,zi)
和dy[i]/dx[j]
,以便在GPU实现中实现可能的加速。
我不确定是否可能,尤其是当zi
非零时。我查看了scipy中的scipy.signal.lfilter
和八度音程中filter
的实现情况。它们都是在时域中直接完成的,scipy使用直接形式2和octave直接形式1(通过查看DLD-FUNCTIONS/filter.cc
中的代码)。对于MATLAB中的FIR滤波器,我没有看到类似于fftfilt
的FFT实现(即a = [1.])。
我尝试过y = ifft(fft(b) / fft(a) * fft(x))
,但这似乎在概念上是错误的。另外,我不知道如何处理初始瞬态zi
。任何引用,指向现有实现的指针都将受到赞赏。
示例代码,
import numpy as np
import scipy.signal as sg
import matplotlib.pyplot as plt
# create an IRR lowpass filter
N = 5
b, a = sg.butter(N, .4)
MN = max(len(a), len(b))
# create a random signal to be filtered
T = 100
P = T + MN - 1
x = np.random.randn(T)
zi = np.zeros(MN-1)
# time domain filter
ylf, zo = sg.lfilter(b, a, x, zi=zi)
# frequency domain filter
af = sg.fft(a, P)
bf = sg.fft(b, P)
xf = sg.fft(x, P)
yfft = np.real(sg.ifft(bf/af * xf))[:T]
# error
print np.linalg.norm(yfft - ylf)
# plot, note error is larger at beginning and with larger N
plt.figure(1)
plt.clf()
plt.plot(ylf)
plt.plot(yfft)
答案 0 :(得分:2)
您可以将P = T + MN - 1
替换为P = T + 2*MN - 1
,从而减少现有实施中的错误。这纯粹是直观的,但在我看来,bf
和af
的划分将需要2*MN
个术语,因为环绕。
C.S。 Burrus有一个非常简洁的文章,介绍如何以面向块的方式{,3}来考虑过滤,无论是FIR还是IIR。我没有详细阅读它,但我认为它为您提供了通过卷积实现IIR滤波所需的方程式,包括中间状态。
答案 1 :(得分:1)
我忘记了我对FFT的了解,但你可以在http://jc.unternet.net/src/查看sedit.py和frequency.py,看看是否有任何帮助。
答案 2 :(得分:1)
尝试scipy.signal.lfiltic(b, a, y, x=None)
获取初始条件。
lfiltic
的文档文字:
Given a linear filter (b,a) and initial conditions on the output y
and the input x, return the inital conditions on the state vector zi
which is used by lfilter to generate the output given the input.
If M=len(b)-1 and N=len(a)-1. Then, the initial conditions are given
in the vectors x and y as
x = {x[-1],x[-2],...,x[-M]}
y = {y[-1],y[-2],...,y[-N]}
If x is not given, its inital conditions are assumed zero.
If either vector is too short, then zeros are added
to achieve the proper length.
The output vector zi contains
zi = {z_0[-1], z_1[-1], ..., z_K-1[-1]} where K=max(M,N).