如何在 Java 中实现 Chebyshev Type 2 LPF?

Posted

技术标签:

【中文标题】如何在 Java 中实现 Chebyshev Type 2 LPF?【英文标题】:How to implement Chebyshev Type 2 LPF in Java? 【发布时间】:2013-06-02 03:58:53 【问题描述】:

我的原始信号图如下。

我打算做的是做“真正的峰值”检测。也就是说,不应计算原始信号中的锯齿状噪声峰值。

在 Python 中实现 Chebyshev Type 2 LPF 后,信号被平滑成下图。

可以看出,我可以在 Python 中实现 LPF。

但我的问题是用 Java 实现它。

是否有任何现成的 LPF 适合我的目的? 或者任何人都可以教我如何用 Java 做到这一点?

参数如下:

截止频率。 = 4赫兹。 采样率 = 350Hz。

【问题讨论】:

我不知道有任何代码可以在 java 中执行此操作(这并不是说它不存在)但是您已经在 python 中设计了过滤器,所以为什么不直接使用您现有设计的系数? @BjornRoche 是的,是的,我可以回收参数。但是确定参数是最简单的部分……难点在于其他部分。 怎么样?过滤器的顺序是什么? (您没有在问题中指定) 如果您提供参数,我可以向您展示如何在 Java(或 C 或其他)中实现过滤器。 @BjornRoche 至于顺序,我没有很严格的数字,以后会调整以达到最佳效果。你可以把它当作 10。谢谢!我需要 JAVA 中的代码。 :) 【参考方案1】:

有多种方法可以实现这样的过滤器。 Direct Form I 既简单又数字稳定,所以我会推荐它。我将显示递归变量的双精度数字以确保准确性。你可能想在所有地方都使用双打来避免转换,但我会用 float 和 double 显示,这样你就可以看到你真正需要双打的地方。

对于这样的高阶过滤器,我没有方便的代码,因此未经测试,但此处的概念和上面的链接将为您提供答案。您可以随时将您的结果与 python 结果进行比较。

首先,您应该已经有了以下形式的系数:

float a[10] =  ... 
float b[10] =  ... 

现在,您需要确保系数已标准化(如果尚未标准化):

for( int i=0; i<10; ++i )
    b[i] /= a[0];
for( int i=1; i<10; ++i )
    a[i] /= a[0];

您的最后一个设置步骤是创建内存缓冲区来存储旧的输入 (x) 和输出 (y):

float x[10] =  0, 0, 0, ... 
double y[10] =  0, 0, 0, ... 

为新数据集“重置”过滤器时,请记住再次将它们的值设置为 0。

现在您可以开始处理了。这包括两个步骤:1. 计算您的输出,以及 2. 更新您存储的值。

float processOneValue( float in ) 
    // calculate new output:
    double out = in * b[0] ;
    for( int i=0; i<9; ++i )
       out += x[i]*b[i+1] ;
    for( int i=0; i<9; ++i )
       out -= y[i]*a[i+1] ;

    // update:
    for( int i=9; i>=1; --i )
       y[i] = y[i-1];
    y[0] = out;

    for( int i=9; i>=1; --i )
       x[i] = x[i-1];
    x[0] = in;

    return out;

由于这是一个如此高阶的过滤器,使用环形缓冲区可能比我用于 x 和 y 的“bucket-brigade”样式更新更有效,但这很有效并且更易于阅读。

现在,要处理数据数组,只需循环 processOneValue()。您可以就地或在新数组中获取输出。

【讨论】:

更多关于 DF I 的信息和一些低阶过滤器(二阶)的工作代码在这里:blog.bjornroche.com/2012/08/basic-audio-eqs.html 代码在 C 中,但非常接近 java。

以上是关于如何在 Java 中实现 Chebyshev Type 2 LPF?的主要内容,如果未能解决你的问题,请参考以下文章

用代码说话:如何在Java中实现线程

如何在 Java 中实现无穷大?

如何在java中实现接口类

如何在 Java 中实现过滤迭代器?

如何在 Java 类中实现运算符

如何在 Java 中实现包装装饰器?