diff options
-rw-r--r-- | engines/sci/resource.h | 1 | ||||
-rw-r--r-- | engines/sci/resource_audio.cpp | 2 | ||||
-rw-r--r-- | engines/sci/sound/drivers/midi.cpp | 47 | ||||
-rw-r--r-- | engines/sci/sound/drivers/mididriver.h | 9 | ||||
-rw-r--r-- | engines/sci/sound/midiparser_sci.cpp | 14 |
5 files changed, 53 insertions, 20 deletions
diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 9fc9708e74..119d8600b0 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -654,6 +654,7 @@ public: struct Track { byte type; byte channelCount; + SciSpan<const byte> header; Channel *channels; int16 digitalChannelNr; uint16 digitalSampleRate; diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index dfc3d2fcfb..58437a653f 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -766,6 +766,8 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers // Digital sample data included? -> Add an additional channel if (resource->getUint8At(0) == 2) _tracks->channelCount++; + // header information that can be passed to the SCI0 sound driver + _tracks->header = resource->subspan(0, _soundVersion == SCI_VERSION_0_EARLY ? 0x11 : 0x21); _tracks->channels = new Channel[_tracks->channelCount]; channel = &_tracks->channels[0]; channel->flags |= 2; // don't remap (SCI0 doesn't have remapping) diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp index 889a875804..4f3f0da4b0 100644 --- a/engines/sci/sound/drivers/midi.cpp +++ b/engines/sci/sound/drivers/midi.cpp @@ -158,10 +158,10 @@ public: int getFirstChannel() const override; int getLastChannel() const override; void setVolume(byte volume) override; - virtual void onNewSound() override; int getVolume() override; void setReverb(int8 reverb) override; void playSwitch(bool play) override; + virtual void initTrack(SciSpan<const byte> &) override; private: bool isMt32GmPatch(const SciSpan<const byte> &data); @@ -479,14 +479,6 @@ int MidiPlayer_Midi::getVolume() { return _masterVolume; } -void MidiPlayer_Midi::onNewSound() { - if (_defaultReverb >= 0) - // SCI0 in combination with MT-32 requires a reset of the reverb to - // the default value that is present in either the MT-32 patch data - // or MT32.DRV itself. - setReverb(_defaultReverb); -} - void MidiPlayer_Midi::setReverb(int8 reverb) { assert(reverb < kReverbConfigNr); @@ -507,6 +499,43 @@ void MidiPlayer_Midi::playSwitch(bool play) { } } +void MidiPlayer_Midi::initTrack(SciSpan<const byte> &header) { + if (_version > SCI_VERSION_0_LATE) + return; + + if (_defaultReverb >= 0) + // SCI0 in combination with MT-32 requires a reset of the reverb to + // the default value that is present in either the MT-32 patch data + // or MT32.DRV itself. + setReverb(_defaultReverb); + + /* TODO: I have no idea what SCI_VERSION_0_EARLY games do here. + Therefore the extra code is restricted to SCI_VERSION_0_LATE for now.*/ + if (_version == SCI_VERSION_0_EARLY) + return; + + uint8 caps = header.getInt8At(0); + if (caps != 0 && caps != 2) + return; + + uint8 readPos = 3; + byte msg[9]; + uint8 flags = 0; + + for (int i = 1; i < 9; ++i) { + readPos++; + flags = header.getInt8At(readPos++); + msg[i - 1] = (flags & 1) ? i : 0x10; + } + + flags = header.getInt8At(readPos); + msg[8] = (flags & 0x80) ? 9 : 0x10; + + // assign channels + Sci::SciSpan<const byte> s(msg, 9); + sendMt32SysEx(0x10000D, s, false); +} + bool MidiPlayer_Midi::isMt32GmPatch(const SciSpan<const byte> &data) { uint32 size = data.size(); diff --git a/engines/sci/sound/drivers/mididriver.h b/engines/sci/sound/drivers/mididriver.h index f51851bde6..73c2fd5737 100644 --- a/engines/sci/sound/drivers/mididriver.h +++ b/engines/sci/sound/drivers/mididriver.h @@ -24,6 +24,7 @@ #define SCI_SFX_SOFTSEQ_MIDIDRIVER_H #include "sci/sci.h" +#include "sci/util.h" #include "audio/mididrv.h" #include "common/error.h" @@ -106,8 +107,6 @@ public: return _driver ? _driver->property(MIDI_PROP_MASTER_VOLUME, 0xffff) : 0; } - virtual void onNewSound() {} - // Returns the current reverb, or -1 when no reverb is active int8 getReverb() const { return _reverb; } // Sets the current reverb, used mainly in MT-32 @@ -121,6 +120,12 @@ public: } } + // Prepares the driver for the playback of SCI0 midi tracks. + // The main purpose is the assignment of voices ("hardware" sound channels) to the 16 midi parts. + // This is basically the predecessor of the 0x4B midi event. + // Some drivers also do other things in here. + virtual void initTrack(SciSpan<const byte> &) {} + protected: SciVersion _version; }; diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index ad4b0da397..22a5c6de9c 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -392,15 +392,11 @@ void MidiParser_SCI::sendInitCommands() { // Set initial voice count if (_pSnd) { if (_soundVersion <= SCI_VERSION_0_LATE) { - static_cast<MidiPlayer *>(_driver)->onNewSound(); - - for (int i = 0; i < 15; ++i) { - byte voiceCount = 0; - if (_channelUsed[i]) { - voiceCount = _pSnd->soundRes->getInitialVoiceCount(i); - sendToDriver(0xB0 | i, 0x4B, voiceCount); - } - } + // Send header data to SCI0 sound drivers. The driver function which parses the header (opcode 3) + // seems to be implemented at least in all SCI0_LATE drivers. The things that the individual drivers + // do in that init function varies. + if (_track->header.byteSize()) + static_cast<MidiPlayer *>(_driver)->initTrack(_track->header); } else { for (int i = 0; i < _track->channelCount; ++i) { byte voiceCount = _track->channels[i].poly; |