Performance of log10 and pow

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

I have a written a plugin that uses log10 and pow to convert an amplitude to decibels and back again (with processing in between, obviously). I have discovered that the call to pow accounts for nearly half of my plug's CPU usage. Are there good, fast approximations for these functions suitable for such usage?

Post

gy wrote:I have a written a plugin that uses log10 and pow to convert an amplitude to decibels and back again (with processing in between, obviously). I have discovered that the call to pow accounts for nearly half of my plug's CPU usage. Are there good, fast approximations for these functions suitable for such usage?
What are you doing that needs you to be in decibels? Is that a per-sample operation? Can you rethink that processing to work in linear amplitude?

(The fastest code is that which never runs...)
Image
Don't do it my way.

Post

Borogove wrote: (The fastest code is that which never runs...)
Ya'know, from now on that's gonna be my excuse for failing to finish applications on time at work:

"Well yeah, it isn't actually finished yet, so it doesn't exactly compile... but I see that as more of a performance feature at this time." :D
Someone shot the food. Remember: don't shoot food!

Post

yes excellent quote.. I hope I never have to use it on my CS assignments.. :o

Post

What are you doing that needs you to be in decibels? Is that a per-sample operation? Can you rethink that processing to work in linear amplitude?
It's a compressor and yes, for each sample I am performing one log10 and one pow operation. I can't see any way around using them so I am looking to speed them up, in particular the pow method.

Post

do u really need one log and one pow PER SAMPLE ?!?
sorry, but i can't believe it, even when it is a compressor ...

Post

gy, most things don't need to be done every sample - even amplitude operations. You could figure it out every 4, 8 or 16 samples and interpolate in between. The difference shouldn't be audible. I have some code I've been using (forget where I found it) for doing fast pow(2, x) operations.. Here it is in case it's helpful.

void makefastpowtable()
{
for(int i=0; i<4097; i++)
tablefracpow2 = powf(2.0, ((float)i-2048)/2048.0);
}


float fastpow2(float x)
{
long *px = (long*)(&x);
const long lx = int(x);
float dx = x-(float)(lx);

int index = int(dx*2048.0)+2048;

index = index & 4095;


x = tablefracpow2[index];
*px += (lx<<23);
return x;
}
David Wallin - White Noise Audio Software
http://www.bleepboxapp.com/
(groove box for iPhone)

http://www.whitenoiseaudio.com/
(VST plugins)

Post

gy wrote:
What are you doing that needs you to be in decibels? Is that a per-sample operation? Can you rethink that processing to work in linear amplitude?
It's a compressor and yes, for each sample I am performing one log10 and one pow operation. I can't see any way around using them so I am looking to speed them up, in particular the pow method.
What are the per-sample operations between the log and the pow? They probably have equivalents which can be done on the untransformed value. To paraphrase Larry Wall, I suspect you're holding a loaded Uzi and asking what the most efficient way to club someone to death with it is.
Image
Don't do it my way.

Post

Firstly, thanks everybody for answering.
What are the per-sample operations between the log and the pow?
It's a simple compression transfer function to reduce the gradient above a threshold. I could operate directly on the amplitude, but to achieve the same transformation there would be a logarithmic curve in the transfer function.

Reducing the frequency of calculation and interpolating is an option, but this would obviously reduce the sensitivity of the compressor to fast transients.

Post

OK. Many thanks to WhiteNoise for the code. I replaced the look-up with a quadratic approximation, which removes the need for the table and its initialization. I find it to be slightly quicker, if slightly less accurate.

I have also adapted a fast log algorithm that works similarly, using the encoding of a float.

For anyone interested:

Code: Select all

inline float FastLog10 (float p_X)
{
    // Retrieve a coarse log value from the exponent of the encoded float
    int* const intX = reinterpret_cast<int*>(&p_X);
    const int coarseLog2 = ((*intX >> 23) & 0xFF) - 127;
    // Set the exponent to 1
    *intX &= 0x007FFFFF;
    *intX |= 0x3F800000;
    // Improve the coarse log value using a quadratic approximation
    // of log over the range [1, 2]
    static const float A = -(1.0f / 3.0f);
    static const float B = 2.0f;
    static const float C = -(5.0f / 3.0f);
    p_X = (((A * p_X) + B) * p_X) + C + static_cast<float>(coarseLog2);
    // Convert log to base 10 and return
    static const float LogBase10of2 = 0.30102999566398119521373889472449f;
    return (p_X * LogBase10of2);
}

inline float FastPow10 (float p_X)
{
    // Change power of 10 to power of 2
    static const float LogBase2of10 = 3.3219280948873623478703194294894f;
    p_X *= LogBase2of10;
    // Obtain the integer and fractional parts of the power
    const int intX = static_cast<int>(p_X);
    float fracX = p_X - static_cast<float>(intX);
    // Use a quadratic approximation for the fractional power of 2
    static const float A = 0.25f;
    static const float B = 0.75f;
    static const float C = 1.00f;
    p_X = (((A * fracX) + B) * fracX) + C;
    // Add the integral power directly to the exponent of the encoded float
    int *intXPtr = reinterpret_cast<int*>(&p_X);
    *intXPtr += (intX << 23);
    return p_X;
}
Thanks again, GY

Post

Welcome gy, good luck with your compressor!
David Wallin - White Noise Audio Software
http://www.bleepboxapp.com/
(groove box for iPhone)

http://www.whitenoiseaudio.com/
(VST plugins)

Post Reply

Return to “DSP and Plugin Development”