0
$\begingroup$

I'm looking to implement the designing of a Butterworth filter based on the implementation in MATLAB/Scipy into C# but I've ran out of knowledge and can't quite seem how to compute the coefficients b and a based on the order and the normalised cutoff frequency.

I think that I am calculating z, p and k correctly using:

var z = new double[0];
var m = new List<double>();

var start = -order + 1;
var step = 2;
while (start <= order)
{
    m.Add(start);
    start += step;
}

var complexP = new List<Complex>();

for (var i = 0; i < m.Count; i++)
{
    complexP.Add(-Complex.Exp(Math.PI*m[i]/(2*order)));
}

var k = 1;

I believe that to calculate b and a using z, p and k I have to find the coefficients of a polynomial based on the root provided by p. But I'm struggling to understand how you calculate a coefficient of a polynomial based on a root value.

I understand the result of this should always return 1 as the first value of the a vector but I can't find anything that describes how to calculate the coefficient, perhaps I've found the answer but I've brushed past it.

For the b value I believe that this is k * polynomialCoefficients(z).

Also to note is that I haven't taken into consideration the cutoff values in to how they relate to z, p and k but this doesn't look too difficult and I don't think it will affect the question.

I'm not looking for this is how you do it in C#, but a general run down of how to calculate the coefficient would help.

$\endgroup$
0
$\begingroup$

Figured out how to correctly change from the zero-poles coefficients to the numerator/denominator coefficients.

Essentially this simply requires a convolution of the negative of each value with 1 being added as the first value in the results vector.

The implementation of this for the application of convolution in the instance of filter design is:

var result = new List<Complex>
{
    1
};

for (var i = 0; i < roots.Length; i++)
{
    var value = -roots[i];
    result.Add(result[result.Count - 1] * value);
    for (var j = result.Count - 2; j >= 1; j--)
    {
        result[j] = result[j] + value * result[j - 1];
    }
 }

To visualise this we start with the roots as being: [0.954697396423354, 0.8855894564017569, 0.86046511627906985, 0.8855894564017569, 0.954697396423354]

Before iteration:

result = [1]

First iteration:

result = [1, -0.9546974]
result[length-1] = 1 * -0.954697396423354

Second iteration:

result = [1, -1.84028685  0.84546995]
result[length-1] = -0.9546974  * -0.8855894564017569
result[length-2] = -0.9546974 + -0.8855894564017569 * 1

Third iteration:

result = [1, -2.70075197  2.42897259 -0.7274974]
result[length-1] = 0.84546995 * 0.86046511627906985
result[length-2] = 0.84546995 + 0.86046511627906985 * -1.84028685
result[length-3] = -1.84028685 + 0.86046511627906985 * 1

And so continues until you reach the end of the input vector.

The main thing to note is that the initial value (1) must never change in the result vector so it is required in the inner loop to make sure you skip the last value, as you've just calculated and added it, and also the first value.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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