From d73b19b9b381b7d0e63da06689a7aaef1ce4aef3 Mon Sep 17 00:00:00 2001 From: Coen Rampen Date: Tue, 3 Aug 2021 21:49:46 +0200 Subject: [PATCH] AUDIO/MIDI: Fix Miles 3 AdLib pitch bend range Miles 2 uses the default MT-32 pitch bend range of 12 semitones for its AdLib driver. Miles 3 switched to the default GM pitch bend range of 2 semitones for AdLib. ScummVM would always use the Miles 2 pitch bend range, which caused pitch bend for Miles 3 games to sound wrong on AdLib. To fix this, a property was added to the Miles AdLib driver to specify which Miles version to emulate. Depending on the value of this option, the correct default pitch bend range is set. --- audio/miles.h | 10 +++++----- audio/miles_adlib.cpp | 34 ++++++++++++++++++++++++++++++++-- engines/saga/music.cpp | 4 +++- engines/saga2/music.cpp | 2 +- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/audio/miles.h b/audio/miles.h index 7a1d689f42b..7fb79da7bbe 100644 --- a/audio/miles.h +++ b/audio/miles.h @@ -86,6 +86,11 @@ namespace Audio { // volume of 256, so use this by default. #define MILES_DEFAULT_SOURCE_NEUTRAL_VOLUME 256 +enum MilesVersion { + MILES_VERSION_2 = 2, + MILES_VERSION_3 +}; + struct MilesMT32InstrumentEntry { byte bankId; byte patchId; @@ -118,11 +123,6 @@ public: class MidiDriver_Miles_Midi : public MidiDriver_MT32GM, public MidiDriver_Miles_Xmidi_Timbres { public: - enum MilesVersion { - MILES_VERSION_2 = 2, - MILES_VERSION_3 - }; - MidiDriver_Miles_Midi(MusicType midiType, MilesMT32InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount); ~MidiDriver_Miles_Midi(); diff --git a/audio/miles_adlib.cpp b/audio/miles_adlib.cpp index 23eddb9c39d..960f4e10775 100644 --- a/audio/miles_adlib.cpp +++ b/audio/miles_adlib.cpp @@ -138,6 +138,8 @@ public: void applySourceVolume(uint8 source) override; void deinitSource(uint8 source) override; + uint32 property(int prop, uint32 param) override; + void setVolume(byte volume); private: @@ -146,6 +148,9 @@ private: byte _modeVirtualFmVoicesCount; bool _modeStereo; + // the version of Miles AIL/MSS to emulate + MilesVersion _milesVersion; + // Structure to hold information about current status of MIDI Channels struct MidiChannelEntry { byte currentPatchBank; @@ -282,6 +287,9 @@ MidiDriver_Miles_AdLib::MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTableP _modePhysicalFmVoicesCount = 18; _modeStereo = true; + // Default to Miles v2 + _milesVersion = MILES_VERSION_2; + // Older Miles Audio drivers did not do a circular assign for physical FM-voices // Sherlock Holmes 2 used the circular assign circularPhysicalAssignment = true; @@ -349,9 +357,9 @@ void MidiDriver_Miles_AdLib::resetData() { _midiChannels[midiChannel].currentVolumeExpression = 127; // Miles Audio 2: hardcoded pitch range as a global (not channel specific), set to 12 - // Miles Audio 3: pitch range per MIDI channel + // Miles Audio 3: pitch range per MIDI channel; default 2 semitones _midiChannels[midiChannel].currentPitchBender = MIDI_PITCH_BEND_DEFAULT; - _midiChannels[midiChannel].currentPitchRange = 12; + _midiChannels[midiChannel].currentPitchRange = _milesVersion == MILES_VERSION_3 ? 2 : 12; } } @@ -448,6 +456,28 @@ void MidiDriver_Miles_AdLib::stopAllNotes(uint8 source, uint8 channel) { } } +uint32 MidiDriver_Miles_AdLib::property(int prop, uint32 param) { + switch (prop) { + case PROP_MILES_VERSION: + if (param == 0xFFFF) + return _milesVersion; + + switch (param) { + case MILES_VERSION_3: + _milesVersion = MILES_VERSION_3; + break; + case MILES_VERSION_2: + default: + _milesVersion = MILES_VERSION_2; + } + + break; + default: + return MidiDriver_Multisource::property(prop, param); + } + return 0; +} + void MidiDriver_Miles_AdLib::applySourceVolume(uint8 source) { if (!(source == 0 || source == 0xFF)) return; diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index d45194fe37c..7e62a0396ed 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -81,6 +81,8 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _par } } else { _driver = new MidiDriver_ADLIB_Multisource(OPL::Config::kOpl3); + _driver->property(MidiDriver::PROP_MILES_VERSION, _vm->getGameId() == GID_ITE ? + Audio::MILES_VERSION_2 : Audio::MILES_VERSION_3); } break; case MT_MT32: @@ -88,7 +90,7 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _par if (_vm->getPlatform() == Common::kPlatformDOS) { _driver = Audio::MidiDriver_Miles_MIDI_create(_musicType, ""); _driver->property(MidiDriver::PROP_MILES_VERSION, _vm->getGameId() == GID_ITE ? - Audio::MidiDriver_Miles_Midi::MILES_VERSION_2 : Audio::MidiDriver_Miles_Midi::MILES_VERSION_3); + Audio::MILES_VERSION_2 : Audio::MILES_VERSION_3); } else { _driver = new MidiDriver_MT32GM(_musicType); } diff --git a/engines/saga2/music.cpp b/engines/saga2/music.cpp index 1a92f62c8ea..5fcc3cafb30 100644 --- a/engines/saga2/music.cpp +++ b/engines/saga2/music.cpp @@ -59,7 +59,6 @@ Music::Music(hResContext *musicRes) : _musicContext(musicRes), _parser(0) { case MT_MT32: case MT_GM: _driver = Audio::MidiDriver_Miles_MIDI_create(_musicType, ""); - _driver->property(MidiDriver::PROP_MILES_VERSION, Audio::MidiDriver_Miles_Midi::MILES_VERSION_3); break; default: _driver = new MidiDriver_NULL_Multisource(); @@ -68,6 +67,7 @@ Music::Music(hResContext *musicRes) : _musicContext(musicRes), _parser(0) { if (_driver) { _driver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true); + _driver->property(MidiDriver::PROP_MILES_VERSION, Audio::MILES_VERSION_3); if (_driver->open() != 0) error("Failed to open MIDI driver.");