aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorFilippos Karapetis2010-11-25 16:09:45 +0000
committerFilippos Karapetis2010-11-25 16:09:45 +0000
commit601494cad4968ac2246a0c0820bfd9f01ec249ad (patch)
treebcdc4ed659d3296887cf4d066284334b5de70f07 /engines/sci
parent16006c78f5e64bbc7f012d1bf6c4a43bbe17ae31 (diff)
downloadscummvm-rg350-601494cad4968ac2246a0c0820bfd9f01ec249ad.tar.gz
scummvm-rg350-601494cad4968ac2246a0c0820bfd9f01ec249ad.tar.bz2
scummvm-rg350-601494cad4968ac2246a0c0820bfd9f01ec249ad.zip
SCI: implemented reverb handling and related functionality
svn-id: r54478
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/savegame.cpp1
-rw-r--r--engines/sci/sound/midiparser_sci.cpp83
-rw-r--r--engines/sci/sound/midiparser_sci.h1
-rw-r--r--engines/sci/sound/music.cpp28
-rw-r--r--engines/sci/sound/music.h7
-rw-r--r--engines/sci/sound/soundcmd.cpp1
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);