aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcountingpine2013-07-16 16:16:08 +0100
committercountingpine2013-07-16 16:16:08 +0100
commit96c4ebe77fff9f23e085bb80a4907e6f857a96c2 (patch)
tree789a1a0ef419d812b9868dde1383e976b7abe83e
parent3d373281b440d5d139fbb01ef1ffa0ad0a76b3e8 (diff)
downloadscummvm-rg350-96c4ebe77fff9f23e085bb80a4907e6f857a96c2.tar.gz
scummvm-rg350-96c4ebe77fff9f23e085bb80a4907e6f857a96c2.tar.bz2
scummvm-rg350-96c4ebe77fff9f23e085bb80a4907e6f857a96c2.zip
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))*b)>>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.
-rw-r--r--engines/scumm/player_mac.cpp10
1 files changed, 7 insertions, 3 deletions
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;
}