diff options
author | Martin Kiewitz | 2009-12-24 11:42:37 +0000 |
---|---|---|
committer | Martin Kiewitz | 2009-12-24 11:42:37 +0000 |
commit | 8e3d34c8a007b719efea04a909fcd648f069c112 (patch) | |
tree | ec705f356bb16519f15694f14414ace42aab88f1 | |
parent | a55e0531e8ffae3e957f1f1e320b8bf5152f09db (diff) | |
download | scummvm-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.cpp | 20 | ||||
-rw-r--r-- | engines/sci/resource.h | 1 | ||||
-rw-r--r-- | engines/sci/sfx/music.cpp | 99 | ||||
-rw-r--r-- | engines/sci/sfx/music.h | 3 |
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; |