我尝试实现一个通用的IIR滤波器。主要内容如下:
// Loop over all SOS sections:
value_type y = x;
BOOST_FOREACH( Sos& n, m_sos )
{
y = update( n, y );
}
与:
...update( Sos& sos, const value_type& x ) const
{
const value_type xs = sos.m_s * x;
const value_type w0 = xs
- sos.m_a( 1 ) * sos.m_w( 0 )
- sos.m_a( 2 ) * sos.m_w( 1 );
const value_type y = w0
+ sos.m_b( 1 ) * sos.m_w( 0 )
+ sos.m_b( 2 ) * sos.m_w( 1 );
sos.m_w( 1 ) = sos.m_w( 0 );
sos.m_w( 0 ) = w0;
return y;
}
系数m_a,m_b是变量,在运行期间从文件读取一次。
因此,在编译期间这些值是未知的。根据设计
过滤器,可能会发生某些系数为1.0或0.0的情况。因此对应
操作可以省略。这样可以节省很多性能。
可以肯定的是,我现在可以针对一个专用过滤器优化代码,但如上所述
实现应非常通用。
我的第一个想法是某种自我修改算法...但是也许有人有一个很棒的想法或暗示... :)
最佳答案
您可以制作过滤功能的模板化版本。我不知道如何将其直接应用于您的代码,但是请考虑以下几点:
// Z1 means "coefficient 1 is zero"
template <bool Z1, bool Z2, bool Z3, bool Z4, bool Z5>
...update( Sos& sos, const value_type& x ) const
{
value_type coef1 = Z1 ? 0 : sos.m_a( 1 ); // or whatever else
value_type coef2 = Z2 ? 0 : ...;
value_type coef3 = Z3 ? 0 : ...;
value_type coef4 = Z4 ? 0 : ...;
value_type coef5 = Z5 ? 0 : ...;
... // the rest of your code
}
到目前为止,它定义了32个不同的函数,每个函数均已得到最大程度的优化(编译器应检测乘以零常数的乘法并优化代码)。然后,您可以使用函数指针数组:
auto my_table[] = {
&update<0, 0, 0, 0, 0>,
&update<0, 0, 0, 0, 1>,
...
&update<1, 1, 1, 1, 1>
};
然后检查性能不重要的系数(从文件中读取系数),从数组中获取函数指针,并将其存储在对象
Sos
中。如果听起来太含糊,我感到抱歉;我对您的代码不够了解,无法用可编译代码表达我的想法。