How to cast from IIRCoefficents to array of float


#1

Hi All Jucers… I need a way to cast a IIRCoefficent to an array of float coefficients so I can use them for designing a filter graph. Is it possible?


#2

Did you take a look at the class documentation? From there it’s easy to find it out. If you didn’t, you should get used to take a look there first :wink:

Now if you’re talking about the old IIRCoefficients class, you’ll find out here https://docs.juce.com/master/classIIRCoefficients.html that it has a public attribute coefficients[5]. So accessing the array is as simple as myIIRCoefficients.coefficients.

If you are talking about the new dsp::IIRCoefficients class, you’ll find out here https://docs.juce.com/master/structdsp_1_1IIR_1_1Coefficients.html that it has the member function getRawCoefficients() returning a pointer to the raw coefficient array. In this case, accessing the array look like myIIRCoefficients.getRawCoefficients()


#3

ok thanks! Now I have access to the coefficents:
I have this code:

dsp::IIR::Coefficients<float>::Ptr newCoefficients;

switch (filterType)
{
    case LowPass:
        newCoefficients = dsp::IIR::Coefficients<float>::makeLowPass (fs, frequency, Q);
        b0 = newCoefficients->getRawCoefficients()[0];
        b1 = newCoefficients->getRawCoefficients()[1];
        b2 = newCoefficients->getRawCoefficients()[2];
        a0 = newCoefficients->getRawCoefficients()[3];
        a1 = newCoefficients->getRawCoefficients()[4];
        a2 = newCoefficients->getRawCoefficients()[5];
        break;
...

And I Pass to this function in paint() of my filterGraph component

    tracePath.clear();

if (traceType == Magnitude)
{
    float scaleFactor = (((height / 2) - (height - 5) / (numHorizontalLines + 1) - 2.5f) / maxdB);

    float traceMagnitude = (float) (filterVector [0].getResponse (lowFreq).magnitudeValue);
    
    for (int i = 1; i < numFilters; i++)
    {
        traceMagnitude *= (float) (filterVector [i].getResponse (lowFreq).magnitudeValue);
    }
    traceMagnitude = 20 * log10 (traceMagnitude);

    tracePath.startNewSubPath (2.5f, (height / 2) - (traceMagnitude * scaleFactor));
    
    for (float xPos = 3.5; xPos < (width - 2.5); xPos += 1)
    {
        float freq = xToFreq (xPos);
        
        traceMagnitude = (float) (filterVector [0].getResponse (freq).magnitudeValue);
        
        for (int i = 1; i < numFilters; i++)
        {
            traceMagnitude *= (float) (filterVector [i].getResponse (freq).magnitudeValue);
        }
        traceMagnitude = 20 * log10 (traceMagnitude);
    
        tracePath.lineTo (xPos, (height / 2) - (traceMagnitude * scaleFactor));
    }
}

if (traceType == Phase)
{
    float scaleFactor = ((height / 2) - (height - 5) / (numHorizontalLines + 1) - 2.5f) / (float_Pi * maxPhas);

    float traceMagnitude = (float) (filterVector [0].getResponse (lowFreq).phaseValue);
    for (int i = 1; i < numFilters; i++)
    {
        traceMagnitude += (float) (filterVector [i].getResponse (lowFreq).phaseValue);
    }
    
    float prevPhase = traceMagnitude;
    float unwrapSummand = 0;
    
    tracePath.startNewSubPath (2.5f, (height / 2) - (traceMagnitude * scaleFactor));
    for (float xPos = 3.5; xPos < (width - 2.5); xPos += 1)
    {
        float freq = xToFreq (xPos);
        
        traceMagnitude = (float) (filterVector [0].getResponse (freq).phaseValue);
        
        for (int i = 1; i < numFilters; i++)
        {
            traceMagnitude += (float) (filterVector [i].getResponse (freq).phaseValue);
        }
    
        if (fabs (traceMagnitude - prevPhase) > 5)
        {
            unwrapSummand += float_Pi * 2;
        }
        
        prevPhase = traceMagnitude;
        
        tracePath.lineTo (xPos, (height / 2) - ((traceMagnitude + unwrapSummand) * scaleFactor));
    }
}

g.setColour (traceColour);
g.strokePath (tracePath, PathStrokeType (1.0f));

And I get this error;


#4

the old working code was:

switch (filterType)
{
    case LowPass:
        b0 =  (1 - cos(w0)) / 2;
        b1 =   1 - cos(w0);
        b2 =  (1 - cos(w0)) / 2;
        a0 =   1 + alpha;
        a1 =  -2 * cos(w0);
        a2 =   1 - alpha;
        break;
...

And with that code the graph is plotted.With the other, the debugger say to me that the traceMagnitude is NaN…


#5

In the line before the error you write:

but the magnitude is likely to be 0 from time to time… so together with log10 it should ring a bell…


#6

sorry, I can’t understand…


#7

The logarithm of 0 is undefined, since the equation y = 10 ^ x has no solution for y == 0. The number you are getting for log10 (0) is NaN (“not a number”). So you should check if traceMagnitude > 0 before trying to compute the log of that.

Or even better, make use of the Decibels::gainToDecibels() function.


#8

ok now I understand, thank you very much!


#9

If I use Decibels::gainToDecibels, the path isn’t plotted…


#10

I haven’t read your code, but you probably have to check your maths and in which range the numbers are:
gain = 0 => dB = -infinity (defaults to -80.0, can be specified)
gain = 0.5 => dB = - 6dB
gain = 1 => dB = 0

so you can simply map to your rect:

auto y = jmap (Decibels::gainToDecibels (magnitude, -80.8f), -80.0f, 0.0f, rect.getBottom(), rect.getY());

BTW. I think this thread will be interesting for you: