aboutsummaryrefslogtreecommitdiff
path: root/engines/sword2/sound.cpp
diff options
context:
space:
mode:
authorMax Horn2006-02-11 22:45:04 +0000
committerMax Horn2006-02-11 22:45:04 +0000
commit26ee630756ebdd7c96bccede0881a8c8b98e8f2b (patch)
tree26e378d5cf990a2b81c2c96e9e683a7f333b62e8 /engines/sword2/sound.cpp
parent2a9a0d4211b1ea5723f1409d91cb95de8984429e (diff)
downloadscummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.gz
scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.bz2
scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.zip
Moved engines to the new engines/ directory
svn-id: r20582
Diffstat (limited to 'engines/sword2/sound.cpp')
-rw-r--r--engines/sword2/sound.cpp319
1 files changed, 319 insertions, 0 deletions
diff --git a/engines/sword2/sound.cpp b/engines/sword2/sound.cpp
new file mode 100644
index 0000000000..d855e88afb
--- /dev/null
+++ b/engines/sword2/sound.cpp
@@ -0,0 +1,319 @@
+/* Copyright (C) 1994-1998 Revolution Software Ltd.
+ * Copyright (C) 2003-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$
+ */
+
+// ---------------------------------------------------------------------------
+// BROKEN SWORD 2
+//
+// SOUND.CPP Contains the sound engine, fx & music functions
+// Some very 'sound' code in here ;)
+//
+// (16Dec96 JEL)
+//
+// ---------------------------------------------------------------------------
+
+#include "common/stdafx.h"
+#include "common/file.h"
+#include "common/system.h"
+
+#include "sword2/sword2.h"
+#include "sword2/defs.h"
+#include "sword2/logic.h"
+#include "sword2/resman.h"
+#include "sword2/sound.h"
+
+#include "sound/wave.h"
+
+namespace Sword2 {
+
+Sound::Sound(Sword2Engine *vm) {
+ int i;
+
+ _vm = vm;
+
+ for (i = 0; i < FXQ_LENGTH; i++)
+ _fxQueue[i].resource = 0;
+
+ for (i = 0; i < MAXMUS; i++) {
+ _music[i] = NULL;
+
+ _musicFile[i].idxTab = NULL;
+ _musicFile[i].idxLen = 0;
+ _musicFile[i].fileSize = 0;
+ _musicFile[i].fileType = 0;
+ _musicFile[i].inUse = false;
+
+ _speechFile[i].idxTab = NULL;
+ _speechFile[i].idxLen = 0;
+ _speechFile[i].fileSize = 0;
+ _speechFile[i].fileType = 0;
+ _speechFile[i].inUse = false;
+ }
+
+ _speechPaused = false;
+ _musicPaused = false;
+ _fxPaused = false;
+
+ _speechMuted = false;
+ _musicMuted = false;
+ _fxMuted = false;
+
+ _reverseStereo = false;
+
+ _loopingMusicId = 0;
+
+ _mixBuffer = NULL;
+ _mixBufferLen = 0;
+
+ _vm->_mixer->setupPremix(this, Audio::Mixer::kMusicSoundType);
+}
+
+Sound::~Sound() {
+ _vm->_mixer->setupPremix(0);
+
+ clearFxQueue();
+ stopMusic(true);
+ stopSpeech();
+
+ free(_mixBuffer);
+
+ for (int i = 0; i < MAXMUS; i++) {
+ if (_musicFile[i].file.isOpen())
+ _musicFile[i].file.close();
+ if (_speechFile[i].file.isOpen())
+ _speechFile[i].file.close();
+
+ free(_musicFile[i].idxTab);
+ free(_speechFile[i].idxTab);
+ }
+}
+
+void Sound::setReverseStereo(bool reverse) {
+ if (reverse != _reverseStereo) {
+ _reverseStereo = reverse;
+
+ for (int i = 0; i < FXQ_LENGTH; i++) {
+ if (!_fxQueue[i].resource)
+ continue;
+
+ _fxQueue[i].pan = -_fxQueue[i].pan;
+ _vm->_mixer->setChannelBalance(_fxQueue[i].handle, _fxQueue[i].pan);
+ }
+ }
+}
+
+/**
+ * Stop all sounds, close their resources and clear the FX queue.
+ */
+
+void Sound::clearFxQueue() {
+ for (int i = 0; i < FXQ_LENGTH; i++) {
+ if (_fxQueue[i].resource) {
+ stopFx(i);
+ }
+ }
+}
+
+/**
+ * Process the FX queue. This function is called once every game cycle.
+ */
+
+void Sound::processFxQueue() {
+ for (int i = 0; i < FXQ_LENGTH; i++) {
+ if (!_fxQueue[i].resource)
+ continue;
+
+ switch (_fxQueue[i].type) {
+ case FX_RANDOM:
+ // 1 in 'delay' chance of this fx occurring
+ if (_vm->_rnd.getRandomNumber(_fxQueue[i].delay) == 0)
+ playFx(&_fxQueue[i]);
+ break;
+ case FX_SPOT:
+ if (_fxQueue[i].delay)
+ _fxQueue[i].delay--;
+ else {
+ playFx(&_fxQueue[i]);
+ _fxQueue[i].type = FX_SPOT2;
+ }
+ break;
+ case FX_LOOP:
+ playFx(&_fxQueue[i]);
+ _fxQueue[i].type = FX_LOOPING;
+ break;
+ case FX_SPOT2:
+ // Once the FX has finished remove it from the queue.
+ if (!_vm->_mixer->isSoundHandleActive(_fxQueue[i].handle)) {
+ _vm->_resman->closeResource(_fxQueue[i].resource);
+ _fxQueue[i].resource = 0;
+ }
+ break;
+ case FX_LOOPING:
+ // Once the looped FX has started we can ignore it,
+ // but we can't close it since the WAV data is in use.
+ break;
+ }
+ }
+}
+
+/**
+ * Queue a sound effect for playing later.
+ * @param res the sound resource number
+ * @param type the type of sound effect
+ * @param delay when to play the sound effect
+ * @param volume the sound effect volume (0 through 16)
+ * @param pan the sound effect panning (-16 through 16)
+ */
+
+void Sound::queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan) {
+ if (_vm->_wantSfxDebug) {
+ const char *typeStr;
+
+ switch (type) {
+ case FX_SPOT:
+ typeStr = "SPOT";
+ break;
+ case FX_LOOP:
+ typeStr = "LOOPED";
+ break;
+ case FX_RANDOM:
+ typeStr = "RANDOM";
+ break;
+ default:
+ typeStr = "INVALID";
+ break;
+ }
+
+ byte buf[NAME_LEN];
+
+ debug(0, "SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", _vm->_resman->fetchName(res, buf), volume, pan, delay, typeStr);
+ }
+
+ for (int i = 0; i < FXQ_LENGTH; i++) {
+ if (!_fxQueue[i].resource) {
+ byte *data = _vm->_resman->openResource(res);
+
+ assert(_vm->_resman->fetchType(data) == WAV_FILE);
+
+ uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();
+
+ if (type == FX_RANDOM) {
+ // For spot effects and loops the delay is the
+ // number of frames to wait. For random
+ // effects, however, it's the average number of
+ // seconds between playing the sound, so we
+ // have to multiply by the frame rate.
+ delay *= 12;
+ }
+
+ volume = (volume * Audio::Mixer::kMaxChannelVolume) / 16;
+ pan = (pan * 127) / 16;
+
+ if (isReverseStereo())
+ pan = -pan;
+
+ _fxQueue[i].resource = res;
+ _fxQueue[i].data = data + ResHeader::size();
+ _fxQueue[i].len = len;
+ _fxQueue[i].delay = delay;
+ _fxQueue[i].volume = volume;
+ _fxQueue[i].pan = pan;
+ _fxQueue[i].type = type;
+
+ // Keep track of the index in the loop so that
+ // fnStopFx() can be used later to kill this sound.
+ // Mainly for FX_LOOP and FX_RANDOM.
+
+ _vm->_logic->writeVar(RESULT, i);
+ return;
+ }
+ }
+
+ warning("No free slot in FX queue");
+}
+
+int32 Sound::playFx(FxQueueEntry *fx) {
+ return playFx(&fx->handle, fx->data, fx->len, fx->volume, fx->pan, (fx->type == FX_LOOP), Audio::Mixer::kSFXSoundType);
+}
+
+int32 Sound::playFx(Audio::SoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, Audio::Mixer::SoundType soundType) {
+ if (_fxMuted)
+ return RD_OK;
+
+ if (_vm->_mixer->isSoundHandleActive(*handle))
+ return RDERR_FXALREADYOPEN;
+
+ Common::MemoryReadStream stream(data, len);
+ int rate, size;
+ byte flags;
+
+ if (!loadWAVFromStream(stream, size, rate, flags)) {
+ warning("playFX: Not a valid WAV file");
+ return RDERR_INVALIDWAV;
+ }
+
+ // The resource manager must have complete control over when resources
+ // are freed, or reference counting will break horribly. Besides, the
+ // data pointer is not valid for passing to free(). Why the hell is the
+ // AUTOFREE flag set by default anyway?
+
+ flags &= ~Audio::Mixer::FLAG_AUTOFREE;
+
+ if (isReverseStereo())
+ flags |= Audio::Mixer::FLAG_REVERSE_STEREO;
+
+ if (loop)
+ flags |= Audio::Mixer::FLAG_LOOP;
+
+ _vm->_mixer->playRaw(handle, data + stream.pos(), size, rate, flags, -1, vol, pan, 0, 0, soundType);
+ return RD_OK;
+}
+
+/**
+ * This function closes a sound effect which has been previously opened for
+ * playing. Sound effects must be closed when they are finished with, otherwise
+ * you will run out of sound effect buffers.
+ * @param i the index of the sound to close
+ */
+
+int32 Sound::stopFx(int32 i) {
+ if (!_fxQueue[i].resource)
+ return RDERR_FXNOTOPEN;
+
+ _vm->_mixer->stopHandle(_fxQueue[i].handle);
+
+ _vm->_resman->closeResource(_fxQueue[i].resource);
+ _fxQueue[i].resource = 0;
+ return RD_OK;
+}
+
+void Sound::pauseAllSound() {
+ pauseMusic();
+ pauseSpeech();
+ pauseFx();
+}
+
+void Sound::unpauseAllSound() {
+ unpauseMusic();
+ unpauseSpeech();
+ unpauseFx();
+}
+
+} // End of namespace Sword2