diff options
author | Filippos Karapetis | 2009-11-04 09:36:18 +0000 |
---|---|---|
committer | Filippos Karapetis | 2009-11-04 09:36:18 +0000 |
commit | 597524b255a75bb61830c8c518d990a38a4923b5 (patch) | |
tree | 45f447cdca0b485e5d6373bf5f1bd2fe64370bb1 /engines/sci | |
parent | 66d3540f2caf23a4ba9fd59bd30d13302f1d8064 (diff) | |
download | scummvm-rg350-597524b255a75bb61830c8c518d990a38a4923b5.tar.gz scummvm-rg350-597524b255a75bb61830c8c518d990a38a4923b5.tar.bz2 scummvm-rg350-597524b255a75bb61830c8c518d990a38a4923b5.zip |
Moved most of the code for playing sound effects and speech into a separate class
svn-id: r45653
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/engine/ksound.cpp | 18 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 3 | ||||
-rw-r--r-- | engines/sci/engine/state.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 4 | ||||
-rw-r--r-- | engines/sci/module.mk | 1 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 5 | ||||
-rw-r--r-- | engines/sci/sci.h | 2 | ||||
-rw-r--r-- | engines/sci/sfx/audio.cpp | 216 | ||||
-rw-r--r-- | engines/sci/sfx/audio.h | 56 | ||||
-rw-r--r-- | engines/sci/sfx/core.cpp | 182 | ||||
-rw-r--r-- | engines/sci/sfx/core.h | 14 |
11 files changed, 295 insertions, 210 deletions
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 3d92f180a4..688e1570cb 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -833,9 +833,9 @@ static reg_t kDoSoundSci1Late(EngineState *s, int argc, reg_t *argv) { if (s->resMan->testResource(ResourceId(kResourceTypeAudio, number)) && getSciVersion() >= SCI_VERSION_1_1) { // Found a relevant audio resource, play it - s->_sound.stopAudio(); + s->_audio->stopAudio(); warning("Initializing audio resource instead of requested sound resource %d", number); - sampleLen = s->_sound.startAudio(65535, number); + sampleLen = s->_audio->startAudio(65535, number); // Also create iterator, that will fire SI_FINISHED event, when the sound is done playing s->_sound.sfx_add_song(build_timeriterator(s, sampleLen), 0, handle, number); } else { @@ -1133,7 +1133,7 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { uint16 module; uint32 number; - s->_sound.stopAudio(); + s->_audio->stopAudio(); if (argc == 2) { module = 65535; @@ -1147,21 +1147,21 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - return make_reg(0, s->_sound.startAudio(module, number)); // return sample length in ticks + return make_reg(0, s->_audio->startAudio(module, number)); // return sample length in ticks } case kSciAudioStop: - s->_sound.stopAudio(); + s->_audio->stopAudio(); break; case kSciAudioPause: - s->_sound.pauseAudio(); + s->_audio->pauseAudio(); break; case kSciAudioResume: - s->_sound.resumeAudio(); + s->_audio->resumeAudio(); break; case kSciAudioPosition: - return make_reg(0, s->_sound.getAudioPosition()); + return make_reg(0, s->_audio->getAudioPosition()); case kSciAudioRate: - s->_sound.setAudioRate(argv[1].toUint16()); + s->_audio->setAudioRate(argv[1].toUint16()); break; case kSciAudioVolume: mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[1].toUint16()); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 5795299570..9f3aa118b4 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -34,6 +34,7 @@ #ifdef INCLUDE_OLDGFX #include "sci/gfx/gfx_state_internal.h" // required for GfxPort, GfxContainer #endif +#include "sci/sfx/audio.h" #include "sci/sfx/core.h" #include "sci/sfx/iterator.h" #include "sci/engine/state.h" @@ -735,7 +736,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { } // FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch. - retval = new EngineState(s->resMan, s->_kernel, s->_voc, s->_gui, s->_cursor); + retval = new EngineState(s->resMan, s->_kernel, s->_voc, s->_gui, s->_cursor, s->_audio); // Copy some old data retval->gfx_state = s->gfx_state; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 35d38e565e..d105a8b6e8 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -32,8 +32,8 @@ namespace Sci { -EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SciGui *gui, SciGuiCursor *cursor) -: resMan(res), _kernel(kernel), _voc(voc), _gui(gui), _cursor(cursor), _dirseeker(this) { +EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SciGui *gui, SciGuiCursor *cursor, AudioPlayer *audio) +: resMan(res), _kernel(kernel), _voc(voc), _gui(gui), _cursor(cursor), _audio(audio), _dirseeker(this) { gfx_state = 0; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 715c74660a..90a81f62c5 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -42,6 +42,7 @@ namespace Common { #include "sci/engine/script.h" #include "sci/engine/seg_manager.h" #include "sci/gfx/gfx_system.h" +#include "sci/sfx/audio.h" #include "sci/sfx/core.h" namespace Sci { @@ -115,7 +116,7 @@ public: struct EngineState : public Common::Serializable { public: - EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SciGui *gui, SciGuiCursor *cursor); + EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SciGui *gui, SciGuiCursor *cursor, AudioPlayer *audio); virtual ~EngineState(); virtual void saveLoadWithSerializer(Common::Serializer &ser); @@ -135,6 +136,7 @@ public: GfxState *gfx_state; /**< Graphics state and driver */ + AudioPlayer *_audio; SfxState _sound; /**< sound subsystem */ int sfx_init_flags; /**< flags the sfx subsystem was initialised with */ unsigned int sound_volume; /**< 0x0 -> 0xf Current volume of sound system */ diff --git a/engines/sci/module.mk b/engines/sci/module.mk index b651dcd9bc..649faea14a 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -67,6 +67,7 @@ MODULE_OBJS := \ gui32/res_pal.o \ gui32/res_pic.o \ gui32/res_view.o \ + sfx/audio.o \ sfx/core.o \ sfx/iterator.o \ sfx/songlib.o \ diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 376d2dc9f3..efd14252b3 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -40,6 +40,7 @@ #include "sci/gfx/gfx_state_internal.h" // required for GfxContainer, GfxPort, GfxVisual #include "sci/gui32/gui32.h" #endif +#include "sci/sfx/audio.h" #include "sci/gui/gui.h" #include "sci/gui/gui_palette.h" #include "sci/gui/gui_cursor.h" @@ -94,6 +95,7 @@ SciEngine::~SciEngine() { // Remove all of our debug levels here Common::clearAllDebugChannels(); + delete _audio; delete _kernel; delete _vocabulary; delete _console; @@ -129,9 +131,10 @@ Common::Error SciEngine::run() { _kernel = new Kernel(_resMan); _vocabulary = new Vocabulary(_resMan); + _audio = new AudioPlayer(_resMan); // We'll set the GUI below - _gamestate = new EngineState(_resMan, _kernel, _vocabulary, NULL, cursor); + _gamestate = new EngineState(_resMan, _kernel, _vocabulary, NULL, cursor, _audio); if (script_init_engine(_gamestate)) return Common::kUnknownError; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 12143fa9e9..8af9450aff 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -38,6 +38,7 @@ struct EngineState; class Kernel; class Vocabulary; class ResourceManager; +class AudioPlayer; // our engine debug levels enum kDebugLevels { @@ -128,6 +129,7 @@ public: private: const ADGameDescription *_gameDescription; + AudioPlayer *_audio; ResourceManager *_resMan; EngineState *_gamestate; Kernel *_kernel; diff --git a/engines/sci/sfx/audio.cpp b/engines/sci/sfx/audio.cpp new file mode 100644 index 0000000000..7a02677f63 --- /dev/null +++ b/engines/sci/sfx/audio.cpp @@ -0,0 +1,216 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "sci/resource.h" +#include "sci/sfx/audio.h" + +#include "common/system.h" + +#include "sound/audiostream.h" +#include "sound/mixer.h" + +namespace Sci { + +int AudioPlayer::startAudio(uint16 module, uint32 number) { + int sampleLen; + Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen); + + if (audioStream) { + g_system->getMixer()->playInputStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); + return sampleLen; + } + + return 0; +} + +int AudioPlayer::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 +} + +enum SolFlags { + kSolFlagCompressed = 1 << 0, + kSolFlagUnknown = 1 << 1, + kSolFlag16Bit = 1 << 2, + kSolFlagIsSigned = 1 << 3 +}; + +// FIXME: Move this to sound/adpcm.cpp? +// Note that the 16-bit version is also used in coktelvideo.cpp +static const uint16 tableDPCM16[128] = { + 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080, + 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120, + 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0, + 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230, + 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280, + 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0, + 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, + 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, + 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0, + 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480, + 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700, + 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, + 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 +}; + +static const byte tableDPCM8[8] = {0, 1, 2, 3, 6, 10, 15, 21}; + +static void deDPCM16(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { + int16 *out = (int16 *) soundBuf; + + int32 s = 0; + for (uint32 i = 0; i < n; i++) { + byte b = audioStream.readByte(); + if (b & 0x80) + s -= tableDPCM16[b & 0x7f]; + else + s += tableDPCM16[b]; + + s = CLIP<int32>(s, -32768, 32767); + *out++ = s; + } +} + +static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) { + if (b & 8) + s -= tableDPCM8[7 - (b & 7)]; + else + s += tableDPCM8[b & 7]; + s = CLIP<int32>(s, 0, 255); + *soundBuf = TO_LE_16(s); +} + +static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { + int32 s = 0x80; + + for (uint i = 0; i < n; i++) { + byte b = audioStream.readByte(); + + deDPCM8Nibble(soundBuf++, s, b >> 4); + deDPCM8Nibble(soundBuf++, s, b & 0xf); + } +} + +// Sierra SOL audio file reader +// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio +static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) { + if (headerSize != 11 && headerSize != 12) { + warning("SOL audio header of size %i not supported", headerSize); + return false; + } + + audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) + audioRate = audioStream->readUint16LE(); + audioFlags = audioStream->readByte(); + + size = audioStream->readUint32LE(); + return true; +} + +static byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, byte audioFlags, byte &flags) { + byte *buffer; + + // Convert the SOL stream flags to our own format + flags = 0; + if (audioFlags & kSolFlag16Bit) + flags |= Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN; + + if (!(audioFlags & kSolFlagIsSigned)) + flags |= Audio::Mixer::FLAG_UNSIGNED; + + if (audioFlags & kSolFlagCompressed) { + buffer = (byte *)malloc(size * 2); + + if (audioFlags & kSolFlag16Bit) + deDPCM16(buffer, *audioStream, size); + else + deDPCM8(buffer, *audioStream, size); + + size *= 2; + } else { + // We assume that the sound data is raw PCM + buffer = (byte *)malloc(size); + audioStream->read(buffer, size); + } + + return buffer; +} + +Audio::AudioStream* AudioPlayer::getAudioStream(uint32 number, uint32 volume, int *sampleLen) { + Audio::AudioStream *audioStream = 0; + uint32 size = 0; + byte *data = 0; + byte flags = 0; + Sci::Resource* audioRes; + + if (volume == 65535) { + audioRes = _resMan->findResource(ResourceId(kResourceTypeAudio, number), false); + if (!audioRes) { + warning("Failed to find audio entry %i", number); + return NULL; + } + } else { + audioRes = _resMan->findResource(ResourceId(kResourceTypeAudio36, volume, number), false); + if (!audioRes) { + warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (number >> 24) & 0xff, + (number >> 16) & 0xff, (number >> 8) & 0xff, number & 0xff); + return NULL; + } + } + + byte audioFlags; + + if (audioRes->headerSize > 0) { + // SCI1.1 + Common::MemoryReadStream headerStream(audioRes->header, audioRes->headerSize, Common::DisposeAfterUse::NO); + + if (readSOLHeader(&headerStream, audioRes->headerSize, size, _audioRate, audioFlags)) { + Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, Common::DisposeAfterUse::NO); + data = readSOLAudio(&dataStream, size, audioFlags, flags); + } + } else { + // SCI1 + size = audioRes->size; + data = (byte *)malloc(size); + assert(data); + memcpy(data, audioRes->data, size); + flags = Audio::Mixer::FLAG_UNSIGNED; + } + + if (data) { + audioStream = Audio::makeLinearInputStream(data, size, _audioRate, + flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); + if (audioStream) { + *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; + return audioStream; + } + } + + return NULL; +} + +} // End of namespace Sci diff --git a/engines/sci/sfx/audio.h b/engines/sci/sfx/audio.h new file mode 100644 index 0000000000..b54b67567c --- /dev/null +++ b/engines/sci/sfx/audio.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* Sound engine */ +#ifndef SCI_AUDIO_H +#define SCI_AUDIO_H + +namespace Sci { + +class ResourceManager; + +class AudioPlayer { +public: + AudioPlayer(ResourceManager *resMan) : _resMan(resMan), _audioRate(11025) { } + AudioPlayer::~AudioPlayer() { stopAudio(); } + + void setAudioRate(uint16 rate) { _audioRate = rate; } + Audio::SoundHandle* getAudioHandle() { return &_audioHandle; } + int getAudioPosition(); + int startAudio(uint16 module, uint32 tuple); + void stopAudio() { g_system->getMixer()->stopHandle(_audioHandle); } + void pauseAudio() { g_system->getMixer()->pauseHandle(_audioHandle, true); } + void resumeAudio() { g_system->getMixer()->pauseHandle(_audioHandle, false); } + +private: + ResourceManager *_resMan; + uint16 _audioRate; + Audio::SoundHandle _audioHandle; + Audio::AudioStream* getAudioStream(uint32 number, uint32 volume, int *sampleLen); +}; + +} // End of namespace Sci + +#endif // SCI_SFX_CORE_H diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp index acc89f6df8..90aa024dcd 100644 --- a/engines/sci/sfx/core.cpp +++ b/engines/sci/sfx/core.cpp @@ -37,7 +37,6 @@ #include "common/system.h" #include "common/timer.h" -#include "sound/audiostream.h" #include "sound/mixer.h" namespace Sci { @@ -359,7 +358,6 @@ SfxState::SfxState() { _song = NULL; _suspended = 0; _syncResource = NULL; - _audioRate = 11025; } SfxState::~SfxState() { @@ -1013,184 +1011,4 @@ void SfxState::sfx_all_stop() { update(); } -int SfxState::startAudio(uint16 module, uint32 number) { - int sampleLen; - Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen); - - if (audioStream) { - g_system->getMixer()->playInputStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); - return sampleLen; - } - - return 0; -} - -int SfxState::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 -} - -enum SolFlags { - kSolFlagCompressed = 1 << 0, - kSolFlagUnknown = 1 << 1, - kSolFlag16Bit = 1 << 2, - kSolFlagIsSigned = 1 << 3 -}; - -// FIXME: Move this to sound/adpcm.cpp? -// Note that the 16-bit version is also used in coktelvideo.cpp -static const uint16 tableDPCM16[128] = { - 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080, - 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120, - 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0, - 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230, - 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280, - 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0, - 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, - 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, - 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0, - 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480, - 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700, - 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, - 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 -}; - -static const byte tableDPCM8[8] = {0, 1, 2, 3, 6, 10, 15, 21}; - -static void deDPCM16(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { - int16 *out = (int16 *) soundBuf; - - int32 s = 0; - for (uint32 i = 0; i < n; i++) { - byte b = audioStream.readByte(); - if (b & 0x80) - s -= tableDPCM16[b & 0x7f]; - else - s += tableDPCM16[b]; - - s = CLIP<int32>(s, -32768, 32767); - *out++ = s; - } -} - -static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) { - if (b & 8) - s -= tableDPCM8[7 - (b & 7)]; - else - s += tableDPCM8[b & 7]; - s = CLIP<int32>(s, 0, 255); - *soundBuf = TO_LE_16(s); -} - -static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { - int32 s = 0x80; - - for (uint i = 0; i < n; i++) { - byte b = audioStream.readByte(); - - deDPCM8Nibble(soundBuf++, s, b >> 4); - deDPCM8Nibble(soundBuf++, s, b & 0xf); - } -} - -// Sierra SOL audio file reader -// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio -static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) { - if (headerSize != 11 && headerSize != 12) { - warning("SOL audio header of size %i not supported", headerSize); - return false; - } - - audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) - audioRate = audioStream->readUint16LE(); - audioFlags = audioStream->readByte(); - - size = audioStream->readUint32LE(); - return true; -} - -static byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, byte audioFlags, byte &flags) { - byte *buffer; - - // Convert the SOL stream flags to our own format - flags = 0; - if (audioFlags & kSolFlag16Bit) - flags |= Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN; - - if (!(audioFlags & kSolFlagIsSigned)) - flags |= Audio::Mixer::FLAG_UNSIGNED; - - if (audioFlags & kSolFlagCompressed) { - buffer = (byte *)malloc(size * 2); - - if (audioFlags & kSolFlag16Bit) - deDPCM16(buffer, *audioStream, size); - else - deDPCM8(buffer, *audioStream, size); - - size *= 2; - } else { - // We assume that the sound data is raw PCM - buffer = (byte *)malloc(size); - audioStream->read(buffer, size); - } - - return buffer; -} - -Audio::AudioStream* SfxState::getAudioStream(uint32 number, uint32 volume, int *sampleLen) { - Audio::AudioStream *audioStream = 0; - uint32 size = 0; - byte *data = 0; - byte flags = 0; - Sci::Resource* audioRes; - - if (volume == 65535) { - audioRes = _resMan->findResource(ResourceId(kResourceTypeAudio, number), false); - if (!audioRes) { - warning("Failed to find audio entry %i", number); - return NULL; - } - } else { - audioRes = _resMan->findResource(ResourceId(kResourceTypeAudio36, volume, number), false); - if (!audioRes) { - warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (number >> 24) & 0xff, - (number >> 16) & 0xff, (number >> 8) & 0xff, number & 0xff); - return NULL; - } - } - - byte audioFlags; - - if (audioRes->headerSize > 0) { - // SCI1.1 - Common::MemoryReadStream headerStream(audioRes->header, audioRes->headerSize, Common::DisposeAfterUse::NO); - - if (readSOLHeader(&headerStream, audioRes->headerSize, size, _audioRate, audioFlags)) { - Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, Common::DisposeAfterUse::NO); - data = readSOLAudio(&dataStream, size, audioFlags, flags); - } - } else { - // SCI1 - size = audioRes->size; - data = (byte *)malloc(size); - assert(data); - memcpy(data, audioRes->data, size); - flags = Audio::Mixer::FLAG_UNSIGNED; - } - - if (data) { - audioStream = Audio::makeLinearInputStream(data, size, _audioRate, - flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); - if (audioStream) { - *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; - return audioStream; - } - } - - return NULL; -} - } // End of namespace Sci diff --git a/engines/sci/sfx/core.h b/engines/sci/sfx/core.h index 1cb6540e8e..92ea788636 100644 --- a/engines/sci/sfx/core.h +++ b/engines/sci/sfx/core.h @@ -169,15 +169,6 @@ public: Common::Error sfx_send_midi(SongHandle handle, int channel, int command, int arg1, int arg2); - // Functions for digital sound - void setAudioRate(uint16 rate) { _audioRate = rate; } - Audio::SoundHandle* getAudioHandle() { return &_audioHandle; } - int getAudioPosition(); - int startAudio(uint16 module, uint32 tuple); - void stopAudio() { g_system->getMixer()->stopHandle(_audioHandle); } - void pauseAudio() { g_system->getMixer()->pauseHandle(_audioHandle, true); } - void resumeAudio() { g_system->getMixer()->pauseHandle(_audioHandle, false); } - // misc /** @@ -207,11 +198,6 @@ protected: void updateSingleSong(); void updateMultiSong(); void update(); - -private: - uint16 _audioRate; - Audio::SoundHandle _audioHandle; - Audio::AudioStream* getAudioStream(uint32 number, uint32 volume, int *sampleLen); }; } // End of namespace Sci |