aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/kyra/kyra_mr.cpp8
-rw-r--r--engines/kyra/resource.cpp43
-rw-r--r--engines/kyra/resource.h4
-rw-r--r--engines/kyra/sound.cpp12
-rw-r--r--engines/kyra/sound.h17
-rw-r--r--engines/kyra/sound_digital.cpp164
6 files changed, 187 insertions, 61 deletions
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index c842e318ec..8a49b8e155 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -59,7 +59,7 @@ const KyraEngine_v2::EngineDesc KyraEngine_MR::_mrEngineDesc = {
KyraEngine_MR::KyraEngine_MR(OSystem *system, const GameFlags &flags) : KyraEngine_v2(system, flags, _mrEngineDesc) {
_soundDigital = 0;
_musicSoundChannel = -1;
- _menuAudioFile = "TITLE1.AUD";
+ _menuAudioFile = "TITLE1";
_lastMusicCommand = -1;
_itemBuffer1 = _itemBuffer2 = 0;
_scoreFile = 0;
@@ -425,7 +425,7 @@ void KyraEngine_MR::snd_playWanderScoreViaMap(int track, int force) {
assert(track < _soundListSize && track >= 0);
char file[13];
- sprintf(file, "%s.AUD", _soundList[track]);
+ sprintf(file, "%s", _soundList[track]);
_musicSoundChannel = _soundDigital->playSound(file, 0xFF, Audio::Mixer::kMusicSoundType);
}
@@ -483,7 +483,7 @@ void KyraEngine_MR::snd_playSoundEffect(int item, int volume) {
if (_sfxFileMap[item*2+0] != 0xFF) {
char filename[16];
assert(_sfxFileMap[item*2+0] < _sfxFileListSize);
- snprintf(filename, 16, "%s.AUD", _sfxFileList[_sfxFileMap[item*2+0]]);
+ snprintf(filename, 16, "%s", _sfxFileList[_sfxFileMap[item*2+0]]);
uint8 priority = _sfxFileMap[item*2+1];
_soundDigital->playSound(filename, priority, Audio::Mixer::kSFXSoundType, volume);
@@ -498,7 +498,7 @@ void KyraEngine_MR::playVoice(int high, int low) {
void KyraEngine_MR::snd_playVoiceFile(int file) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::snd_playVoiceFile(%d)", file);
char filename[16];
- snprintf(filename, 16, "%u.AUD", (uint)file);
+ snprintf(filename, 16, "%.08u", (uint)file);
_voiceSoundChannel = _soundDigital->playSound(filename, 0xFE, Audio::Mixer::kSpeechSoundType, 255);
}
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index 46c73c9d3b..01702f08b3 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -543,6 +543,20 @@ bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableRe
return true;
}
+namespace {
+
+Common::String readString(Common::SeekableReadStream &stream) {
+ Common::String result;
+ char c = 0;
+
+ while ((c = stream.readByte()) != 0)
+ result += c;
+
+ return result;
+}
+
+} // end of anonymous namespace
+
bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const {
uint32 filesize = stream.size();
@@ -610,6 +624,33 @@ bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableRead
startoffset = endoffset;
}
+ FileList::const_iterator iter = Common::find(files.begin(), files.end(), Common::String("LINKLIST"));
+ if (iter != files.end()) {
+ stream.seek(iter->entry.offset, SEEK_SET);
+
+ uint32 magic = stream.readUint32BE();
+
+ if (magic != MKID_BE('SCVM'))
+ error("LINKLIST file does not contain 'SCVM' header");
+
+ uint32 links = stream.readUint32BE();
+ for (uint i = 0; i < links; ++i) {
+ Common::String linksTo = readString(stream);
+ uint32 sources = stream.readUint32BE();
+
+ iter = Common::find(files.begin(), files.end(), linksTo);
+ if (iter == files.end())
+ error("PAK file link destination '%s' not found", linksTo.c_str());
+
+ for (uint j = 0; j < sources; ++j) {
+ Common::String dest = readString(stream);
+ files.push_back(File(dest, iter->entry));
+ // Better safe than sorry, we update the 'iter' value, in case push_back invalidated it
+ iter = Common::find(files.begin(), files.end(), linksTo);
+ }
+ }
+ }
+
return true;
}
@@ -767,7 +808,7 @@ bool ResLoaderTlk::loadFile(const Common::String &filename, Common::SeekableRead
entry.offset = resOffset+4;
char realFilename[20];
- snprintf(realFilename, 20, "%u.AUD", resFilename);
+ snprintf(realFilename, 20, "%.08u.AUD", resFilename);
uint32 curOffset = stream.pos();
stream.seek(resOffset, SEEK_SET);
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 167ccd7943..d43f730e6b 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -75,6 +75,10 @@ public:
File() : filename(), entry() {}
File(const Common::String &f, const ResFileEntry &e) : filename(f), entry(e) {}
+ bool operator ==(const Common::String &r) const {
+ return filename.equalsIgnoreCase(r);
+ }
+
Common::String filename;
ResFileEntry entry;
};
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index 8f9077705e..f56c43aabd 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -50,9 +50,9 @@ Sound::~Sound() {
bool Sound::voiceFileIsPresent(const char *file) {
char filenamebuffer[25];
- for (int i = 0; _supportedCodes[i].fileext; ++i) {
+ for (int i = 0; _supportedCodecs[i].fileext; ++i) {
strcpy(filenamebuffer, file);
- strcat(filenamebuffer, _supportedCodes[i].fileext);
+ strcat(filenamebuffer, _supportedCodecs[i].fileext);
if (_vm->resource()->getFileSize(filenamebuffer) > 0)
return true;
}
@@ -77,14 +77,14 @@ int32 Sound::voicePlay(const char *file, bool isSfx) {
Audio::AudioStream *audioStream = 0;
- for (int i = 0; _supportedCodes[i].fileext; ++i) {
+ for (int i = 0; _supportedCodecs[i].fileext; ++i) {
strcpy(filenamebuffer, file);
- strcat(filenamebuffer, _supportedCodes[i].fileext);
+ strcat(filenamebuffer, _supportedCodecs[i].fileext);
Common::SeekableReadStream *stream = _vm->resource()->getFileStream(filenamebuffer);
if (!stream)
continue;
- audioStream = _supportedCodes[i].streamFunc(stream, true, 0, 0, 1);
+ audioStream = _supportedCodecs[i].streamFunc(stream, true, 0, 0, 1);
break;
}
@@ -551,7 +551,7 @@ bool KyraEngine_v1::snd_voiceIsPlaying() {
// static res
-const Sound::SpeechCodecs Sound::_supportedCodes[] = {
+const Sound::SpeechCodecs Sound::_supportedCodecs[] = {
#ifdef USE_FLAC
{ ".VOF", Audio::makeFlacStream },
#endif // USE_FLAC
diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h
index 2427a6cdde..1baeb3064a 100644
--- a/engines/kyra/sound.h
+++ b/engines/kyra/sound.h
@@ -232,7 +232,7 @@ private:
uint numLoops);
};
- static const SpeechCodecs _supportedCodes[];
+ static const SpeechCodecs _supportedCodecs[];
};
class AdlibDriver;
@@ -498,6 +498,7 @@ private:
// Digital Audio
class AUDStream;
+class KyraAudioStream;
class KyraEngine_MR;
/**
@@ -564,8 +565,20 @@ private:
char filename[16];
uint8 priority;
- AUDStream *stream;
+ KyraAudioStream *stream;
} _sounds[4];
+
+ struct AudioCodecs {
+ const char *fileext;
+ Audio::AudioStream *(*streamFunc)(
+ Common::SeekableReadStream *stream,
+ bool disposeAfterUse,
+ uint32 startTime,
+ uint32 duration,
+ uint numLoops);
+ };
+
+ static const AudioCodecs _supportedCodecs[];
};
} // end of namespace Kyra
diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp
index bac7d67129..20f3a7f9f9 100644
--- a/engines/kyra/sound_digital.cpp
+++ b/engines/kyra/sound_digital.cpp
@@ -29,8 +29,79 @@
#include "sound/audiostream.h"
+#include "sound/mp3.h"
+#include "sound/vorbis.h"
+#include "sound/flac.h"
+
namespace Kyra {
+class KyraAudioStream : public Audio::AudioStream {
+public:
+ KyraAudioStream(Audio::AudioStream *impl) : _impl(impl), _rate(impl->getRate()), _fadeSamples(0), _fadeCount(0), _fading(0), _endOfData(false) {}
+ ~KyraAudioStream() { delete _impl; _impl = 0; }
+
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const { return _impl->isStereo(); }
+ bool endOfData() const { return _impl->endOfData() | _endOfData; }
+ int getRate() const { return _rate; }
+ int32 getTotalPlayTime() const { return _impl->getTotalPlayTime(); }
+
+ void setRate(int newRate) { _rate = newRate; }
+ void beginFadeOut(uint32 millis);
+private:
+ Audio::AudioStream *_impl;
+
+ int _rate;
+
+ int32 _fadeSamples;
+ int32 _fadeCount;
+ int _fading;
+
+ bool _endOfData;
+};
+
+void KyraAudioStream::beginFadeOut(uint32 millis) {
+ _fadeSamples = (millis * getRate()) / 1000;
+ if (_fading == 0)
+ _fadeCount = _fadeSamples;
+ _fading = -1;
+}
+
+int KyraAudioStream::readBuffer(int16 *buffer, const int numSamples) {
+ int samplesRead = _impl->readBuffer(buffer, numSamples);
+
+ if (_fading) {
+ int samplesProcessed = 0;
+ for (; samplesProcessed < samplesRead; ++samplesProcessed) {
+ // To help avoid overflows for long fade times, we divide both
+ // _fadeSamples and _fadeCount when calculating the new sample.
+
+ int32 div = _fadeSamples / 256;
+ if (_fading) {
+ *buffer = (*buffer * (_fadeCount / 256)) / div;
+ ++buffer;
+
+ _fadeCount += _fading;
+
+ if (_fadeCount < 0) {
+ _fadeCount = 0;
+ _endOfData = true;
+ } else if (_fadeCount > _fadeSamples) {
+ _fadeCount = _fadeSamples;
+ _fading = 0;
+ }
+ }
+ }
+
+ if (_endOfData) {
+ memset(buffer, 0, (samplesRead - samplesProcessed) * sizeof(int16));
+ samplesRead = samplesProcessed;
+ }
+ }
+
+ return samplesRead;
+}
+
// Thanks to Torbjorn Andersson (eriktorbjorn) for his aud player on which
// this code is based on
@@ -46,11 +117,7 @@ public:
bool isStereo() const { return false; }
bool endOfData() const { return _endOfData; }
- void setRate(int newRate) { _rate = newRate; }
int getRate() const { return _rate; }
-
- void beginFadeIn(uint32 millis);
- void beginFadeOut(uint32 millis);
private:
Common::SeekableReadStream *_stream;
bool _loop;
@@ -69,10 +136,6 @@ private:
byte *_inBuffer;
uint _inBufferSize;
- int32 _fadeSamples;
- int32 _fadeCount;
- int _fading;
-
int readChunk(int16 *buffer, const int maxSamples);
static const int8 WSTable2Bit[];
@@ -93,9 +156,6 @@ AUDStream::AUDStream(Common::SeekableReadStream *stream, bool loop) : _stream(st
_totalSize = _stream->readUint32LE();
_loop = loop;
- _fadeSamples = 0;
- _fading = 0;
-
// TODO?: add checks
int flags = _stream->readByte(); // flags
int type = _stream->readByte(); // type
@@ -114,20 +174,6 @@ AUDStream::~AUDStream() {
delete _stream;
}
-void AUDStream::beginFadeIn(uint32 millis) {
- _fadeSamples = (millis * getRate()) / 1000;
- if (_fading == 0)
- _fadeCount = 0;
- _fading = 1;
-}
-
-void AUDStream::beginFadeOut(uint32 millis) {
- _fadeSamples = (millis * getRate()) / 1000;
- if (_fading == 0)
- _fadeCount = _fadeSamples;
- _fading = -1;
-}
-
int AUDStream::readBuffer(int16 *buffer, const int numSamples) {
int samplesRead = 0, samplesLeft = numSamples;
@@ -288,34 +334,13 @@ int AUDStream::readChunk(int16 *buffer, const int maxSamples) {
samplesProcessed += samples;
_bytesLeft -= samples;
- // To help avoid overflows for long fade times, we divide both
- // _fadeSamples and _fadeCount when calculating the new sample.
-
- int32 div = _fadeSamples / 256;
-
while (samples--) {
int16 sample = (_outBuffer[_outBufferOffset++] << 8) ^ 0x8000;
- if (_fading) {
- sample = (sample * (_fadeCount / 256)) / div;
- _fadeCount += _fading;
-
- if (_fadeCount < 0) {
- _fadeCount = 0;
- _endOfData = true;
- } else if (_fadeCount > _fadeSamples) {
- _fadeCount = _fadeSamples;
- _fading = 0;
- }
- }
-
*buffer++ = sample;
}
}
- if (_fading < 0 && _fadeCount == 0)
- _fading = 0;
-
return samplesProcessed;
}
@@ -367,7 +392,19 @@ int SoundDigital::playSound(const char *filename, uint8 priority, Audio::Mixer::
}
}
- Common::SeekableReadStream *stream = _vm->resource()->getFileStream(filename);
+ Common::SeekableReadStream *stream = 0;
+ int usedCodec = -1;
+ for (int i = 0; _supportedCodecs[i].fileext; ++i) {
+ Common::String file = filename;
+ file += _supportedCodecs[i].fileext;
+
+ if (!_vm->resource()->exists(file.c_str()))
+ continue;
+
+ stream = _vm->resource()->getFileStream(file);
+ usedCodec = i;
+ }
+
if (!stream) {
warning("Couldn't find soundfile '%s'", filename);
return -1;
@@ -375,7 +412,13 @@ int SoundDigital::playSound(const char *filename, uint8 priority, Audio::Mixer::
strncpy(use->filename, filename, sizeof(use->filename));
use->priority = priority;
- use->stream = new AUDStream(stream, loop);
+ Audio::AudioStream *audioStream = _supportedCodecs[usedCodec].streamFunc(stream, true, 0, 0, loop ? 0 : 1);
+ if (!audioStream) {
+ warning("Couldn't create audio stream for file '%s'", filename);
+ return -1;
+ }
+ use->stream = new KyraAudioStream(audioStream);
+ assert(use->stream);
if (use->stream->endOfData()) {
delete use->stream;
use->stream = 0;
@@ -428,5 +471,30 @@ void SoundDigital::beginFadeOut(int channel, int ticks) {
_sounds[channel].stream->beginFadeOut(ticks * _vm->tickLength());
}
+// static res
+
+namespace {
+
+Audio::AudioStream *makeAUDStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 startTime, uint32 duration, uint numLoops) {
+ return new AUDStream(stream, numLoops == 0 ? true : false);
+}
+
+} // end of anonymous namespace
+
+const SoundDigital::AudioCodecs SoundDigital::_supportedCodecs[] = {
+#ifdef USE_FLAC
+ { ".FLA", Audio::makeFlacStream },
+#endif // USE_FLAC
+#ifdef USE_VORBIS
+ { ".OGG", Audio::makeVorbisStream },
+#endif // USE_VORBIS
+#ifdef USE_MAD
+ { ".MP3", Audio::makeMP3Stream },
+#endif // USE_MAD
+ { ".AUD", makeAUDStream },
+ { 0, 0 }
+};
+
+
} // end of namespace Kyra