mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
285 lines
7.7 KiB
C++
285 lines
7.7 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
|
|
#include "common/scummsys.h"
|
|
|
|
#include "audio/audiostream.h"
|
|
#include "audio/decoders/flac.h"
|
|
#include "audio/decoders/voc.h"
|
|
#include "audio/decoders/vorbis.h"
|
|
#include "audio/decoders/mp3.h"
|
|
|
|
#include "scumm/resource.h"
|
|
#include "scumm/scumm.h"
|
|
#include "scumm/imuse_digi/dimuse_bndmgr.h"
|
|
#include "scumm/imuse_digi/dimuse_codecs.h"
|
|
#include "scumm/imuse_digi/dimuse_sndmgr.h"
|
|
|
|
namespace Scumm {
|
|
|
|
ImuseDigiSndMgr::ImuseDigiSndMgr(ScummEngine *scumm) {
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
memset(&_sounds[l], 0, sizeof(SoundDesc));
|
|
}
|
|
_vm = scumm;
|
|
_disk = 0;
|
|
_cacheBundleDir = new BundleDirCache(scumm);
|
|
assert(_cacheBundleDir);
|
|
BundleCodecs::initializeImcTables();
|
|
}
|
|
|
|
ImuseDigiSndMgr::~ImuseDigiSndMgr() {
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
closeSound(&_sounds[l]);
|
|
}
|
|
|
|
delete _cacheBundleDir;
|
|
BundleCodecs::releaseImcTables();
|
|
}
|
|
|
|
ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::allocSlot() {
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
if (!_sounds[l].inUse) {
|
|
_sounds[l].inUse = true;
|
|
_sounds[l].scheduledForDealloc = false;
|
|
return &_sounds[l];
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool ImuseDigiSndMgr::openMusicBundle(SoundDesc *sound, int &disk) {
|
|
bool result = false;
|
|
bool compressed = false;
|
|
|
|
sound->bundle = new BundleMgr(_vm, _cacheBundleDir);
|
|
assert(sound->bundle);
|
|
if (_vm->_game.id == GID_CMI) {
|
|
if (_vm->_game.features & GF_DEMO) {
|
|
result = sound->bundle->open("music.bun", compressed);
|
|
} else {
|
|
char musicfile[20];
|
|
if (disk == -1)
|
|
disk = _vm->VAR(_vm->VAR_CURRENTDISK);
|
|
Common::sprintf_s(musicfile, "musdisk%d.bun", disk);
|
|
// if (_disk != _vm->VAR(_vm->VAR_CURRENTDISK)) {
|
|
// _vm->_DiMUSE_v1->parseScriptCmds(0x1000, 0, 0, 0, 0, 0, 0, 0);
|
|
// _vm->_DiMUSE_v1->parseScriptCmds(0x2000, 0, 0, 0, 0, 0, 0, 0);
|
|
// _vm->_DiMUSE_v1->stopAllSounds();
|
|
// sound->bundle->closeFile();
|
|
// }
|
|
|
|
result = sound->bundle->open(musicfile, compressed);
|
|
|
|
// FIXME: Shouldn't we only set _disk if result == true?
|
|
_disk = (byte)_vm->VAR(_vm->VAR_CURRENTDISK);
|
|
}
|
|
} else if (_vm->_game.id == GID_DIG)
|
|
result = sound->bundle->open("digmusic.bun", compressed);
|
|
else
|
|
error("ImuseDigiSndMgr::openMusicBundle() Don't know which bundle file to load");
|
|
|
|
_vm->VAR(_vm->VAR_MUSIC_BUNDLE_LOADED) = result ? 1 : 0;
|
|
|
|
return result;
|
|
}
|
|
|
|
bool ImuseDigiSndMgr::openVoiceBundle(SoundDesc *sound, int &disk) {
|
|
bool result = false;
|
|
bool compressed = false;
|
|
|
|
sound->bundle = new BundleMgr(_vm, _cacheBundleDir);
|
|
assert(sound->bundle);
|
|
if (_vm->_game.id == GID_CMI) {
|
|
if (_vm->_game.features & GF_DEMO) {
|
|
result = sound->bundle->open("voice.bun", compressed);
|
|
} else {
|
|
char voxfile[20];
|
|
if (disk == -1)
|
|
disk = _vm->VAR(_vm->VAR_CURRENTDISK);
|
|
Common::sprintf_s(voxfile, "voxdisk%d.bun", disk);
|
|
// if (_disk != _vm->VAR(_vm->VAR_CURRENTDISK)) {
|
|
// _vm->_DiMUSE_v1->parseScriptCmds(0x1000, 0, 0, 0, 0, 0, 0, 0);
|
|
// _vm->_DiMUSE_v1->parseScriptCmds(0x2000, 0, 0, 0, 0, 0, 0, 0);
|
|
// _vm->_DiMUSE_v1->stopAllSounds();
|
|
// sound->bundle->closeFile();
|
|
// }
|
|
|
|
result = sound->bundle->open(voxfile, compressed);
|
|
|
|
// FIXME: Shouldn't we only set _disk if result == true?
|
|
_disk = (byte)_vm->VAR(_vm->VAR_CURRENTDISK);
|
|
}
|
|
} else if (_vm->_game.id == GID_DIG)
|
|
result = sound->bundle->open("digvoice.bun", compressed);
|
|
else
|
|
error("ImuseDigiSndMgr::openVoiceBundle() Don't know which bundle file to load");
|
|
|
|
_vm->VAR(_vm->VAR_VOICE_BUNDLE_LOADED) = result ? 1 : 0;
|
|
|
|
return result;
|
|
}
|
|
|
|
ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk) {
|
|
assert(soundId >= 0);
|
|
assert(soundType);
|
|
|
|
SoundDesc *sound = allocSlot();
|
|
if (!sound) {
|
|
error("ImuseDigiSndMgr::openSound() can't alloc free sound slot");
|
|
}
|
|
|
|
const bool header_outside = ((_vm->_game.id == GID_CMI) && !(_vm->_game.features & GF_DEMO));
|
|
bool result = false;
|
|
byte *ptr = nullptr;
|
|
|
|
switch (soundType) {
|
|
case IMUSE_RESOURCE:
|
|
assert(soundName[0] == 0); // Paranoia check
|
|
|
|
_vm->_res->lock(rtSound, soundId);
|
|
ptr = _vm->getResourceAddress(rtSound, soundId);
|
|
if (ptr == nullptr) {
|
|
closeSound(sound);
|
|
return nullptr;
|
|
}
|
|
sound->resPtr = ptr;
|
|
sound->resSize = _vm->getResourceSize(rtSound, soundId) - 8;
|
|
break;
|
|
case IMUSE_BUNDLE:
|
|
if (volGroupId == IMUSE_VOLGRP_VOICE)
|
|
result = openVoiceBundle(sound, disk);
|
|
else if (volGroupId == IMUSE_VOLGRP_MUSIC)
|
|
result = openMusicBundle(sound, disk);
|
|
else
|
|
error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
|
|
if (!result) {
|
|
closeSound(sound);
|
|
return nullptr;
|
|
}
|
|
|
|
if (soundName[0] != 0) {
|
|
if (sound->bundle->readFile(soundName, 0x2000, &ptr, header_outside) == 0 || ptr == nullptr) {
|
|
closeSound(sound);
|
|
free(ptr);
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
sound->resPtr = nullptr;
|
|
break;
|
|
default:
|
|
error("ImuseDigiSndMgr::openSound() Unknown soundType %d (trying to load sound %d)", soundType, soundId);
|
|
}
|
|
|
|
Common::strlcpy(sound->name, soundName, sizeof(sound->name));
|
|
sound->soundId = soundId;
|
|
|
|
if (soundType == IMUSE_BUNDLE) {
|
|
free(ptr);
|
|
}
|
|
return sound;
|
|
}
|
|
|
|
void ImuseDigiSndMgr::closeSound(SoundDesc *soundDesc) {
|
|
// Check if there's an actual sound to close...
|
|
if (!checkForProperHandle(soundDesc))
|
|
return;
|
|
|
|
if (soundDesc->resPtr) {
|
|
bool found = false;
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
if ((_sounds[l].soundId == soundDesc->soundId) && (&_sounds[l] != soundDesc))
|
|
found = true;
|
|
}
|
|
if (!found)
|
|
_vm->_res->unlock(rtSound, soundDesc->soundId);
|
|
}
|
|
|
|
delete soundDesc->bundle;
|
|
|
|
memset(soundDesc, 0, sizeof(SoundDesc));
|
|
}
|
|
|
|
ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::findSoundById(int soundId) {
|
|
SoundDesc *soundDesc = nullptr;
|
|
for (int i = 0; i < MAX_IMUSE_SOUNDS; i++) {
|
|
if (_sounds[i].soundId == soundId) {
|
|
soundDesc = &_sounds[i];
|
|
break;
|
|
}
|
|
}
|
|
return soundDesc;
|
|
}
|
|
|
|
ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::getSounds() {
|
|
return _sounds;
|
|
}
|
|
|
|
void ImuseDigiSndMgr::scheduleSoundForDeallocation(int soundId) {
|
|
SoundDesc *soundDesc = nullptr;
|
|
for (int i = 0; i < MAX_IMUSE_SOUNDS; i++) {
|
|
if (_sounds[i].soundId == soundId) {
|
|
soundDesc = &_sounds[i];
|
|
}
|
|
}
|
|
|
|
// Check if there's an actual sound to deallocate...
|
|
if (!checkForProperHandle(soundDesc))
|
|
return;
|
|
|
|
soundDesc->scheduledForDealloc = true;
|
|
}
|
|
|
|
void ImuseDigiSndMgr::closeSoundById(int soundId) {
|
|
SoundDesc *soundDesc = nullptr;
|
|
for (int i = 0; i < MAX_IMUSE_SOUNDS; i++) {
|
|
if (_sounds[i].soundId == soundId) {
|
|
soundDesc = &_sounds[i];
|
|
}
|
|
}
|
|
|
|
if (soundDesc) {
|
|
assert(checkForProperHandle(soundDesc));
|
|
|
|
if (soundDesc->resPtr) {
|
|
_vm->_res->unlock(rtSound, soundDesc->soundId);
|
|
}
|
|
|
|
delete soundDesc->bundle;
|
|
|
|
memset(soundDesc, 0, sizeof(SoundDesc));
|
|
}
|
|
}
|
|
|
|
bool ImuseDigiSndMgr::checkForProperHandle(SoundDesc *soundDesc) {
|
|
if (!soundDesc)
|
|
return false;
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
if (soundDesc == &_sounds[l])
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // End of namespace Scumm
|