aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO3
-rw-r--r--dists/msvc7/scumm.vcproj10
-rw-r--r--scumm/imuse_digi/dimuse.cpp538
-rw-r--r--scumm/imuse_digi/dimuse.h28
-rw-r--r--scumm/imuse_digi/dimuse_music.cpp16
-rw-r--r--scumm/imuse_digi/dimuse_script.cpp363
-rw-r--r--scumm/imuse_digi/dimuse_sndmgr.cpp223
-rw-r--r--scumm/imuse_digi/dimuse_sndmgr.h43
-rw-r--r--scumm/imuse_digi/dimuse_track.cpp242
-rw-r--r--scumm/module.mk2
10 files changed, 805 insertions, 663 deletions
diff --git a/TODO b/TODO
index fd626d3848..16755f42aa 100644
--- a/TODO
+++ b/TODO
@@ -255,9 +255,6 @@ SCUMM
on small devices
* Fix codec44 for nut fonts
* iMUSE Digital:
- - Cleanup startSound code
- - Make struct sync, jump, regions use dynamic memory usage
- - Add pool method for FT voc samples from resource
- Fix music code
- Recheck 'next region' code
- Implement pool method data transfer between imuse and sound mixer
diff --git a/dists/msvc7/scumm.vcproj b/dists/msvc7/scumm.vcproj
index 4566e52cc8..58bb914518 100644
--- a/dists/msvc7/scumm.vcproj
+++ b/dists/msvc7/scumm.vcproj
@@ -176,6 +176,9 @@
RelativePath="..\..\scumm\imuse_digi\dimuse_music.cpp">
</File>
<File
+ RelativePath="..\..\scumm\imuse_digi\dimuse_script.cpp">
+ </File>
+ <File
RelativePath="..\..\scumm\imuse_digi\dimuse_sndmgr.cpp">
</File>
<File
@@ -184,6 +187,9 @@
<File
RelativePath="..\..\scumm\imuse_digi\dimuse_tables.cpp">
</File>
+ <File
+ RelativePath="..\..\scumm\imuse_digi\dimuse_track.cpp">
+ </File>
</Filter>
<Filter
Name="insane"
@@ -403,10 +409,10 @@
RelativePath="..\..\scumm\scumm-md5.h">
</File>
<File
- RelativePath="..\..\scumm\scumm.h">
+ RelativePath="..\..\scumm\scumm.cpp">
</File>
<File
- RelativePath="..\..\scumm\scumm.cpp">
+ RelativePath="..\..\scumm\scumm.h">
</File>
<File
RelativePath="..\..\scumm\sound.cpp">
diff --git a/scumm/imuse_digi/dimuse.cpp b/scumm/imuse_digi/dimuse.cpp
index 97628c1598..3a1700c25b 100644
--- a/scumm/imuse_digi/dimuse.cpp
+++ b/scumm/imuse_digi/dimuse.cpp
@@ -71,18 +71,6 @@ void IMuseDigital::resetState() {
_curSeqAtribPos = 0;
}
-void IMuseDigital::setGroupVoiceVolume(int volume) {
- _volVoice = volume;
-}
-
-void IMuseDigital::setGroupMusicVolume(int volume) {
- _volMusic = volume;
-}
-
-void IMuseDigital::setGroupSfxVolume(int volume) {
- _volSfx = volume;
-}
-
void IMuseDigital::callback() {
Common::StackLock lock(_mutex, "IMuseDigital::callback()");
int l = 0;
@@ -138,11 +126,11 @@ void IMuseDigital::callback() {
int pan = (_track[l].pan != 64) ? 2 * _track[l].pan - 127 : 0;
int vol = _track[l].vol / 1000;
- if (_track[l].soundGroup == 1)
+ if (_track[l].volGroupId == 1)
vol = (vol * _volVoice) / 128;
- if (_track[l].soundGroup == 2)
+ if (_track[l].volGroupId == 2)
vol = (vol * _volSfx) / 128;
- if (_track[l].soundGroup == 3)
+ if (_track[l].volGroupId == 3)
vol = (vol * _volMusic) / 128;
if (_vm->_mixer->isReady()) {
@@ -257,524 +245,4 @@ void IMuseDigital::switchToNextRegion(int track) {
_track[track].regionOffset = 0;
}
-void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, int soundGroup, AudioStream *input, int hookId, int volume, int priority) {
- Common::StackLock lock(_mutex, "IMuseDigital::startSound()");
- debug(5, "IMuseDigital::startSound(%d)", soundId);
- int l;
- int lower_priority = 127;
- bool found_free = false;
-
- for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if (!_track[l].used && !_track[l].handle.isActive())
- found_free = true;
- }
-
- if (!found_free) {
- warning("IMuseDigital::startSound(): All slots are full");
- for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if (_track[l].used && _track[l].handle.isActive() &&
- (lower_priority > _track[l].priority) && (!_track[l].stream2))
- lower_priority = _track[l].priority;
- }
- if (lower_priority <= priority) {
- int track_id = -1;
- for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if (_track[l].used && _track[l].handle.isActive() &&
- (lower_priority == _track[l].priority) && (!_track[l].stream2)) {
- track_id = l;
- }
- }
- assert(track_id != -1);
- _track[track_id].stream->finish();
- _track[track_id].stream = NULL;
- _vm->_mixer->stopHandle(_track[track_id].handle);
- _sound->closeSound(_track[track_id].soundHandle);
- _track[track_id].used = false;
- assert(!_track[track_id].handle.isActive());
- warning("IMuseDigital::startSound(): Removed sound %d from track %d", _track[track_id].soundId, track_id);
- } else {
- warning("IMuseDigital::startSound(): Priority sound too low");
- return;
- }
- }
-
- for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if (!_track[l].used && !_track[l].handle.isActive()) {
- _track[l].pan = 64;
- _track[l].vol = volume * 1000;
- _track[l].volFadeDest = 0;
- _track[l].volFadeStep = 0;
- _track[l].volFadeDelay = 0;
- _track[l].volFadeUsed = false;
- _track[l].soundId = soundId;
- _track[l].started = false;
- _track[l].soundGroup = soundGroup;
- _track[l].curHookId = hookId;
- _track[l].priority = priority;
- _track[l].curRegion = -1;
- _track[l].dataOffset = 0;
- _track[l].regionOffset = 0;
- _track[l].trackOffset = 0;
- _track[l].mod = 0;
- _track[l].toBeRemoved = false;
-
- int bits = 0, freq = 0, channels = 0, mixerFlags = 0;
-
- if (input) {
- _track[l].iteration = 1; // ?
- // Do nothing here, we already have an audio stream
- } else {
- _track[l].soundHandle = _sound->openSound(soundId, soundName, soundType, soundGroup);
-
- if (_track[l].soundHandle == NULL)
- return;
-
- bits = _sound->getBits(_track[l].soundHandle);
- channels = _sound->getChannels(_track[l].soundHandle);
- freq = _sound->getFreq(_track[l].soundHandle);
-
- if ((soundId == kTalkSoundID) && (soundType == IMUSE_BUNDLE)) {
- if (_vm->_actorToPrintStrFor != 0xFF && _vm->_actorToPrintStrFor != 0) {
- Actor *a = _vm->derefActor(_vm->_actorToPrintStrFor, "IMuseDigital::startSound");
- freq = (freq * a->talkFrequency) / 256;
- _track[l].pan = a->talkPan;
- _track[l].vol = a->talkVolume * 1000;
- }
- }
-
- assert(bits == 8 || bits == 12 || bits == 16);
- assert(channels == 1 || channels == 2);
- assert(0 < freq && freq <= 65535);
-
- // Round the frequency to a multiple of 25. This is done to
- // ensure we don't run into data under-/overflows (this is a
- // design limitation of the current IMuseDigital code, which
- // pushes data 'blindly' into the mixer, instead of providing
- // a pull based interface, i.e. a custom AudioInputStream
- // subclass).
- freq -= (freq % 25);
-
- _track[l].iteration = _track[l].pullSize = freq * channels;
-
- if (channels == 2)
- mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
-
- if ((bits == 12) || (bits == 16)) {
- mixerFlags |= SoundMixer::FLAG_16BITS;
- _track[l].iteration = _track[l].pullSize *= 2;
- } else if (bits == 8) {
- mixerFlags |= SoundMixer::FLAG_UNSIGNED;
- } else
- error("IMuseDigital::startSound(): Can't handle %d bit samples", bits);
-
- _track[l].pullSize /= 25; // We want a "frame rate" of 25 audio blocks per second
- }
-
- if (input) {
- _track[l].stream2 = input;
- _track[l].stream = NULL;
- } else {
- _track[l].stream2 = NULL;
- _track[l].stream = makeAppendableAudioStream(freq, mixerFlags, 100000);
- _vm->_mixer->playInputStream(&_track[l].handle, _track[l].stream, false, _track[l].vol / 1000, _track[l].pan, -1);
- }
-
- _track[l].used = true;
- return;
- }
- }
-
- warning("it should not happen");
- assert(0);
-}
-
-void IMuseDigital::stopSound(int soundId) {
- Common::StackLock lock(_mutex, "IMuseDigital::stopSound()");
- debug(5, "IMuseDigital::stopSound(%d)", soundId);
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == soundId) && _track[l].used) {
- if (_track[l].stream) {
- _track[l].toBeRemoved = true;
- }
- else if (_track[l].stream2)
- _vm->_mixer->stopHandle(_track[l].handle);
- }
- }
-}
-
-void IMuseDigital::setPriority(int soundId, int priority) {
- Common::StackLock lock(_mutex, "IMuseDigital::setPriority()");
- debug(5, "IMuseDigital::setPriority(%d, %d)", soundId, priority);
-
- assert ((priority >= 0) && (priority <= 127));
-
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == soundId) && _track[l].used) {
- _track[l].priority = priority;
- }
- }
-}
-
-void IMuseDigital::setVolume(int soundId, int volume) {
- Common::StackLock lock(_mutex, "IMuseDigital::setVolume()");
- debug(5, "IMuseDigital::setVolume(%d, %d)", soundId, volume);
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == soundId) && _track[l].used) {
- _track[l].vol = volume * 1000;
- }
- }
-}
-
-void IMuseDigital::setPan(int soundId, int pan) {
- Common::StackLock lock(_mutex, "IMuseDigital::setPan()");
- debug(5, "IMuseDigital::setPan(%d, %d)", soundId, pan);
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == soundId) && _track[l].used) {
- _track[l].pan = pan;
- }
- }
-}
-
-void IMuseDigital::selectGroupVolume(int soundId, int groupId) {
- Common::StackLock lock(_mutex, "IMuseDigital::setGroupVolume()");
- debug(5, "IMuseDigital::setGroupVolume(%d, %d)", soundId, groupId);
- assert((groupId >= 1) && (groupId <= 3));
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == soundId) && _track[l].used) {
- _track[l].soundGroup = groupId;
- }
- }
-}
-
-void IMuseDigital::setFade(int soundId, int destVolume, int delay60HzTicks) {
- Common::StackLock lock(_mutex, "IMuseDigital::setFade()");
- debug(5, "IMuseDigital::setFade(%d, %d, %d)", soundId, destVolume, delay60HzTicks);
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == soundId) && _track[l].used) {
- _track[l].volFadeDelay = delay60HzTicks;
- _track[l].volFadeDest = destVolume * 1000;
- _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * delay60HzTicks);
- _track[l].volFadeUsed = true;
- }
- }
-}
-
-void IMuseDigital::refreshScripts() {
- bool found = false;
- {
- Common::StackLock lock(_mutex, "IMuseDigital::refreshScripts()");
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].used) && (_track[l].soundGroup == IMUSE_MUSIC) && (!_track[l].volFadeUsed)) {
- found = true;
- }
- }
- }
-
- if ((!found) && (_curMusicSeq != 0)) {
- parseScriptCmds(0x1001, 0, 0, 0, 0, 0, 0, 0);
- }
-}
-
-void IMuseDigital::stopAllSounds(bool waitForStop) {
- debug(5, "IMuseDigital::stopAllSounds");
- {
- Common::StackLock lock(_mutex, "IMuseDigital::stopAllSounds()");
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if (_track[l].used) {
- if (_track[l].stream) {
- _track[l].toBeRemoved = true;
- } else if (_track[l].stream2)
- _vm->_mixer->stopHandle(_track[l].handle);
- }
- }
- }
-
- if (waitForStop) {
- bool used;
- do {
- used = false;
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if (_track[l].used)
- used = true;
- }
- g_system->delay_msecs(10);
- } while (used);
- }
-}
-
-void IMuseDigital::fadeOutMusic(int fadeDelay) {
- Common::StackLock lock(_mutex, "IMuseDigital::fadeOutMusic()");
- debug(5, "IMuseDigital::fadeOutMusic");
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].used) && (_track[l].soundGroup == IMUSE_MUSIC) && (!_track[l].volFadeUsed)) {
- _track[l].volFadeDelay = fadeDelay;
- _track[l].volFadeDest = 0;
- _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * fadeDelay);
- _track[l].volFadeUsed = true;
- }
- }
-}
-
-void IMuseDigital::pause(bool p) {
- Common::StackLock lock(_mutex, "IMuseDigital::pause()");
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if (_track[l].used) {
- _vm->_mixer->pauseHandle(_track[l].handle, p);
- }
- }
- _pause = p;
-}
-
-void IMuseDigital::parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h) {
- int cmd = a;
- int soundId = b;
- int sub_cmd = c;
-
- if (!cmd)
- return;
-
- switch (cmd) {
- case 10: // ImuseStopAllSounds
- stopAllSounds();
- break;
- case 12: // ImuseSetParam
- switch (sub_cmd) {
- case 0x400: // select group volume
- selectGroupVolume(soundId, d);
- break;
- case 0x500: // set priority
- setPriority(soundId, d);
- break;
- case 0x600: // set volume
- setVolume(soundId, d);
- break;
- case 0x700: // set pan
- setPan(soundId, d);
- break;
- default:
- warning("IMuseDigital::doCommand SetParam DEFAULT command %d", sub_cmd);
- break;
- }
- break;
- case 14: // ImuseFadeParam
- switch (sub_cmd) {
- case 0x600: // set volume fading
- if ((d != 0) && (e == 0))
- setVolume(soundId, d);
- else if ((d == 0) && (e == 0))
- stopSound(soundId);
- else
- setFade(soundId, d, e);
- break;
- default:
- warning("IMuseDigital::doCommand FadeParam DEFAULT sub command %d", sub_cmd);
- break;
- }
- break;
- case 25: // ImuseStartStream
- debug(5, "ImuseStartStream (%d, %d, %d)", soundId, c, d);
- break;
- case 26: // ImuseSwitchStream
- debug(5, "ImuseSwitchStream (%d, %d, %d, %d, %d)", soundId, c, d, e, f);
- break;
- case 0x1000: // ImuseSetState
- debug(5, "ImuseSetState (%d)", b);
- if ((_vm->_gameId == GID_DIG) && (_vm->_features & GF_DEMO)) {
- if (b == 1) {
- fadeOutMusic(200);
- startMusic(1, 127);
- } else {
- if (getSoundStatus(2) == 0) {
- fadeOutMusic(200);
- startMusic(2, 127);
- }
- }
- } else if ((_vm->_gameId == GID_CMI) && (_vm->_features & GF_DEMO)) {
- fadeOutMusic(120);
- if (b == 2) {
- startMusic("in1.imx", 1100, 0, 127);
- } else if (b == 4) {
- startMusic("in2.imx", 1120, 0, 127);
- } else if (b == 8) {
- startMusic("out1.imx", 1140, 0, 127);
- } else if (b == 9) {
- startMusic("out2.imx", 1150, 0, 127);
- } else if (b == 16) {
- startMusic("gun.imx", 1210, 0, 127);
- } else {
- warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, _vm->_currentRoom);
- }
- } else if (_vm->_gameId == GID_DIG) {
- setDigMusicState(b);
- } else if (_vm->_gameId == GID_CMI) {
- setComiMusicState(b);
- } else if (_vm->_gameId == GID_FT) {
- setFtMusicState(b);
- }
- break;
- case 0x1001: // ImuseSetSequence
- debug(5, "ImuseSetSequence (%d)", b);
- if (_vm->_gameId == GID_DIG) {
- setDigMusicSequence(b);
- } else if (_vm->_gameId == GID_CMI) {
- setComiMusicSequence(b);
- } else if (_vm->_gameId == GID_FT) {
- setFtMusicSequence(b);
- }
- break;
- case 0x1002: // ImuseSetCuePoint
- debug(5, "ImuseSetCuePoint (%d)", b);
- if (_vm->_gameId == GID_FT) {
- setFtMusicCuePoint(b);
- }
- break;
- case 0x1003: // ImuseSetAttribute
- debug(5, "ImuseSetAttribute (%d, %d)", b, c);
- assert((_vm->_gameId == GID_DIG) || (_vm->_gameId == GID_FT));
- if (_vm->_gameId == GID_DIG) {
- _attributes[b] = c;
- }
- break;
- case 0x2000: // ImuseSetGroupSfxVolume
- debug(5, "ImuseSetGroupSFXVolume (%d)", b);
-// setGroupSfxVolume(b);
- break;
- case 0x2001: // ImuseSetGroupVoiceVolume
- debug(5, "ImuseSetGroupVoiceVolume (%d)", b);
-// setGroupVoiceVolume(b);
- break;
- case 0x2002: // ImuseSetGroupMusicVolume
- debug(5, "ImuseSetGroupMusicVolume (%d)", b);
-// setGroupMusicVolume(b);
- break;
- default:
- warning("IMuseDigital::doCommand DEFAULT command %d", cmd);
- }
-}
-
-int IMuseDigital::getSoundStatus(int sound) const {
- Common::StackLock lock(_mutex, "IMuseDigital::getSoundStatus()");
- debug(5, "IMuseDigital::getSoundStatus(%d)", sound);
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == sound) && _track[l].used) {
- return 1;
- }
- }
-
- return 0;
-}
-
-void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width, int32 &height) {
- int32 sync_size;
- byte *sync_ptr;
-
- msPos /= 16;
- if (msPos < 65536) {
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == soundId) && _track[l].used) {
- _sound->getSyncSizeAndPtrById(_track[l].soundHandle, syncId, sync_size, &sync_ptr);
- if ((sync_size != 0) && (sync_ptr != NULL)) {
- sync_size /= 4;
- while (sync_size--) {
- if (READ_BE_UINT16(sync_ptr) >= msPos)
- break;
- sync_ptr += 4;
- }
- if (sync_size < 0)
- sync_ptr -= 4;
- else
- if (READ_BE_UINT16(sync_ptr) > msPos)
- sync_ptr -= 4;
-
- width = sync_ptr[2];
- height = sync_ptr[3];
- return;
- }
- }
- }
- }
-}
-
-int32 IMuseDigital::getPosInMs(int soundId) {
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].soundId == soundId) && (_track[l].used)) {
- int32 pos = (5 * (_track[l].dataOffset + _track[l].regionOffset)) / (_track[l].iteration / 200);
- return pos;
- }
- }
-
- return 0;
-}
-
-int32 IMuseDigital::getCurMusicPosInMs() {
- Common::StackLock lock(_mutex, "IMuseDigital::getCurMusicPosInMs()");
- int soundId = -1;
-
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].used) && (_track[l].soundGroup == IMUSE_MUSIC) && (!_track[l].volFadeUsed)) {
- soundId = _track[l].soundId;
- }
- }
-
- int32 msPos = getPosInMs(soundId);
- debug(5, "IMuseDigital::getCurMusicPosInMs(%d) = %d", soundId, msPos);
- return msPos;
-}
-
-int32 IMuseDigital::getCurVoiceLipSyncWidth() {
- Common::StackLock lock(_mutex, "IMuseDigital::getCutVoiceLipSyncWidth()");
- int32 msPos = getPosInMs(kTalkSoundID) + 50;
- int32 width = 0, height = 0;
-
- debug(5, "IMuseDigital::getCurVoiceLipSyncWidth(%d)", kTalkSoundID);
- getLipSync(kTalkSoundID, 0, msPos, width, height);
- return width;
-}
-
-int32 IMuseDigital::getCurVoiceLipSyncHeight() {
- Common::StackLock lock(_mutex, "IMuseDigital::getCurVoiceLipSyncHeight()");
- int32 msPos = getPosInMs(kTalkSoundID) + 50;
- int32 width = 0, height = 0;
-
- debug(5, "IMuseDigital::getCurVoiceLipSyncHeight(%d)", kTalkSoundID);
- getLipSync(kTalkSoundID, 0, msPos, width, height);
- return height;
-}
-
-int32 IMuseDigital::getCurMusicLipSyncWidth(int syncId) {
- Common::StackLock lock(_mutex, "IMuseDigital::getCurMusicLipSyncWidth()");
- int soundId = -1;
-
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].used) && (_track[l].soundGroup == IMUSE_MUSIC) && (!_track[l].volFadeUsed)) {
- soundId = _track[l].soundId;
- }
- }
-
- int32 msPos = getPosInMs(soundId) + 50;
- int32 width = 0, height = 0;
-
- debug(5, "IMuseDigital::getCurVoiceLipSyncWidth(%d, %d)", soundId, msPos);
- getLipSync(soundId, syncId, msPos, width, height);
- return width;
-}
-
-int32 IMuseDigital::getCurMusicLipSyncHeight(int syncId) {
- Common::StackLock lock(_mutex, "IMuseDigital::getCurMusicLipSyncHeight()");
- int soundId = -1;
-
- for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
- if ((_track[l].used) && (_track[l].soundGroup == IMUSE_MUSIC) && (!_track[l].volFadeUsed)) {
- soundId = _track[l].soundId;
- }
- }
-
- int32 msPos = getPosInMs(soundId) + 50;
- int32 width = 0, height = 0;
-
- debug(5, "IMuseDigital::getCurVoiceLipSyncHeight(%d, %d)", soundId, msPos);
- getLipSync(soundId, syncId, msPos, width, height);
- return height;
-}
-
} // End of namespace Scumm
diff --git a/scumm/imuse_digi/dimuse.h b/scumm/imuse_digi/dimuse.h
index 995ed5f856..8320104c95 100644
--- a/scumm/imuse_digi/dimuse.h
+++ b/scumm/imuse_digi/dimuse.h
@@ -59,7 +59,7 @@ private:
int32 dataOffset;
int curRegion;
int curHookId;
- int soundGroup;
+ int volGroupId;
int iteration;
int mod;
int32 pullSize;
@@ -93,7 +93,8 @@ private:
static void timer_handler(void *refConf);
void callback();
void switchToNextRegion(int track);
- void startSound(int soundId, const char *soundName, int soundType, int soundGroup, AudioStream *input, int hookId, int volume, int priority);
+ void allocSlot(int priority);
+ void startSound(int soundId, const char *soundName, int soundType, int volGroupId, AudioStream *input, int hookId, int volume, int priority);
int32 getPosInMs(int soundId);
void getLipSync(int soundId, int syncId, int32 msPos, int32 &width, int32 &height);
@@ -118,24 +119,19 @@ public:
IMuseDigital(ScummEngine *scumm);
virtual ~IMuseDigital();
- void startVoice(int soundId, AudioStream *input)
- { debug(5, "startVoiceStream(%d)", soundId); startSound(soundId, NULL, 0, IMUSE_VOICE, input, 0, 127, 127); }
- void startVoice(int soundId, const char *soundName)
- { debug(5, "startVoiceBundle(%s)", soundName); startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOICE, NULL, 0, 127, 127); }
- void startMusic(int soundId, int volume)
- { debug(5, "startMusicResource(%d)", soundId); startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_MUSIC, NULL, 0, volume, 126); }
- void startMusic(const char *soundName, int soundId, int hookId, int volume)
- { debug(5, "startMusicBundle(%s)", soundName); startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_MUSIC, NULL, hookId, volume, 126); }
- void startSfx(int soundId, int priority)
- { debug(5, "startSfx(%d)", soundId); startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_SFX, NULL, 0, 127, priority); }
+ void startVoice(int soundId, AudioStream *input);
+ void startVoice(int soundId, const char *soundName);
+ void startMusic(int soundId, int volume);
+ void startMusic(const char *soundName, int soundId, int hookId, int volume);
+ void startSfx(int soundId, int priority);
void startSound(int soundId)
{ error("MusicEngine::startSound() Should be never called"); }
void resetState();
- void setGroupVoiceVolume(int volume);
- void setGroupSfxVolume(int volume);
- void setGroupMusicVolume(int volume);
+ void setGroupVoiceVolume(int volume) { _volVoice = volume; }
+ void setGroupSfxVolume(int volume) { _volSfx = volume; }
+ void setGroupMusicVolume(int volume) { _volMusic = volume; }
int getGroupVoiceVolume() { return _volVoice; }
int getGroupSfxVolume() { return _volSfx; }
int getGroupMusicVolume() { return _volMusic; }
@@ -144,7 +140,7 @@ public:
void setVolume(int soundId, int volume);
void setPan(int soundId, int pan);
void setFade(int soundId, int destVolume, int delay60HzTicks);
- void selectGroupVolume(int soundId, int groupId);
+ void selectVolumeGroup(int soundId, int volGroupId);
void setMasterVolume(int vol) {}
void stopSound(int soundId);
void stopAllSounds() { stopAllSounds(false); }
diff --git a/scumm/imuse_digi/dimuse_music.cpp b/scumm/imuse_digi/dimuse_music.cpp
index 11d23a1740..345a274619 100644
--- a/scumm/imuse_digi/dimuse_music.cpp
+++ b/scumm/imuse_digi/dimuse_music.cpp
@@ -30,6 +30,22 @@ namespace Scumm {
#define COMI_STATE_OFFSET 3
#define COMI_SEQ_OFFSET (COMI_STATE_OFFSET + 94)
+void IMuseDigital::refreshScripts() {
+ bool found = false;
+ {
+ Common::StackLock lock(_mutex, "IMuseDigital::refreshScripts()");
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].used) && (_track[l].volGroupId == IMUSE_VOLGRP_MUSIC) && (!_track[l].volFadeUsed)) {
+ found = true;
+ }
+ }
+ }
+
+ if ((!found) && (_curMusicSeq != 0)) {
+ parseScriptCmds(0x1001, 0, 0, 0, 0, 0, 0, 0);
+ }
+}
+
void IMuseDigital::setDigMusicState(int stateId) {
int l, num = -1;
diff --git a/scumm/imuse_digi/dimuse_script.cpp b/scumm/imuse_digi/dimuse_script.cpp
new file mode 100644
index 0000000000..6d44b55796
--- /dev/null
+++ b/scumm/imuse_digi/dimuse_script.cpp
@@ -0,0 +1,363 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "common/timer.h"
+
+#include "scumm/actor.h"
+#include "scumm/scumm.h"
+#include "scumm/sound.h"
+#include "scumm/imuse_digi/dimuse.h"
+#include "scumm/imuse_digi/dimuse_bndmgr.h"
+
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
+namespace Scumm {
+
+void IMuseDigital::parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h) {
+ int cmd = a;
+ int soundId = b;
+ int sub_cmd = c;
+
+ if (!cmd)
+ return;
+
+ switch (cmd) {
+ case 10: // ImuseStopAllSounds
+ stopAllSounds();
+ break;
+ case 12: // ImuseSetParam
+ switch (sub_cmd) {
+ case 0x400: // select group volume
+ selectVolumeGroup(soundId, d);
+ break;
+ case 0x500: // set priority
+ setPriority(soundId, d);
+ break;
+ case 0x600: // set volume
+ setVolume(soundId, d);
+ break;
+ case 0x700: // set pan
+ setPan(soundId, d);
+ break;
+ default:
+ warning("IMuseDigital::doCommand SetParam DEFAULT command %d", sub_cmd);
+ break;
+ }
+ break;
+ case 14: // ImuseFadeParam
+ switch (sub_cmd) {
+ case 0x600: // set volume fading
+ if ((d != 0) && (e == 0))
+ setVolume(soundId, d);
+ else if ((d == 0) && (e == 0))
+ stopSound(soundId);
+ else
+ setFade(soundId, d, e);
+ break;
+ default:
+ warning("IMuseDigital::doCommand FadeParam DEFAULT sub command %d", sub_cmd);
+ break;
+ }
+ break;
+ case 25: // ImuseStartStream
+ debug(5, "ImuseStartStream (%d, %d, %d)", soundId, c, d);
+ break;
+ case 26: // ImuseSwitchStream
+ debug(5, "ImuseSwitchStream (%d, %d, %d, %d, %d)", soundId, c, d, e, f);
+ break;
+ case 0x1000: // ImuseSetState
+ debug(5, "ImuseSetState (%d)", b);
+ if ((_vm->_gameId == GID_DIG) && (_vm->_features & GF_DEMO)) {
+ if (b == 1) {
+ fadeOutMusic(200);
+ startMusic(1, 127);
+ } else {
+ if (getSoundStatus(2) == 0) {
+ fadeOutMusic(200);
+ startMusic(2, 127);
+ }
+ }
+ } else if ((_vm->_gameId == GID_CMI) && (_vm->_features & GF_DEMO)) {
+ fadeOutMusic(120);
+ if (b == 2) {
+ startMusic("in1.imx", 1100, 0, 127);
+ } else if (b == 4) {
+ startMusic("in2.imx", 1120, 0, 127);
+ } else if (b == 8) {
+ startMusic("out1.imx", 1140, 0, 127);
+ } else if (b == 9) {
+ startMusic("out2.imx", 1150, 0, 127);
+ } else if (b == 16) {
+ startMusic("gun.imx", 1210, 0, 127);
+ } else {
+ warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, _vm->_currentRoom);
+ }
+ } else if (_vm->_gameId == GID_DIG) {
+ setDigMusicState(b);
+ } else if (_vm->_gameId == GID_CMI) {
+ setComiMusicState(b);
+ } else if (_vm->_gameId == GID_FT) {
+ setFtMusicState(b);
+ }
+ break;
+ case 0x1001: // ImuseSetSequence
+ debug(5, "ImuseSetSequence (%d)", b);
+ if (_vm->_gameId == GID_DIG) {
+ setDigMusicSequence(b);
+ } else if (_vm->_gameId == GID_CMI) {
+ setComiMusicSequence(b);
+ } else if (_vm->_gameId == GID_FT) {
+ setFtMusicSequence(b);
+ }
+ break;
+ case 0x1002: // ImuseSetCuePoint
+ debug(5, "ImuseSetCuePoint (%d)", b);
+ if (_vm->_gameId == GID_FT) {
+ setFtMusicCuePoint(b);
+ }
+ break;
+ case 0x1003: // ImuseSetAttribute
+ debug(5, "ImuseSetAttribute (%d, %d)", b, c);
+ assert((_vm->_gameId == GID_DIG) || (_vm->_gameId == GID_FT));
+ if (_vm->_gameId == GID_DIG) {
+ _attributes[b] = c;
+ }
+ break;
+ case 0x2000: // ImuseSetGroupSfxVolume
+ debug(5, "ImuseSetGroupSFXVolume (%d)", b);
+// setGroupSfxVolume(b);
+ break;
+ case 0x2001: // ImuseSetGroupVoiceVolume
+ debug(5, "ImuseSetGroupVoiceVolume (%d)", b);
+// setGroupVoiceVolume(b);
+ break;
+ case 0x2002: // ImuseSetGroupMusicVolume
+ debug(5, "ImuseSetGroupMusicVolume (%d)", b);
+// setGroupMusicVolume(b);
+ break;
+ default:
+ warning("IMuseDigital::doCommand DEFAULT command %d", cmd);
+ }
+}
+
+void IMuseDigital::startVoice(int soundId, AudioStream *input) {
+ debug(5, "startVoiceStream(%d)", soundId);
+ startSound(soundId, NULL, 0, IMUSE_VOLGRP_VOICE, input, 0, 127, 127);
+}
+
+void IMuseDigital::startVoice(int soundId, const char *soundName) {
+ debug(5, "startVoiceBundle(%s)", soundName);
+ startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOLGRP_VOICE, NULL, 0, 127, 127);
+}
+
+void IMuseDigital::startMusic(int soundId, int volume) {
+ debug(5, "startMusicResource(%d)", soundId);
+ startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_VOLGRP_MUSIC, NULL, 0, volume, 126);
+}
+
+void IMuseDigital::startMusic(const char *soundName, int soundId, int hookId, int volume) {
+ debug(5, "startMusicBundle(%s)", soundName);
+ startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOLGRP_MUSIC, NULL, hookId, volume, 126);
+}
+
+void IMuseDigital::startSfx(int soundId, int priority) {
+ debug(5, "startSfx(%d)", soundId);
+ startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_VOLGRP_SFX, NULL, 0, 127, priority);
+}
+
+void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width, int32 &height) {
+ int32 sync_size;
+ byte *sync_ptr;
+
+ msPos /= 16;
+ if (msPos < 65536) {
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == soundId) && _track[l].used) {
+ _sound->getSyncSizeAndPtrById(_track[l].soundHandle, syncId, sync_size, &sync_ptr);
+ if ((sync_size != 0) && (sync_ptr != NULL)) {
+ sync_size /= 4;
+ while (sync_size--) {
+ if (READ_BE_UINT16(sync_ptr) >= msPos)
+ break;
+ sync_ptr += 4;
+ }
+ if (sync_size < 0)
+ sync_ptr -= 4;
+ else
+ if (READ_BE_UINT16(sync_ptr) > msPos)
+ sync_ptr -= 4;
+
+ width = sync_ptr[2];
+ height = sync_ptr[3];
+ return;
+ }
+ }
+ }
+ }
+}
+
+int32 IMuseDigital::getPosInMs(int soundId) {
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == soundId) && (_track[l].used)) {
+ int32 pos = (5 * (_track[l].dataOffset + _track[l].regionOffset)) / (_track[l].iteration / 200);
+ return pos;
+ }
+ }
+
+ return 0;
+}
+
+int IMuseDigital::getSoundStatus(int sound) const {
+ Common::StackLock lock(_mutex, "IMuseDigital::getSoundStatus()");
+ debug(5, "IMuseDigital::getSoundStatus(%d)", sound);
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == sound) && _track[l].used) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void IMuseDigital::stopSound(int soundId) {
+ Common::StackLock lock(_mutex, "IMuseDigital::stopSound()");
+ debug(5, "IMuseDigital::stopSound(%d)", soundId);
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == soundId) && _track[l].used) {
+ if (_track[l].stream) {
+ _track[l].toBeRemoved = true;
+ }
+ else if (_track[l].stream2)
+ _vm->_mixer->stopHandle(_track[l].handle);
+ }
+ }
+}
+
+int32 IMuseDigital::getCurMusicPosInMs() {
+ Common::StackLock lock(_mutex, "IMuseDigital::getCurMusicPosInMs()");
+ int soundId = -1;
+
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].used) && (_track[l].volGroupId == IMUSE_VOLGRP_MUSIC) && (!_track[l].volFadeUsed)) {
+ soundId = _track[l].soundId;
+ }
+ }
+
+ int32 msPos = getPosInMs(soundId);
+ debug(5, "IMuseDigital::getCurMusicPosInMs(%d) = %d", soundId, msPos);
+ return msPos;
+}
+
+int32 IMuseDigital::getCurVoiceLipSyncWidth() {
+ Common::StackLock lock(_mutex, "IMuseDigital::getCutVoiceLipSyncWidth()");
+ int32 msPos = getPosInMs(kTalkSoundID) + 50;
+ int32 width = 0, height = 0;
+
+ debug(5, "IMuseDigital::getCurVoiceLipSyncWidth(%d)", kTalkSoundID);
+ getLipSync(kTalkSoundID, 0, msPos, width, height);
+ return width;
+}
+
+int32 IMuseDigital::getCurVoiceLipSyncHeight() {
+ Common::StackLock lock(_mutex, "IMuseDigital::getCurVoiceLipSyncHeight()");
+ int32 msPos = getPosInMs(kTalkSoundID) + 50;
+ int32 width = 0, height = 0;
+
+ debug(5, "IMuseDigital::getCurVoiceLipSyncHeight(%d)", kTalkSoundID);
+ getLipSync(kTalkSoundID, 0, msPos, width, height);
+ return height;
+}
+
+int32 IMuseDigital::getCurMusicLipSyncWidth(int syncId) {
+ Common::StackLock lock(_mutex, "IMuseDigital::getCurMusicLipSyncWidth()");
+ int soundId = -1;
+
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].used) && (_track[l].volGroupId == IMUSE_VOLGRP_MUSIC) && (!_track[l].volFadeUsed)) {
+ soundId = _track[l].soundId;
+ }
+ }
+
+ int32 msPos = getPosInMs(soundId) + 50;
+ int32 width = 0, height = 0;
+
+ debug(5, "IMuseDigital::getCurVoiceLipSyncWidth(%d, %d)", soundId, msPos);
+ getLipSync(soundId, syncId, msPos, width, height);
+ return width;
+}
+
+int32 IMuseDigital::getCurMusicLipSyncHeight(int syncId) {
+ Common::StackLock lock(_mutex, "IMuseDigital::getCurMusicLipSyncHeight()");
+ int soundId = -1;
+
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].used) && (_track[l].volGroupId == IMUSE_VOLGRP_MUSIC) && (!_track[l].volFadeUsed)) {
+ soundId = _track[l].soundId;
+ }
+ }
+
+ int32 msPos = getPosInMs(soundId) + 50;
+ int32 width = 0, height = 0;
+
+ debug(5, "IMuseDigital::getCurVoiceLipSyncHeight(%d, %d)", soundId, msPos);
+ getLipSync(soundId, syncId, msPos, width, height);
+ return height;
+}
+
+void IMuseDigital::stopAllSounds(bool waitForStop) {
+ debug(5, "IMuseDigital::stopAllSounds");
+ {
+ Common::StackLock lock(_mutex, "IMuseDigital::stopAllSounds()");
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (_track[l].used) {
+ if (_track[l].stream) {
+ _track[l].toBeRemoved = true;
+ } else if (_track[l].stream2)
+ _vm->_mixer->stopHandle(_track[l].handle);
+ }
+ }
+ }
+
+ if (waitForStop) {
+ bool used;
+ do {
+ used = false;
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (_track[l].used)
+ used = true;
+ }
+ g_system->delay_msecs(10);
+ } while (used);
+ }
+}
+
+void IMuseDigital::pause(bool p) {
+ Common::StackLock lock(_mutex, "IMuseDigital::pause()");
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (_track[l].used) {
+ _vm->_mixer->pauseHandle(_track[l].handle, p);
+ }
+ }
+ _pause = p;
+}
+
+} // End of namespace Scumm
diff --git a/scumm/imuse_digi/dimuse_sndmgr.cpp b/scumm/imuse_digi/dimuse_sndmgr.cpp
index 9d6201a755..afdc36d3f0 100644
--- a/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -47,38 +47,111 @@ ImuseDigiSndMgr::~ImuseDigiSndMgr() {
#endif
}
+void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs) {
+ uint32 tag;
+ int32 size = 0;
+
+ do {
+ tag = READ_BE_UINT32(ptr); ptr += 4;
+ switch(tag) {
+ case MKID_BE('TEXT'):
+ case MKID_BE('STOP'):
+ case MKID_BE('FRMT'):
+ case MKID_BE('DATA'):
+ size = READ_BE_UINT32(ptr); ptr += size + 4;
+ break;
+ case MKID_BE('REGN'):
+ numRegions++;
+ size = READ_BE_UINT32(ptr); ptr += size + 4;
+ break;
+ case MKID_BE('JUMP'):
+ numJumps++;
+ size = READ_BE_UINT32(ptr); ptr += size + 4;
+ break;
+ case MKID_BE('SYNC'):
+ numSyncs++;
+ size = READ_BE_UINT32(ptr); ptr += size + 4;
+ break;
+ default:
+ error("ImuseDigiSndMgr::countElements() Unknown sfx header '%s'", tag2str(tag));
+ }
+ } while (tag != MKID_BE('DATA'));
+}
+
void ImuseDigiSndMgr::prepareSound(byte *ptr, int slot) {
if (READ_UINT32(ptr) == MKID('Crea')) {
- int size = 0, rate = 0, loops = 0, begin_loop = 0, end_loop = 0;
- _sounds[slot].resPtr = readVOCFromMemory(ptr, size, rate, loops, begin_loop, end_loop);
- _sounds[slot].freeResPtr = true;
+ bool quit = false;
+
+ int32 offset = READ_LE_UINT16(ptr + 20);
+ int16 version = READ_LE_UINT16(ptr + 22);
+ int16 code = READ_LE_UINT16(ptr + 24);
+ assert(version == 0x010A || version == 0x0114);
+ assert(code == ~version + 0x1234);
+
+ _sounds[slot].region = (_region *)malloc(sizeof(_region) * 4);
+ _sounds[slot].jump = (_jump *)malloc(sizeof(_jump));
+ _sounds[slot].resPtr = ptr;
_sounds[slot].bits = 8;
- _sounds[slot].freq = rate;
_sounds[slot].channels = 1;
- _sounds[slot].region[0].offset = 0;
- _sounds[slot].region[0].length = size;
- _sounds[slot].numRegions++;
- if (loops != 0) {
- if (begin_loop == 0) {
- _sounds[slot].region[1].offset = end_loop;
+
+ while (!quit) {
+ int len = READ_LE_UINT32(ptr + offset);
+ offset += 4;
+ code = len & 0xFF;
+ len >>= 8;
+ switch(code) {
+ case 0:
+ quit = true;
+ break;
+ case 1:
+ {
+ int time_constant = ptr[offset];
+ offset += 2;
+ len -= 2;
+ _sounds[slot].freq = getSampleRateFromVOCRate(time_constant);
+ _sounds[slot].region[_sounds[slot].numRegions].offset = offset;
+ _sounds[slot].region[_sounds[slot].numRegions].length = len;
+ _sounds[slot].numRegions++;
+ }
+ break;
+ case 6: // begin of loop
+ _sounds[slot].jump[0].dest = offset + 8;
+ _sounds[slot].jump[0].hookId = 0;
+ _sounds[slot].jump[0].fadeDelay = 0;
+ break;
+ case 7: // end of loop
+ _sounds[slot].jump[0].offset = offset - 4;
+ _sounds[slot].numJumps++;
+ _sounds[slot].region[_sounds[slot].numRegions].offset = offset - 4;
+ _sounds[slot].region[_sounds[slot].numRegions].length = 0;
_sounds[slot].numRegions++;
- } else {
- _sounds[slot].region[0].length = begin_loop;
- _sounds[slot].region[1].offset = begin_loop;
- _sounds[slot].region[1].length = end_loop - begin_loop;
- _sounds[slot].region[2].offset = end_loop;
- _sounds[slot].numRegions += 2;
+ break;
+ default:
+ error("Invalid code in VOC file : %d", code);
+ quit = true;
+ break;
}
- _sounds[slot].jump[0].dest = begin_loop;
- _sounds[slot].jump[0].offset = end_loop;
- _sounds[slot].numJumps++;
+ // FIXME some FT samples (ex. 362) has bad length, 2 bytes too short
+ offset += len;
}
} else if (READ_UINT32(ptr) == MKID('iMUS')) {
uint32 tag;
int32 size = 0;
byte *s_ptr = ptr;
-
ptr += 16;
+
+ int curIndexRegion = 0;
+ int curIndexJump = 0;
+ int curIndexSync = 0;
+
+ _sounds[slot].numRegions = 0;
+ _sounds[slot].numJumps = 0;
+ _sounds[slot].numSyncs = 0;
+ countElements(ptr, _sounds[slot].numRegions, _sounds[slot].numJumps, _sounds[slot].numSyncs);
+ _sounds[slot].region = (_region *)malloc(sizeof(_region) * _sounds[slot].numRegions);
+ _sounds[slot].jump = (_jump *)malloc(sizeof(_jump) * _sounds[slot].numJumps);
+ _sounds[slot].sync = (_sync *)malloc(sizeof(_sync) * _sounds[slot].numSyncs);
+
do {
tag = READ_BE_UINT32(ptr); ptr += 4;
switch(tag) {
@@ -87,57 +160,35 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, int slot) {
_sounds[slot].bits = READ_BE_UINT32(ptr); ptr += 4;
_sounds[slot].freq = READ_BE_UINT32(ptr); ptr += 4;
_sounds[slot].channels = READ_BE_UINT32(ptr); ptr += 4;
- break;
+ break;
case MKID_BE('TEXT'):
+ case MKID_BE('STOP'):
size = READ_BE_UINT32(ptr); ptr += size + 4;
break;
case MKID_BE('REGN'):
- size = READ_BE_UINT32(ptr); ptr += 4;
- if (_sounds[slot].numRegions >= MAX_IMUSE_REGIONS) {
- warning("ImuseDigiSndMgr::prepareSound(%d/%s) Not enough space for Region", _sounds[slot].soundId, _sounds[slot].name);
- ptr += 8;
- break;
- }
- _sounds[slot].region[_sounds[slot].numRegions].offset = READ_BE_UINT32(ptr); ptr += 4;
- _sounds[slot].region[_sounds[slot].numRegions].length = READ_BE_UINT32(ptr); ptr += 4;
-// if (_sounds[slot].soundId == 2311)
-// printf("REGN: offset: %d, length: %d\n", _sounds[slot].region[_sounds[slot].numRegions].offset, _sounds[slot].region[_sounds[slot].numRegions].length);
- _sounds[slot].numRegions++;
- break;
- case MKID_BE('STOP'):
ptr += 4;
- _sounds[slot].offsetStop = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].region[curIndexRegion].offset = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].region[curIndexRegion].length = READ_BE_UINT32(ptr); ptr += 4;
+ curIndexRegion++;
break;
case MKID_BE('JUMP'):
- size = READ_BE_UINT32(ptr); ptr += 4;
- if (_sounds[slot].numJumps >= MAX_IMUSE_JUMPS) {
- warning("ImuseDigiSndMgr::prepareSound(%d/%s) Not enough space for Jump", _sounds[slot].soundId, _sounds[slot].name);
- ptr += size;
- break;
- }
- _sounds[slot].jump[_sounds[slot].numJumps].offset = READ_BE_UINT32(ptr); ptr += 4;
- _sounds[slot].jump[_sounds[slot].numJumps].dest = READ_BE_UINT32(ptr); ptr += 4;
- _sounds[slot].jump[_sounds[slot].numJumps].hookId = READ_BE_UINT32(ptr); ptr += 4;
- _sounds[slot].jump[_sounds[slot].numJumps].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
-// if (_sounds[slot].soundId == 2311)
-// printf("JUMP: offset: %d, dest: %d, hookId: %d\n", _sounds[slot].jump[_sounds[slot].numJumps].offset, _sounds[slot].jump[_sounds[slot].numJumps].dest, _sounds[slot].jump[_sounds[slot].numJumps].hookId);
- _sounds[slot].numJumps++;
+ ptr += 4;
+ _sounds[slot].jump[curIndexJump].offset = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].jump[curIndexJump].dest = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].jump[curIndexJump].hookId = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].jump[curIndexJump].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
+ curIndexJump++;
break;
case MKID_BE('SYNC'):
size = READ_BE_UINT32(ptr); ptr += 4;
- if (_sounds[slot].numSyncs >= MAX_IMUSE_SYNCS) {
- warning("ImuseDigiSndMgr::prepareSound(%d/%s) Not enough space for Sync", _sounds[slot].soundId, _sounds[slot].name);
- ptr += size;
- break;
- }
- _sounds[slot].sync[_sounds[slot].numSyncs].size = size;
- _sounds[slot].sync[_sounds[slot].numSyncs].ptr = (byte *)malloc(size);
- memcpy(_sounds[slot].sync[_sounds[slot].numSyncs].ptr, ptr, size);
- _sounds[slot].numSyncs++;
+ _sounds[slot].sync[curIndexSync].size = size;
+ _sounds[slot].sync[curIndexSync].ptr = (byte *)malloc(size);
+ memcpy(_sounds[slot].sync[curIndexSync].ptr, ptr, size);
+ curIndexSync++;
ptr += size;
break;
case MKID_BE('DATA'):
- size = READ_BE_UINT32(ptr); ptr += 4;
+ ptr += 4;
break;
default:
error("ImuseDigiSndMgr::prepareSound(%d/%s) Unknown sfx header '%s'", _sounds[slot].soundId, _sounds[slot].name, tag2str(tag));
@@ -163,24 +214,24 @@ int ImuseDigiSndMgr::allocSlot() {
bool ImuseDigiSndMgr::openMusicBundle(int slot) {
bool result = false;
- _sounds[slot]._bundle = new BundleMgr(_cacheBundleDir);
+ _sounds[slot].bundle = new BundleMgr(_cacheBundleDir);
if (_vm->_gameId == GID_CMI) {
if (_vm->_features & GF_DEMO) {
- result = _sounds[slot]._bundle->openFile("music.bun", _vm->getGameDataPath());
+ result = _sounds[slot].bundle->openFile("music.bun", _vm->getGameDataPath());
} else {
char musicfile[20];
sprintf(musicfile, "musdisk%d.bun", _vm->VAR(_vm->VAR_CURRENTDISK));
if (_disk != _vm->VAR(_vm->VAR_CURRENTDISK))
- _sounds[slot]._bundle->closeFile();
+ _sounds[slot].bundle->closeFile();
- result = _sounds[slot]._bundle->openFile(musicfile, _vm->getGameDataPath());
+ result = _sounds[slot].bundle->openFile(musicfile, _vm->getGameDataPath());
if (result == false)
- result = _sounds[slot]._bundle->openFile("music.bun", _vm->getGameDataPath());
+ result = _sounds[slot].bundle->openFile("music.bun", _vm->getGameDataPath());
_disk = (byte)_vm->VAR(_vm->VAR_CURRENTDISK);
}
} else if (_vm->_gameId == GID_DIG)
- result = _sounds[slot]._bundle->openFile("digmusic.bun", _vm->getGameDataPath());
+ result = _sounds[slot].bundle->openFile("digmusic.bun", _vm->getGameDataPath());
else
error("ImuseDigiSndMgr::openMusicBundle() Don't know which bundle file to load");
@@ -190,31 +241,31 @@ bool ImuseDigiSndMgr::openMusicBundle(int slot) {
bool ImuseDigiSndMgr::openVoiceBundle(int slot) {
bool result = false;
- _sounds[slot]._bundle = new BundleMgr(_cacheBundleDir);
+ _sounds[slot].bundle = new BundleMgr(_cacheBundleDir);
if (_vm->_gameId == GID_CMI) {
if (_vm->_features & GF_DEMO) {
- result = _sounds[slot]._bundle->openFile("voice.bun", _vm->getGameDataPath());
+ result = _sounds[slot].bundle->openFile("voice.bun", _vm->getGameDataPath());
} else {
char voxfile[20];
sprintf(voxfile, "voxdisk%d.bun", _vm->VAR(_vm->VAR_CURRENTDISK));
if (_disk != _vm->VAR(_vm->VAR_CURRENTDISK))
- _sounds[slot]._bundle->closeFile();
+ _sounds[slot].bundle->closeFile();
- result = _sounds[slot]._bundle->openFile(voxfile, _vm->getGameDataPath());
+ result = _sounds[slot].bundle->openFile(voxfile, _vm->getGameDataPath());
if (result == false)
- result = _sounds[slot]._bundle->openFile("voice.bun", _vm->getGameDataPath());
+ result = _sounds[slot].bundle->openFile("voice.bun", _vm->getGameDataPath());
_disk = (byte)_vm->VAR(_vm->VAR_CURRENTDISK);
}
} else if (_vm->_gameId == GID_DIG)
- result = _sounds[slot]._bundle->openFile("digvoice.bun", _vm->getGameDataPath());
+ result = _sounds[slot].bundle->openFile("digvoice.bun", _vm->getGameDataPath());
else
error("ImuseDigiSndMgr::openVoiceBundle() Don't know which bundle file to load");
return result;
}
-ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int soundGroup) {
+ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId) {
assert(soundId >= 0);
assert(soundType);
@@ -237,13 +288,13 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch
result = true;
} else if (soundType == IMUSE_BUNDLE) {
bool header_outside = ((_vm->_gameId == GID_CMI) && !(_vm->_features & GF_DEMO));
- if (soundGroup == IMUSE_VOICE)
+ if (volGroupId == IMUSE_VOLGRP_VOICE)
result = openVoiceBundle(slot);
- else if (soundGroup == IMUSE_MUSIC)
+ else if (volGroupId == IMUSE_VOLGRP_MUSIC)
result = openMusicBundle(slot);
- else
+ else
error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
- _sounds[slot]._bundle->decompressSampleByIndex(soundId, 0, 0x2000, &ptr, 0, header_outside);
+ _sounds[slot].bundle->decompressSampleByIndex(soundId, 0, 0x2000, &ptr, 0, header_outside);
_sounds[slot].name[0] = 0;
_sounds[slot].soundId = soundId;
} else {
@@ -252,13 +303,13 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch
} else {
if (soundType == IMUSE_BUNDLE) {
bool header_outside = ((_vm->_gameId == GID_CMI) && !(_vm->_features & GF_DEMO));
- if (soundGroup == IMUSE_VOICE)
+ if (volGroupId == IMUSE_VOLGRP_VOICE)
result = openVoiceBundle(slot);
- else if (soundGroup == IMUSE_MUSIC)
+ else if (volGroupId == IMUSE_VOLGRP_MUSIC)
result = openMusicBundle(slot);
else
error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
- _sounds[slot]._bundle->decompressSampleByName(soundName, 0, 0x2000, &ptr, header_outside);
+ _sounds[slot].bundle->decompressSampleByName(soundName, 0, 0x2000, &ptr, header_outside);
strcpy(_sounds[slot].name, soundName);
_sounds[slot].soundId = soundId;
} else {
@@ -283,13 +334,17 @@ void ImuseDigiSndMgr::closeSound(soundStruct *soundHandle) {
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
if (&_sounds[l] == soundHandle) {
- if (_sounds[l].freeResPtr)
- free(_sounds[l].resPtr);
- if (_sounds[l]._bundle)
- delete _sounds[l]._bundle;
+ if (_sounds[l].bundle)
+ delete _sounds[l].bundle;
for (int r = 0; r < _sounds[l].numSyncs; r++)
if (_sounds[l].sync[r].ptr)
free(_sounds[l].sync[r].ptr);
+ if (_sounds[l].region)
+ free(_sounds[l].region);
+ if (_sounds[l].jump)
+ free(_sounds[l].jump);
+ if (_sounds[l].sync)
+ free(_sounds[l].sync);
memset(&_sounds[l], 0, sizeof(soundStruct));
}
}
@@ -408,8 +463,8 @@ int32 ImuseDigiSndMgr::getDataFromRegion(soundStruct *soundHandle, int region, b
int header_size = soundHandle->offsetData;
bool header_outside = ((_vm->_gameId == GID_CMI) && !(_vm->_features & GF_DEMO));
- if (soundHandle->_bundle) {
- size = soundHandle->_bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside);
+ if (soundHandle->bundle) {
+ size = soundHandle->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside);
} else if (soundHandle->resPtr) {
*buf = (byte *)malloc(size);
memcpy(*buf, soundHandle->resPtr + start + offset + header_size, size);
diff --git a/scumm/imuse_digi/dimuse_sndmgr.h b/scumm/imuse_digi/dimuse_sndmgr.h
index c0d1b28783..c6055e5e0a 100644
--- a/scumm/imuse_digi/dimuse_sndmgr.h
+++ b/scumm/imuse_digi/dimuse_sndmgr.h
@@ -34,17 +34,14 @@ class BundleMgr;
class ImuseDigiSndMgr {
public:
-#define MAX_IMUSE_SOUNDS 16
-#define MAX_IMUSE_JUMPS 80
-#define MAX_IMUSE_REGIONS 85
-#define MAX_IMUSE_SYNCS 4
+#define MAX_IMUSE_SOUNDS 10
#define IMUSE_RESOURCE 1
#define IMUSE_BUNDLE 2
-#define IMUSE_VOICE 1
-#define IMUSE_SFX 2
-#define IMUSE_MUSIC 3
+#define IMUSE_VOLGRP_VOICE 1
+#define IMUSE_VOLGRP_SFX 2
+#define IMUSE_VOLGRP_MUSIC 3
private:
struct _region {
@@ -55,25 +52,27 @@ private:
struct _jump {
int32 offset; // jump offset position
int32 dest; // jump to dest position
- byte hookId; // id of hook
- int16 fadeDelay; // fade delay in ms
+ byte hookId; // id of hook
+ int16 fadeDelay; // fade delay in ms
};
struct _sync {
- int32 size; // size of sync
- byte *ptr; // pointer to sync
+ int32 size; // size of sync
+ byte *ptr; // pointer to sync
};
public:
struct soundStruct {
- uint16 freq; // frequency
+ uint16 freq; // frequency
byte channels; // stereo or mono
byte bits; // 8, 12, 16
- int8 numJumps; // number of Jumps
- int8 numRegions; // number of Regions
- int8 numSyncs; // number of Syncs
- int32 offsetStop; // end offset in source data
+ int numJumps; // number of Jumps
+ int numRegions; // number of Regions
+ int numSyncs; // number of Syncs
+ _region *region;
+ _jump *jump;
+ _sync *sync;
bool endFlag;
bool inUse;
byte *allData;
@@ -81,11 +80,7 @@ public:
byte *resPtr;
char name[15];
int16 soundId;
- bool freeResPtr;
- BundleMgr *_bundle;
- _region region[MAX_IMUSE_REGIONS];
- _jump jump[MAX_IMUSE_JUMPS];
- _sync sync[MAX_IMUSE_SYNCS];
+ BundleMgr *bundle;
};
private:
@@ -103,12 +98,14 @@ private:
bool openMusicBundle(int slot);
bool openVoiceBundle(int slot);
+ void countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs);
+
public:
ImuseDigiSndMgr(ScummEngine *scumm);
~ImuseDigiSndMgr();
-
- soundStruct * openSound(int32 soundId, const char *soundName, int soundType, int soundGroup);
+
+ soundStruct * openSound(int32 soundId, const char *soundName, int soundType, int volGroupId);
void closeSound(soundStruct *soundHandle);
int getFreq(soundStruct *soundHandle);
diff --git a/scumm/imuse_digi/dimuse_track.cpp b/scumm/imuse_digi/dimuse_track.cpp
new file mode 100644
index 0000000000..36d3618af1
--- /dev/null
+++ b/scumm/imuse_digi/dimuse_track.cpp
@@ -0,0 +1,242 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "common/timer.h"
+
+#include "scumm/actor.h"
+#include "scumm/scumm.h"
+#include "scumm/sound.h"
+#include "scumm/imuse_digi/dimuse.h"
+#include "scumm/imuse_digi/dimuse_bndmgr.h"
+
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
+namespace Scumm {
+
+void IMuseDigital::allocSlot(int priority) {
+ int l;
+ int lower_priority = 127;
+ bool found_free = false;
+
+ for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (!_track[l].used && !_track[l].handle.isActive())
+ found_free = true;
+ }
+
+ if (!found_free) {
+ warning("IMuseDigital::startSound(): All slots are full");
+ for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (_track[l].used && _track[l].handle.isActive() &&
+ (lower_priority > _track[l].priority) && (!_track[l].stream2))
+ lower_priority = _track[l].priority;
+ }
+ if (lower_priority <= priority) {
+ int track_id = -1;
+ for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (_track[l].used && _track[l].handle.isActive() &&
+ (lower_priority == _track[l].priority) && (!_track[l].stream2)) {
+ track_id = l;
+ }
+ }
+ assert(track_id != -1);
+ _track[track_id].stream->finish();
+ _track[track_id].stream = NULL;
+ _vm->_mixer->stopHandle(_track[track_id].handle);
+ _sound->closeSound(_track[track_id].soundHandle);
+ _track[track_id].used = false;
+ assert(!_track[track_id].handle.isActive());
+ warning("IMuseDigital::startSound(): Removed sound %d from track %d", _track[track_id].soundId, track_id);
+ } else {
+ warning("IMuseDigital::startSound(): Priority sound too low");
+ return;
+ }
+ }
+}
+
+void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, int volGroupId, AudioStream *input, int hookId, int volume, int priority) {
+ Common::StackLock lock(_mutex, "IMuseDigital::startSound()");
+ debug(5, "IMuseDigital::startSound(%d)", soundId);
+ int l;
+
+ allocSlot(priority);
+
+ for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (!_track[l].used && !_track[l].handle.isActive()) {
+ _track[l].pan = 64;
+ _track[l].vol = volume * 1000;
+ _track[l].volFadeDest = 0;
+ _track[l].volFadeStep = 0;
+ _track[l].volFadeDelay = 0;
+ _track[l].volFadeUsed = false;
+ _track[l].soundId = soundId;
+ _track[l].started = false;
+ _track[l].volGroupId = volGroupId;
+ _track[l].curHookId = hookId;
+ _track[l].priority = priority;
+ _track[l].curRegion = -1;
+ _track[l].dataOffset = 0;
+ _track[l].regionOffset = 0;
+ _track[l].trackOffset = 0;
+ _track[l].mod = 0;
+ _track[l].toBeRemoved = false;
+
+ int bits = 0, freq = 0, channels = 0, mixerFlags = 0;
+
+ if (input) {
+ _track[l].iteration = 1; // ?
+ // Do nothing here, we already have an audio stream
+ } else {
+ _track[l].soundHandle = _sound->openSound(soundId, soundName, soundType, volGroupId);
+
+ if (_track[l].soundHandle == NULL)
+ return;
+
+ bits = _sound->getBits(_track[l].soundHandle);
+ channels = _sound->getChannels(_track[l].soundHandle);
+ freq = _sound->getFreq(_track[l].soundHandle);
+
+ if ((soundId == kTalkSoundID) && (soundType == IMUSE_BUNDLE)) {
+ if (_vm->_actorToPrintStrFor != 0xFF && _vm->_actorToPrintStrFor != 0) {
+ Actor *a = _vm->derefActor(_vm->_actorToPrintStrFor, "IMuseDigital::startSound");
+ freq = (freq * a->talkFrequency) / 256;
+ _track[l].pan = a->talkPan;
+ _track[l].vol = a->talkVolume * 1000;
+ }
+ }
+
+ assert(bits == 8 || bits == 12 || bits == 16);
+ assert(channels == 1 || channels == 2);
+ assert(0 < freq && freq <= 65535);
+
+ // Round the frequency to a multiple of 25. This is done to
+ // ensure we don't run into data under-/overflows (this is a
+ // design limitation of the current IMuseDigital code, which
+ // pushes data 'blindly' into the mixer, instead of providing
+ // a pull based interface, i.e. a custom AudioInputStream
+ // subclass).
+ freq -= (freq % 25);
+
+ _track[l].iteration = _track[l].pullSize = freq * channels;
+
+ if (channels == 2)
+ mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
+
+ if ((bits == 12) || (bits == 16)) {
+ mixerFlags |= SoundMixer::FLAG_16BITS;
+ _track[l].iteration = _track[l].pullSize *= 2;
+ } else if (bits == 8) {
+ mixerFlags |= SoundMixer::FLAG_UNSIGNED;
+ } else
+ error("IMuseDigital::startSound(): Can't handle %d bit samples", bits);
+
+ _track[l].pullSize /= 25; // We want a "frame rate" of 25 audio blocks per second
+ }
+
+ if (input) {
+ _track[l].stream2 = input;
+ _track[l].stream = NULL;
+ } else {
+ _track[l].stream2 = NULL;
+ _track[l].stream = makeAppendableAudioStream(freq, mixerFlags, 100000);
+ _vm->_mixer->playInputStream(&_track[l].handle, _track[l].stream, false, _track[l].vol / 1000, _track[l].pan, -1);
+ }
+
+ _track[l].used = true;
+ return;
+ }
+ }
+
+ warning("it should not happen");
+ assert(0);
+}
+
+void IMuseDigital::setPriority(int soundId, int priority) {
+ Common::StackLock lock(_mutex, "IMuseDigital::setPriority()");
+ debug(5, "IMuseDigital::setPriority(%d, %d)", soundId, priority);
+
+ assert ((priority >= 0) && (priority <= 127));
+
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == soundId) && _track[l].used) {
+ _track[l].priority = priority;
+ }
+ }
+}
+
+void IMuseDigital::setVolume(int soundId, int volume) {
+ Common::StackLock lock(_mutex, "IMuseDigital::setVolume()");
+ debug(5, "IMuseDigital::setVolume(%d, %d)", soundId, volume);
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == soundId) && _track[l].used) {
+ _track[l].vol = volume * 1000;
+ }
+ }
+}
+
+void IMuseDigital::setPan(int soundId, int pan) {
+ Common::StackLock lock(_mutex, "IMuseDigital::setPan()");
+ debug(5, "IMuseDigital::setPan(%d, %d)", soundId, pan);
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == soundId) && _track[l].used) {
+ _track[l].pan = pan;
+ }
+ }
+}
+
+void IMuseDigital::selectVolumeGroup(int soundId, int volGroupId) {
+ Common::StackLock lock(_mutex, "IMuseDigital::setGroupVolume()");
+ debug(5, "IMuseDigital::setGroupVolume(%d, %d)", soundId, volGroupId);
+ assert((volGroupId >= 1) && (volGroupId <= 3));
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == soundId) && _track[l].used) {
+ _track[l].volGroupId = volGroupId;
+ }
+ }
+}
+
+void IMuseDigital::setFade(int soundId, int destVolume, int delay60HzTicks) {
+ Common::StackLock lock(_mutex, "IMuseDigital::setFade()");
+ debug(5, "IMuseDigital::setFade(%d, %d, %d)", soundId, destVolume, delay60HzTicks);
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].soundId == soundId) && _track[l].used) {
+ _track[l].volFadeDelay = delay60HzTicks;
+ _track[l].volFadeDest = destVolume * 1000;
+ _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * delay60HzTicks);
+ _track[l].volFadeUsed = true;
+ }
+ }
+}
+
+void IMuseDigital::fadeOutMusic(int fadeDelay) {
+ Common::StackLock lock(_mutex, "IMuseDigital::fadeOutMusic()");
+ debug(5, "IMuseDigital::fadeOutMusic");
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].used) && (_track[l].volGroupId == IMUSE_VOLGRP_MUSIC) && (!_track[l].volFadeUsed)) {
+ _track[l].volFadeDelay = fadeDelay;
+ _track[l].volFadeDest = 0;
+ _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * fadeDelay);
+ _track[l].volFadeUsed = true;
+ }
+ }
+}
+
+} // End of namespace Scumm
diff --git a/scumm/module.mk b/scumm/module.mk
index 220adc6327..01a6de5db8 100644
--- a/scumm/module.mk
+++ b/scumm/module.mk
@@ -50,6 +50,8 @@ MODULE_OBJS := \
scumm/imuse_digi/dimuse_codecs.o \
scumm/imuse_digi/dimuse_music.o \
scumm/imuse_digi/dimuse_sndmgr.o \
+ scumm/imuse_digi/dimuse_script.o \
+ scumm/imuse_digi/dimuse_track.o \
scumm/imuse_digi/dimuse_tables.o \
scumm/insane/insane.o \
scumm/insane/insane_ben.o \