0
$\begingroup$

I am trying to rewrite some Python signal processing code in C++ and am stuck trying to figure out how to replicate behavior of lfilter with initial condition.

The documentation for lfilter says that the kwarg zi input is 'Initial conditions for the filter delays'. When I run lfilter and ippsIIR64f on the same data with the same filter coefficients and no delay, I get the same results. I tried using the IIRSetDlyLine function to set the delay line contents, but the results look wildly different (see image below).

Here is the code I used when setting the delay with IPP:

st |= ippsIIRSetDlyLine_64f(pStateIIR, pDlyLine);

versus in python:

signal.lfilter(brov, arov, data, axis = 0, zi=delayValues)

where pDlyLine and delayValues contain the same values.

enter image description here

$\endgroup$

1 Answer 1

2
$\begingroup$

To manually seed the initial state of a filter you need to know the exact topology of the implementation. signal.lfilter() uses Transposed Form II and hence the state is NOT the previous versions of input or output but that of an internal state variable that needs to be manually calculated from the previous inputs and outputs and the filter coefficients.

I took a quick peek at the documentation of ippsIIR64fbut wasn't able to determine the topology. I suggest deep diving in the documentation or reverse engineering it using some simple test signals.

Another note: From the the documentation of signal.lfilter() :

The function sosfilt (and filter design using output='sos') should be preferred over lfilter for most filtering tasks, as second-order sections have fewer numerical problems.

Cascaded second order sections are always preferable. You are going to have a lot less stability and noise problems. See the section picture in https://ww2.lacan.upc.edu/doc/intel/ipp/ipp_manual/IPPS/ipps_ch6/ch6_iir_filter_functions.htm

$\endgroup$
2
  • $\begingroup$ From the documentatoin of IIR filters, I found this: intel.com/content/www/us/en/develop/documentation/… It looks like it uses something similar - I also found this C code which also produces the same output as signal.lfilter: github.com/frankxiongzz/lfilter_c which also uses the DF2 calculations described in the IPP IIR documentation. $\endgroup$
    – yunyun333
    Commented Dec 19, 2022 at 16:45
  • $\begingroup$ After further testing it looks like IPP actually does utilize the delay the same way as scipy lfilter; the problem I found was due to small differences in the delay values which caused huge differences due to instability. $\endgroup$
    – yunyun333
    Commented Dec 19, 2022 at 19:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.