diff options
Diffstat (limited to 'engines/simon/sound.cpp')
| -rw-r--r-- | engines/simon/sound.cpp | 714 |
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 |
