From d1b64aab0cd1477f6d56c9ced8b84886d66de4d8 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 14 Jul 2019 20:44:25 +0200 Subject: SCUMM: (iMuse/Amiga) - improve accuracy This fixes the issue that some rhythm instruments didn't receive correct notes. The changes have been limited to the Amiga versions. --- engines/scumm/imuse/imuse.cpp | 5 +++++ engines/scumm/imuse/imuse.h | 1 + engines/scumm/imuse/imuse_internal.h | 2 ++ engines/scumm/imuse/imuse_part.cpp | 33 ++++++++++++++++++++++++++++++--- engines/scumm/scumm.cpp | 2 ++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index ad921e47a9..37a0465153 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -45,6 +45,7 @@ namespace Scumm { IMuseInternal::IMuseInternal() : _native_mt32(false), _enable_gs(false), + _isAmiga(false), _midi_adlib(NULL), _midi_native(NULL), _sysex(NULL), @@ -481,6 +482,10 @@ uint32 IMuseInternal::property(int prop, uint32 value) { } break; + case IMuse::PROP_AMIGA: + _isAmiga = (value > 0); + break; + case IMuse::PROP_LIMIT_PLAYERS: if (value > 0 && value <= ARRAYSIZE(_players)) _player_limit = (int)value; diff --git a/engines/scumm/imuse/imuse.h b/engines/scumm/imuse/imuse.h index a30d3db8b2..7b2fb81967 100644 --- a/engines/scumm/imuse/imuse.h +++ b/engines/scumm/imuse/imuse.h @@ -53,6 +53,7 @@ public: PROP_TEMPO_BASE, PROP_NATIVE_MT32, PROP_GS, + PROP_AMIGA, PROP_LIMIT_PLAYERS, PROP_RECYCLE_PLAYERS, PROP_GAME_ID, diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h index 7aff68ae76..4b9b7502b7 100644 --- a/engines/scumm/imuse/imuse_internal.h +++ b/engines/scumm/imuse/imuse_internal.h @@ -372,6 +372,7 @@ struct Part : public Common::Serializable { private: void sendPitchBend(); + void sendTranspose(); void sendPanPosition(uint8 value); void sendEffectLevel(uint8 value); }; @@ -399,6 +400,7 @@ class IMuseInternal : public IMuse { protected: bool _native_mt32; bool _enable_gs; + bool _isAmiga; MidiDriver *_midi_adlib; MidiDriver *_midi_native; TimerCallbackInfo _timer_info_adlib; diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp index 33492a1363..1614076ee0 100644 --- a/engines/scumm/imuse/imuse_part.cpp +++ b/engines/scumm/imuse/imuse_part.cpp @@ -145,8 +145,17 @@ void Part::set_pan(int8 pan) { void Part::set_transpose(int8 transpose) { _transpose = transpose; - _transpose_eff = (_transpose == -128) ? 0 : transpose_clamp(_transpose + _player->getTranspose(), -24, 24); - sendPitchBend(); + + if (_se->_isAmiga) { + // The Amiga version does a check like this. While this is probably a bug (a signed int8 can never be 128), + // the playback depends on this being implemented exactly like in the original driver. I found this bug with + // the WinUAE debugger. I don't know whether this is an Amiga only thing... + _transpose_eff = /*(_transpose == 128) ? 0 : */transpose_clamp(_transpose + _player->getTranspose(), -12, 12); + sendTranspose(); + } else { + _transpose_eff = (_transpose == -128) ? 0 : transpose_clamp(_transpose + _player->getTranspose(), -24, 24); + sendPitchBend(); + } } void Part::sustain(bool value) { @@ -332,6 +341,7 @@ void Part::sendAll() { return; _mc->pitchBendFactor(_pitchbend_factor); + sendTranspose(); sendPitchBend(); _mc->volume(_vol_eff); _mc->sustain(_pedal); @@ -358,7 +368,24 @@ void Part::sendPitchBend() { // so we'll do the scaling ourselves. if (_player->_se->isNativeMT32()) bend = bend * _pitchbend_factor / 12; - _mc->pitchBend(clamp(bend + (_detune_eff * 64 / 12) + (_transpose_eff * 8192 / 12), -8192, 8191)); + + // We send the transpose value separately for Amiga (which is more like the original handles this). + // Some rhythm instruments depend on this. + int8 transpose = _se->_isAmiga ? 0 : _transpose_eff; + _mc->pitchBend(clamp(bend + (_detune_eff * 64 / 12) + (transpose * 8192 / 12), -8192, 8191)); +} + +void Part::sendTranspose() { + if (!_mc) + return; + + // See comment above. The transpose function was never implemented into our other drivers, + // since this seems to have been handled via pitchBend() instead. The original drivers do have + // such functions. + if (!_se->_isAmiga) + return; + + _mc->transpose(_transpose_eff); } void Part::programChange(byte value) { diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index f6e0f9ede6..64f45c1b98 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -2039,6 +2039,8 @@ void ScummEngine::setupMusic(int midi) { } if (_sound->_musicType == MDT_PCSPK) _imuse->property(IMuse::PROP_PC_SPEAKER, 1); + if (_sound->_musicType == MDT_AMIGA) + _imuse->property(IMuse::PROP_AMIGA, 1); } } } -- cgit v1.2.3