From 61215fd53d586e92b87522b9940a63a400cc8234 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 16 Jul 2011 09:15:21 +0000 Subject: [PATCH] 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. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42435 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../media/media-add-ons/mixer/Interpolate.cpp | 359 ++++++------------ 1 file changed, 109 insertions(+), 250 deletions(-) diff --git a/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp b/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp index c2c0c9b298..8fe9b71373 100644 --- a/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp +++ b/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp @@ -44,32 +44,19 @@ Interpolate::float_to_float(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } } @@ -95,33 +82,20 @@ Interpolate::int32_to_float(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } } @@ -147,33 +121,20 @@ Interpolate::int16_to_float(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } } @@ -199,33 +160,20 @@ Interpolate::int8_to_float(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } } @@ -251,33 +199,20 @@ Interpolate::uint8_to_float(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } } @@ -309,46 +244,27 @@ Interpolate::float_to_int32(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } } @@ -380,43 +296,24 @@ Interpolate::float_to_int16(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } } @@ -448,43 +345,24 @@ Interpolate::float_to_int8(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } } @@ -516,43 +394,24 @@ Interpolate::float_to_uint8(const void *_src, int32 srcSampleOffset, 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; - } - } - } 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; + 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; } } }