diff options
-rw-r--r-- | engines/sci/engine/savegame.cpp | 1 | ||||
-rw-r--r-- | engines/sci/sound/midiparser_sci.cpp | 83 | ||||
-rw-r--r-- | engines/sci/sound/midiparser_sci.h | 1 | ||||
-rw-r--r-- | engines/sci/sound/music.cpp | 28 | ||||
-rw-r--r-- | engines/sci/sound/music.h | 7 | ||||
-rw-r--r-- | engines/sci/sound/soundcmd.cpp | 1 |
6 files changed, 108 insertions, 13 deletions
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 0df6515483..8d941d38b9 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -601,6 +601,7 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { soundRes = 0; pMidiParser = 0; pStreamAud = 0; + reverb = -1; // invalid reverb, will be initialized in processInitSound() } } diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index ed6026932a..60fe1255b7 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -500,11 +500,16 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { // http://wiki.scummvm.org/index.php/SCI/Specifications/Sound/SCI0_Resource_Format#Status_Reference // Also, sci/sound/iterator/iterator.cpp, function BaseSongIterator::parseMidiCommand() switch (info.basic.param1) { - case kSetReverb: - // TODO: This should be the song's reverb, and we need to check it against - // the global one - if (info.basic.param2 != 127) // 127: SCI invalid, ignore - ((MidiPlayer *)_driver)->setReverb(info.basic.param2); + case kSetReverb: { + MidiPlayer *driver = ((MidiPlayer *)_driver); + if (info.basic.param2 == 127) { // Set global reverb instead + byte globalReverb = _music->getGlobalReverb(); + if (globalReverb != 127) + driver->setReverb(globalReverb); + } else { + driver->setReverb(info.basic.param2); + } + } break; case kMidiHold: // Check if the hold ID marker is the same as the hold ID @@ -627,6 +632,74 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { }// switch (info.command()) } +byte MidiParser_SCI::getSongReverb() { + byte curEvent = 0, prevEvent = 0, command = 0; + bool endOfTrack = false; + const byte *channelData = _mixedData; + + do { + while (*channelData == 0xF8) + channelData++; + + channelData++; // delta + + if ((*channelData & 0xF0) >= 0x80) + curEvent = *(channelData++); + else + curEvent = prevEvent; + if (curEvent < 0x80) + continue; + + prevEvent = curEvent; + command = curEvent >> 4; + + byte channel; + + switch (command) { + case 0xC: // program change + case 0xD: + channelData++; // param1 + break; + case 0xB: { + byte param1 = *channelData++; + byte param2 = *channelData++; + channel = curEvent & 0x0F; + if (channel == 0xF) { // SCI special + if (param1 == kSetReverb) + return param2; + } + } + break; + case 0x8: + case 0x9: + case 0xA: + case 0xE: + channelData++; // param1 + channelData++; // param2 + break; + case 0xF: + if ((curEvent & 0x0F) == 0x2) { + channelData++; // param1 + channelData++; // param2 + } else if ((curEvent & 0x0F) == 0x3) { + channelData++; // param1 + } else if ((curEvent & 0x0F) == 0xF) { // META + byte type = *channelData++; + if (type == 0x2F) {// end of track reached + endOfTrack = true; + } else { + // no further processing necessary + } + } + break; + default: + break; + } + } while (!endOfTrack); + + return 127; // no reverb found, return invalid +} + void MidiParser_SCI::allNotesOff() { if (!_driver) return; diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 9d0cb15e74..fa24a209e4 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -80,6 +80,7 @@ public: void allNotesOff(); const byte *getMixedData() const { return _mixedData; } + byte getSongReverb(); void tryToOwnChannels(); void lostChannels(); diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 443f743ee6..ad6a869ccc 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -39,7 +39,7 @@ namespace Sci { SciMusic::SciMusic(SciVersion soundVersion) - : _soundVersion(soundVersion), _soundOn(true), _masterVolume(0) { + : _soundVersion(soundVersion), _soundOn(true), _masterVolume(0), _globalReverb(-1) { // Reserve some space in the playlist, to avoid expensive insertion // operations @@ -225,15 +225,30 @@ MusicEntry *SciMusic::getActiveSci0MusicSlot() { return highestPrioritySlot; } -void SciMusic::setGlobalReverb(byte reverb) { +void SciMusic::setGlobalReverb(int8 reverb) { Common::StackLock lock(_mutex); if (reverb != 127) { // Set global reverb normally - // TODO: Set global music reverb - // TODO: Only set reverb when the reverb of the active song is 127 - _pMidiDrv->setReverb(reverb); + _globalReverb = reverb; + + // Check the reverb of the active song... + const MusicList::iterator end = _playList.end(); + for (MusicList::iterator i = _playList.begin(); i != end; ++i) { + if ((*i)->status == kSoundPlaying) { + if ((*i)->reverb == 127) // Active song has no reverb + _pMidiDrv->setReverb(reverb); // Set the global reverb + break; + } + } } else { - // TODO: Set reverb of the active song + // Set reverb of the active song + const MusicList::iterator end = _playList.end(); + for (MusicList::iterator i = _playList.begin(); i != end; ++i) { + if ((*i)->status == kSoundPlaying) { + _pMidiDrv->setReverb((*i)->reverb); // Set the song's reverb + break; + } + } } } @@ -300,6 +315,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); + pSnd->reverb = pSnd->pMidiParser->getSongReverb(); pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); } diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index c29a8456b5..f735fcd6c5 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -76,7 +76,7 @@ public: uint16 loop; int16 volume; int16 hold; - int16 reverb; + int8 reverb; int16 pauseCounter; uint sampleLoopCounter; @@ -188,7 +188,9 @@ public: void sendMidiCommand(uint32 cmd); void sendMidiCommand(MusicEntry *pSnd, uint32 cmd); - void setGlobalReverb(byte reverb); + void setGlobalReverb(int8 reverb); + int8 getGlobalReverb() { return _globalReverb; } + byte getCurrentReverb(); virtual void saveLoadWithSerializer(Common::Serializer &ser); @@ -220,6 +222,7 @@ private: bool _soundOn; byte _masterVolume; MusicEntry *_usedChannel[16]; + int8 _globalReverb; MidiCommandQueue _queuedCommands; MusicType _musicType; diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 3592f736ea..863fe6c33a 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -75,6 +75,7 @@ void SoundCommandParser::processInitSound(reg_t obj) { newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(pri)) & 0xFF; if (_soundVersion >= SCI_VERSION_1_EARLY) newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX); + newSound->reverb = -1; // initialize to SCI invalid, it'll be set correctly in soundInitSnd() below debugC(2, kDebugLevelSound, "kDoSound(init): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), resourceId, newSound->loop, newSound->priority, newSound->volume); |