2004-01-06 17:28:29 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
2005-01-01 16:09:25 +00:00
|
|
|
* Copyright (C) 2001-2005 The ScummVM project
|
2004-01-06 17:28:29 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2004-05-23 19:44:10 +00:00
|
|
|
* $Header$
|
2004-01-06 17:28:29 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "common/scummsys.h"
|
|
|
|
#include "common/util.h"
|
2005-04-10 12:59:17 +00:00
|
|
|
|
2004-01-06 17:28:29 +00:00
|
|
|
#include "sound/voc.h"
|
2005-01-25 22:21:26 +00:00
|
|
|
#include "sound/vorbis.h"
|
2005-01-28 11:03:34 +00:00
|
|
|
#include "sound/mp3.h"
|
2005-04-10 12:59:17 +00:00
|
|
|
|
2004-01-06 17:28:29 +00:00
|
|
|
#include "scumm/scumm.h"
|
2005-04-10 12:59:17 +00:00
|
|
|
#include "scumm/util.h"
|
2004-04-09 05:43:24 +00:00
|
|
|
#include "scumm/imuse_digi/dimuse.h"
|
2004-01-06 17:28:29 +00:00
|
|
|
#include "scumm/imuse_digi/dimuse_sndmgr.h"
|
|
|
|
#include "scumm/imuse_digi/dimuse_bndmgr.h"
|
|
|
|
|
|
|
|
namespace Scumm {
|
|
|
|
|
|
|
|
ImuseDigiSndMgr::ImuseDigiSndMgr(ScummEngine *scumm) {
|
2004-01-18 11:18:46 +00:00
|
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
|
|
memset(&_sounds[l], 0, sizeof(soundStruct));
|
|
|
|
}
|
2004-01-08 20:37:26 +00:00
|
|
|
_vm = scumm;
|
2004-01-06 17:28:29 +00:00
|
|
|
_disk = 0;
|
2004-01-07 04:50:38 +00:00
|
|
|
_cacheBundleDir = new BundleDirCache();
|
2004-01-06 17:28:29 +00:00
|
|
|
BundleCodecs::initializeImcTables();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImuseDigiSndMgr::~ImuseDigiSndMgr() {
|
|
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
2004-01-18 09:35:05 +00:00
|
|
|
closeSound(&_sounds[l]);
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
2004-01-08 12:14:48 +00:00
|
|
|
#ifdef __PALM_OS__
|
|
|
|
BundleCodecs::releaseImcTables();
|
|
|
|
#endif
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-04-06 19:46:43 +00:00
|
|
|
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'));
|
|
|
|
}
|
|
|
|
|
2005-01-25 22:21:26 +00:00
|
|
|
void ImuseDigiSndMgr::prepareSoundFromRMAP(File *file, soundStruct *sound, int32 offset, int32 size) {
|
|
|
|
int l;
|
|
|
|
|
|
|
|
file->seek(offset, SEEK_SET);
|
|
|
|
uint32 tag = file->readUint32BE();
|
|
|
|
assert(tag == 'RMAP');
|
2005-01-30 20:45:02 +00:00
|
|
|
int32 version = file->readUint32BE();
|
|
|
|
if (version != 2) {
|
|
|
|
error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 2, but it's: %d.", version);
|
|
|
|
}
|
|
|
|
sound->bits = file->readUint32BE();
|
|
|
|
sound->freq = file->readUint32BE();
|
|
|
|
sound->channels = file->readUint32BE();
|
2005-01-25 22:21:26 +00:00
|
|
|
sound->numRegions = file->readUint32BE();
|
|
|
|
sound->numJumps = file->readUint32BE();
|
|
|
|
sound->numSyncs = file->readUint32BE();
|
|
|
|
sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions);
|
|
|
|
sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps);
|
|
|
|
sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs);
|
|
|
|
for (l = 0; l < sound->numRegions; l++) {
|
|
|
|
sound->region[l].offset = file->readUint32BE();
|
|
|
|
sound->region[l].length = file->readUint32BE();
|
|
|
|
}
|
|
|
|
for (l = 0; l < sound->numJumps; l++) {
|
|
|
|
sound->jump[l].offset = file->readUint32BE();
|
|
|
|
sound->jump[l].dest = file->readUint32BE();
|
|
|
|
sound->jump[l].hookId = file->readUint32BE();
|
|
|
|
sound->jump[l].fadeDelay = file->readUint32BE();
|
|
|
|
}
|
|
|
|
for (l = 0; l < sound->numSyncs; l++) {
|
|
|
|
sound->sync[l].size = file->readUint32BE();
|
|
|
|
sound->sync[l].ptr = (byte *)malloc(sound->sync[l].size);
|
|
|
|
file->read(sound->sync[l].ptr, sound->sync[l].size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {
|
2004-01-06 17:28:29 +00:00
|
|
|
if (READ_UINT32(ptr) == MKID('Crea')) {
|
2004-04-06 19:46:43 +00:00
|
|
|
bool quit = false;
|
2004-04-25 19:51:46 +00:00
|
|
|
int len;
|
2004-04-06 19:46:43 +00:00
|
|
|
|
|
|
|
int32 offset = READ_LE_UINT16(ptr + 20);
|
|
|
|
int16 code = READ_LE_UINT16(ptr + 24);
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->region = (_region *)malloc(sizeof(_region) * 70);
|
|
|
|
sound->jump = (_jump *)malloc(sizeof(_jump));
|
|
|
|
sound->resPtr = ptr;
|
|
|
|
sound->bits = 8;
|
|
|
|
sound->channels = 1;
|
2004-04-06 19:46:43 +00:00
|
|
|
|
|
|
|
while (!quit) {
|
2004-04-25 19:51:46 +00:00
|
|
|
len = READ_LE_UINT32(ptr + offset);
|
2004-04-06 19:46:43 +00:00
|
|
|
code = len & 0xFF;
|
2004-04-25 19:51:46 +00:00
|
|
|
if ((code != 0) && (code != 1) && (code != 6) && (code != 7)) {
|
|
|
|
// try again with 2 bytes forward (workaround for some FT sounds (ex.362, 363)
|
|
|
|
offset += 2;
|
|
|
|
len = READ_LE_UINT32(ptr + offset);
|
|
|
|
code = len & 0xFF;
|
|
|
|
if ((code != 0) && (code != 1) && (code != 6) && (code != 7)) {
|
|
|
|
error("Invalid code in VOC file : %d", code);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
offset += 4;
|
2004-04-06 19:46:43 +00:00
|
|
|
len >>= 8;
|
|
|
|
switch(code) {
|
|
|
|
case 0:
|
|
|
|
quit = true;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
int time_constant = ptr[offset];
|
|
|
|
offset += 2;
|
|
|
|
len -= 2;
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->freq = getSampleRateFromVOCRate(time_constant);
|
|
|
|
sound->region[sound->numRegions].offset = offset;
|
|
|
|
sound->region[sound->numRegions].length = len;
|
|
|
|
sound->numRegions++;
|
2004-04-06 19:46:43 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 6: // begin of loop
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->jump[0].dest = offset + 8;
|
|
|
|
sound->jump[0].hookId = 0;
|
|
|
|
sound->jump[0].fadeDelay = 0;
|
2004-04-06 19:46:43 +00:00
|
|
|
break;
|
|
|
|
case 7: // end of loop
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->jump[0].offset = offset - 4;
|
|
|
|
sound->numJumps++;
|
|
|
|
sound->region[sound->numRegions].offset = offset - 4;
|
|
|
|
sound->region[sound->numRegions].length = 0;
|
|
|
|
sound->numRegions++;
|
2004-04-06 19:46:43 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("Invalid code in VOC file : %d", code);
|
|
|
|
quit = true;
|
|
|
|
break;
|
2004-02-14 15:14:30 +00:00
|
|
|
}
|
2004-04-06 19:46:43 +00:00
|
|
|
offset += len;
|
2004-02-14 15:14:30 +00:00
|
|
|
}
|
2004-01-06 17:28:29 +00:00
|
|
|
} else if (READ_UINT32(ptr) == MKID('iMUS')) {
|
|
|
|
uint32 tag;
|
|
|
|
int32 size = 0;
|
|
|
|
byte *s_ptr = ptr;
|
|
|
|
ptr += 16;
|
2004-04-06 19:46:43 +00:00
|
|
|
|
|
|
|
int curIndexRegion = 0;
|
|
|
|
int curIndexJump = 0;
|
|
|
|
int curIndexSync = 0;
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->numRegions = 0;
|
|
|
|
sound->numJumps = 0;
|
|
|
|
sound->numSyncs = 0;
|
|
|
|
countElements(ptr, sound->numRegions, sound->numJumps, sound->numSyncs);
|
|
|
|
sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions);
|
|
|
|
sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps);
|
|
|
|
sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs);
|
2004-04-06 19:46:43 +00:00
|
|
|
|
2004-01-06 17:28:29 +00:00
|
|
|
do {
|
|
|
|
tag = READ_BE_UINT32(ptr); ptr += 4;
|
|
|
|
switch(tag) {
|
|
|
|
case MKID_BE('FRMT'):
|
|
|
|
ptr += 12;
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->bits = READ_BE_UINT32(ptr); ptr += 4;
|
|
|
|
sound->freq = READ_BE_UINT32(ptr); ptr += 4;
|
|
|
|
sound->channels = READ_BE_UINT32(ptr); ptr += 4;
|
2004-04-06 19:46:43 +00:00
|
|
|
break;
|
2004-01-06 17:28:29 +00:00
|
|
|
case MKID_BE('TEXT'):
|
2004-04-06 19:46:43 +00:00
|
|
|
case MKID_BE('STOP'):
|
2004-01-18 16:59:54 +00:00
|
|
|
size = READ_BE_UINT32(ptr); ptr += size + 4;
|
2004-01-06 17:28:29 +00:00
|
|
|
break;
|
|
|
|
case MKID_BE('REGN'):
|
|
|
|
ptr += 4;
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->region[curIndexRegion].offset = READ_BE_UINT32(ptr); ptr += 4;
|
|
|
|
sound->region[curIndexRegion].length = READ_BE_UINT32(ptr); ptr += 4;
|
2004-04-06 19:46:43 +00:00
|
|
|
curIndexRegion++;
|
2004-01-06 17:28:29 +00:00
|
|
|
break;
|
|
|
|
case MKID_BE('JUMP'):
|
2004-04-06 19:46:43 +00:00
|
|
|
ptr += 4;
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->jump[curIndexJump].offset = READ_BE_UINT32(ptr); ptr += 4;
|
|
|
|
sound->jump[curIndexJump].dest = READ_BE_UINT32(ptr); ptr += 4;
|
|
|
|
sound->jump[curIndexJump].hookId = READ_BE_UINT32(ptr); ptr += 4;
|
|
|
|
sound->jump[curIndexJump].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
|
2004-04-06 19:46:43 +00:00
|
|
|
curIndexJump++;
|
2004-01-06 17:28:29 +00:00
|
|
|
break;
|
|
|
|
case MKID_BE('SYNC'):
|
2004-01-09 20:20:01 +00:00
|
|
|
size = READ_BE_UINT32(ptr); ptr += 4;
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->sync[curIndexSync].size = size;
|
|
|
|
sound->sync[curIndexSync].ptr = (byte *)malloc(size);
|
|
|
|
memcpy(sound->sync[curIndexSync].ptr, ptr, size);
|
2004-04-06 19:46:43 +00:00
|
|
|
curIndexSync++;
|
2004-01-09 20:20:01 +00:00
|
|
|
ptr += size;
|
2004-01-06 17:28:29 +00:00
|
|
|
break;
|
|
|
|
case MKID_BE('DATA'):
|
2004-04-06 19:46:43 +00:00
|
|
|
ptr += 4;
|
2004-01-06 17:28:29 +00:00
|
|
|
break;
|
|
|
|
default:
|
2004-06-19 17:48:06 +00:00
|
|
|
error("ImuseDigiSndMgr::prepareSound(%d/%s) Unknown sfx header '%s'", sound->soundId, sound->name, tag2str(tag));
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
} while (tag != MKID_BE('DATA'));
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->offsetData = ptr - s_ptr;
|
2004-01-06 17:28:29 +00:00
|
|
|
} else {
|
|
|
|
error("ImuseDigiSndMgr::prepareSound(): Unknown sound format");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::allocSlot() {
|
2004-01-06 17:28:29 +00:00
|
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
|
|
if (!_sounds[l].inUse) {
|
|
|
|
_sounds[l].inUse = true;
|
2004-06-19 17:48:06 +00:00
|
|
|
return &_sounds[l];
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
return NULL;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) {
|
2004-01-06 17:28:29 +00:00
|
|
|
bool result = false;
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->bundle = new BundleMgr(_cacheBundleDir);
|
2004-01-08 20:37:26 +00:00
|
|
|
if (_vm->_gameId == GID_CMI) {
|
|
|
|
if (_vm->_features & GF_DEMO) {
|
2005-01-25 22:21:26 +00:00
|
|
|
result = sound->bundle->open("music.bun", sound->compressed);
|
2004-01-06 17:28:29 +00:00
|
|
|
} else {
|
|
|
|
char musicfile[20];
|
2004-06-01 19:32:36 +00:00
|
|
|
if (disk == -1)
|
2004-08-28 14:33:34 +00:00
|
|
|
disk = _vm->VAR(_vm->VAR_CURRENTDISK);
|
|
|
|
sprintf(musicfile, "musdisk%d.bun", disk);
|
2004-06-01 19:32:36 +00:00
|
|
|
// if (_disk != _vm->VAR(_vm->VAR_CURRENTDISK)) {
|
2004-05-02 13:06:40 +00:00
|
|
|
// _vm->_imuseDigital->parseScriptCmds(0x1000, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
// _vm->_imuseDigital->parseScriptCmds(0x2000, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
// _vm->_imuseDigital->stopAllSounds();
|
2004-06-19 17:48:06 +00:00
|
|
|
// sound->bundle->closeFile();
|
2004-06-01 19:32:36 +00:00
|
|
|
// }
|
2004-01-06 17:28:29 +00:00
|
|
|
|
2005-01-25 22:21:26 +00:00
|
|
|
result = sound->bundle->open(musicfile, sound->compressed);
|
2004-01-06 17:28:29 +00:00
|
|
|
|
2004-08-28 14:33:34 +00:00
|
|
|
// FIXME: Shouldn't we only set _disk if result == true?
|
2004-01-08 20:37:26 +00:00
|
|
|
_disk = (byte)_vm->VAR(_vm->VAR_CURRENTDISK);
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
2004-01-08 20:37:26 +00:00
|
|
|
} else if (_vm->_gameId == GID_DIG)
|
2005-01-25 22:21:26 +00:00
|
|
|
result = sound->bundle->open("digmusic.bun", sound->compressed);
|
2004-01-06 17:28:29 +00:00
|
|
|
else
|
|
|
|
error("ImuseDigiSndMgr::openMusicBundle() Don't know which bundle file to load");
|
|
|
|
|
2004-08-28 14:33:34 +00:00
|
|
|
_vm->VAR(_vm->VAR_MUSIC_BUNDLE_LOADED) = result ? 1 : 0;
|
2004-07-04 06:14:18 +00:00
|
|
|
|
2004-01-06 17:28:29 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) {
|
2004-01-06 17:28:29 +00:00
|
|
|
bool result = false;
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
sound->bundle = new BundleMgr(_cacheBundleDir);
|
2004-01-08 20:37:26 +00:00
|
|
|
if (_vm->_gameId == GID_CMI) {
|
|
|
|
if (_vm->_features & GF_DEMO) {
|
2005-01-25 22:21:26 +00:00
|
|
|
result = sound->bundle->open("voice.bun", sound->compressed);
|
2004-01-06 17:28:29 +00:00
|
|
|
} else {
|
|
|
|
char voxfile[20];
|
2004-06-01 19:32:36 +00:00
|
|
|
if (disk == -1)
|
2004-08-28 14:33:34 +00:00
|
|
|
disk = _vm->VAR(_vm->VAR_CURRENTDISK);
|
|
|
|
sprintf(voxfile, "voxdisk%d.bun", disk);
|
2004-06-01 19:32:36 +00:00
|
|
|
// if (_disk != _vm->VAR(_vm->VAR_CURRENTDISK)) {
|
2004-05-02 13:06:40 +00:00
|
|
|
// _vm->_imuseDigital->parseScriptCmds(0x1000, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
// _vm->_imuseDigital->parseScriptCmds(0x2000, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
// _vm->_imuseDigital->stopAllSounds();
|
2004-06-19 17:48:06 +00:00
|
|
|
// sound->bundle->closeFile();
|
2004-06-01 19:32:36 +00:00
|
|
|
// }
|
2004-01-06 17:28:29 +00:00
|
|
|
|
2005-01-25 22:21:26 +00:00
|
|
|
result = sound->bundle->open(voxfile, sound->compressed);
|
2004-01-06 17:28:29 +00:00
|
|
|
|
2004-08-28 14:33:34 +00:00
|
|
|
// FIXME: Shouldn't we only set _disk if result == true?
|
2004-01-08 20:37:26 +00:00
|
|
|
_disk = (byte)_vm->VAR(_vm->VAR_CURRENTDISK);
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
2004-01-08 20:37:26 +00:00
|
|
|
} else if (_vm->_gameId == GID_DIG)
|
2005-01-25 22:21:26 +00:00
|
|
|
result = sound->bundle->open("digvoice.bun", sound->compressed);
|
2004-01-06 17:28:29 +00:00
|
|
|
else
|
|
|
|
error("ImuseDigiSndMgr::openVoiceBundle() Don't know which bundle file to load");
|
|
|
|
|
2004-08-28 14:33:34 +00:00
|
|
|
_vm->VAR(_vm->VAR_VOICE_BUNDLE_LOADED) = result ? 1 : 0;
|
2004-07-04 06:14:18 +00:00
|
|
|
|
2004-01-06 17:28:29 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-06-01 19:32:36 +00:00
|
|
|
ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk) {
|
2004-01-06 17:28:29 +00:00
|
|
|
assert(soundId >= 0);
|
|
|
|
assert(soundType);
|
|
|
|
|
2004-06-19 17:48:06 +00:00
|
|
|
soundStruct *sound = allocSlot();
|
|
|
|
if (!sound) {
|
2004-01-06 17:28:29 +00:00
|
|
|
error("ImuseDigiSndMgr::openSound() can't alloc free sound slot");
|
|
|
|
}
|
|
|
|
|
2004-08-28 14:19:56 +00:00
|
|
|
const bool header_outside = ((_vm->_gameId == GID_CMI) && !(_vm->_features & GF_DEMO));
|
2004-01-06 17:28:29 +00:00
|
|
|
bool result = false;
|
|
|
|
byte *ptr = NULL;
|
2004-08-28 14:19:56 +00:00
|
|
|
|
|
|
|
switch (soundType) {
|
|
|
|
case IMUSE_RESOURCE:
|
|
|
|
assert(soundName[0] == 0); // Paranoia check
|
|
|
|
|
|
|
|
_vm->ensureResourceLoaded(rtSound, soundId);
|
2005-03-31 21:39:31 +00:00
|
|
|
_vm->res.lock(rtSound, soundId);
|
2004-08-28 14:19:56 +00:00
|
|
|
ptr = _vm->getResourceAddress(rtSound, soundId);
|
|
|
|
if (ptr == NULL) {
|
|
|
|
closeSound(sound);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
sound->resPtr = ptr;
|
|
|
|
break;
|
|
|
|
case IMUSE_BUNDLE:
|
|
|
|
if (volGroupId == IMUSE_VOLGRP_VOICE)
|
|
|
|
result = openVoiceBundle(sound, disk);
|
|
|
|
else if (volGroupId == IMUSE_VOLGRP_MUSIC)
|
|
|
|
result = openMusicBundle(sound, disk);
|
|
|
|
else
|
2004-01-06 17:28:29 +00:00
|
|
|
error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
|
2004-08-28 14:19:56 +00:00
|
|
|
if (!result) {
|
|
|
|
closeSound(sound);
|
|
|
|
return NULL;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
2005-01-25 22:21:26 +00:00
|
|
|
if (sound->compressed) {
|
|
|
|
char fileName[24];
|
|
|
|
int32 offset = 0, size = 0;
|
|
|
|
sprintf(fileName, "%s.map", soundName);
|
|
|
|
File *rmapFile = sound->bundle->getFile(fileName, offset, size);
|
2005-02-06 10:09:37 +00:00
|
|
|
if (!rmapFile) {
|
|
|
|
closeSound(sound);
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-01-25 22:21:26 +00:00
|
|
|
prepareSoundFromRMAP(rmapFile, sound, offset, size);
|
|
|
|
strcpy(sound->name, soundName);
|
|
|
|
sound->soundId = soundId;
|
|
|
|
sound->type = soundType;
|
|
|
|
sound->volGroupId = volGroupId;
|
|
|
|
sound->disk = _disk;
|
|
|
|
return sound;
|
|
|
|
} else if (soundName[0] == 0) {
|
2004-08-28 14:19:56 +00:00
|
|
|
if (sound->bundle->decompressSampleByIndex(soundId, 0, 0x2000, &ptr, 0, header_outside) == 0 || ptr == NULL) {
|
2004-06-19 17:48:06 +00:00
|
|
|
closeSound(sound);
|
2004-04-24 15:33:36 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2004-08-28 14:19:56 +00:00
|
|
|
} else {
|
|
|
|
if (sound->bundle->decompressSampleByName(soundName, 0, 0x2000, &ptr, header_outside) == 0 || ptr == NULL) {
|
2004-06-20 13:19:22 +00:00
|
|
|
closeSound(sound);
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
2004-08-28 14:19:56 +00:00
|
|
|
sound->resPtr = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("ImuseDigiSndMgr::openSound() Unknown soundType %d (trying to load sound %d)", soundType, soundId);
|
2004-01-08 15:48:41 +00:00
|
|
|
}
|
2004-01-06 17:28:29 +00:00
|
|
|
|
2004-08-28 14:19:56 +00:00
|
|
|
strcpy(sound->name, soundName);
|
|
|
|
sound->soundId = soundId;
|
|
|
|
sound->type = soundType;
|
|
|
|
sound->volGroupId = volGroupId;
|
|
|
|
sound->disk = _disk;
|
|
|
|
prepareSound(ptr, sound);
|
|
|
|
return sound;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
void ImuseDigiSndMgr::closeSound(soundStruct *soundHandle) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-06 17:28:29 +00:00
|
|
|
|
2004-06-19 14:41:04 +00:00
|
|
|
if (soundHandle->resPtr) {
|
|
|
|
bool found = false;
|
|
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
|
|
if ((_sounds[l].soundId == soundHandle->soundId) && (&_sounds[l] != soundHandle))
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
if (!found)
|
2005-03-31 21:39:31 +00:00
|
|
|
_vm->res.unlock(rtSound, soundHandle->soundId);
|
2004-06-19 14:41:04 +00:00
|
|
|
}
|
2004-04-26 19:22:27 +00:00
|
|
|
|
2005-01-25 22:21:26 +00:00
|
|
|
if (soundHandle->compressedStream)
|
|
|
|
delete soundHandle->compressedStream;
|
|
|
|
|
2004-04-10 00:17:42 +00:00
|
|
|
delete soundHandle->bundle;
|
2005-01-25 22:21:26 +00:00
|
|
|
|
2004-04-10 00:17:42 +00:00
|
|
|
for (int r = 0; r < soundHandle->numSyncs; r++)
|
|
|
|
free(soundHandle->sync[r].ptr);
|
|
|
|
free(soundHandle->region);
|
|
|
|
free(soundHandle->jump);
|
|
|
|
free(soundHandle->sync);
|
|
|
|
memset(soundHandle, 0, sizeof(soundStruct));
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-04-11 14:48:50 +00:00
|
|
|
ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::cloneSound(soundStruct *soundHandle) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-04-11 14:48:50 +00:00
|
|
|
|
2004-06-01 19:32:36 +00:00
|
|
|
return openSound(soundHandle->soundId, soundHandle->name, soundHandle->type, soundHandle->volGroupId, soundHandle->disk);
|
2004-04-11 14:48:50 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
bool ImuseDigiSndMgr::checkForProperHandle(soundStruct *soundHandle) {
|
2004-08-28 14:33:34 +00:00
|
|
|
if (!soundHandle)
|
|
|
|
return false;
|
2004-01-06 17:28:29 +00:00
|
|
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
|
|
|
if (soundHandle == &_sounds[l])
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-01-25 22:21:26 +00:00
|
|
|
bool ImuseDigiSndMgr::isCompressed(soundStruct *soundHandle) {
|
|
|
|
assert(checkForProperHandle(soundHandle));
|
|
|
|
return soundHandle->compressed;
|
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int ImuseDigiSndMgr::getFreq(soundStruct *soundHandle) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-07 21:02:48 +00:00
|
|
|
return soundHandle->freq;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int ImuseDigiSndMgr::getBits(soundStruct *soundHandle) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-07 21:02:48 +00:00
|
|
|
return soundHandle->bits;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int ImuseDigiSndMgr::getChannels(soundStruct *soundHandle) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-07 21:02:48 +00:00
|
|
|
return soundHandle->channels;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
bool ImuseDigiSndMgr::isEndOfRegion(soundStruct *soundHandle, int region) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-07 21:02:48 +00:00
|
|
|
assert(region >= 0 && region < soundHandle->numRegions);
|
|
|
|
return soundHandle->endFlag;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int ImuseDigiSndMgr::getNumRegions(soundStruct *soundHandle) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-07 21:02:48 +00:00
|
|
|
return soundHandle->numRegions;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int ImuseDigiSndMgr::getNumJumps(soundStruct *soundHandle) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-07 21:02:48 +00:00
|
|
|
return soundHandle->numJumps;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-15 06:37:00 +00:00
|
|
|
int ImuseDigiSndMgr::getRegionOffset(soundStruct *soundHandle, int region) {
|
2004-09-12 18:21:21 +00:00
|
|
|
debug(5, "getRegionOffset() region:%d", region);
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-15 06:37:00 +00:00
|
|
|
assert(region >= 0 && region < soundHandle->numRegions);
|
|
|
|
return soundHandle->region[region].offset;
|
|
|
|
}
|
|
|
|
|
2004-04-09 21:44:29 +00:00
|
|
|
int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(soundStruct *soundHandle, int region, int hookId) {
|
2004-04-24 20:41:30 +00:00
|
|
|
debug(5, "getJumpIdByRegionAndHookId() region:%d, hookId:%d", region, hookId);
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-14 22:07:24 +00:00
|
|
|
assert(region >= 0 && region < soundHandle->numRegions);
|
2004-05-23 19:32:11 +00:00
|
|
|
int32 offset = soundHandle->region[region].offset;
|
2004-01-07 21:02:48 +00:00
|
|
|
for (int l = 0; l < soundHandle->numJumps; l++) {
|
2004-05-23 19:32:11 +00:00
|
|
|
if (offset == soundHandle->jump[l].offset) {
|
2004-04-09 21:44:29 +00:00
|
|
|
if (soundHandle->jump[l].hookId == hookId)
|
|
|
|
return l;
|
2004-01-06 19:55:44 +00:00
|
|
|
}
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2004-01-09 22:36:40 +00:00
|
|
|
void ImuseDigiSndMgr::getSyncSizeAndPtrById(soundStruct *soundHandle, int number, int32 &sync_size, byte **sync_ptr) {
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-09 22:36:40 +00:00
|
|
|
assert(number >= 0);
|
|
|
|
if (number < soundHandle->numSyncs) {
|
|
|
|
sync_size = soundHandle->sync[number].size;
|
|
|
|
*sync_ptr = soundHandle->sync[number].ptr;
|
|
|
|
} else {
|
|
|
|
sync_size = 0;
|
|
|
|
*sync_ptr = NULL;
|
|
|
|
}
|
2004-01-09 22:10:32 +00:00
|
|
|
}
|
|
|
|
|
2004-01-14 22:07:24 +00:00
|
|
|
int ImuseDigiSndMgr::getRegionIdByJumpId(soundStruct *soundHandle, int jumpId) {
|
2004-04-24 20:41:30 +00:00
|
|
|
debug(5, "getRegionIdByJumpId() jumpId:%d", jumpId);
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-14 22:07:24 +00:00
|
|
|
assert(jumpId >= 0 && jumpId < soundHandle->numJumps);
|
2004-05-23 19:32:11 +00:00
|
|
|
int32 dest = soundHandle->jump[jumpId].dest;
|
2004-01-14 22:07:24 +00:00
|
|
|
for (int l = 0; l < soundHandle->numRegions; l++) {
|
2004-05-23 19:32:11 +00:00
|
|
|
if (dest == soundHandle->region[l].offset) {
|
2004-01-14 22:07:24 +00:00
|
|
|
return l;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int ImuseDigiSndMgr::getJumpHookId(soundStruct *soundHandle, int number) {
|
2004-04-24 20:41:30 +00:00
|
|
|
debug(5, "getJumpHookId() number:%d", number);
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-07 21:02:48 +00:00
|
|
|
assert(number >= 0 && number < soundHandle->numJumps);
|
|
|
|
return soundHandle->jump[number].hookId;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int ImuseDigiSndMgr::getJumpFade(soundStruct *soundHandle, int number) {
|
2004-04-24 20:41:30 +00:00
|
|
|
debug(5, "getJumpFade() number:%d", number);
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-07 21:02:48 +00:00
|
|
|
assert(number >= 0 && number < soundHandle->numJumps);
|
|
|
|
return soundHandle->jump[number].fadeDelay;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int32 ImuseDigiSndMgr::getDataFromRegion(soundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size) {
|
2004-04-24 20:41:30 +00:00
|
|
|
debug(5, "getDataFromRegion() region:%d, offset:%d, size:%d, numRegions:%d", region, offset, size, soundHandle->numRegions);
|
2004-08-28 14:33:34 +00:00
|
|
|
assert(checkForProperHandle(soundHandle));
|
2004-01-06 17:28:29 +00:00
|
|
|
assert(buf && offset >= 0 && size >= 0);
|
2004-01-07 21:02:48 +00:00
|
|
|
assert(region >= 0 && region < soundHandle->numRegions);
|
2004-01-06 17:28:29 +00:00
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int32 region_offset = soundHandle->region[region].offset;
|
|
|
|
int32 region_length = soundHandle->region[region].length;
|
|
|
|
int32 offset_data = soundHandle->offsetData;
|
2004-01-06 17:28:29 +00:00
|
|
|
int32 start = region_offset - offset_data;
|
|
|
|
|
|
|
|
if (offset + size + offset_data > region_length) {
|
|
|
|
size = region_length - offset;
|
2004-01-07 21:02:48 +00:00
|
|
|
soundHandle->endFlag = true;
|
2004-01-06 17:28:29 +00:00
|
|
|
} else {
|
2004-01-07 21:02:48 +00:00
|
|
|
soundHandle->endFlag = false;
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
|
|
|
|
2004-01-07 21:02:48 +00:00
|
|
|
int header_size = soundHandle->offsetData;
|
2004-01-09 15:13:56 +00:00
|
|
|
bool header_outside = ((_vm->_gameId == GID_CMI) && !(_vm->_features & GF_DEMO));
|
2005-01-25 22:21:26 +00:00
|
|
|
if ((soundHandle->bundle) && (!soundHandle->compressed)) {
|
2004-04-06 19:46:43 +00:00
|
|
|
size = soundHandle->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside);
|
2004-01-07 21:02:48 +00:00
|
|
|
} else if (soundHandle->resPtr) {
|
2004-01-06 17:28:29 +00:00
|
|
|
*buf = (byte *)malloc(size);
|
2004-01-07 21:02:48 +00:00
|
|
|
memcpy(*buf, soundHandle->resPtr + start + offset + header_size, size);
|
2005-01-25 22:21:26 +00:00
|
|
|
} else if ((soundHandle->bundle) && (soundHandle->compressed)) {
|
|
|
|
*buf = (byte *)malloc(size);
|
|
|
|
char fileName[24];
|
2005-01-28 11:03:34 +00:00
|
|
|
sprintf(fileName, "%s_reg%03d", soundHandle->name, region);
|
2005-01-25 22:21:26 +00:00
|
|
|
if (scumm_stricmp(fileName, soundHandle->lastFileName) != 0) {
|
2005-01-27 16:48:30 +00:00
|
|
|
int32 offs = 0, len = 0;
|
2005-01-28 11:03:34 +00:00
|
|
|
File *cmpFile;
|
|
|
|
bool oggMode = false;
|
|
|
|
sprintf(fileName, "%s_reg%03d.mp3", soundHandle->name, region);
|
|
|
|
cmpFile = soundHandle->bundle->getFile(fileName, offs, len);
|
2005-01-28 14:42:47 +00:00
|
|
|
#ifndef USE_MAD
|
2005-01-28 23:30:51 +00:00
|
|
|
if (len)
|
2005-01-28 14:42:47 +00:00
|
|
|
error("Mad library compiled support needed!");
|
|
|
|
#endif
|
2005-01-28 23:30:51 +00:00
|
|
|
if (!len) {
|
2005-01-28 11:03:34 +00:00
|
|
|
sprintf(fileName, "%s_reg%03d.ogg", soundHandle->name, region);
|
|
|
|
cmpFile = soundHandle->bundle->getFile(fileName, offs, len);
|
2005-01-28 14:42:47 +00:00
|
|
|
#ifndef USE_VORBIS
|
2005-01-28 23:30:51 +00:00
|
|
|
if (len)
|
2005-01-28 14:55:52 +00:00
|
|
|
error("Vorbis library compiled support needed!");
|
2005-01-28 14:42:47 +00:00
|
|
|
#endif
|
2005-01-28 23:30:51 +00:00
|
|
|
assert(len);
|
2005-01-28 11:03:34 +00:00
|
|
|
oggMode = true;
|
|
|
|
}
|
2005-01-25 22:21:26 +00:00
|
|
|
if (!soundHandle->compressedStream) {
|
2005-01-28 11:43:25 +00:00
|
|
|
#ifdef USE_VORBIS
|
2005-01-28 11:03:34 +00:00
|
|
|
if (oggMode)
|
|
|
|
soundHandle->compressedStream = makeVorbisStream(cmpFile, len);
|
2005-01-28 11:43:25 +00:00
|
|
|
#endif
|
|
|
|
#ifdef USE_MAD
|
2005-01-28 15:04:37 +00:00
|
|
|
if (!oggMode)
|
2005-01-28 11:03:34 +00:00
|
|
|
soundHandle->compressedStream = makeMP3Stream(cmpFile, len);
|
2005-01-28 11:43:25 +00:00
|
|
|
#endif
|
2005-01-25 22:21:26 +00:00
|
|
|
assert(soundHandle->compressedStream);
|
|
|
|
}
|
|
|
|
strcpy(soundHandle->lastFileName, fileName);
|
|
|
|
}
|
|
|
|
size = soundHandle->compressedStream->readBuffer((int16 *)*buf, size / 2) * 2;
|
|
|
|
if (soundHandle->compressedStream->endOfData()) {
|
|
|
|
delete soundHandle->compressedStream;
|
|
|
|
soundHandle->compressedStream = NULL;
|
2005-01-26 14:11:27 +00:00
|
|
|
soundHandle->lastFileName[0] = 0;
|
2005-01-25 22:21:26 +00:00
|
|
|
}
|
2004-01-06 17:28:29 +00:00
|
|
|
}
|
2005-01-25 22:21:26 +00:00
|
|
|
|
2004-01-06 17:28:29 +00:00
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // End of namespace Scumm
|