diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | scumm/imuse_digi/dimuse.cpp | 181 | ||||
-rw-r--r-- | scumm/imuse_digi/dimuse.h | 8 | ||||
-rw-r--r-- | scumm/imuse_digi/dimuse_script.cpp | 62 | ||||
-rw-r--r-- | scumm/imuse_digi/dimuse_sndmgr.cpp | 17 | ||||
-rw-r--r-- | scumm/imuse_digi/dimuse_sndmgr.h | 5 | ||||
-rw-r--r-- | scumm/imuse_digi/dimuse_track.cpp | 202 |
7 files changed, 289 insertions, 187 deletions
@@ -256,7 +256,6 @@ SCUMM * Fix codec44 for nut fonts * iMUSE Digital: - Fix music code (done, but not tested yet) - - Implement 'fade buffers' stuff, to handle fadeParam in JUMP opcode - Implement pool method data transfer between imuse and sound mixer - Add save/load code - Add code for MP3 and Ogg Vorbis compressed datafiles diff --git a/scumm/imuse_digi/dimuse.cpp b/scumm/imuse_digi/dimuse.cpp index 86b955cd7c..7a1add676c 100644 --- a/scumm/imuse_digi/dimuse.cpp +++ b/scumm/imuse_digi/dimuse.cpp @@ -50,6 +50,10 @@ IMuseDigital::IMuseDigital(ScummEngine *scumm) _volSfx = 0; _volMusic = 0; resetState(); + for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { + _track[l] = new Track; + _track[l]->used = false; + } _vm->_timer->installTimerProc(timer_handler, 1000000 / 25, this); } @@ -59,6 +63,9 @@ IMuseDigital::~IMuseDigital() { Common::StackLock lock(_mutex, "IMuseDigital::~IMuseDigital()"); _vm->_timer->removeTimerProc(timer_handler); } + for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { + delete _track[l]; + } delete _sound; g_system->deleteMutex(_mutex); } @@ -78,113 +85,114 @@ void IMuseDigital::callback() { if (_pause || !_vm) return; - for (l = 0; l < MAX_DIGITAL_TRACKS;l ++) { - if (_track[l].used) { - if (_track[l].stream2) { - if (!_track[l].handle.isActive() && _track[l].started) { - debug(5, "IMuseDigital::callback() A: stopped sound: %d", _track[l].soundId); - delete _track[l].stream2; - _track[l].stream2 = NULL; - _track[l].used = false; + for (l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { + if (_track[l]->used) { + if (_track[l]->stream2) { + if (!_track[l]->handle.isActive() && _track[l]->started) { + debug(5, "IMuseDigital::callback() A: stopped sound: %d", _track[l]->soundId); + delete _track[l]->stream2; + _track[l]->stream2 = NULL; + _track[l]->used = false; continue; } - } else if (_track[l].stream) { - if (_track[l].toBeRemoved) { - debug(5, "IMuseDigital::callback() B: stopped sound: %d", _track[l].soundId); - _track[l].stream->finish(); - _track[l].stream = NULL; - _sound->closeSound(_track[l].soundHandle); - _track[l].used = false; + } else if (_track[l]->stream) { + if (_track[l]->toBeRemoved) { + debug(5, "IMuseDigital::callback() B: stopped sound: %d", _track[l]->soundId); + _track[l]->stream->finish(); + _track[l]->stream = NULL; + _sound->closeSound(_track[l]->soundHandle); + _track[l]->soundHandle = NULL; + _track[l]->used = false; continue; } } - if (_track[l].volFadeUsed) { - if (_track[l].volFadeStep < 0) { - if (_track[l].vol > _track[l].volFadeDest) { - _track[l].vol += _track[l].volFadeStep; - if (_track[l].vol < _track[l].volFadeDest) { - _track[l].vol = _track[l].volFadeDest; - _track[l].volFadeUsed = false; + if (_track[l]->volFadeUsed) { + if (_track[l]->volFadeStep < 0) { + if (_track[l]->vol > _track[l]->volFadeDest) { + _track[l]->vol += _track[l]->volFadeStep; + if (_track[l]->vol < _track[l]->volFadeDest) { + _track[l]->vol = _track[l]->volFadeDest; + _track[l]->volFadeUsed = false; } - if (_track[l].vol == 0) { - _track[l].toBeRemoved = true; + if (_track[l]->vol == 0) { + _track[l]->toBeRemoved = true; } } - } else if (_track[l].volFadeStep > 0) { - if (_track[l].vol < _track[l].volFadeDest) { - _track[l].vol += _track[l].volFadeStep; - if (_track[l].vol > _track[l].volFadeDest) { - _track[l].vol = _track[l].volFadeDest; - _track[l].volFadeUsed = false; + } else if (_track[l]->volFadeStep > 0) { + if (_track[l]->vol < _track[l]->volFadeDest) { + _track[l]->vol += _track[l]->volFadeStep; + if (_track[l]->vol > _track[l]->volFadeDest) { + _track[l]->vol = _track[l]->volFadeDest; + _track[l]->volFadeUsed = false; } } } - debug(5, "Fade: sound(%d), Vol(%d)", _track[l].soundId, _track[l].vol / 1000); + debug(5, "Fade: sound(%d), Vol(%d)", _track[l]->soundId, _track[l]->vol / 1000); } - int pan = (_track[l].pan != 64) ? 2 * _track[l].pan - 127 : 0; - int vol = _track[l].vol / 1000; + int pan = (_track[l]->pan != 64) ? 2 * _track[l]->pan - 127 : 0; + int vol = _track[l]->vol / 1000; - if (_track[l].volGroupId == 1) + if (_track[l]->volGroupId == 1) vol = (vol * _volVoice) / 128; - if (_track[l].volGroupId == 2) + if (_track[l]->volGroupId == 2) vol = (vol * _volSfx) / 128; - if (_track[l].volGroupId == 3) + if (_track[l]->volGroupId == 3) vol = (vol * _volMusic) / 128; if (_vm->_mixer->isReady()) { - if (_track[l].stream2) { - if (!_track[l].started) { - _track[l].started = true; - _vm->_mixer->playInputStream(&_track[l].handle, _track[l].stream2, false, _track[l].vol / 1000, _track[l].pan, -1, false); + if (_track[l]->stream2) { + if (!_track[l]->started) { + _track[l]->started = true; + _vm->_mixer->playInputStream(&_track[l]->handle, _track[l]->stream2, false, _track[l]->vol / 1000, _track[l]->pan, -1, false); } else { - _vm->_mixer->setChannelVolume(_track[l].handle, vol); - _vm->_mixer->setChannelBalance(_track[l].handle, pan); + _vm->_mixer->setChannelVolume(_track[l]->handle, vol); + _vm->_mixer->setChannelBalance(_track[l]->handle, pan); } continue; } } - if (_track[l].stream) { - int32 mixer_size = _track[l].pullSize; + if (_track[l]->stream) { + int32 mixer_size = _track[l]->pullSize; byte *data = NULL; int32 result = 0; - if (_track[l].stream->endOfData()) { + if (_track[l]->stream->endOfData()) { mixer_size *= 2; } - if (_track[l].curRegion == -1) + if (_track[l]->curRegion == -1) switchToNextRegion(l); - int bits = _sound->getBits(_track[l].soundHandle); + int bits = _sound->getBits(_track[l]->soundHandle); do { if (bits == 12) { byte *ptr = NULL; - mixer_size += _track[l].mod; + mixer_size += _track[l]->mod; int mixer_size_12 = (mixer_size * 3) / 4; int length = (mixer_size_12 / 3) * 4; - _track[l].mod = mixer_size - length; + _track[l]->mod = mixer_size - length; - int32 offset = (_track[l].regionOffset * 3) / 4; - int result2 = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &ptr, offset, mixer_size_12); + int32 offset = (_track[l]->regionOffset * 3) / 4; + int result2 = _sound->getDataFromRegion(_track[l]->soundHandle, _track[l]->curRegion, &ptr, offset, mixer_size_12); result = BundleCodecs::decode12BitsSample(ptr, &data, result2); free(ptr); } else if (bits == 16) { - result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &data, _track[l].regionOffset, mixer_size); - if (_sound->getChannels(_track[l].soundHandle) == 1) { + result = _sound->getDataFromRegion(_track[l]->soundHandle, _track[l]->curRegion, &data, _track[l]->regionOffset, mixer_size); + if (_sound->getChannels(_track[l]->soundHandle) == 1) { result &= ~1; } - if (_sound->getChannels(_track[l].soundHandle) == 2) { + if (_sound->getChannels(_track[l]->soundHandle) == 2) { if (result & 2) result &= ~2; } } else if (bits == 8) { - result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &data, _track[l].regionOffset, mixer_size); - if (_sound->getChannels(_track[l].soundHandle) == 2) { + result = _sound->getDataFromRegion(_track[l]->soundHandle, _track[l]->curRegion, &data, _track[l]->regionOffset, mixer_size); + if (_sound->getChannels(_track[l]->soundHandle) == 2) { result &= ~1; } } @@ -193,17 +201,17 @@ void IMuseDigital::callback() { result = mixer_size; if (_vm->_mixer->isReady()) { - _vm->_mixer->setChannelVolume(_track[l].handle, vol); - _vm->_mixer->setChannelBalance(_track[l].handle, pan); - _track[l].stream->append(data, result); - _track[l].regionOffset += result; - _track[l].trackOffset += result; + _vm->_mixer->setChannelVolume(_track[l]->handle, vol); + _vm->_mixer->setChannelBalance(_track[l]->handle, pan); + _track[l]->stream->append(data, result); + _track[l]->regionOffset += result; + _track[l]->trackOffset += result; free(data); } - if (_sound->isEndOfRegion(_track[l].soundHandle, _track[l].curRegion)) { + if (_sound->isEndOfRegion(_track[l]->soundHandle, _track[l]->curRegion)) { switchToNextRegion(l); - if (_track[l].toBeRemoved) + if (_track[l]->toBeRemoved) break; } mixer_size -= result; @@ -215,36 +223,51 @@ void IMuseDigital::callback() { } void IMuseDigital::switchToNextRegion(int track) { - int num_regions = _sound->getNumRegions(_track[track].soundHandle); + if (track >= MAX_DIGITAL_TRACKS) { + _track[track]->toBeRemoved = true; + return; + } + + int num_regions = _sound->getNumRegions(_track[track]->soundHandle); - if (++_track[track].curRegion == num_regions) { - _track[track].toBeRemoved = true; + if (++_track[track]->curRegion == num_regions) { + _track[track]->toBeRemoved = true; return; } - int jumpId = _sound->getJumpIdByRegionAndHookId(_track[track].soundHandle, _track[track].curRegion, _track[track].curHookId); + int jumpId = _sound->getJumpIdByRegionAndHookId(_track[track]->soundHandle, _track[track]->curRegion, _track[track]->curHookId); if (jumpId == -1) - jumpId = _sound->getJumpIdByRegionAndHookId(_track[track].soundHandle, _track[track].curRegion, 0); + jumpId = _sound->getJumpIdByRegionAndHookId(_track[track]->soundHandle, _track[track]->curRegion, 0); if (jumpId != -1) { - int region = _sound->getRegionIdByJumpId(_track[track].soundHandle, jumpId); + int region = _sound->getRegionIdByJumpId(_track[track]->soundHandle, jumpId); assert(region != -1); - int sampleHookId = _sound->getJumpHookId(_track[track].soundHandle, jumpId); + int sampleHookId = _sound->getJumpHookId(_track[track]->soundHandle, jumpId); assert(sampleHookId != -1); + int fadeDelay = (60 * _sound->getJumpFade(_track[track]->soundHandle, jumpId)) / 1000; if (sampleHookId != 0) { - if (_track[track].curHookId == sampleHookId) { - _track[track].curRegion = region; - debug(5, "switchToNextRegion-sound(%d) jump to %d region, curHookId: %d", _track[track].soundId, _track[track].curRegion, _track[track].curHookId); - _track[track].curHookId = 0; + if (_track[track]->curHookId == sampleHookId) { + int fadeTrack = cloneToFadeOutTrack(track, fadeDelay, false); + _track[fadeTrack]->dataOffset = _sound->getRegionOffset(_track[fadeTrack]->soundHandle, _track[fadeTrack]->curRegion); + _track[fadeTrack]->regionOffset = 0; + debug(5, "switchToNextRegion-sound(%d) select %d region, curHookId: %d", _track[fadeTrack]->soundId, _track[fadeTrack]->curRegion, _track[fadeTrack]->curHookId); + _track[track]->curRegion = region; + debug(5, "switchToNextRegion-sound(%d) jump to %d region, curHookId: %d", _track[track]->soundId, _track[track]->curRegion, _track[track]->curHookId); + _track[track]->curHookId = 0; + _track[fadeTrack]->curHookId = 0; } } else { - _track[track].curRegion = region; - debug(5, "switchToNextRegion-sound(%d) jump to %d region, curHookId: %d", _track[track].soundId, _track[track].curRegion, _track[track].curHookId); + int fadeTrack = cloneToFadeOutTrack(track, fadeDelay, false); + _track[fadeTrack]->dataOffset = _sound->getRegionOffset(_track[fadeTrack]->soundHandle, _track[fadeTrack]->curRegion); + _track[fadeTrack]->regionOffset = 0; + debug(5, "switchToNextRegion-sound(%d) select %d region, curHookId: %d", _track[fadeTrack]->soundId, _track[fadeTrack]->curRegion, _track[fadeTrack]->curHookId); + _track[track]->curRegion = region; + debug(5, "switchToNextRegion-sound(%d) jump to %d region, curHookId: %d", _track[track]->soundId, _track[track]->curRegion, _track[track]->curHookId); } } - debug(5, "switchToNextRegion-sound(%d) select %d region, curHookId: %d", _track[track].soundId, _track[track].curRegion, _track[track].curHookId); - _track[track].dataOffset = _sound->getRegionOffset(_track[track].soundHandle, _track[track].curRegion); - _track[track].regionOffset = 0; + debug(5, "switchToNextRegion-sound(%d) select %d region, curHookId: %d", _track[track]->soundId, _track[track]->curRegion, _track[track]->curHookId); + _track[track]->dataOffset = _sound->getRegionOffset(_track[track]->soundHandle, _track[track]->curRegion); + _track[track]->regionOffset = 0; } } // End of namespace Scumm diff --git a/scumm/imuse_digi/dimuse.h b/scumm/imuse_digi/dimuse.h index 61a4c8da4c..1e1763762a 100644 --- a/scumm/imuse_digi/dimuse.h +++ b/scumm/imuse_digi/dimuse.h @@ -34,6 +34,7 @@ namespace Scumm { #define MAX_DIGITAL_TRACKS 8 +#define MAX_DIGITAL_FADETRACKS 8 struct imuseDigTable; struct imuseComiTable; @@ -63,6 +64,8 @@ private: int iteration; int mod; int32 pullSize; + int32 mixerFlags; + ImuseDigiSndMgr::soundStruct *soundHandle; PlayingSoundHandle handle; AppendableAudioStream *stream; @@ -71,7 +74,7 @@ private: Track(); }; - Track _track[MAX_DIGITAL_TRACKS]; + Track *_track[MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS]; OSystem::MutexRef _mutex; ScummEngine *_vm; @@ -94,12 +97,14 @@ private: void switchToNextRegion(int track); void allocSlot(int priority); void startSound(int soundId, const char *soundName, int soundType, int volGroupId, AudioStream *input, int hookId, int volume, int priority); + void selectVolumeGroup(int soundId, int volGroupId); int32 getPosInMs(int soundId); void getLipSync(int soundId, int syncId, int32 msPos, int32 &width, int32 &height); int getSoundIdByName(const char *soundName); void fadeOutMusic(int fadeDelay); + int cloneToFadeOutTrack(int track, int fadeDelay, int killNormalTrack); void setFtMusicState(int stateId); void setFtMusicSequence(int seqId); @@ -139,7 +144,6 @@ public: void setVolume(int soundId, int volume); void setPan(int soundId, int pan); void setFade(int soundId, int destVolume, int delay60HzTicks); - 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_script.cpp b/scumm/imuse_digi/dimuse_script.cpp index fb26ce6120..abc0acc5f5 100644 --- a/scumm/imuse_digi/dimuse_script.cpp +++ b/scumm/imuse_digi/dimuse_script.cpp @@ -163,7 +163,7 @@ void IMuseDigital::refreshScripts() { Common::StackLock lock(_mutex, "IMuseDigital::refreshScripts()"); bool found = false; for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { - if ((_track[l].used) && (_track[l].volGroupId == IMUSE_VOLGRP_MUSIC) && (!_track[l].volFadeUsed)) { + if ((_track[l]->used) && (_track[l]->volGroupId == IMUSE_VOLGRP_MUSIC)) { found = true; } } @@ -175,7 +175,7 @@ void IMuseDigital::refreshScripts() { void IMuseDigital::startVoice(int soundId, AudioStream *input) { debug(5, "startVoiceStream(%d)", soundId); - startSound(soundId, NULL, 0, IMUSE_VOLGRP_VOICE, input, 0, 127, 127); + startSound(soundId, "", 0, IMUSE_VOLGRP_VOICE, input, 0, 127, 127); } void IMuseDigital::startVoice(int soundId, const char *soundName) { @@ -185,7 +185,7 @@ void IMuseDigital::startVoice(int soundId, const char *soundName) { void IMuseDigital::startMusic(int soundId, int volume) { debug(5, "startMusicResource(%d)", soundId); - startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_VOLGRP_MUSIC, NULL, 0, volume, 126); + startSound(soundId, "", IMUSE_RESOURCE, IMUSE_VOLGRP_MUSIC, NULL, 0, volume, 126); } void IMuseDigital::startMusic(const char *soundName, int soundId, int hookId, int volume) { @@ -195,7 +195,7 @@ void IMuseDigital::startMusic(const char *soundName, int soundId, int hookId, in void IMuseDigital::startSfx(int soundId, int priority) { debug(5, "startSfx(%d)", soundId); - startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_VOLGRP_SFX, NULL, 0, 127, priority); + startSound(soundId, "", IMUSE_RESOURCE, IMUSE_VOLGRP_SFX, NULL, 0, 127, priority); } void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width, int32 &height) { @@ -205,8 +205,8 @@ void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width 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 ((_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--) { @@ -231,8 +231,8 @@ void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width 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); + if ((_track[l]->soundId == soundId) && (_track[l]->used)) { + int32 pos = (5 * (_track[l]->dataOffset + _track[l]->regionOffset)) / (_track[l]->iteration / 200); return pos; } } @@ -244,7 +244,7 @@ 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) { + if ((_track[l]->soundId == sound) && _track[l]->used) { return 1; } } @@ -256,12 +256,12 @@ 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; + 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); + else if (_track[l]->stream2) + _vm->_mixer->stopHandle(_track[l]->handle); } } } @@ -271,8 +271,8 @@ int32 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; + if ((_track[l]->used) && (_track[l]->volGroupId == IMUSE_VOLGRP_MUSIC)) { + soundId = _track[l]->soundId; } } @@ -306,8 +306,8 @@ int32 IMuseDigital::getCurMusicLipSyncWidth(int syncId) { 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; + if ((_track[l]->used) && (_track[l]->volGroupId == IMUSE_VOLGRP_MUSIC)) { + soundId = _track[l]->soundId; } } @@ -324,8 +324,8 @@ int32 IMuseDigital::getCurMusicLipSyncHeight(int syncId) { 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; + if ((_track[l]->used) && (_track[l]->volGroupId == IMUSE_VOLGRP_MUSIC)) { + soundId = _track[l]->soundId; } } @@ -341,12 +341,12 @@ 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); + for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { + if (_track[l]->used) { + if (_track[l]->stream) { + _track[l]->toBeRemoved = true; + } else if (_track[l]->stream2) + _vm->_mixer->stopHandle(_track[l]->handle); } } } @@ -355,8 +355,8 @@ void IMuseDigital::stopAllSounds(bool waitForStop) { bool used; do { used = false; - for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { - if (_track[l].used) + for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { + if (_track[l]->used) used = true; } g_system->delay_msecs(10); @@ -366,9 +366,9 @@ void IMuseDigital::stopAllSounds(bool waitForStop) { 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); + for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { + if (_track[l]->used) { + _vm->_mixer->pauseHandle(_track[l]->handle, p); } } _pause = p; diff --git a/scumm/imuse_digi/dimuse_sndmgr.cpp b/scumm/imuse_digi/dimuse_sndmgr.cpp index 63d2d2c0f0..7664c08713 100644 --- a/scumm/imuse_digi/dimuse_sndmgr.cpp +++ b/scumm/imuse_digi/dimuse_sndmgr.cpp @@ -286,7 +286,8 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch bool result = false; byte *ptr = NULL; - if (soundName == NULL) { + if (soundName[0] == 0) { + _sounds[slot].name[0] = 0; if ((soundType == IMUSE_RESOURCE)) { ptr = _vm->getResourceAddress(rtSound, soundId); if (ptr == NULL) { @@ -294,6 +295,9 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch return NULL; } _sounds[slot].resPtr = ptr; + _sounds[slot].soundId = soundId; + _sounds[slot].type = soundType; + _sounds[slot].volGroupId = volGroupId; result = true; } else if (soundType == IMUSE_BUNDLE) { bool header_outside = ((_vm->_gameId == GID_CMI) && !(_vm->_features & GF_DEMO)); @@ -304,8 +308,9 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch 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].name[0] = 0; _sounds[slot].soundId = soundId; + _sounds[slot].type = soundType; + _sounds[slot].volGroupId = volGroupId; } else { error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId); } @@ -321,6 +326,8 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch _sounds[slot].bundle->decompressSampleByName(soundName, 0, 0x2000, &ptr, header_outside); strcpy(_sounds[slot].name, soundName); _sounds[slot].soundId = soundId; + _sounds[slot].type = soundType; + _sounds[slot].volGroupId = volGroupId; } else { error("ImuseDigiSndMgr::openSound() Don't know how load sound: %s", soundName); } @@ -350,6 +357,12 @@ void ImuseDigiSndMgr::closeSound(soundStruct *soundHandle) { memset(soundHandle, 0, sizeof(soundStruct)); } +ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::cloneSound(soundStruct *soundHandle) { + assert(soundHandle && checkForProperHandle(soundHandle)); + + return openSound(soundHandle->soundId, soundHandle->name, soundHandle->type, soundHandle->volGroupId); +} + bool ImuseDigiSndMgr::checkForProperHandle(soundStruct *soundHandle) { for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { if (soundHandle == &_sounds[l]) diff --git a/scumm/imuse_digi/dimuse_sndmgr.h b/scumm/imuse_digi/dimuse_sndmgr.h index c6055e5e0a..ba9f28b852 100644 --- a/scumm/imuse_digi/dimuse_sndmgr.h +++ b/scumm/imuse_digi/dimuse_sndmgr.h @@ -81,6 +81,8 @@ public: char name[15]; int16 soundId; BundleMgr *bundle; + int type; + int volGroupId; }; private: @@ -105,8 +107,9 @@ public: ImuseDigiSndMgr(ScummEngine *scumm); ~ImuseDigiSndMgr(); - soundStruct * openSound(int32 soundId, const char *soundName, int soundType, int volGroupId); + soundStruct *openSound(int32 soundId, const char *soundName, int soundType, int volGroupId); void closeSound(soundStruct *soundHandle); + soundStruct *cloneSound(soundStruct *soundHandle); int getFreq(soundStruct *soundHandle); int getBits(soundStruct *soundHandle); diff --git a/scumm/imuse_digi/dimuse_track.cpp b/scumm/imuse_digi/dimuse_track.cpp index be15e46fa9..8f70edabe3 100644 --- a/scumm/imuse_digi/dimuse_track.cpp +++ b/scumm/imuse_digi/dimuse_track.cpp @@ -38,33 +38,33 @@ void IMuseDigital::allocSlot(int priority) { bool found_free = false; for (l = 0; l < MAX_DIGITAL_TRACKS; l++) { - if (!_track[l].used && !_track[l].handle.isActive()) + 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 (_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)) { + 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); + _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; @@ -80,46 +80,47 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, 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 (!_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]->mixerFlags = 0; + _track[l]->toBeRemoved = false; + + int bits = 0, freq = 0, channels = 0; if (input) { - _track[l].iteration = 1; // ? + _track[l]->iteration = 1; // ? // Do nothing here, we already have an audio stream } else { - _track[l].soundHandle = _sound->openSound(soundId, soundName, soundType, volGroupId); + _track[l]->soundHandle = _sound->openSound(soundId, soundName, soundType, volGroupId); - if (_track[l].soundHandle == NULL) + if (_track[l]->soundHandle == NULL) return; - bits = _sound->getBits(_track[l].soundHandle); - channels = _sound->getChannels(_track[l].soundHandle); - freq = _sound->getFreq(_track[l].soundHandle); + 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; + _track[l]->pan = a->talkPan; + _track[l]->vol = a->talkVolume * 1000; } } @@ -135,32 +136,32 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, // subclass). freq -= (freq % 25); - _track[l].iteration = _track[l].pullSize = freq * channels; + _track[l]->iteration = _track[l]->pullSize = freq * channels; if (channels == 2) - mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO; + _track[l]->mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO; if ((bits == 12) || (bits == 16)) { - mixerFlags |= SoundMixer::FLAG_16BITS; - _track[l].iteration = _track[l].pullSize *= 2; + _track[l]->mixerFlags |= SoundMixer::FLAG_16BITS; + _track[l]->iteration = _track[l]->pullSize *= 2; } else if (bits == 8) { - mixerFlags |= SoundMixer::FLAG_UNSIGNED; + _track[l]->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 + _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; + _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]->stream2 = NULL; + _track[l]->stream = makeAppendableAudioStream(freq, _track[l]->mixerFlags, 100000); + _vm->_mixer->playInputStream(&_track[l]->handle, _track[l]->stream, false, _track[l]->vol / 1000, _track[l]->pan, -1); } - _track[l].used = true; + _track[l]->used = true; return; } } @@ -175,8 +176,8 @@ void IMuseDigital::setPriority(int soundId, int 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; + if ((_track[l]->soundId == soundId) && _track[l]->used) { + _track[l]->priority = priority; } } } @@ -185,8 +186,8 @@ 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; + if ((_track[l]->soundId == soundId) && _track[l]->used) { + _track[l]->vol = volume * 1000; } } } @@ -195,8 +196,8 @@ 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; + if ((_track[l]->soundId == soundId) && _track[l]->used) { + _track[l]->pan = pan; } } } @@ -210,8 +211,8 @@ void IMuseDigital::selectVolumeGroup(int soundId, int volGroupId) { volGroupId = 3; for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { - if ((_track[l].soundId == soundId) && _track[l].used) { - _track[l].volGroupId = volGroupId; + if ((_track[l]->soundId == soundId) && _track[l]->used) { + _track[l]->volGroupId = volGroupId; } } } @@ -220,11 +221,11 @@ 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; + 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; } } } @@ -233,13 +234,72 @@ 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; + if ((_track[l]->used) && (_track[l]->volGroupId == IMUSE_VOLGRP_MUSIC)) { + cloneToFadeOutTrack(l, fadeDelay, true); } } } +int IMuseDigital::cloneToFadeOutTrack(int track, int fadeDelay, int killNormalTrack) { + Common::StackLock lock(_mutex, "IMuseDigital::cloneToFadeOutTrack()"); + debug(5, "IMuseDigital::cloneToFadeOutTrack(%d, %d)", track, fadeDelay); + int fadeTrack = -1; + + for (int l = MAX_DIGITAL_TRACKS; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { + if (!_track[l]->used) { + fadeTrack = l; + break; + } + } + if (fadeTrack == -1) + error("IMuseDigital::cloneToFadeTrack() Can't find free fade track"); + + // swap track to fade track + Track *tmpTrack = _track[track]; + _track[track] = _track[fadeTrack]; + _track[fadeTrack] = tmpTrack; + + // copy track params from swaped fade track to new track + _track[track]->pan = _track[fadeTrack]->pan; + _track[track]->vol = _track[fadeTrack]->vol; + _track[track]->volGroupId = _track[fadeTrack]->volGroupId; + _track[track]->volFadeDelay = _track[fadeTrack]->volFadeDelay; + _track[track]->volFadeDest = _track[fadeTrack]->volFadeDest; + _track[track]->volFadeStep = _track[fadeTrack]->volFadeStep; + _track[track]->volFadeUsed = _track[fadeTrack]->volFadeUsed; + _track[track]->priority = _track[fadeTrack]->priority; + _track[track]->soundId = _track[fadeTrack]->soundId; + _track[track]->dataOffset = _track[fadeTrack]->dataOffset; + _track[track]->regionOffset = _track[fadeTrack]->regionOffset; + _track[track]->trackOffset = _track[fadeTrack]->trackOffset; + _track[track]->curRegion = _track[fadeTrack]->curRegion; + _track[track]->curHookId = _track[fadeTrack]->curHookId; + _track[track]->iteration = _track[fadeTrack]->iteration; + _track[track]->mixerFlags = _track[fadeTrack]->mixerFlags; + _track[track]->mod = _track[fadeTrack]->mod; + _track[track]->pullSize = _track[fadeTrack]->pullSize; + _track[track]->used = _track[fadeTrack]->used; + _track[track]->toBeRemoved = _track[fadeTrack]->toBeRemoved; + _track[track]->started = _track[fadeTrack]->started; + _track[track]->stream2 = _track[fadeTrack]->stream2; + + _track[track]->soundHandle = NULL; + _track[track]->stream = NULL; + + _track[fadeTrack]->volFadeDelay = fadeDelay; + _track[fadeTrack]->volFadeDest = 0; + _track[fadeTrack]->volFadeStep = (_track[fadeTrack]->volFadeDest - _track[fadeTrack]->vol) * 60 * 40 / (1000 * fadeDelay); + _track[fadeTrack]->volFadeUsed = true; + + if (killNormalTrack) { + _track[track]->used = false; + } else { + _track[track]->soundHandle = _sound->cloneSound(_track[fadeTrack]->soundHandle); + _track[track]->stream = makeAppendableAudioStream(_sound->getFreq(_track[track]->soundHandle), _track[track]->mixerFlags, 100000); + _vm->_mixer->playInputStream(&_track[track]->handle, _track[track]->stream, false, _track[track]->vol / 1000, _track[track]->pan, -1); + } + + return fadeTrack; +} + } // End of namespace Scumm |