我读到Matlab滤波器命令用于求解差分方程。 filter()内部是使用z-Transform还是仅使用递归,即使用起始值x(0),y(0),它只是在时间上向前运行差分方程?对不起,如果这个问题没有意义,我是这个领域的新手。
谢谢,
答案 0 :(得分:3)
滤波器实现可能是频域技术的一些巧妙使用,但是根据MATLAB文档,它 在数学上等同于求解差分方程:
Y = FILTER(B,A,X) filters the data in vector X with the filter described by vectors A and B to create the filtered data Y. The filter is a "Direct Form II Transposed" implementation of the standard difference equation: a(1)*y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb) - a(2)*y(n-1) - ... - a(na+1)*y(n-na)
初始条件被选为全零,因为我们假设在开始过滤之前根本没有信号(全零)。如果您想指定这些初始条件,filter
命令允许您指定初始(Zi
)和最终(Zf
)条件的向量:[Y,Zf] = FILTER(B,A,X,Zi)
答案 1 :(得分:2)
MatLab filter()函数实现了iir滤波器(递归滤波器),即它解决了差分方程。频域中的实现将具有高得多的成本。时域为O(N),频域理想情况下为log(N),如果使用FFT,则为O(N²)。
答案 2 :(得分:1)
以下是我在一段时间以前在C ++中实现MATLAB内置filter
功能的方法,如果有人需要的话。在Zi
中,您传递初始条件并在需要时收集最终条件。
#include <vector>
#include <exception>
#include <algorithm>
typedef vector<double> vectord;
void filter(vectord B, vectord A, const vectord &X, vectord &Y, vectord &Zi)
{
if (A.empty())
throw std::domain_error("The feedback filter coefficients are empty.");
if (std::all_of(A.begin(), A.end(), [](double coef){ return coef == 0; }))
throw std::domain_error("At least one of the feedback filter coefficients has to be non-zero.");
if (A[0] == 0)
throw std::domain_error("First feedback coefficient has to be non-zero.");
// Normalize feedback coefficients if a[0] != 1;
auto a0 = A[0];
if (a0 != 1.0)
{
std::transform(A.begin(), A.end(), A.begin(), [a0](double v) { return v / a0; });
std::transform(B.begin(), B.end(), B.begin(), [a0](double v) { return v / a0; });
}
size_t input_size = X.size();
size_t filter_order = std::max(A.size(), B.size());
B.resize(filter_order, 0);
A.resize(filter_order, 0);
Zi.resize(filter_order, 0);
Y.resize(input_size);
for (size_t i = 0; i < input_size; ++i)
{
size_t order = filter_order - 1;
while (order)
{
if (i >= order)
Zi[order - 1] = B[order] * X[i - order] - A[order] * Y[i - order] + Zi[order];
--order;
}
Y[i] = B[0] * X[i] + Zi[0];
}
Zi.resize(filter_order - 1);
}
可以使用以下代码进行测试:
TEST_METHOD(TestFilter)
{
vectord b_coeff = { /* Initialise your feedforward coefficients here */ };
vectord a_coeff = { /* Initialise your feedback coefficients here */ };
vectord input_signal = { /* Some input data to be filtered */ };
vectord y_filter_ori = { /* MATLAB output from calling y_filter_ori = filter(b_coeff, a_coeff, input_signal); */ };
vectord y_filter_out; vectord zi = { 0 }; // Set empty initial conditions
filter(b_coeff, a_coeff, input_signal, y_filter_out, zi);
Assert::IsTrue(compare(y_filter_out, y_filter_ori, 0.0001));
}
bool compare(const vectord &original, const vectord &expected, double tolerance = DBL_EPSILON)
{
if (original.size() != expected.size())
return false;
size_t size = original.size();
for (size_t i = 0; i < size; ++i)
{
auto diff = abs(original[i] - expected[i]);
if (diff >= tolerance)
return false;
}
return true;
}