aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2009-05-25 10:30:19 +0000
committerFilippos Karapetis2009-05-25 10:30:19 +0000
commitd59796fb544fea69d1b2f27f89d6eb30bf5d0780 (patch)
tree558e122a71e404cd56aa7742c57b16f108a28f46
parent5ef58bdfbe443c19d2f185d924b5058f25cab962 (diff)
downloadscummvm-rg350-d59796fb544fea69d1b2f27f89d6eb30bf5d0780.tar.gz
scummvm-rg350-d59796fb544fea69d1b2f27f89d6eb30bf5d0780.tar.bz2
scummvm-rg350-d59796fb544fea69d1b2f27f89d6eb30bf5d0780.zip
Objectified the AudioResource code (used for speech and digitized music in CD talkie games)
svn-id: r40880
-rw-r--r--engines/sci/engine/ksound.cpp114
-rw-r--r--engines/sci/resource.cpp109
-rw-r--r--engines/sci/resource.h29
-rw-r--r--engines/sci/sfx/core.cpp7
-rw-r--r--engines/sci/sfx/core.h3
5 files changed, 166 insertions, 96 deletions
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 74a62da356..a5b30d13b2 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -86,11 +86,6 @@ namespace Sci {
#define _K_SCI1_SOUND_REVERB 19 /* Get/Set */
#define _K_SCI1_SOUND_UPDATE_VOL_PRI 20
-Audio::SoundHandle _audioHandle;
-uint16 _audioRate;
-int16 _lang;
-byte *_audioMap;
-
enum AudioCommands {
// TODO: find the difference between kSci1AudioWPlay and kSci1AudioPlay
kSci1AudioWPlay = 1, /* Plays an audio stream */
@@ -999,33 +994,6 @@ reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return kDoSound_SCI0(s, funct_nr, argc, argv);
}
-bool findAudEntry(uint16 audioNumber, byte& volume, uint32& offset, uint32& size) {
- // AUDIO00X.MAP contains 10-byte entries:
- // w nEntry
- // dw offset+volume (as in resource.map)
- // dw size
- // ending with 10 0xFFs
- uint16 n;
- uint32 off;
-
- if (_audioMap == 0)
- return false;
-
- byte *ptr = _audioMap;
- while ((n = READ_UINT16(ptr)) != 0xFFFF) {
- if (n == audioNumber) {
- off = READ_LE_UINT32(ptr + 2);
- size = READ_LE_UINT32(ptr + 6);
- volume = off >> 28;
- offset = off & 0x0FFFFFFF;
- return true;
- }
- ptr += 10;
- }
-
- return false;
-}
-
// Used for speech playback in CD games
reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) {
Audio::Mixer *mixer = g_system->getMixer();
@@ -1034,94 +1002,50 @@ reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) {
switch (UKPV(0)) {
case kSci1AudioWPlay:
case kSci1AudioPlay: {
- mixer->stopHandle(_audioHandle);
+ s->sound.audioResource->stop();
+
+ Audio::AudioStream *audioStream = 0;
// Try to load from an external patch file first
Sci::Resource* audioRes = s->resmgr->findResource(kResourceTypeAudio, UKPV(1), 1);
- Audio::AudioStream *audioStream = 0;
if (audioRes) {
- audioStream = Audio::makeLinearInputStream(audioRes->data, audioRes->size, _audioRate, Audio::Mixer::FLAG_UNSIGNED, 0, 0);
- sampleLen = audioRes->size * 60 / _audioRate;
+ audioStream = s->sound.audioResource->getAudioStream(audioRes, &sampleLen);
} else {
// No patch file found, read it from the audio volume
- byte volume;
- uint32 offset;
- uint32 size;
-
- if (findAudEntry(UKPV(1), volume, offset, size)) {
- uint32 start = offset * 1000 / _audioRate;
- uint32 duration = size * 1000 / _audioRate;
-
- char filename[40];
- sprintf(filename, "AUDIO%03d.%03d", _lang, volume);
-
- // Try to load compressed
- audioStream = Audio::AudioStream::openStreamFile(filename, start, duration);
- if (!audioStream) {
- // Compressed file load failed, try to load original raw data
- byte *soundbuff = (byte *)malloc(size);
- Common::File* audioFile = new Common::File();
- if (audioFile->open(filename)) {
- audioFile->seek(offset);
- audioFile->read(soundbuff, size);
- audioFile->close();
- delete audioFile;
-
- audioStream = Audio::makeLinearInputStream(soundbuff, size, _audioRate,
- Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED, 0, 0);
- }
- }
-
- sampleLen = size * 60 / _audioRate;
- }
+ audioStream = s->sound.audioResource->getAudioStream(UKPV(1), &sampleLen);
}
if (audioStream)
- mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream);
- }
+ mixer->playInputStream(Audio::Mixer::kSpeechSoundType, s->sound.audioResource->getAudioHandle(), audioStream);
+ }
return make_reg(0, sampleLen); // return sample length in ticks
case kSci1AudioStop:
- mixer->stopHandle(_audioHandle);
+ s->sound.audioResource->stop();
break;
case kSci1AudioPause:
- mixer->pauseHandle(_audioHandle, true);
+ s->sound.audioResource->pause();
break;
case kSci1AudioResume:
- mixer->pauseHandle(_audioHandle, false);
+ s->sound.audioResource->resume();
break;
case kSci1AudioPosition:
- if (mixer->isSoundHandleActive(_audioHandle)) {
- return make_reg(0, mixer->getSoundElapsedTime(_audioHandle) * 6 / 100); // return elapsed time in ticks
- } else {
- return make_reg(0, -1); // Sound finished
- }
+ return make_reg(0, s->sound.audioResource->getAudioPosition());
case kSci1AudioRate:
- _audioRate = UKPV(1);
+ s->sound.audioResource->setAudioRate(UKPV(1));
break;
case kSci1AudioVolume:
mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, UKPV(1));
break;
case kSci1AudioLanguage:
- // TODO: CD Audio (used for example in the end credits of KQ6CD)
- if (SKPV(1) != -1) {
- _lang = UKPV(1);
-
- char filename[40];
- sprintf(filename, "AUDIO%03d.MAP", _lang);
-
- Common::File* audioMapFile = new Common::File();
- if (audioMapFile->open(filename)) {
- // TODO: This needs to be freed, right now we got a memory leak here!
- _audioMap = new byte[audioMapFile->size()];
- audioMapFile->read(_audioMap, audioMapFile->size());
- audioMapFile->close();
- delete audioMapFile;
- } else {
- _audioMap = 0;
- }
- }
+ if (s->sound.audioResource)
+ delete s->sound.audioResource;
+
+ // The audio resource is freed when freeing all resources
+ s->sound.audioResource = new AudioResource();
+ s->sound.audioResource->setAudioLang(SKPV(1));
+
break;
default:
warning("kDoAudio: Unhandled case %d", UKPV(0));
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 576b2afc20..e65e1c89d4 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -1159,4 +1159,113 @@ void ResourceSync::stopSync() {
//syncStarted = false; // not used
}
+
+AudioResource::AudioResource() {
+ _audioRate = 0;
+ _lang = 0;
+ _audioMap = 0;
+}
+
+AudioResource::~AudioResource() {
+ delete _audioMap;
+ _audioMap = 0;
+}
+
+void AudioResource::setAudioLang(int16 lang) {
+ // TODO: CD Audio (used for example in the end credits of KQ6CD)
+ if (lang != -1) {
+ _lang = lang;
+
+ char filename[40];
+ sprintf(filename, "AUDIO%03d.MAP", _lang);
+
+ Common::File* audioMapFile = new Common::File();
+ if (audioMapFile->open(filename)) {
+ // The audio map is freed in the destructor
+ _audioMap = new byte[audioMapFile->size()];
+ audioMapFile->read(_audioMap, audioMapFile->size());
+ audioMapFile->close();
+ delete audioMapFile;
+ } else {
+ _audioMap = 0;
+ }
+ }
+}
+
+int AudioResource::getAudioPosition() {
+ if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) {
+ return g_system->getMixer()->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks
+ } else {
+ return -1; // Sound finished
+ }
+}
+
+bool AudioResource::findAudEntry(uint16 audioNumber, byte& volume, uint32& offset, uint32& size) {
+ // AUDIO00X.MAP contains 10-byte entries:
+ // w nEntry
+ // dw offset+volume (as in resource.map)
+ // dw size
+ // ending with 10 0xFFs
+ uint16 n;
+ uint32 off;
+
+ if (_audioMap == 0)
+ return false;
+
+ byte *ptr = _audioMap;
+ while ((n = READ_UINT16(ptr)) != 0xFFFF) {
+ if (n == audioNumber) {
+ off = READ_LE_UINT32(ptr + 2);
+ size = READ_LE_UINT32(ptr + 6);
+ volume = off >> 28;
+ offset = off & 0x0FFFFFFF;
+ return true;
+ }
+ ptr += 10;
+ }
+
+ return false;
+}
+
+Audio::AudioStream* AudioResource::getAudioStream(uint16 audioNumber, int* sampleLen) {
+ Audio::AudioStream *audioStream = 0;
+ byte volume;
+ uint32 offset;
+ uint32 size;
+
+ if (findAudEntry(audioNumber, volume, offset, size)) {
+ uint32 start = offset * 1000 / _audioRate;
+ uint32 duration = size * 1000 / _audioRate;
+
+ char filename[40];
+ sprintf(filename, "AUDIO%03d.%03d", _lang, volume);
+
+ // Try to load compressed
+ audioStream = Audio::AudioStream::openStreamFile(filename, start, duration);
+ if (!audioStream) {
+ // Compressed file load failed, try to load original raw data
+ byte *soundbuff = (byte *)malloc(size);
+ Common::File* audioFile = new Common::File();
+ if (audioFile->open(filename)) {
+ audioFile->seek(offset);
+ audioFile->read(soundbuff, size);
+ audioFile->close();
+ delete audioFile;
+
+ audioStream = Audio::makeLinearInputStream(soundbuff, size, _audioRate,
+ Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED, 0, 0);
+ }
+ }
+
+ *sampleLen = size * 60 / _audioRate;
+ }
+
+ return audioStream;
+}
+
+Audio::AudioStream* AudioResource::getAudioStream(Resource* audioRes, int* sampleLen) {
+ *sampleLen = audioRes->size * 60 / _audioRate;
+ return Audio::makeLinearInputStream(audioRes->data, audioRes->size, _audioRate, Audio::Mixer::FLAG_UNSIGNED, 0, 0);
+}
+
} // End of namespace Sci
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 8899cbdc6b..f3593ded32 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -30,6 +30,9 @@
#include "common/file.h"
#include "common/archive.h"
+#include "sound/audiostream.h"
+#include "sound/mixer.h" // for SoundHandle
+
#include "sci/engine/vm.h" // for Object
#include "sci/decompressor.h"
@@ -299,6 +302,32 @@ protected:
//bool _syncStarted; // not used
};
+class AudioResource {
+public:
+ AudioResource();
+ ~AudioResource();
+
+ void setAudioRate(uint16 audioRate) { _audioRate = audioRate; }
+ void setAudioLang(int16 lang);
+
+ Audio::SoundHandle* getAudioHandle() { return &_audioHandle; }
+ int getAudioPosition();
+ Audio::AudioStream* getAudioStream(uint16 audioNumber, int* sampleLen);
+ Audio::AudioStream* getAudioStream(Resource* audioRes, int* sampleLen);
+
+ void stop() { g_system->getMixer()->stopHandle(_audioHandle); }
+ void pause() { g_system->getMixer()->pauseHandle(_audioHandle, true); }
+ void resume() { g_system->getMixer()->pauseHandle(_audioHandle, false); }
+
+private:
+ Audio::SoundHandle _audioHandle;
+ uint16 _audioRate;
+ int16 _lang;
+ byte *_audioMap;
+
+ bool findAudEntry(uint16 audioNumber, byte& volume, uint32& offset, uint32& size);
+};
+
} // End of namespace Sci
#endif // SCI_SCICORE_RESOURCE_H
diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp
index 1b4b7e7d96..ccf2052e85 100644
--- a/engines/sci/sfx/core.cpp
+++ b/engines/sci/sfx/core.cpp
@@ -367,6 +367,7 @@ void sfx_init(sfx_state_t *self, ResourceManager *resmgr, int flags) {
self->flags = flags;
self->debug = 0; /* Disable all debugging by default */
self->soundSync = NULL;
+ self->audioResource = NULL;
if (flags & SFX_STATE_FLAG_NOSOUND) {
player = NULL;
@@ -443,6 +444,12 @@ void sfx_exit(sfx_state_t *self) {
if (strcmp(player->name, "new") == 0)
g_system->getMixer()->stopAll();
+
+ // Delete audio resources for CD talkie games
+ if (self->audioResource) {
+ delete self->audioResource;
+ self->audioResource = 0;
+ }
}
void sfx_suspend(sfx_state_t *self, int suspend) {
diff --git a/engines/sci/sfx/core.h b/engines/sci/sfx/core.h
index acf8c67d70..9c0d25862f 100644
--- a/engines/sci/sfx/core.h
+++ b/engines/sci/sfx/core.h
@@ -55,7 +55,8 @@ struct sfx_state_t {
song_t *song; /* Active song, or start of active song chain */
int suspended; /* Whether we are suspended */
unsigned int debug; /* Debug flags */
- ResourceSync *soundSync; /* Used by kDoSync for speech syncing in talkie games */
+ ResourceSync *soundSync; /* Used by kDoSync for speech syncing in CD talkie games */
+ AudioResource *audioResource; /* Used for audio resources in CD talkie games */
};
/***********/