aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kiewitz2009-12-24 11:42:37 +0000
committerMartin Kiewitz2009-12-24 11:42:37 +0000
commit8e3d34c8a007b719efea04a909fcd648f069c112 (patch)
treeec705f356bb16519f15694f14414ace42aab88f1
parenta55e0531e8ffae3e957f1f1e320b8bf5152f09db (diff)
downloadscummvm-rg350-8e3d34c8a007b719efea04a909fcd648f069c112.tar.gz
scummvm-rg350-8e3d34c8a007b719efea04a909fcd648f069c112.tar.bz2
scummvm-rg350-8e3d34c8a007b719efea04a909fcd648f069c112.zip
SCI: channels are now filtered for sci0 (fixes garbled music)
svn-id: r46525
-rw-r--r--engines/sci/resource.cpp20
-rw-r--r--engines/sci/resource.h1
-rw-r--r--engines/sci/sfx/music.cpp99
-rw-r--r--engines/sci/sfx/music.h3
4 files changed, 119 insertions, 4 deletions
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 7a9cfc24c1..33da5a4427 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -1926,4 +1926,24 @@ SoundResource::Track* SoundResource::getTrackByType(TrackType type) {
return NULL;
}
+// Gets the filter-mask for SCI0 sound resources
+int SoundResource::getChannelFilterMask(int hardwareMask) {
+ byte *data = _innerResource->data;
+ int channelMask = 0;
+
+ if (_soundVersion == SCI_VERSION_0_EARLY) {
+ data++; // Skip over digital sample flag
+ for (int channelNr = 0; channelNr < 16; channelNr++) {
+ data++;
+ channelMask = channelMask >> 1;
+ if (*data & hardwareMask) {
+ // this Channel is supposed to get played for hardware
+ channelMask |= 0x8000;
+ }
+ data++;
+ }
+ }
+ return channelMask;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index f857b6ab30..ab66fa4ac6 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -459,6 +459,7 @@ public:
~SoundResource();
Track *getTrackByNumber(uint16 number);
Track *getTrackByType(TrackType type);
+ int getChannelFilterMask(int hardwareMask);
private:
SciVersion _soundVersion;
diff --git a/engines/sci/sfx/music.cpp b/engines/sci/sfx/music.cpp
index 66b5acfda7..e0628abe28 100644
--- a/engines/sci/sfx/music.cpp
+++ b/engines/sci/sfx/music.cpp
@@ -283,6 +283,7 @@ void SciMusic::loadPatchMT32() {
//----------------------------------------
void SciMusic::soundInitSnd(MusicEntry *pSnd) {
SoundResource::Track *track = NULL;
+ int channelFilterMask = 0;
//_mutex.lock();
switch (_midiType) {
@@ -331,7 +332,9 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
pSnd->pMidiParser->setMidiDriver(_pMidiDrv);
pSnd->pMidiParser->setTimerRate(_dwTempo);
}
- pSnd->pMidiParser->loadMusic(track, pSnd);
+ // Find out what channels to filter for SCI0
+ channelFilterMask = pSnd->soundRes->getChannelFilterMask(0x04); // Adlib hardcoded (TODO)
+ pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask);
}
}
@@ -493,12 +496,18 @@ MidiParser_SCI::~MidiParser_SCI() {
unloadMusic();
}
//---------------------------------------------
-bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd) {
+bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask) {
unloadMusic();
_track = track;
_pSnd = psnd;
setVolume(psnd->volume);
- midiMixChannels();
+
+ if (channelFilterMask) {
+ // SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection
+ midiFilterChannels(channelFilterMask);
+ } else {
+ midiMixChannels();
+ }
_num_tracks = 1;
_tracks[0] = _mixedData;
@@ -722,6 +731,90 @@ byte *MidiParser_SCI::midiMixChannels() {
return _mixedData;
}
+// This is used for SCI0 sound-data. SCI0 only has one stream that may contain several channels and according to output
+// device we remove certain channels from that data
+byte *MidiParser_SCI::midiFilterChannels(int channelMask) {
+ SoundResource::Channel *channel = &_track->channels[0];
+ byte *channelData = channel->data;
+ byte *channelDataEnd = channel->data + channel->size;
+ byte *filterData = new byte[channel->size];
+ byte curChannel, curByte;
+ byte command, lastCommand;
+ int delta = 0;
+ int dataLeft = channel->size;
+ int midiParamCount;
+
+ _mixedData = filterData;
+ lastCommand = 0;
+
+ // Find out which channels to filter out
+
+ while (channelData <= channelDataEnd) {
+ delta += *channelData++;
+ curByte = *channelData++;
+
+ switch (curByte) {
+ case 0xF0: // sysEx
+ case 0xFC: // end of channel
+ curChannel = 15;
+ break;
+ default:
+ if (curByte & 0x80) {
+ command = curByte;
+ curChannel = command & 0x0F;
+ midiParamCount = nMidiParams[(command >> 4) - 8];
+ }
+ }
+ if ((1 << curChannel) & channelMask) {
+ if (command != 0xFC) {
+ // Write delta
+ while (delta > 240) {
+ *filterData++ = 0xF8;
+ delta -= 240;
+ }
+ *filterData++ = (byte)delta;
+ delta = 0;
+ }
+ // Write command
+ switch (command) {
+ case 0xF0: // sysEx
+ *filterData++ = command;
+ do {
+ curByte = *channelData++;
+ *filterData++ = curByte; // out
+ } while (curByte != 0xF7);
+ break;
+
+ case 0xFC: // end of channel
+ *filterData++ = command;
+ break;
+
+ default: // MIDI command
+ if (curByte & 0x80) {
+ if (lastCommand != command) {
+ *filterData++ = command;
+ }
+ if (midiParamCount > 0)
+ *filterData++ = *channelData++;
+ } else {
+ *filterData++ = curByte;
+ }
+ if (midiParamCount > 1)
+ *filterData++ = *channelData++;
+ }
+ } else {
+ if (curByte & 0x80) {
+ channelData += midiParamCount;
+ } else {
+ channelData += midiParamCount - 1;
+ }
+ }
+ lastCommand = command;
+ }
+
+ return _mixedData;
+}
+
void MidiParser_SCI::setVolume(byte bVolume) {
if (bVolume > 0x7F)
bVolume = 0x7F;
diff --git a/engines/sci/sfx/music.h b/engines/sci/sfx/music.h
index 057bd21cf8..5e9d477453 100644
--- a/engines/sci/sfx/music.h
+++ b/engines/sci/sfx/music.h
@@ -163,7 +163,7 @@ class MidiParser_SCI : public MidiParser {
public:
MidiParser_SCI();
~MidiParser_SCI();
- bool loadMusic(SoundResource::Track *track, MusicEntry *psnd);
+ bool loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask);
bool loadMusic(byte *, uint32) {
return false;
}
@@ -179,6 +179,7 @@ public:
protected:
void parseNextEvent(EventInfo &info);
byte *midiMixChannels();
+ byte *midiFilterChannels(int channelMask);
byte midiGetNextChannel(long ticker);
byte *_mixedData;
SoundResource::Track *_track;