diff options
author | countingpine | 2013-07-16 16:16:08 +0100 |
---|---|---|
committer | countingpine | 2013-07-16 16:16:08 +0100 |
commit | 96c4ebe77fff9f23e085bb80a4907e6f857a96c2 (patch) | |
tree | 789a1a0ef419d812b9868dde1383e976b7abe83e | |
parent | 3d373281b440d5d139fbb01ef1ffa0ad0a76b3e8 (diff) | |
download | scummvm-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.cpp | 10 |
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; } |