aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorJohannes Schickel2011-11-02 23:56:45 +0100
committerJohannes Schickel2011-11-06 13:33:55 +0100
commit09708f7224cc388ef45ec570a477a8ace0e61bec (patch)
treebf560850c9ff6b8bccd70f86f665bd137c850f1b /engines/scumm
parent9fa9f68789ef51e078cb8631e06bead13cae13f2 (diff)
downloadscummvm-rg350-09708f7224cc388ef45ec570a477a8ace0e61bec.tar.gz
scummvm-rg350-09708f7224cc388ef45ec570a477a8ace0e61bec.tar.bz2
scummvm-rg350-09708f7224cc388ef45ec570a477a8ace0e61bec.zip
SCUMM: Stream sfx/voice sounds from mouster.sou.
This fixes sound corruption when using the new VOC streaming code. It also reduces the runtime memory needed for compressed sound files slightly, since it does not preload them into memory anymore. This comes at the expense of one file descriptor needed per sfx being played though. Thanks to Kirben for his review and feedback.
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/he/sound_he.cpp20
-rw-r--r--engines/scumm/sound.cpp103
-rw-r--r--engines/scumm/sound.h5
3 files changed, 79 insertions, 49 deletions
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index 5c15a85929..85e2a2f1dd 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -770,24 +770,30 @@ void SoundHE::startHETalkSound(uint32 offset) {
if (ConfMan.getBool("speech_mute"))
return;
- assert(_sfxFile);
- if (!_sfxFile->isOpen()) {
+ if (_sfxFilename.empty()) {
// This happens in the Pajama Sam's Lost & Found demo, on the
// main menu screen, so don't make it a fatal error.
- warning("startHETalkSound: Speech file is not open");
+ warning("startHETalkSound: Speech file is not found");
return;
}
+ ScummFile file;
+ if (!_vm->openFile(file, _sfxFilename)) {
+ warning("startHETalkSound: Could not open speech file %s", _sfxFilename.c_str());
+ return;
+ }
+ file.setEnc(_sfxFileEncByte);
+
_sfxMode |= 2;
_vm->_res->nukeResource(rtSound, 1);
- _sfxFile->seek(offset + 4, SEEK_SET);
- size = _sfxFile->readUint32BE();
- _sfxFile->seek(offset, SEEK_SET);
+ file.seek(offset + 4, SEEK_SET);
+ size = file.readUint32BE();
+ file.seek(offset, SEEK_SET);
_vm->_res->createResource(rtSound, 1, size);
ptr = _vm->getResourceAddress(rtSound, 1);
- _sfxFile->read(ptr, size);
+ file.read(ptr, size);
int channel = (_vm->VAR_TALK_CHANNEL != 0xFF) ? _vm->VAR(_vm->VAR_TALK_CHANNEL) : 0;
addSoundToQueue2(1, 0, channel, 0);
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 8178fc2636..f058ef1a2c 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -23,6 +23,8 @@
#include "common/config-manager.h"
#include "common/timer.h"
#include "common/util.h"
+#include "common/ptr.h"
+#include "common/substream.h"
#include "scumm/actor.h"
#include "scumm/file.h"
@@ -62,7 +64,8 @@ Sound::Sound(ScummEngine *parent, Audio::Mixer *mixer)
_mixer(mixer),
_soundQuePos(0),
_soundQue2Pos(0),
- _sfxFile(0),
+ _sfxFilename(),
+ _sfxFileEncByte(0),
_offsetTable(0),
_numSoundEffects(0),
_soundMode(kVOCMode),
@@ -91,7 +94,6 @@ Sound::Sound(ScummEngine *parent, Audio::Mixer *mixer)
Sound::~Sound() {
stopCDTimer();
g_system->getAudioCDManager()->stop();
- delete _sfxFile;
}
void Sound::addSoundToQueue(int sound, int heOffset, int heChannel, int heFlags) {
@@ -490,6 +492,7 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
int num = 0, i;
int size = 0;
int id = -1;
+ Common::ScopedPtr<ScummFile> file;
if (_vm->_game.id == GID_CMI) {
_sfxMode |= mode;
@@ -523,25 +526,29 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
return;
}
- _sfxFile->close();
+ file.reset(new ScummFile());
+ if (!file)
+ error("startTalkSound: Out of memory");
+
sprintf(filename, "audio/%s.%u/%u.voc", roomname, offset, b);
- _vm->openFile(*_sfxFile, filename);
- if (!_sfxFile->isOpen()) {
+ if (!_vm->openFile(*file, filename)) {
sprintf(filename, "audio/%s_%u/%u.voc", roomname, offset, b);
- _vm->openFile(*_sfxFile, filename);
+ _vm->openFile(*file, filename);
}
- if (!_sfxFile->isOpen()) {
+
+ if (!file->isOpen()) {
sprintf(filename, "%u.%u.voc", offset, b);
- _vm->openFile(*_sfxFile, filename);
+ _vm->openFile(*file, filename);
}
- if (!_sfxFile->isOpen()) {
+
+ if (!file->isOpen()) {
warning("startTalkSound: dig demo: voc file not found");
return;
}
} else {
- if (!_sfxFile->isOpen()) {
- warning("startTalkSound: SFX file is not open");
+ if (_sfxFilename.empty()) {
+ warning("startTalkSound: SFX file not found");
return;
}
@@ -581,11 +588,30 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
size = -1;
}
- _sfxFile->seek(offset, SEEK_SET);
+ file.reset(new ScummFile());
+ if (!file)
+ error("startTalkSound: Out of memory");
+
+ if (!_vm->openFile(*file, _sfxFilename)) {
+ warning("startTalkSound: could not open sfx file %s", _sfxFilename.c_str());
+ return;
+ }
+
+ file->setEnc(_sfxFileEncByte);
+ file->seek(offset, SEEK_SET);
assert(num + 1 < (int)ARRAYSIZE(_mouthSyncTimes));
for (i = 0; i < num; i++)
- _mouthSyncTimes[i] = _sfxFile->readUint16BE();
+ _mouthSyncTimes[i] = file->readUint16BE();
+
+ // Adjust offset to account for the mouth sync times. It is noteworthy
+ // that we do not adjust the size here for compressed streams, since
+ // they only set size to the size of the compressed sound data.
+ offset += num * 2;
+ // TODO: In case we ever set up the size for VOC streams, we should
+ // really check whether the size contains the _mouthSyncTimes.
+ //if (_soundMode == kVOCMode)
+ // size -= num * 2;
_mouthSyncTimes[i] = 0xFFFF;
_sfxMode |= mode;
@@ -601,9 +627,7 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
#ifdef USE_MAD
{
assert(size > 0);
- Common::SeekableReadStream *tmp = _sfxFile->readStream(size);
- assert(tmp);
- input = Audio::makeMP3Stream(tmp, DisposeAfterUse::YES);
+ input = Audio::makeMP3Stream(new Common::SeekableSubReadStream(file.release(), offset, offset + size, DisposeAfterUse::YES), DisposeAfterUse::YES);
}
#endif
break;
@@ -611,9 +635,7 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
#ifdef USE_VORBIS
{
assert(size > 0);
- Common::SeekableReadStream *tmp = _sfxFile->readStream(size);
- assert(tmp);
- input = Audio::makeVorbisStream(tmp, DisposeAfterUse::YES);
+ input = Audio::makeVorbisStream(new Common::SeekableSubReadStream(file.release(), offset, offset + size, DisposeAfterUse::YES), DisposeAfterUse::YES);
}
#endif
break;
@@ -621,14 +643,12 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
#ifdef USE_FLAC
{
assert(size > 0);
- Common::SeekableReadStream *tmp = _sfxFile->readStream(size);
- assert(tmp);
- input = Audio::makeFLACStream(tmp, DisposeAfterUse::YES);
+ input = Audio::makeFLACStream(new Common::SeekableSubReadStream(file.release(), offset, offset + size, DisposeAfterUse::YES), DisposeAfterUse::YES);
}
#endif
break;
default:
- input = Audio::makeVOCStream(_sfxFile, Audio::FLAG_UNSIGNED);
+ input = Audio::makeVOCStream(file.release(), Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
break;
}
@@ -848,12 +868,10 @@ void Sound::talkSound(uint32 a, uint32 b, int mode, int channel) {
}
void Sound::setupSound() {
- delete _sfxFile;
-
- _sfxFile = openSfxFile();
+ setupSfxFile();
if (_vm->_game.id == GID_FT) {
- _vm->VAR(_vm->VAR_VOICE_BUNDLE_LOADED) = _sfxFile->isOpen();
+ _vm->VAR(_vm->VAR_VOICE_BUNDLE_LOADED) = _sfxFilename.empty() ? 0 : 1;
}
}
@@ -885,7 +903,7 @@ void Sound::pauseSounds(bool pause) {
}
}
-BaseScummFile *Sound::openSfxFile() {
+void Sound::setupSfxFile() {
struct SoundFileExtensions {
const char *ext;
SoundMode mode;
@@ -905,8 +923,10 @@ BaseScummFile *Sound::openSfxFile() {
{ 0, kVOCMode }
};
- ScummFile *file = new ScummFile();
+ ScummFile file;
_offsetTable = NULL;
+ _sfxFileEncByte = 0;
+ _sfxFilename.clear();
/* Try opening the file <baseName>.sou first, e.g. tentacle.sou.
* That way, you can keep .sou files for multiple games in the
@@ -931,15 +951,20 @@ BaseScummFile *Sound::openSfxFile() {
tmp = basename[0] + "tlk";
}
- if (file->open(tmp) && _vm->_game.heversion <= 74)
- file->setEnc(0x69);
+ if (file.open(tmp))
+ _sfxFilename = tmp;
+
+ if (_vm->_game.heversion <= 74)
+ _sfxFileEncByte = 0x69;
+
_soundMode = kVOCMode;
} else {
- for (uint j = 0; j < 2 && !file->isOpen(); ++j) {
+ for (uint j = 0; j < 2 && !file.isOpen(); ++j) {
for (int i = 0; extensions[i].ext; ++i) {
tmp = basename[j] + extensions[i].ext;
- if (_vm->openFile(*file, tmp)) {
+ if (_vm->openFile(file, tmp)) {
_soundMode = extensions[i].mode;
+ _sfxFilename = tmp;
break;
}
}
@@ -963,23 +988,21 @@ BaseScummFile *Sound::openSfxFile() {
*/
int size, compressed_offset;
MP3OffsetTable *cur;
- compressed_offset = file->readUint32BE();
+ compressed_offset = file.readUint32BE();
_offsetTable = (MP3OffsetTable *) malloc(compressed_offset);
_numSoundEffects = compressed_offset / 16;
size = compressed_offset;
cur = _offsetTable;
while (size > 0) {
- cur->org_offset = file->readUint32BE();
- cur->new_offset = file->readUint32BE() + compressed_offset + 4; /* The + 4 is to take into accound the 'size' field */
- cur->num_tags = file->readUint32BE();
- cur->compressed_size = file->readUint32BE();
+ cur->org_offset = file.readUint32BE();
+ cur->new_offset = file.readUint32BE() + compressed_offset + 4; /* The + 4 is to take into accound the 'size' field */
+ cur->num_tags = file.readUint32BE();
+ cur->compressed_size = file.readUint32BE();
size -= 4 * 4;
cur++;
}
}
-
- return file;
}
bool Sound::isSfxFinished() const {
diff --git a/engines/scumm/sound.h b/engines/scumm/sound.h
index e9a37ac9fa..48f28d51ff 100644
--- a/engines/scumm/sound.h
+++ b/engines/scumm/sound.h
@@ -69,7 +69,8 @@ protected:
int16 flags;
} _soundQue2[10];
- BaseScummFile *_sfxFile;
+ Common::String _sfxFilename;
+ byte _sfxFileEncByte;
SoundMode _soundMode;
MP3OffsetTable *_offsetTable; // For compressed audio
int _numSoundEffects; // For compressed audio
@@ -126,7 +127,7 @@ public:
void saveLoadWithSerializer(Serializer *ser);
protected:
- BaseScummFile *openSfxFile();
+ void setupSfxFile();
bool isSfxFinished() const;
void processSfxQueues();