From 23c8240048209cd53d5d12874e28d9f9382f64c5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 25 Jun 2007 18:23:01 +0000 Subject: Add support for compressed sound effects, digital music and speech to the SAGA engine svn-id: r27713 --- engines/saga/saga.h | 5 ++++- engines/saga/sndres.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++--- engines/saga/sound.cpp | 35 ++++++++++++++++++++++++++++++++++- engines/saga/sound.h | 11 +++++++++++ 4 files changed, 93 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/saga/saga.h b/engines/saga/saga.h index 9532d2fd56..c5038e5c5d 100644 --- a/engines/saga/saga.h +++ b/engines/saga/saga.h @@ -224,7 +224,10 @@ enum GameSoundTypes { kSoundVOX = 1, kSoundVOC = 2, kSoundWAV = 3, - kSoundMacPCM = 4 + kSoundMacPCM = 4, + kSoundMP3 = 5, + kSoundOGG = 6, + kSoundFLAC = 7 }; enum TextStringIds { diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp index c0442c75de..39dd9b5c06 100644 --- a/engines/saga/sndres.cpp +++ b/engines/saga/sndres.cpp @@ -156,7 +156,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff return false; } - _vm->_resource->loadResource(context, resourceId, soundResource, soundResourceLength); if ((context->fileType & GAME_VOICEFILE) != 0) { @@ -175,8 +174,19 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff if (soundResourceLength >= 8) { if (!memcmp(soundResource, "Creative", 8)) { resourceType = kSoundVOC; - } else if (!memcmp(soundResource, "RIFF", 4) != 0) { + } else if (!memcmp(soundResource, "RIFF", 4) != 0) { resourceType = kSoundWAV; + } else if (soundResource[0] == char(0)) { + readS.seek(1); + uint16 test = readS.readUint16LE(); // the frequency + // the sound's frequency is not supposed to be 0, if it is then it's an empty sound, + // so don't treat it as MP3 + if (test > 0) // Skip compression identifier byte + resourceType = kSoundMP3; + } else if (soundResource[0] == char(1)) { + resourceType = kSoundOGG; + } else if (soundResource[0] == char(2)) { + resourceType = kSoundFLAC; } } @@ -188,6 +198,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff buffer.sampleBits = soundInfo->sampleBits; buffer.size = soundResourceLength; buffer.stereo = soundInfo->stereo; + buffer.isCompressed = false; if (onlyHeader) { buffer.buffer = NULL; free(soundResource); @@ -202,6 +213,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff buffer.sampleBits = soundInfo->sampleBits; buffer.size = soundResourceLength - 36; buffer.stereo = soundInfo->stereo; + buffer.isCompressed = false; if (onlyHeader) { buffer.buffer = NULL; } else { @@ -217,6 +229,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff buffer.sampleBits = soundInfo->sampleBits; buffer.stereo = soundInfo->stereo; buffer.size = soundResourceLength * 4; + buffer.isCompressed = false; if (onlyHeader) { buffer.buffer = NULL; free(soundResource); @@ -239,6 +252,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff buffer.stereo = false; buffer.isSigned = false; buffer.size = size; + buffer.isCompressed = false; if (onlyHeader) { buffer.buffer = NULL; free(data); @@ -256,6 +270,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff buffer.stereo = ((flags & Audio::Mixer::FLAG_STEREO) != 0); buffer.isSigned = true; buffer.size = size; + buffer.isCompressed = false; if (onlyHeader) { buffer.buffer = NULL; } else { @@ -266,6 +281,29 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff } free(soundResource); break; + case kSoundMP3: + case kSoundOGG: + case kSoundFLAC: + ResourceData *resourceData; + resourceData = _vm->_resource->getResourceData(context, resourceId); + + readS.seek(1); // Skip compression identifier byte + + buffer.frequency = readS.readUint16LE(); + buffer.size = soundResourceLength; + buffer.originalSize = readS.readUint32LE(); + buffer.sampleBits = readS.readByte(); + buffer.stereo = (readS.readByte() == char(0)) ? false : true; + buffer.isCompressed = true; + buffer.soundType = resourceType; + buffer.soundFile = context->getFile(resourceData); + buffer.fileOffset = resourceData->offset; + + buffer.buffer = NULL; + + result = true; + free(soundResource); + break; default: error("SndRes::load Unknown sound type"); } @@ -286,7 +324,10 @@ int SndRes::getVoiceLength(uint32 resourceId) { return -1; } - msDouble = (double)buffer.size; + if (!buffer.isCompressed) + msDouble = (double)buffer.size; + else + msDouble = (double)buffer.originalSize; if (buffer.sampleBits == 16) { msDouble /= 2.0; } diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp index a4ce79b9c4..b0f4f8319b 100644 --- a/engines/saga/sound.cpp +++ b/engines/saga/sound.cpp @@ -80,7 +80,40 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int if (!buffer.isSigned) flags |= Audio::Mixer::FLAG_UNSIGNED; - _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume); + if (!buffer.isCompressed) { + _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume); + } else { + buffer.soundFile->seek((long)buffer.fileOffset, SEEK_SET); + Audio::AudioStream *stream = NULL; + + switch (buffer.soundType) { +#ifdef USE_MAD + case kSoundMP3: + debug(1, "Playing MP3 compressed sound"); + stream = Audio::makeMP3Stream(buffer.soundFile, buffer.size); + break; +#endif +#ifdef USE_VORBIS + case kSoundOGG: + debug(1, "Playing OGG compressed sound"); + stream = Audio::makeVorbisStream(buffer.soundFile, buffer.size); + break; +#endif +#ifdef USE_FLAC + case kSoundFLAC: + debug(1, "Playing FLAC compressed sound"); + stream = Audio::makeFlacStream(buffer.soundFile, buffer.size); + break; +#endif + default: + // Unknown compression + error("Trying to play a compressed sound, but the compression is not known"); + break; + } + + if (stream != NULL) + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, stream, -1, volume, 0, true, false); + } } void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) { diff --git a/engines/saga/sound.h b/engines/saga/sound.h index 3abea583ba..b75c194da4 100644 --- a/engines/saga/sound.h +++ b/engines/saga/sound.h @@ -28,7 +28,13 @@ #ifndef SAGA_SOUND_H #define SAGA_SOUND_H +#include "common/file.h" #include "sound/mixer.h" +#include "sound/mp3.h" +#include "sound/vorbis.h" +#include "sound/flac.h" +#include "sound/rate.h" +#include "sound/wave.h" namespace Saga { @@ -46,7 +52,12 @@ struct SoundBuffer { byte *buffer; size_t size; + size_t originalSize; bool isBigEndian; + bool isCompressed; + GameSoundTypes soundType; + Common::File *soundFile; + size_t fileOffset; }; enum sndHandleType { -- cgit v1.2.3