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.
This commit is contained in:
Coen Rampen 2021-08-03 21:49:46 +02:00
parent c0c5330986
commit d73b19b9b3
4 changed files with 41 additions and 9 deletions

View file

@ -86,6 +86,11 @@ namespace Audio {
// volume of 256, so use this by default. // volume of 256, so use this by default.
#define MILES_DEFAULT_SOURCE_NEUTRAL_VOLUME 256 #define MILES_DEFAULT_SOURCE_NEUTRAL_VOLUME 256
enum MilesVersion {
MILES_VERSION_2 = 2,
MILES_VERSION_3
};
struct MilesMT32InstrumentEntry { struct MilesMT32InstrumentEntry {
byte bankId; byte bankId;
byte patchId; byte patchId;
@ -118,11 +123,6 @@ public:
class MidiDriver_Miles_Midi : public MidiDriver_MT32GM, public MidiDriver_Miles_Xmidi_Timbres { class MidiDriver_Miles_Midi : public MidiDriver_MT32GM, public MidiDriver_Miles_Xmidi_Timbres {
public: public:
enum MilesVersion {
MILES_VERSION_2 = 2,
MILES_VERSION_3
};
MidiDriver_Miles_Midi(MusicType midiType, MilesMT32InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount); MidiDriver_Miles_Midi(MusicType midiType, MilesMT32InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount);
~MidiDriver_Miles_Midi(); ~MidiDriver_Miles_Midi();

View file

@ -138,6 +138,8 @@ public:
void applySourceVolume(uint8 source) override; void applySourceVolume(uint8 source) override;
void deinitSource(uint8 source) override; void deinitSource(uint8 source) override;
uint32 property(int prop, uint32 param) override;
void setVolume(byte volume); void setVolume(byte volume);
private: private:
@ -146,6 +148,9 @@ private:
byte _modeVirtualFmVoicesCount; byte _modeVirtualFmVoicesCount;
bool _modeStereo; bool _modeStereo;
// the version of Miles AIL/MSS to emulate
MilesVersion _milesVersion;
// Structure to hold information about current status of MIDI Channels // Structure to hold information about current status of MIDI Channels
struct MidiChannelEntry { struct MidiChannelEntry {
byte currentPatchBank; byte currentPatchBank;
@ -282,6 +287,9 @@ MidiDriver_Miles_AdLib::MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTableP
_modePhysicalFmVoicesCount = 18; _modePhysicalFmVoicesCount = 18;
_modeStereo = true; _modeStereo = true;
// Default to Miles v2
_milesVersion = MILES_VERSION_2;
// Older Miles Audio drivers did not do a circular assign for physical FM-voices // Older Miles Audio drivers did not do a circular assign for physical FM-voices
// Sherlock Holmes 2 used the circular assign // Sherlock Holmes 2 used the circular assign
circularPhysicalAssignment = true; circularPhysicalAssignment = true;
@ -349,9 +357,9 @@ void MidiDriver_Miles_AdLib::resetData() {
_midiChannels[midiChannel].currentVolumeExpression = 127; _midiChannels[midiChannel].currentVolumeExpression = 127;
// Miles Audio 2: hardcoded pitch range as a global (not channel specific), set to 12 // 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].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) { void MidiDriver_Miles_AdLib::applySourceVolume(uint8 source) {
if (!(source == 0 || source == 0xFF)) if (!(source == 0 || source == 0xFF))
return; return;

View file

@ -81,6 +81,8 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _par
} }
} else { } else {
_driver = new MidiDriver_ADLIB_Multisource(OPL::Config::kOpl3); _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; break;
case MT_MT32: case MT_MT32:
@ -88,7 +90,7 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _par
if (_vm->getPlatform() == Common::kPlatformDOS) { if (_vm->getPlatform() == Common::kPlatformDOS) {
_driver = Audio::MidiDriver_Miles_MIDI_create(_musicType, ""); _driver = Audio::MidiDriver_Miles_MIDI_create(_musicType, "");
_driver->property(MidiDriver::PROP_MILES_VERSION, _vm->getGameId() == GID_ITE ? _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 { } else {
_driver = new MidiDriver_MT32GM(_musicType); _driver = new MidiDriver_MT32GM(_musicType);
} }

View file

@ -59,7 +59,6 @@ Music::Music(hResContext *musicRes) : _musicContext(musicRes), _parser(0) {
case MT_MT32: case MT_MT32:
case MT_GM: case MT_GM:
_driver = Audio::MidiDriver_Miles_MIDI_create(_musicType, ""); _driver = Audio::MidiDriver_Miles_MIDI_create(_musicType, "");
_driver->property(MidiDriver::PROP_MILES_VERSION, Audio::MidiDriver_Miles_Midi::MILES_VERSION_3);
break; break;
default: default:
_driver = new MidiDriver_NULL_Multisource(); _driver = new MidiDriver_NULL_Multisource();
@ -68,6 +67,7 @@ Music::Music(hResContext *musicRes) : _musicContext(musicRes), _parser(0) {
if (_driver) { if (_driver) {
_driver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true); _driver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true);
_driver->property(MidiDriver::PROP_MILES_VERSION, Audio::MILES_VERSION_3);
if (_driver->open() != 0) if (_driver->open() != 0)
error("Failed to open MIDI driver."); error("Failed to open MIDI driver.");