From 96c4ebe77fff9f23e085bb80a4907e6f857a96c2 Mon Sep 17 00:00:00 2001 From: countingpine Date: Tue, 16 Jul 2013 16:16:08 +0100 Subject: SCUMM: Better Player_Mac::durationToSamples Uses the fact that 4*480*480 == 225 << 12, and the identity (a*b)>>n == (a>>n)*b + ((a%(1<>n (assuming non-overflowing math), except the rhs uses smaller intermediate values and does not overflow(*). Compared to the original code, this uses 1 fewer division and eliminates the rounding error. (*) Technical note: In some cases the right hand side of the above identity still has possibilities of intermediate overflow, but only if b > (1 << n), or if (b << n) overflows, neither of which are true here.--- engines/scumm/player_mac.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'engines/scumm') diff --git a/engines/scumm/player_mac.cpp b/engines/scumm/player_mac.cpp index c16c85bff3..a60736df5e 100644 --- a/engines/scumm/player_mac.cpp +++ b/engines/scumm/player_mac.cpp @@ -289,12 +289,16 @@ uint32 Player_Mac::durationToSamples(uint16 duration) { // (duration * 473 * _sampleRate) / (4 * 480 * 480) // // But that's likely to cause integer overflow, so we do it in two - // steps and hope that the rounding error won't be noticeable. + // steps using bitwise operations to perform + // ((duration * 473 * _sampleRate) / 4096) without overflowing, + // then divide this by 225 + // (note that 4 * 480 * 480 == 225 * 4096 == 225 << 12) // // The original code is a bit unclear on if it should be 473 or 437, // but since the comments indicated 473 I'm assuming 437 was a typo. - uint32 samples = (duration * _sampleRate) / (4 * 480); - samples = (samples * 473) / 480; + uint32 samples = (duration * _sampleRate); + samples = (samples >> 12) * 473 + (((samples & 4095) * 473) >> 12); + samples = samples / 225; return samples; } -- cgit v1.2.3