Search code examples
c#directxdirectshowdirectsound

Get the inverse of a function, millibels to percentage & percentage to millibels


Audio noob here and math challenged. I'm working with DirectSound which uses a -10000 to 0 range, converting that to a 0-100 scale. I found this function here to obtain the millibels based on a percentage:

    private int ConvertPercentageToMillibels(double value)
    {
        double attenuation = 1.0 / 1024.0 + value / 100.0 * 1023.0 / 1024.0;
        double db = 10 * Math.Log10(attenuation) / Math.Log10(2);
        return (int)(db * 100);
    }

I need help getting the inverse of this function, basically to get the percentage based on millibels. Here is what I've got so far, which isn't working:

    private double ConvertMillibelsToPercentage(int value)
    {
        double db = value / 100;
        double attenuation = Math.Pow(10, db) / 10 * Math.Pow(10, 2);
        double percentage = (1.0 * attenuation) - (1024.0 * 100.0 / 1023.0 * 1024.0);
        return percentage;
    }

Solution

  • Here you go!

    private double ConvertMillibelsToPercentage(int value)
    {
        double exponent = ((value / 1000.0) + 10);
        double numerator = 100.0 * (Math.Pow(2, exponent) - 1);
        return numerator / 1023.0;
    }
    

    Answer will differ slightly due to obvious issues that arise from going between an int and a double.

    EDIT: Per the teach how to fish request, here are the first mathematical steps toward arriving at the solution. I didn't show the whole thing because I didn't want to spoil allll the fun. All log functions should be considered Log base 10 unless otherwise noted:

    millibels = db*100; // Beginning to work backward
    millibels = 10*Log(attenuation)*(1/Log(2))*1000; // Substituting for db
    millibels = 1000*Log(attenuation)/Log(2); // Simplifying
    

    let millibels = m. Then:

    m = 1000*Log(attenuation)/Log(2);
    

    from here you can go two routes, you can either use properties of logs to find that:

    m = 1000* Log_2(attenuation);// That is, log base 2 here
    attenuation = 2^(m/1000);
    

    OR you can ignore that particular property and realize:

    attenuation = 10^(m*Log(2)/1000);
    

    Try to work it out from one of the above options by plugging in the value that you know for attenuation:

    attenuation = (1/1024)+(percentage/100)*(1023/1024);
    

    And then solving for percentage. Good luck!

    PS If you ever get stuck on things like this, I highly recommend going to the math stack exchange - there are some smart people there who love to solve math problems.

    OR if you are particularly lazy and just want the answer, you can often simply type this stuff into Wolfram Alpha and it will "magically" give you the answer. Check this out