diff options
Diffstat (limited to 'engines/tinsel/sound.cpp')
-rw-r--r-- | engines/tinsel/sound.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp new file mode 100644 index 0000000000..0a3b01089f --- /dev/null +++ b/engines/tinsel/sound.cpp @@ -0,0 +1,257 @@ +/* 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 functionality + */ + +#include "tinsel/sound.h" + +#include "tinsel/dw.h" +#include "tinsel/config.h" +#include "tinsel/music.h" +#include "tinsel/strres.h" +#include "tinsel/tinsel.h" + +#include "common/endian.h" +#include "common/file.h" +#include "common/system.h" + +#include "sound/mixer.h" +#include "sound/audiocd.h" + +namespace Tinsel { + +//--------------------------- General data ---------------------------------- + +// get set when music/sample driver is installed +static bool bInstalled = false; + +SoundManager::SoundManager(TinselEngine *vm) : + //_vm(vm), // TODO: Enable this once global _vm var is gone + _sampleIndex(0), _sampleIndexLen(0) { +} + +SoundManager::~SoundManager() { + free(_sampleIndex); +} + +/** + * Plays the specified sample through the sound driver. + * @param id Identifier of sample to be played + * @param type type of sound (voice or sfx) + * @param handle sound handle + */ +bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) { + // Floppy version has no sample file + if (_vm->getFeatures() & GF_FLOPPY) + return false; + + // no sample driver? + if (!_vm->_mixer->isReady()) + return false; + + // stop any currently playing sample + _vm->_mixer->stopHandle(_handle); + + // make sure id is in range + assert(id > 0 && id < _sampleIndexLen); + + // get file offset for this sample + uint32 dwSampleIndex = _sampleIndex[id]; + + // move to correct position in the sample file + _sampleStream.seek(dwSampleIndex); + if (_sampleStream.ioFailed() || _sampleStream.pos() != dwSampleIndex) + error("File %s is corrupt", SAMPLE_FILE); + + // read the length of the sample + uint32 sampleLen = _sampleStream.readUint32LE(); + if (_sampleStream.ioFailed()) + error("File %s is corrupt", SAMPLE_FILE); + + // allocate a buffer + void *sampleBuf = malloc(sampleLen); + assert(sampleBuf); + + // read all of the sample + if (_sampleStream.read(sampleBuf, sampleLen) != sampleLen) + error("File %s is corrupt", SAMPLE_FILE); + + // FIXME: Should set this in a different place ;) + _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volSound); + //_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic); + _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volVoice); + + + // play it + _vm->_mixer->playRaw(type, &_handle, sampleBuf, sampleLen, 22050, + Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); + + if (handle) + *handle = _handle; + + return true; +} + +/** + * Returns TRUE if there is a sample for the specified sample identifier. + * @param id Identifier of sample to be checked + */ +bool SoundManager::sampleExists(int id) { + if (_vm->_mixer->isReady()) { + // make sure id is in range + if (id > 0 && id < _sampleIndexLen) { + // check for a sample index + if (_sampleIndex[id]) + return true; + } + } + + // no sample driver or no sample + return false; +} + +/** + * Returns true if a sample is currently playing. + */ +bool SoundManager::sampleIsPlaying(void) { + return _vm->_mixer->isSoundHandleActive(_handle); +} + +/** + * Stops any currently playing sample. + */ +void SoundManager::stopAllSamples(void) { + // stop currently playing sample + _vm->_mixer->stopHandle(_handle); +} + +/** + * Opens and inits all sound sample files. + */ +void SoundManager::openSampleFiles(void) { + // Floppy and demo versions have no sample files + if (_vm->getFeatures() & GF_FLOPPY || _vm->getFeatures() & GF_DEMO) + return; + + Common::File f; + + if (_sampleIndex) + // already allocated + return; + + // open sample index file in binary mode + if (f.open(SAMPLE_INDEX)) { + // get length of index file + f.seek(0, SEEK_END); // move to end of file + _sampleIndexLen = f.pos(); // get file pointer + f.seek(0, SEEK_SET); // back to beginning + + if (_sampleIndex == NULL) { + // allocate a buffer for the indices + _sampleIndex = (uint32 *)malloc(_sampleIndexLen); + + // make sure memory allocated + if (_sampleIndex == NULL) { + // disable samples if cannot alloc buffer for indices + // TODO: Disabled sound if we can't load the sample index? + return; + } + } + + // load data + if (f.read(_sampleIndex, _sampleIndexLen) != (uint32)_sampleIndexLen) + // file must be corrupt if we get to here + error("File %s is corrupt", SAMPLE_FILE); + +#ifdef SCUMM_BIG_ENDIAN + // Convert all ids from LE to native format + for (uint i = 0; i < _sampleIndexLen / sizeof(uint32); ++i) { + _sampleIndex[i] = READ_LE_UINT32(_sampleIndex + i); + } +#endif + + // close the file + f.close(); + + // convert file size to size in DWORDs + _sampleIndexLen /= sizeof(uint32); + } else + error("Cannot find file %s", SAMPLE_INDEX); + + // open sample file in binary mode + if (!_sampleStream.open(SAMPLE_FILE)) + error("Cannot find file %s", SAMPLE_FILE); + +/* + // gen length of the largest sample + sampleBuffer.size = _sampleStream.readUint32LE(); + if (_sampleStream.ioFailed()) + error("File %s is corrupt", SAMPLE_FILE); +*/ +} + +/** + * Initialises the sound driver. + */ + +bool SoundInit(void) { + if (!bInstalled) { +// if (mDriver != NULL) { + if (true) { // TODO: Check that a MIDI music output device is available + // open MIDI files + OpenMidiFiles(); + } + + if (_vm->_mixer->isReady()) { + // open sample files + _vm->_sound->openSampleFiles(); + } + bInstalled = true; + return true; + } else { + // already installed + return false; + } +} + + +/** + * De-initialises the sound driver. + */ + +bool SoundDeinit(void) { + if (bInstalled) { + bInstalled = false; + AudioCD.stop(); + StopMidi(); + _vm->_sound->stopAllSamples(); + DeleteMidiBuffer(); + return true; + } else { + // not installed + return false; + } +} + +} // end of namespace Tinsel |