ruohoruotsi / Butterworth-Filter-Design

C++ classes for designing high-order Butterworth IIR & equalization filters
GNU General Public License v3.0
163 stars 42 forks source link

Butterworth odd orders look incorrect #6

Open johnmgithub opened 5 years ago

johnmgithub commented 5 years ago

For odd filter orders a pair of real poles get added rather than a single pole, don't think that is right. In Butterworth::prototypeAnalogLowPass(int filterOrder) rather than

for(uint32_t k = 0; k < (filterOrder + 1) / 2; k++){ double theta = (double)(2 * k + 1) * M_PI / (2 * filterOrder); double real = -sin(theta); double imag = cos(theta); poles.push_back(complex_double(real, imag)); poles.push_back(complex_double(real, -imag)); // conjugate }

might need something like

for(uint32_t k = 0; k < filterOrder / 2; k++){ double theta = (double)(2 * k + 1) * M_PI / (2 * filterOrder); double real = -sin(theta); double imag = cos(theta); poles.push_back(complex_double(real, imag)); poles.push_back(complex_double(real, -imag)); // conjugate } if (filterOrder % 2 == 1){ poles.push_back(complex_double(-1, 0); } `

ruohoruotsi commented 5 years ago

Thank you John, do you want to submit a pull-request and a unit test? This issues highlights the need for more comprehensive tests as well as visual reasoning aids for pedagogical purposes. Cheers.

johnmgithub commented 5 years ago

Afraid I don't have a C++ dev environment, Java for me. Was just mooching about looking at Butterworth pole calculations to extract Q values for cascaded biquads and noticed it looked off.

ruohoruotsi commented 5 years ago

okay, thank you for the heads up. I'll fix it, I also wonder if its related to the gain issues someone else reported https://github.com/ruohoruotsi/Butterworth-Filter-Design/issues/3 (which I also need to fix). Cheers!

Uight commented 2 weeks ago

@johnmgithub is actually right with this. The poles for all odd filter orders are wrong if not corrected as show in the code he shared. I converted your code to c# and with that i was able to show that against some manual test i did against matlab. This bug however is not related to the one described in #3.

i verified all zero, poles and gains before the method zp2SOS which makes me believe that zp2Sos is actually wrong. If you apply the fix from here and use the method described in #3 where you multiple the gain with the values from ab[] then you can get first order and second order running for everything

ruohoruotsi commented 2 weeks ago

thank you @Uight, looks like I need to get on with fixing some of these issues, notably with zp2SOS ...thank you for you comment and attention. I'll make it a priority! 🙇