ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

stark/resources/sound.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/resources/sound.h"
00024 
00025 #include "audio/decoders/vorbis.h"
00026 
00027 #include "common/system.h"
00028 
00029 #include "engines/stark/formats/iss.h"
00030 #include "engines/stark/formats/xrc.h"
00031 #include "engines/stark/services/archiveloader.h"
00032 #include "engines/stark/services/global.h"
00033 #include "engines/stark/services/services.h"
00034 #include "engines/stark/services/stateprovider.h"
00035 
00036 namespace Stark {
00037 namespace Resources {
00038 
00039 Sound::~Sound() {
00040 }
00041 
00042 Sound::Sound(Object *parent, byte subType, uint16 index, const Common::String &name) :
00043         Object(parent, subType, index, name),
00044         _enabled(0),
00045         _looping(false),
00046         _field_64(0),
00047         _loopIndefinitely(false),
00048         _loadFromFile(true),
00049         _maxDuration(0),
00050         _stockSoundType(0),
00051         _field_6C(0),
00052         _soundType(0),
00053         _pan(0),
00054         _volume(0),
00055         _fadeDurationRemaining(0),
00056         _fadeTargetVolume(0.0),
00057         _fadeTargetPan(0.0),
00058         _shouldStopOnDestroy(true) {
00059     _type = TYPE;
00060 }
00061 
00062 Audio::RewindableAudioStream *Sound::makeAudioStream() {
00063     Common::SeekableReadStream *stream = nullptr;
00064     Audio::RewindableAudioStream *audioStream = nullptr;
00065 
00066     // First try the .iss / isn files
00067     if (_loadFromFile) {
00068         stream = StarkArchiveLoader->getExternalFile(_filename, _archiveName);
00069     } else {
00070         stream = StarkArchiveLoader->getFile(_filename, _archiveName);
00071     }
00072 
00073     if (stream) {
00074         audioStream = Formats::makeISSStream(stream, DisposeAfterUse::YES);
00075     }
00076 
00077     if (!audioStream) {
00078         // The 2 CD version uses Ogg Vorbis
00079         Common::String filename = _filename;
00080         if (_filename.hasSuffix(".iss") || _filename.hasSuffix(".isn")) {
00081             filename = Common::String(_filename.c_str(), _filename.size() - 4) + ".ovs";
00082         }
00083 
00084         stream = StarkArchiveLoader->getExternalFile(filename, _archiveName);
00085         if (stream) {
00086 #ifdef USE_VORBIS
00087             audioStream = Audio::makeVorbisStream(stream, DisposeAfterUse::YES);
00088 #else
00089             warning("Cannot decode sound '%s', Vorbis support is not compiled in", filename.c_str());
00090             delete stream;
00091 #endif
00092         }
00093     }
00094 
00095     if (!audioStream) {
00096         warning("Unable to load sound '%s'", _filename.c_str());
00097     }
00098 
00099     return audioStream;
00100 }
00101 
00102 Audio::Mixer::SoundType Sound::getMixerSoundType() {
00103     switch (_soundType) {
00104     case kSoundTypeVoice:
00105         return Audio::Mixer::kSpeechSoundType;
00106     case kSoundTypeEffect:
00107         return Audio::Mixer::kSFXSoundType;
00108     case kSoundTypeMusic:
00109         return Audio::Mixer::kMusicSoundType;
00110     default:
00111         error("Unknown sound type '%d'", _soundType);
00112     }
00113 }
00114 
00115 void Sound::play() {
00116     Audio::RewindableAudioStream *rewindableStream = makeAudioStream();
00117 
00118     if (!rewindableStream) {
00119         return;
00120     }
00121 
00122     Audio::AudioStream *playStream;
00123     if (_looping) {
00124         playStream = Audio::makeLoopingAudioStream(rewindableStream, 0);
00125     } else {
00126         playStream = rewindableStream;
00127     }
00128 
00129     g_system->getMixer()->playStream(getMixerSoundType(), &_handle, playStream, -1,
00130                                      _volume * Audio::Mixer::kMaxChannelVolume, _pan * 127);
00131 }
00132 
00133 bool Sound::isPlaying() {
00134     return g_system->getMixer()->isSoundHandleActive(_handle);
00135 }
00136 
00137 void Sound::stop() {
00138     g_system->getMixer()->stopHandle(_handle);
00139     _handle = Audio::SoundHandle();
00140 }
00141 
00142 void Sound::onPreDestroy() {
00143     Object::onPreDestroy();
00144 
00145     if (_shouldStopOnDestroy) {
00146         stop();
00147     }
00148 }
00149 
00150 void Sound::readData(Formats::XRCReadStream *stream) {
00151     _filename = stream->readString();
00152     _enabled = stream->readUint32LE();
00153     _looping = stream->readBool();
00154     _field_64 = stream->readUint32LE();
00155     _loopIndefinitely = stream->readBool();
00156     _maxDuration = stream->readUint32LE();
00157     _loadFromFile = stream->readBool(); // Used only in the 4CD version
00158     _stockSoundType = stream->readUint32LE();
00159     _soundName = stream->readString();
00160     _field_6C = stream->readUint32LE();
00161     _soundType = stream->readUint32LE();
00162     _pan = stream->readFloatLE();
00163     _volume = stream->readFloatLE();
00164     _archiveName = stream->getArchiveName();
00165 }
00166 
00167 void Sound::printData() {
00168     debug("filename: %s", _filename.c_str());
00169     debug("enabled: %d", _enabled);
00170     debug("looping: %d", _looping);
00171     debug("field_64: %d", _field_64);
00172     debug("loopIndefinitely: %d", _loopIndefinitely);
00173     debug("maxDuration: %d", _maxDuration);
00174     debug("loadFromFile: %d", _loadFromFile);
00175     debug("stockSoundType: %d", _stockSoundType);
00176     debug("soundName: %s", _soundName.c_str());
00177     debug("field_6C: %d", _field_6C);
00178     debug("soundType: %d", _soundType);
00179     debug("pan: %f", _pan);
00180     debug("volume: %f", _volume);
00181 }
00182 
00183 void Sound::onGameLoop() {
00184     Object::onGameLoop();
00185 
00186     if (_looping && !_loopIndefinitely) {
00187         // Automatically stop after the maximum run time has been reached
00188         uint32 elapsedTime = g_system->getMixer()->getSoundElapsedTime(_handle);
00189         if (elapsedTime > _maxDuration) {
00190             stop();
00191         }
00192     }
00193 
00194     if (_fadeDurationRemaining > 0 && isPlaying()) {
00195         _volume += (_fadeTargetVolume - _volume) * StarkGlobal->getMillisecondsPerGameloop() / (float) _fadeDurationRemaining;
00196         _pan += (_fadeTargetPan - _pan) * StarkGlobal->getMillisecondsPerGameloop() / (float) _fadeDurationRemaining;
00197 
00198         _fadeDurationRemaining -= StarkGlobal->getMillisecondsPerGameloop();
00199 
00200         if (_fadeDurationRemaining <= 0) {
00201             _fadeDurationRemaining = 0;
00202 
00203             _volume = _fadeTargetVolume;
00204             _pan = _fadeTargetPan;
00205         }
00206 
00207         g_system->getMixer()->setChannelVolume(_handle, _volume * Audio::Mixer::kMaxChannelVolume);
00208         g_system->getMixer()->setChannelBalance(_handle, _pan * 127);
00209     }
00210 }
00211 
00212 uint32 Sound::getStockSoundType() const {
00213     return _stockSoundType;
00214 }
00215 
00216 void Sound::changeVolumePan(int32 volume, int32 pan, int32 duration) {
00217     if (isPlaying()) {
00218         _fadeDurationRemaining = duration;
00219 
00220         if (_fadeDurationRemaining > 0) {
00221             _fadeTargetVolume = volume / 100.0f;
00222             _fadeTargetPan = pan / 100.0f;
00223         } else {
00224             _volume = volume / 100.0f;
00225             _pan = pan / 100.0f;
00226 
00227             g_system->getMixer()->setChannelVolume(_handle, _volume * Audio::Mixer::kMaxChannelVolume);
00228             g_system->getMixer()->setChannelBalance(_handle, _pan * 127);
00229         }
00230     } else {
00231         if (_fadeDurationRemaining == 0) {
00232             _volume = volume / 100.0f;
00233             _pan = pan / 100.0f;
00234         }
00235     }
00236 }
00237 
00238 void Sound::saveLoadCurrent(ResourceSerializer *serializer) {
00239     bool playing = isPlaying();
00240     serializer->syncAsUint32LE(playing);
00241 
00242     if (_subType != kSoundSub3 && playing) {
00243         uint32 elapsed = g_system->getMixer()->getSoundElapsedTime(_handle);
00244         serializer->syncAsUint32LE(elapsed);
00245         serializer->syncAsFloat(_volume);
00246         serializer->syncAsFloat(_pan);
00247         serializer->syncAsUint32LE(_fadeDurationRemaining);
00248         serializer->syncAsFloat(_fadeTargetVolume);
00249         serializer->syncAsFloat(_fadeTargetPan);
00250 
00251         if (serializer->isLoading()) {
00252             play();
00253             // TODO: Seek to the "elapsed" position
00254         }
00255     }
00256 }
00257 
00258 void Sound::onEnginePause(bool pause) {
00259     g_system->getMixer()->pauseHandle(_handle, pause);
00260 }
00261 
00262 void Sound::setStopOnDestroy(bool stopOnDestroy) {
00263     _shouldStopOnDestroy = stopOnDestroy;
00264 }
00265 
00266 } // End of namespace Resources
00267 } // End of namespace Stark


Generated on Sat Mar 16 2019 05:01:54 for ResidualVM by doxygen 1.7.1
curved edge   curved edge