实现数字滤波器 - 通过卷积或差分方程?
我是一位非常有经验的软件工程师,并且在大学里学过一些 EE 课程。我正在 iPhone 和 Android 上编程,我想为实时麦克风和加速度计数据实现数字滤波器(例如低通、带通、带阻等)。
我知道有多种等效方法可以在时域样本窗口上实现数字滤波器。我正在考虑的两种方法是:
直接在 C/Java 代码中实现差分方程(例如 y[i] = y[i-1] + 2 * x[i])。我相信这可以在 O(N) 时间内运行, 其中N是样本窗口的长度,例如N=512。
在样本窗口和窗口之间实现卷积 FIR 滤波器的时域表示,通常是某种形式的 sinc 功能。我问
现在,通过阅读各种在线资源,我发现 C/Java 编程的首选传统智慧方法是上面的 (1),即实现差分方程。这是一个正确的结论吗?
这是我发现的:
Apple 的加速计过滤器 代码实现了差异
这个 Stackoverflow 问题 如何实现低通滤波器? 建议利用差异
关于低通滤波器的维基百科文章提供了一种算法 使用差分方程。
总而言之,我的问题实际上是:
实现差分方程(而不是通过快速卷积)是在 C/Java 中编写滤波器的方法吗?
上面的参考文献都没有说明如何在给定特定截止频率或带阻频率的情况下设计差分方程。我知道我不久前研究过这个。是否有任何滤波器参考供程序员使用此类信息?
I'm a very experienced software engineer, and I've taken some EE classes in college. I'm programming on iPhone and Android, and I want to implement digital filters (e.g. low-pass, band-pass, band-stop, etc.) for real-time microphone and accelerometer data.
I know that there are multiple, equivalent ways to implement a digital filter on a window of time-domain samples. Two approaches I'm looking at are:
Implementing a difference equation directly in C/Java code (e.g.
y[i] = y[i-1] + 2 * x[i]). I believe this can run in O(N) time,
where N is the length of the sample window, e.g. N=512.Implementing the convolution between the sample window and the
time-domain representation of an FIR filter, typically some form of sinc
function. I asked this question awhile ago. This can be done in O(N
lg N) if you use fast-convolution involving FFT and IFFT.
Now, from reading various online resources, I've found that the preferred, conventional-wisdom approach for C/Java programming is (1) above, implementing a difference equation. Is this a correct conclusion?
Here is what I've found:
Apple's accelerometer filter code implements a difference
equation.This Stackoverflow question of How to implement a LowPass Filter? suggests the use of a difference
equation.The Wikipedia article on low-pass filter provides an algorithm
using a difference equation.
So in summary, my questions really are:
Is implementing a difference equation (rather than through fast convolution) the way to go for writing filters in C/Java?
None of the references above say how to design a difference equation given specific cut-off frequencies or band-stop frequencies. I know I studied this awhile ago. Are there are any filter references for programmers with this kind of information?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
时域差分方程是卷积。您所想到的基于 FFT 的方法是频域卷积,又名快速卷积,这实际上只是一种性能优化 - 它在数学上等同于时域卷积。通常,对于较小的滤波器长度,直接时域卷积速度更快,而当滤波器长度较大时,频域方法更胜一筹。根据经验,对于 1D 滤波,“大”意味着 N > 1。 50.
在上一段中我们只是讨论 FIR 滤波器。对于 IIR 滤波器,频域卷积不是一种选择(除非您在任意点截断脉冲响应),但通常 IIR 滤波器与 FIR 滤波器相比往往相对较短。
为了生成滤波器系数(即设计滤波器),您通常从滤波器规范开始,然后使用许多现有软件包之一来生成系数。如果您确实愿意,您可以实现自己的滤波器设计例程 - 查看诸如 Remez 交换 之类的算法。
The time domain difference equation is convolution. What you're thinking of with the FFT-based approach is frequency domain convolution aka fast convolution, which is really just a performance optimisation - it's mathematically equivalent to time domain convolution. Typically direct time domain convolution is faster for small filter lengths while the frequency domain approach wins when the filter length is large. As a rule of thumb, for 1D filtering "large" means, say, N > 50.
In the above paragraph we're just talking about FIR filters. For IIR filters frequency domain convolution is not an option (unless you truncate the impulse response at some arbitrary point), but typically IIR filters tend to be relatively short compared to FIR filters.
In order to generate filter coefficients (ie. design a filter) you typically start with a filter specification and then use one of many existing software packages to generate coefficients. You can implement your own filter design routine if you really want to - look at algorithms such as Remez exchange.
如果低阶 IIR 滤波器(使用短差分方程)满足您的滤波器规格,则其计算速度比 FIR 卷积或使用 FFT 的快速卷积快得多。它们也类似于电路设计人员可能熟悉的低元件数模拟滤波器。
如果您没有复杂的滤波器规范或要求(无法在少量极点和零点中足够接近地近似),为什么要在 FIR 或 FFT 上消耗更多 CPU 周期呢?但如果您确实需要更专业的过滤器,那么您就需要了。
这是一个非常常用的方法,用于确定双二阶的 IIR 系数。双二阶 IIR 滤波器还可以级联以实现更高阶的滤波。
Low-order IIR filters (using short difference equations) can be computationally much faster than either FIR convolution, or fast convolution using FFTs, if they meet your filter specification. They are also similar to low-component-count analog filters with which a circuit designer might be familiar.
If you don't have a sophisticated filter specification or requirement (one that can't be approximated closely enough in a small number of poles and zeros), why burn more CPU cycles on a FIR or FFT? But if you do need a more specialized filter, then you do.
Here is a very commonly used recipe for determining IIR coefficients for biquads. biquad IIR filters can also be cascaded for higher order filtering.
我会赞同使用传统时域数字滤波器的建议,即使用延迟、加法器和乘法器。对于简单的实时过滤,这种方法可能更快且不太复杂。
在实时应用程序中使用 FFT 是否合适取决于目标。例如,如果您想要进行实时频谱分析(例如,对于涉及音频的机器学习任务),那么 FFT 效果很好,因为它们快速、简单,并且可以提供高频谱分辨率。
您对 FIR 与 IIR 的评论是正确的。如果您给出一些(示例)滤波器规范,那么我们可能能够就选择哪种滤波器类型以及如何定义滤波器抽头(即系数)提供更多帮助。例如,如果您可以访问 Matlab 或 Python-Scipy,则可以使用它们来设计过滤器。
(查看 dsp.stackexchange 了解有关信号处理的更多信息。)
I'll second the suggestion to use traditional time-domain digital filters, i.e., using delays, adders, and multipliers. For simple real-time filtering, this approach is likely faster and less complex.
Using FFTs in a real-time application is fine depending on the goal. For example, if you want to do real-time spectral analysis (say, for a machine learning task involving audio), then FFTs work well because they are fast, easy, and can give high spectral resolution.
Your comment is correct about FIR vs. IIR. If you give some (example) filter specifications, then we may be able to give more help as to which filter type to choose, and how to define the filter taps (i.e., coefficients). For example, if you have access to Matlab or Python-Scipy, you could use those to design your filters.
(Check out dsp.stackexchange for more on signal processing.)