aboutsummaryrefslogtreecommitdiff
path: root/engines/simon/sound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/simon/sound.cpp')
-rw-r--r--engines/simon/sound.cpp714
1 files changed, 0 insertions, 714 deletions
diff --git a/engines/simon/sound.cpp b/engines/simon/sound.cpp
deleted file mode 100644
index 42c2df1723..0000000000
--- a/engines/simon/sound.cpp
+++ /dev/null
@@ -1,714 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2001 Ludvig Strigeus
- * Copyright (C) 2001-2006 The ScummVM project
- *
- * 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 "common/stdafx.h"
-
-#include "common/file.h"
-#include "common/util.h"
-
-#include "agos/agos.h"
-#include "agos/sound.h"
-
-#include "sound/adpcm.h"
-#include "sound/audiostream.h"
-#include "sound/flac.h"
-#include "sound/mp3.h"
-#include "sound/voc.h"
-#include "sound/vorbis.h"
-#include "sound/wave.h"
-
-using Common::File;
-
-namespace Simon {
-
-#define SOUND_BIG_ENDIAN true
-
-class BaseSound {
-protected:
- File *_file;
- uint32 *_offsets;
- Audio::Mixer *_mixer;
- bool _freeOffsets;
-
-public:
- BaseSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigendian = false);
- BaseSound(Audio::Mixer *mixer, File *file, uint32 *offsets, bool bigendian = false);
- virtual ~BaseSound();
- virtual void playSound(uint sound, Audio::SoundHandle *handle, byte flags) = 0;
-};
-
-class WavSound : public BaseSound {
-public:
- WavSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigendian = false) : BaseSound(mixer, file, base, bigendian) {};
- WavSound(Audio::Mixer *mixer, File *file, uint32 *offsets) : BaseSound(mixer, file, offsets) {};
- void playSound(uint sound, Audio::SoundHandle *handle, byte flags);
-};
-
-class VocSound : public BaseSound {
-public:
- VocSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigendian = false) : BaseSound(mixer, file, base, bigendian) {};
- void playSound(uint sound, Audio::SoundHandle *handle, byte flags);
-};
-class RawSound : public BaseSound {
-public:
- RawSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigendian = false) : BaseSound(mixer, file, base, bigendian) {};
- void playSound(uint sound, Audio::SoundHandle *handle, byte flags);
-};
-
-BaseSound::BaseSound(Audio::Mixer *mixer, File *file, uint32 base, bool bigendian) {
- _mixer = mixer;
- _file = file;
-
- uint res = 0;
- uint32 size;
-
- _file->seek(base + sizeof(uint32), SEEK_SET);
- if (bigendian)
- size = _file->readUint32BE();
- else
- size = _file->readUint32LE();
-
- // The Feeble Files uses set amount of voice offsets
- if (size == 0)
- size = 40000;
-
- res = size / sizeof(uint32);
-
- _offsets = (uint32 *)malloc(size + sizeof(uint32));
- _freeOffsets = true;
-
- _file->seek(base, SEEK_SET);
-
- if (_file->read(_offsets, size) != size)
- error("BaseSound: Can't read offsets");
-
- for (uint i = 0; i < res; i++) {
-#if defined(SCUMM_BIG_ENDIAN)
- if (!(bigendian))
- _offsets[i] = FROM_LE_32(_offsets[i]);
-#endif
- if (bigendian)
- _offsets[i] = TO_BE_32(_offsets[i]);
- _offsets[i] += base;
- }
-
- // only needed for mp3
- _offsets[res] = _file->size();
-}
-
-BaseSound::BaseSound(Audio::Mixer *mixer, File *file, uint32 *offsets, bool bigendian) {
- _mixer = mixer;
- _file = file;
- _offsets = offsets;
- _freeOffsets = false;
-}
-
-BaseSound::~BaseSound() {
- if (_freeOffsets)
- free(_offsets);
- delete _file;
-}
-
-void WavSound::playSound(uint sound, Audio::SoundHandle *handle, byte flags) {
- if (_offsets == NULL)
- return;
-
- _file->seek(_offsets[sound], SEEK_SET);
-
- byte wavFlags;
- int size, rate;
- if (!Audio::loadWAVFromStream(*_file, size, rate, wavFlags))
- error("playSound: Not a valid WAV file");
-
- flags |= wavFlags;
-
- byte *buffer = (byte *)malloc(size);
- // Check whether malloc was successful.
- // TODO: Maybe we can handle this more graceful, by reverting to a smaller
- // buffer and reading the audio data one piece at a time?
- if (buffer) {
- _file->read(buffer, size);
- _mixer->playRaw(handle, buffer, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE);
- }
-}
-
-void VocSound::playSound(uint sound, Audio::SoundHandle *handle, byte flags) {
- if (_offsets == NULL)
- return;
-
- _file->seek(_offsets[sound], SEEK_SET);
-
- int size, rate;
- byte *buffer = Audio::loadVOCFromStream(*_file, size, rate);
- _mixer->playRaw(handle, buffer, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE);
-}
-
-void RawSound::playSound(uint sound, Audio::SoundHandle *handle, byte flags) {
- if (_offsets == NULL)
- return;
-
- _file->seek(_offsets[sound], SEEK_SET);
-
- uint size = _file->readUint32BE();
- byte *buffer = (byte *)malloc(size);
- // Check whether malloc was successful.
- // TODO: Maybe we can handle this more graceful, by reverting to a smaller
- // buffer and reading the audio data one piece at a time?
- if (buffer) {
- _file->read(buffer, size);
- _mixer->playRaw(handle, buffer, size, 22050, flags | Audio::Mixer::FLAG_AUTOFREE);
- }
-}
-
-#ifdef USE_MAD
-class MP3Sound : public BaseSound {
-public:
- MP3Sound(Audio::Mixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {};
- void playSound(uint sound, Audio::SoundHandle *handle, byte flags);
-};
-
-void MP3Sound::playSound(uint sound, Audio::SoundHandle *handle, byte flags)
-{
- if (_offsets == NULL)
- return;
-
- _file->seek(_offsets[sound], SEEK_SET);
-
- int i = 1;
- while (_offsets[sound + i] == _offsets[sound])
- i++;
-
- uint32 size = _offsets[sound + i] - _offsets[sound];
-
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, Audio::makeMP3Stream(_file, size));
-}
-#endif
-
-#ifdef USE_VORBIS
-class VorbisSound : public BaseSound {
-public:
- VorbisSound(Audio::Mixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {};
- void playSound(uint sound, Audio::SoundHandle *handle, byte flags);
-};
-
-void VorbisSound::playSound(uint sound, Audio::SoundHandle *handle, byte flags)
-{
- if (_offsets == NULL)
- return;
-
- _file->seek(_offsets[sound], SEEK_SET);
-
- int i = 1;
- while (_offsets[sound + i] == _offsets[sound])
- i++;
-
- uint32 size = _offsets[sound + i] - _offsets[sound];
-
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, Audio::makeVorbisStream(_file, size));
-}
-#endif
-
-#ifdef USE_FLAC
-class FlacSound : public BaseSound {
-public:
- FlacSound(Audio::Mixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {};
- void playSound(uint sound, Audio::SoundHandle *handle, byte flags);
-};
-
-void FlacSound::playSound(uint sound, Audio::SoundHandle *handle, byte flags)
-{
- if (_offsets == NULL)
- return;
-
- _file->seek(_offsets[sound], SEEK_SET);
-
- int i = 1;
- while (_offsets[sound + i] == _offsets[sound])
- i++;
-
- uint32 size = _offsets[sound + i] - _offsets[sound];
-
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, Audio::makeFlacStream(_file, size));
-}
-#endif
-
-Sound::Sound(SimonEngine *vm, const GameSpecificSettings *gss, Audio::Mixer *mixer)
- : _vm(vm), _mixer(mixer) {
- _voice = 0;
- _effects = 0;
-
- _effectsPaused = false;
- _ambientPaused = false;
- _sfx5Paused = false;
-
- _filenums = 0;
- _lastVoiceFile = 0;
- _offsets = 0;
-
- _hasEffectsFile = false;
- _hasVoiceFile = false;
-
- _ambientPlaying = 0;
-
- if (_vm->getFeatures() & GF_TALKIE) {
- loadVoiceFile(gss);
-
- if (_vm->getGameType() == GType_SIMON1)
- loadSfxFile(gss);
- }
-}
-
-Sound::~Sound() {
- delete _voice;
- delete _effects;
-
- free(_filenums);
- free(_offsets);
-}
-
-void Sound::loadVoiceFile(const GameSpecificSettings *gss) {
- // Game versions which use separate voice files
- if (_vm->getGameType() == GType_FF || _vm->getGameId() == GID_SIMON1CD32)
- return;
-
- char filename[16];
- File *file = new File();
-
-#ifdef USE_FLAC
- if (!_hasVoiceFile) {
- sprintf(filename, "%s.fla", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new FlacSound(_mixer, file);
- }
- }
-#endif
-#ifdef USE_MAD
- if (!_hasVoiceFile) {
- sprintf(filename, "%s.mp3", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new MP3Sound(_mixer, file);
- }
- }
-#endif
-#ifdef USE_VORBIS
- if (!_hasVoiceFile) {
- sprintf(filename, "%s.ogg", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new VorbisSound(_mixer, file);
- }
- }
-#endif
- if (!_hasVoiceFile && _vm->getGameType() == GType_SIMON2) {
- // for simon2 mac/amiga, only read index file
- file->open("voices.idx");
- if (file->isOpen() == true) {
- int end = file->size();
- _filenums = (uint16 *)malloc((end / 6 + 1) * 2);
- _offsets = (uint32 *)malloc((end / 6 + 1) * 4);
-
- for (int i = 1; i <= end / 6; i++) {
- _filenums[i] = file->readUint16BE();
- _offsets[i] = file->readUint32BE();
- }
- _hasVoiceFile = true;
- }
- }
- if (!_hasVoiceFile) {
- sprintf(filename, "%s.wav", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new WavSound(_mixer, file);
- }
- }
- if (!_hasVoiceFile) {
- sprintf(filename, "%s.voc", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new VocSound(_mixer, file);
- }
- }
- if (!_hasVoiceFile) {
- sprintf(filename, "%s", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- if (_vm->getGameType() == GType_PP)
- _voice = new WavSound(_mixer, file);
- else
- _voice = new VocSound(_mixer, file);
- }
- }
-}
-
-void Sound::loadSfxFile(const GameSpecificSettings *gss) {
- char filename[16];
- File *file = new File();
-
-#ifdef USE_MAD
- if (!_hasEffectsFile) {
- sprintf(filename, "%s.mp3", gss->effects_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasEffectsFile = true;
- _effects = new MP3Sound(_mixer, file);
- }
- }
-#endif
-#ifdef USE_VORBIS
- if (!_hasEffectsFile) {
- sprintf(filename, "%s.ogg", gss->effects_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasEffectsFile = true;
- _effects = new VorbisSound(_mixer, file);
- }
- }
-#endif
-#ifdef USE_FLAC
- if (!_hasEffectsFile) {
- sprintf(filename, "%s.fla", gss->effects_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasEffectsFile = true;
- _effects = new FlacSound(_mixer, file);
- }
- }
-#endif
- if (!_hasEffectsFile) {
- sprintf(filename, "%s.voc", gss->effects_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasEffectsFile = true;
- _effects = new VocSound(_mixer, file);
- }
- }
- if (!_hasEffectsFile) {
- sprintf(filename, "%s", gss->effects_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasEffectsFile = true;
- _effects = new VocSound(_mixer, file);
- }
- }
-}
-
-void Sound::readSfxFile(const char *filename) {
- if (_hasEffectsFile)
- return;
-
- stopAll();
-
- File *file = new File();
- file->open(filename);
-
- if (file->isOpen() == false) {
- error("readSfxFile: Can't load sfx file %s", filename);
- }
-
- delete _effects;
- if (_vm->getGameId() == GID_SIMON1CD32) {
- _effects = new VocSound(_mixer, file, 0, SOUND_BIG_ENDIAN);
- } else
- _effects = new WavSound(_mixer, file);
-}
-
-void Sound::loadSfxTable(File *gameFile, uint32 base) {
- stopAll();
-
- if (_vm->getPlatform() == Common::kPlatformWindows)
- _effects = new WavSound(_mixer, gameFile, base);
- else
- _effects = new VocSound(_mixer, gameFile, base);
-}
-
-void Sound::readVoiceFile(const char *filename) {
- stopAll();
-
- File *file = new File();
- file->open(filename);
-
- if (file->isOpen() == false)
- error("readVoiceFile: Can't load voice file %s", filename);
-
- delete _voice;
- _voice = new RawSound(_mixer, file, 0, SOUND_BIG_ENDIAN);
-}
-
-void Sound::playVoice(uint sound) {
- if (_filenums) {
- if (_lastVoiceFile != _filenums[sound]) {
- stopAll();
-
- char filename[16];
- _lastVoiceFile = _filenums[sound];
- sprintf(filename, "voices%d.dat", _filenums[sound]);
- File *file = new File();
- file->open(filename);
- if (file->isOpen() == false)
- error("playVoice: Can't load voice file %s", filename);
-
- delete _voice;
- _voice = new WavSound(_mixer, file, _offsets);
- }
- }
-
- if (!_voice)
- return;
-
- _mixer->stopHandle(_voiceHandle);
- if (_vm->getGameType() == GType_PP) {
- _voice->playSound(sound, &_voiceHandle, Audio::Mixer::FLAG_LOOP);
- } else if (_vm->getGameType() == GType_FF || _vm->getGameId() == GID_SIMON1CD32) {
- _voice->playSound(sound, &_voiceHandle, 0);
- } else {
- _voice->playSound(sound, &_voiceHandle, Audio::Mixer::FLAG_UNSIGNED);
- }
-}
-
-void Sound::playEffects(uint sound) {
- if (!_effects)
- return;
-
- if (_effectsPaused)
- return;
-
- _effects->playSound(sound, &_effectsHandle, (_vm->getGameId() == GID_SIMON1CD32) ? 0 : Audio::Mixer::FLAG_UNSIGNED);
-}
-
-void Sound::playAmbient(uint sound) {
- if (!_effects)
- return;
-
- if (sound == _ambientPlaying)
- return;
-
- _ambientPlaying = sound;
-
- if (_ambientPaused)
- return;
-
- _mixer->stopHandle(_ambientHandle);
- _effects->playSound(sound, &_ambientHandle, Audio::Mixer::FLAG_LOOP|Audio::Mixer::FLAG_UNSIGNED);
-}
-
-bool Sound::hasVoice() const {
- return _hasVoiceFile;
-}
-
-bool Sound::isVoiceActive() const {
- return _mixer->isSoundHandleActive(_voiceHandle);
-}
-
-void Sound::stopAllSfx() {
- _mixer->stopHandle(_ambientHandle);
- _mixer->stopHandle(_effectsHandle);
- _mixer->stopHandle(_sfx5Handle);
- _ambientPlaying = 0;
-}
-
-void Sound::stopVoice() {
- _mixer->stopHandle(_voiceHandle);
-}
-
-void Sound::stopAll() {
- _mixer->stopAll();
- _ambientPlaying = 0;
-}
-
-void Sound::effectsPause(bool b) {
- _effectsPaused = b;
- _sfx5Paused = b;
-}
-
-void Sound::ambientPause(bool b) {
- _ambientPaused = b;
-
- if (_ambientPaused && _ambientPlaying) {
- _mixer->stopHandle(_ambientHandle);
- } else if (_ambientPlaying) {
- uint tmp = _ambientPlaying;
- _ambientPlaying = 0;
- playAmbient(tmp);
- }
-}
-
-// Feeble Files specific
-void Sound::playAmbientData(byte *soundData, uint sound, uint pan, uint vol) {
- if (sound == _ambientPlaying)
- return;
-
- _ambientPlaying = sound;
-
- if (_ambientPaused)
- return;
-
- _mixer->stopHandle(_ambientHandle);
- playSoundData(&_ambientHandle, soundData, sound, pan, vol, true);
-}
-
-void Sound::playSfxData(byte *soundData, uint sound, uint pan, uint vol) {
- if (_effectsPaused)
- return;
-
- playSoundData(&_effectsHandle, soundData, sound, pan, vol, false);
-}
-
-void Sound::playSfx5Data(byte *soundData, uint sound, uint pan, uint vol) {
- if (_sfx5Paused)
- return;
-
- _mixer->stopHandle(_sfx5Handle);
- playSoundData(&_sfx5Handle, soundData, sound, pan, vol, true);
-}
-
-void Sound::playVoiceData(byte *soundData, uint sound) {
- _mixer->stopHandle(_voiceHandle);
- playSoundData(&_voiceHandle, soundData, sound);
-}
-
-void Sound::playSoundData(Audio::SoundHandle *handle, byte *soundData, uint sound, int pan, int vol, bool loop) {
- byte *buffer, flags;
- uint16 compType;
- int blockAlign, rate;
-
- int size = READ_LE_UINT32(soundData + 4);
- Common::MemoryReadStream stream(soundData, size);
- if (!Audio::loadWAVFromStream(stream, size, rate, flags, &compType, &blockAlign))
- error("playSoundData: Not a valid WAV data");
-
- // The Feeble Files originally used DirectSound, which specifies volume
- // and panning differently than ScummVM does, using a logarithmic scale
- // rather than a linear one.
- //
- // Volume is a value between -10,000 and 0.
- // Panning is a value between -10,000 and 10,000.
- //
- // In both cases, the -10,000 represents -100 dB. When panning, only
- // one speaker's volume is affected - just like in ScummVM - with
- // negative values affecting the left speaker, and positive values
- // affecting the right speaker. Thus -10,000 means the left speaker is
- // silent.
-
- int v, p;
-
- vol = CLIP(vol, -10000, 0);
- pan = CLIP(pan, -10000, 10000);
-
- if (vol) {
- v = (int)((double)Audio::Mixer::kMaxChannelVolume * pow(10.0, (double)vol / 2000.0) + 0.5);
- } else {
- v = Audio::Mixer::kMaxChannelVolume;
- }
-
- if (pan < 0) {
- p = (int)(255.0 * pow(10.0, (double)pan / 2000.0) + 127.5);
- } else if (pan > 0) {
- p = (int)(255.0 * pow(10.0, (double)pan / -2000.0) - 127.5);
- } else {
- p = 0;
- }
-
- if (loop == true)
- flags |= Audio::Mixer::FLAG_LOOP;
-
- if (compType == 2) {
- Audio::AudioStream *sndStream = Audio::makeADPCMStream(&stream, size, Audio::kADPCMMS, rate, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1, blockAlign);
- buffer = (byte *)malloc(size * 4);
- size = sndStream->readBuffer((int16*)buffer, size * 2);
- size *= 2; // 16bits.
- delete sndStream;
- } else {
- buffer = (byte *)malloc(size);
- memcpy(buffer, soundData + stream.pos(), size);
- }
-
- _mixer->playRaw(handle, buffer, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE, -1, v, p);
-}
-
-void Sound::stopSfx5() {
- _mixer->stopHandle(_sfx5Handle);
-}
-
-void Sound::switchVoiceFile(const GameSpecificSettings *gss, uint disc) {
- if (_lastVoiceFile == disc)
- return;
-
- stopAll();
- delete _voice;
-
- _hasVoiceFile = false;
- _lastVoiceFile = disc;
-
- char filename[16];
- File *file = new File();
-
-#ifdef USE_FLAC
- if (!_hasVoiceFile) {
- sprintf(filename, "%s%d.fla", gss->speech_filename, disc);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new FlacSound(_mixer, file);
- }
- }
-#endif
-#ifdef USE_MAD
- if (!_hasVoiceFile) {
- sprintf(filename, "%s%d.mp3", gss->speech_filename, disc);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new MP3Sound(_mixer, file);
- }
- }
-#endif
-#ifdef USE_VORBIS
- if (!_hasVoiceFile) {
- sprintf(filename, "%s%d.ogg", gss->speech_filename, disc);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new VorbisSound(_mixer, file);
- }
- }
-#endif
- if (!_hasVoiceFile) {
- sprintf(filename, "%s%d.wav", gss->speech_filename, disc);
- file->open(filename);
- if (file->isOpen() == false) {
- error("switchVoiceFile: Can't load voice file %s", filename);
- }
- _hasVoiceFile = true;
- _voice = new WavSound(_mixer, file);
- }
-}
-
-} // End of namespace Simon