Author: pulkomandy Date: 2011-07-16 11:15:21 +0200 (Sat, 16 Jul 2011) New Revision: 42435 Changeset: https://dev.haiku-os.org/changeset/42435 Ticket: https://dev.haiku-os.org/ticket/1351 Modified: haiku/trunk/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp Log: fix bugs in interpolating resampler : * I got the downsampling version completely wrong. It should now be much better. * A small bug in the delta calculation sometimes caused an off-by-one read to the source and a crash of the media add-on server Effect of this resampler can be heard very clearly using the following setup in Cortex : * Demo Audio producer producing a sinewave at any frequency (sampling rate is hardcoded at 44100Hz) * Audio output set to 48000 Hz * system mixer in between select either resampler in the mixer and you'll hear the difference immediately. Should finally fix #1351. Modified: haiku/trunk/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp =================================================================== --- haiku/trunk/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp 2011-07-16 03:01:21 UTC (rev 42434) +++ haiku/trunk/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp 2011-07-16 09:15:21 UTC (rev 42435) @@ -44,33 +44,20 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; #define SRC(n) *(const float*)(src + n * srcSampleOffset) - if (delta < 1.0) { - // upsample - while (count--) { - *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current) ; - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current) ; + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - *(float*)dest = gain - * (SRC(0) + (SRC((int)skipcount) - SRC(0)) * offset); - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } } @@ -95,34 +82,21 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; #undef SRC #define SRC(n) *(const int32*)(src + n * srcSampleOffset) - if (delta < 1.0) { - // upsample - while (count--) { - *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current) ; - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current) ; + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - *(float*)dest = gain * (SRC(0) + (SRC((int)skipcount) - SRC(0)) - * offset); - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } } @@ -147,34 +121,21 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; #undef SRC #define SRC(n) *(const int16*)(src + n * srcSampleOffset) - if (delta < 1.0) { - // upsample - while (count--) { - *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current); - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current); + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - *(float*)dest = gain * (SRC(0) + (SRC((int)skipcount) - SRC(0)) - * offset); - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } } @@ -199,34 +160,21 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; #undef SRC #define SRC(n) *(const int8*)(src + n * srcSampleOffset) - if (delta < 1.0) { - // upsample - while (count--) { - *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current) ; - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current) ; + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - *(float*)dest = gain * (SRC(0) + (SRC((int)skipcount) - SRC(0)) - * offset); - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } } @@ -251,34 +199,21 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; #undef SRC #define SRC(n) ( *(const uint8*)(src + n * srcSampleOffset) - 128) - if (delta < 1.0) { - // upsample - while (count--) { - *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current); - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + *(float*)dest = gain * (SRC(0) + (SRC(1) - SRC(0)) * current); + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - *(float*)dest = gain * (SRC(0) + (SRC((int)skipcount) - SRC(0)) - * offset); - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } } @@ -309,47 +244,28 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; #undef SRC #define SRC(n) *(const float*)(src + n * srcSampleOffset) - if (delta < 1.0) { - // upsample - while (count--) { - register float sample = gain * (SRC(0) + (SRC(1) - SRC(0)) - * current); - if (sample > 2147483647.0f) - *(int32 *)dest = 2147483647L; - else if (sample < -2147483647.0f) - *(int32 *)dest = -2147483647L; - else - *(int32 *)dest = (int32)sample; - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + register float sample = gain * (SRC(0) + (SRC(1) - SRC(0)) + * current); + if (sample > 2147483647.0f) + *(int32 *)dest = 2147483647L; + else if (sample < -2147483647.0f) + *(int32 *)dest = -2147483647L; + else + *(int32 *)dest = (int32)sample; + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - register float sample = gain * (SRC(0) + (SRC((int)skipcount) - - SRC(0)) * offset); - if (sample > 2147483647.0f) - *(int32 *)dest = 2147483647L; - else if (sample < -2147483647.0f) - *(int32 *)dest = -2147483647L; - else - *(int32 *)dest = (int32)sample; - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } } @@ -380,44 +296,25 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; - if (delta < 1.0) { - // upsample - while (count--) { - register float sample = gain * (SRC(0) + (SRC(1) - SRC(0)) - * current); - if (sample > 32767.0f) - *(int16 *)dest = 32767; - else if (sample < -32767.0f) - *(int16 *)dest = -32767; - else - *(int16 *)dest = (int16)sample; - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + register float sample = gain * (SRC(0) + (SRC(1) - SRC(0)) + * current); + if (sample > 32767.0f) + *(int16 *)dest = 32767; + else if (sample < -32767.0f) + *(int16 *)dest = -32767; + else + *(int16 *)dest = (int16)sample; + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - register float sample = gain * (SRC(0) + (SRC((int)skipcount) - - SRC(0)) * offset); - if (sample > 32767.0f) - *(int16 *)dest = 32767; - else if (sample < -32767.0f) - *(int16 *)dest = -32767; - else - *(int16 *)dest = (int16)sample; - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } } @@ -448,44 +345,25 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; - if (delta < 1.0) { - // upsample - while (count--) { - register float sample = gain * (SRC(0) + (SRC(1) - SRC(0)) - * current); - if (sample > 127.0f) - *(int8 *)dest = 127; - else if (sample < -127.0f) - *(int8 *)dest = -127; - else - *(int8 *)dest = (int8)sample; - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + register float sample = gain * (SRC(0) + (SRC(1) - SRC(0)) + * current); + if (sample > 127.0f) + *(int8 *)dest = 127; + else if (sample < -127.0f) + *(int8 *)dest = -127; + else + *(int8 *)dest = (int8)sample; + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - register float sample = gain * (SRC(0) + (SRC((int)skipcount) - - SRC(0)) * offset); - if (sample > 127.0f) - *(int8 *)dest = 127; - else if (sample < -127.0f) - *(int8 *)dest = -127; - else - *(int8 *)dest = (int8)sample; - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } } @@ -516,44 +394,25 @@ return; } - register float delta = float(srcSampleCount) / float(destSampleCount); + register float delta = float(srcSampleCount - 1) / float(destSampleCount - 1); register float current = 0.0f; - if (delta < 1.0) { - // upsample - while (count--) { - register float sample = gain * (SRC(0) + (SRC(1) - SRC(0)) - * current); - if (sample > 255.0f) - *(uint8 *)dest = 255; - else if (sample < 1.0f) - *(uint8 *)dest = 1; - else - *(uint8 *)dest = (uint8)sample; - dest += destSampleOffset; - current += delta; - if (current >= 1.0f) { - current -= 1.0f; - src += srcSampleOffset; - } + while (count--) { + register float sample = gain * (SRC(0) + (SRC(1) - SRC(0)) + * current); + if (sample > 255.0f) + *(uint8 *)dest = 255; + else if (sample < 1.0f) + *(uint8 *)dest = 1; + else + *(uint8 *)dest = (uint8)sample; + dest += destSampleOffset; + current += delta; + if (current >= 1.0f) { + double ipart; + current = modf(current, &ipart); + src += srcSampleOffset * (int)ipart; } - } else { - // downsample - while (count--) { - double skipcount; - register float offset = modf(current, &skipcount); - register float sample = gain * (SRC(0) + (SRC((int)skipcount) - - SRC(0)) * offset) + 128.0f; - if (sample > 255.0f) - *(uint8 *)dest = 255; - else if (sample < 1.0f) - *(uint8 *)dest = 1; - else - *(uint8 *)dest = (uint8)sample; - dest += destSampleOffset; - current += delta - skipcount; - src += (int)skipcount * srcSampleOffset; - } } }