2015-01-14 17:54:15 +01:00
|
|
|
/* ResidualVM - A 3D game interpreter
|
|
|
|
*
|
|
|
|
* ResidualVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the AUTHORS
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "engines/stark/resources/sound.h"
|
|
|
|
|
2015-01-14 20:43:09 +01:00
|
|
|
#include "audio/decoders/vorbis.h"
|
|
|
|
|
|
|
|
#include "common/system.h"
|
|
|
|
|
|
|
|
#include "engines/stark/formats/iss.h"
|
2015-01-14 18:10:09 +01:00
|
|
|
#include "engines/stark/formats/xrc.h"
|
2015-01-14 20:43:09 +01:00
|
|
|
#include "engines/stark/services/archiveloader.h"
|
|
|
|
#include "engines/stark/services/services.h"
|
2015-01-14 17:54:15 +01:00
|
|
|
|
|
|
|
namespace Stark {
|
2015-02-13 11:10:44 +01:00
|
|
|
namespace Resources {
|
2015-01-14 17:54:15 +01:00
|
|
|
|
|
|
|
Sound::~Sound() {
|
|
|
|
}
|
|
|
|
|
2015-02-13 11:16:34 +01:00
|
|
|
Sound::Sound(Object *parent, byte subType, uint16 index, const Common::String &name) :
|
|
|
|
Object(parent, subType, index, name),
|
2015-01-14 17:54:15 +01:00
|
|
|
_enabled(0),
|
|
|
|
_looping(0),
|
|
|
|
_field_64(0),
|
2015-09-24 20:21:00 +02:00
|
|
|
_loopIndefinitely(0),
|
2015-01-14 17:54:15 +01:00
|
|
|
_maxDuration(0),
|
|
|
|
_stockSoundType(0),
|
|
|
|
_field_6C(0),
|
|
|
|
_soundType(0),
|
|
|
|
_pan(0),
|
|
|
|
_volume(0) {
|
|
|
|
_type = TYPE;
|
|
|
|
}
|
|
|
|
|
2015-01-14 20:43:09 +01:00
|
|
|
Audio::RewindableAudioStream *Sound::makeAudioStream() {
|
|
|
|
Audio::RewindableAudioStream *audioStream = nullptr;
|
|
|
|
|
|
|
|
// First try the .iss / isn files
|
2015-07-16 20:04:00 +02:00
|
|
|
Common::SeekableReadStream *stream = StarkArchiveLoader->getExternalFile(_filename, _archiveName);
|
2015-01-14 20:43:09 +01:00
|
|
|
if (stream) {
|
2015-02-13 12:52:32 +01:00
|
|
|
audioStream = Formats::makeISSStream(stream, DisposeAfterUse::YES);
|
2015-01-14 20:43:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!audioStream) {
|
|
|
|
// The 2 CD version uses Ogg Vorbis
|
|
|
|
Common::String filename = _filename;
|
|
|
|
if (_filename.hasSuffix(".iss") || _filename.hasSuffix(".isn")) {
|
|
|
|
filename = Common::String(_filename.c_str(), _filename.size() - 4) + ".ovs";
|
|
|
|
}
|
|
|
|
|
2015-07-16 20:04:00 +02:00
|
|
|
stream = StarkArchiveLoader->getExternalFile(filename, _archiveName);
|
2015-01-14 20:43:09 +01:00
|
|
|
if (stream) {
|
2015-12-19 09:05:39 +01:00
|
|
|
#ifdef USE_VORBIS
|
2015-01-14 20:43:09 +01:00
|
|
|
audioStream = Audio::makeVorbisStream(stream, DisposeAfterUse::YES);
|
2015-12-19 09:05:39 +01:00
|
|
|
#else
|
|
|
|
warning("Cannot decode sound '%s', Vorbis support is not compiled in", filename.c_str());
|
|
|
|
delete stream;
|
|
|
|
#endif
|
2015-01-14 20:43:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!audioStream) {
|
2015-01-16 09:35:47 +01:00
|
|
|
warning("Unable to load sound '%s'", _filename.c_str());
|
2015-01-14 20:43:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return audioStream;
|
|
|
|
}
|
|
|
|
|
|
|
|
Audio::Mixer::SoundType Sound::getMixerSoundType() {
|
|
|
|
switch (_soundType) {
|
|
|
|
case kSoundTypeVoice:
|
|
|
|
return Audio::Mixer::kSpeechSoundType;
|
|
|
|
case kSoundTypeEffect:
|
|
|
|
return Audio::Mixer::kSFXSoundType;
|
|
|
|
case kSoundTypeMusic:
|
|
|
|
return Audio::Mixer::kMusicSoundType;
|
|
|
|
default:
|
|
|
|
error("Unknown sound type '%d'", _soundType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sound::play() {
|
2015-01-17 10:01:05 +01:00
|
|
|
Audio::RewindableAudioStream *rewindableStream = makeAudioStream();
|
2015-01-14 20:43:09 +01:00
|
|
|
|
2015-01-17 10:01:05 +01:00
|
|
|
if (!rewindableStream) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Audio::AudioStream *playStream;
|
2015-01-14 20:43:09 +01:00
|
|
|
if (_looping) {
|
2015-01-17 10:01:05 +01:00
|
|
|
playStream = Audio::makeLoopingAudioStream(rewindableStream, 0);
|
2015-01-14 20:43:09 +01:00
|
|
|
} else {
|
2015-01-17 10:01:05 +01:00
|
|
|
playStream = rewindableStream;
|
2015-01-14 20:43:09 +01:00
|
|
|
}
|
|
|
|
|
2015-01-17 10:01:05 +01:00
|
|
|
g_system->getMixer()->playStream(getMixerSoundType(), &_handle, playStream, -1, _volume * Audio::Mixer::kMaxChannelVolume);
|
2015-01-14 20:43:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Sound::isPlaying() {
|
|
|
|
return g_system->getMixer()->isSoundHandleActive(_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sound::stop() {
|
|
|
|
g_system->getMixer()->stopHandle(_handle);
|
|
|
|
_handle = Audio::SoundHandle();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sound::onPreDestroy() {
|
2015-02-13 11:16:34 +01:00
|
|
|
Object::onPreDestroy();
|
2015-01-14 20:43:09 +01:00
|
|
|
stop();
|
|
|
|
}
|
|
|
|
|
2015-02-13 12:52:32 +01:00
|
|
|
void Sound::readData(Formats::XRCReadStream *stream) {
|
2015-01-14 17:54:15 +01:00
|
|
|
_filename = stream->readString();
|
|
|
|
_enabled = stream->readUint32LE();
|
2015-09-24 20:21:00 +02:00
|
|
|
_looping = stream->readBool();
|
2015-01-14 17:54:15 +01:00
|
|
|
_field_64 = stream->readUint32LE();
|
2015-09-24 20:21:00 +02:00
|
|
|
_loopIndefinitely = stream->readBool();
|
2015-01-14 17:54:15 +01:00
|
|
|
_maxDuration = stream->readUint32LE();
|
|
|
|
stream->readUint32LE(); // Skipped ?
|
|
|
|
_stockSoundType = stream->readUint32LE();
|
|
|
|
_soundName = stream->readString();
|
|
|
|
_field_6C = stream->readUint32LE();
|
|
|
|
_soundType = stream->readUint32LE();
|
|
|
|
_pan = stream->readUint32LE();
|
|
|
|
_volume = stream->readFloat();
|
|
|
|
_archiveName = stream->getArchiveName();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sound::printData() {
|
|
|
|
debug("filename: %s", _filename.c_str());
|
|
|
|
debug("enabled: %d", _enabled);
|
|
|
|
debug("looping: %d", _looping);
|
|
|
|
debug("field_64: %d", _field_64);
|
2015-09-24 20:21:00 +02:00
|
|
|
debug("loopIndefinitely: %d", _loopIndefinitely);
|
2015-01-14 17:54:15 +01:00
|
|
|
debug("maxDuration: %d", _maxDuration);
|
|
|
|
debug("stockSoundType: %d", _stockSoundType);
|
|
|
|
debug("soundName: %s", _soundName.c_str());
|
|
|
|
debug("field_6C: %d", _field_6C);
|
|
|
|
debug("soundType: %d", _soundType);
|
|
|
|
debug("pan: %d", _pan);
|
|
|
|
debug("volume: %f", _volume);
|
|
|
|
}
|
|
|
|
|
2015-09-24 20:21:00 +02:00
|
|
|
void Sound::onGameLoop() {
|
|
|
|
Object::onGameLoop();
|
|
|
|
|
|
|
|
if (_looping && !_loopIndefinitely) {
|
|
|
|
// Automatically stop after the maximum run time has been reached
|
|
|
|
uint32 elapsedTime = g_system->getMixer()->getSoundElapsedTime(_handle);
|
|
|
|
if (elapsedTime > _maxDuration) {
|
|
|
|
stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-02-13 11:10:44 +01:00
|
|
|
} // End of namespace Resources
|
2015-01-14 17:54:15 +01:00
|
|
|
} // End of namespace Stark
|