aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/resource.h1
-rw-r--r--engines/sci/resource_audio.cpp2
-rw-r--r--engines/sci/sound/drivers/midi.cpp47
-rw-r--r--engines/sci/sound/drivers/mididriver.h9
-rw-r--r--engines/sci/sound/midiparser_sci.cpp14
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;