I've been doing some profiling lately and I've encountered one case which is driving me nuts. The following is a piece of unsafe C# code which basically copies a source sample buffer to a target buffer with a different sample rate. As it is now, it takes up ~0.17% of the total processing time per frame. What I don't get is that if I use floats instead of doubles, the processing time will raise to 0.38%. Could someone please explain what's going on here?
Fast version (~17%)
double rateIncr = ...
double readOffset = ...
double offsetIncr = ...
float v = ... // volume
// Source and target buffers.
float* src = ...
float* tgt = ...
for( var c = 0; c < chunkCount; ++c)
{
for( var s = 0; s < chunkSampleSize; ++s )
{
// Source sample
var iReadOffset = (int)readOffset;
// Interpolate factor
var k = (float)readOffset - iReadOffset;
// Linearly interpolate 2 contiguous samples and write result to target.
*tgt++ += (src[ iReadOffset ] * (1f - k) + src[ iReadOffset + 1 ] * k) * v;
// Increment source offset.
readOffset += offsetIncr;
}
// Increment sample rate
offsetIncr += rateIncr;
}
Slow version (~38%)
float rateIncr = ...
float readOffset = ...
float offsetIncr = ...
float v = ... // volume
// Source and target buffers.
float* src = ...
float* tgt = ...
for( var c = 0; c < chunkCount; ++c)
{
for( var s = 0; s < chunkSampleSize; ++s )
{
var iReadOffset = (int)readOffset;
// The cast to float is removed
var k = readOffset - iReadOffset;
*tgt++ += (src[ iReadOffset ] * (1f - k) + src[ iReadOffset + 1 ] * k) * v;
readOffset += offsetIncr;
}
offsetIncr += rateIncr;
}
Odd version(~22%)
float rateIncr = ...
float readOffset = ...
float offsetIncr = ...
float v = ... // volume
// Source and target buffers.
float* src = ...
float* tgt = ...
for( var c = 0; c < chunkCount; ++c)
{
for( var s = 0; s < chunkSampleSize; ++s )
{
var iReadOffset = (int)readOffset;
var k = readOffset - iReadOffset;
// By just placing this test it goes down from 38% to 22%,
// and the condition is NEVER met.
if( (k != 0) && Math.Abs( k ) < 1e-38 )
{
Console.WriteLine( "Denormalized float?" );
}
*tgt++ += (src[ iReadOffset ] * (1f - k) + src[ iReadOffset + 1 ] * k) * v;
readOffset += offsetIncr;
}
offsetIncr += rateIncr;
}
All I know by now is that I know nothing