C++中实现IIR低通滤波器

3
我有一个Butterworth低通滤波器的滤波系数,来自Matlab函数[b, a] = butter(3, 0.4, 'low'),我根据他们的文档实现了与Matlab相同的计算方式,用于filter(b, a, X)。例如,过滤一个恒定信号5.0的结果是一样的,但只对前10个值有效!?我猜我的循环缓冲区有问题,但我找不到任何问题。使用filter方法将值正确写入x,数组以零初始化,循环缓冲区指针n具有正确的值...你有什么想法吗?
// Interface
class LowpassFilter {
private:
    double x[10]; // input vector
    double y[10]; // output vector
    int n;    // pointer to the current array index

public:
    LowpassFilter(); 
    double filter(double sample);
};


// Implementation

// filter coefficients a and b
const double a[] = {1.0, -0.577240524806303, 0.421787048689562, -0.056297236491843};
const double b[] = {0.098531160923927, 0.295593482771781, 0.295593482771781, 0.098531160923927};
static int c = 0;

LowpassFilter::LowpassFilter() : x{0.0}, y{0.0}, n(0) { } // Constructor

double LowpassFilter::filter(double sample)
{
    x[n] = sample;
    y[n] = b[0] * x[n] + b[1] * x[(n-1)%10] + b[2] * x[(n-2)%10] + b[3] * x[(n-3)%10]
                       - a[1] * y[(n-1)%10] - a[2] * y[(n-2)%10] - a[3] * y[(n-3)%10];

    std::cout << c++ << ": " << y[n] << std::endl; // for checking the result with the Matlab results

    double result = y[n];
    n = (n + 1) % 10; // new pointer index 
    return result;
}

1
当n == 0且(n-2)%10时,模数会发生什么变化?请查看此链接 - emsr
你的输出是什么?你遇到了什么问题? - emsr
1
@MichaelDorner:模运算确实会有负值,这就是问题的原因。将例如(n-1)%10替换为(n+10-1)%10以确保您始终获得预期的正值。 - Mike Seymour
非常感谢,你是完全正确的! - Michael Dorner
1个回答

3
感谢Mike Seymouremsr,问题在于计算y[n]时使用了负索引。解决问题只需采用一行代码即可:
y[n] = b[0] * x[n] + b[1] * x[(n-1+m)%m] + b[2] * x[(n-2+m)%m] + b[3] * x[(n-3+m)%m]
                   - a[1] * y[(n-1+m)%m] - a[2] * y[(n-2+m)%m] - a[3] * y[(n-3+m)%m];

确保索引为正数。现在它运行良好。非常感谢!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接