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

myst3/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/myst3/ambient.h"
00024 #include "engines/myst3/database.h"
00025 #include "engines/myst3/myst3.h"
00026 #include "engines/myst3/sound.h"
00027 #include "engines/myst3/state.h"
00028 
00029 #include "audio/audiostream.h"
00030 #include "audio/decoders/asf.h"
00031 #include "audio/decoders/mp3.h"
00032 #include "audio/decoders/wave.h"
00033 
00034 #include "common/archive.h"
00035 #include "common/config-manager.h"
00036 
00037 namespace Myst3 {
00038 
00039 Sound::Sound(Myst3Engine *vm) :
00040         _vm(vm) {
00041     for (uint i = 0; i < kNumChannels; i++)
00042         _channels[i] = new SoundChannel(_vm);
00043 }
00044 
00045 Sound::~Sound() {
00046     for (uint i = 0; i < kNumChannels; i++)
00047         delete _channels[i];
00048 }
00049 
00050 void Sound::playEffect(uint32 id, uint32 volume, uint16 heading, uint16 attenuation) {
00051     id = _vm->_state->valueOrVarValue(id);
00052 
00053     SoundChannel *channel = getChannelForSound(id, kEffect);
00054     channel->play(id, volume, heading, attenuation, false, kEffect);
00055 }
00056 
00057 void Sound::playEffectLooping(uint32 id, uint32 volume, uint16 heading, uint16 attenuation) {
00058     id = _vm->_state->valueOrVarValue(id);
00059 
00060     bool alreadyPlaying;
00061     SoundChannel *channel = getChannelForSound(id, kEffect, &alreadyPlaying);
00062 
00063     if (!alreadyPlaying) {
00064         channel->play(id, volume, heading, attenuation, true, kEffect);
00065     }
00066 }
00067 
00068 void Sound::playEffectFadeInOut(uint32 id, uint32 volume, uint16 heading, uint16 attenuation,
00069         uint32 fadeInDuration, uint32 playDuration, uint32 fadeOutDuration) {
00070 
00071     SoundChannel *channel = getChannelForSound(id, kEffect);
00072     channel->play(id, fadeInDuration == 0 ? volume : 0, heading, attenuation, true, kEffect);
00073 
00074     uint32 effectiveVolume = channel->adjustVolume(volume);
00075     if (channel->_playing) {
00076         channel->_fadeArrayPosition = 0;
00077         channel->_fadeDurations[0] = 0;
00078         channel->_fadeDurations[1] = 0;
00079         channel->_fadeDurations[2] = playDuration;
00080         channel->_fadeDurations[3] = fadeOutDuration;
00081         channel->_fadeVolumes[0] = 0;
00082         channel->_fadeVolumes[1] = effectiveVolume;
00083         channel->_fadeVolumes[2] = effectiveVolume;
00084         channel->_fadeVolumes[3] = 0;
00085         channel->fade(effectiveVolume, heading, attenuation, fadeInDuration);
00086         channel->_hasFadeArray = true;
00087     }
00088 }
00089 
00090 void Sound::stopEffect(uint32 id, uint32 fadeDuration) {
00091     bool found;
00092     SoundChannel *channel = getChannelForSound(id, kEffect, &found);
00093 
00094     if (found) {
00095         channel->fadeOut(fadeDuration);
00096     }
00097 }
00098 
00099 void Sound::stopMusic(uint32 fadeDelay) {
00100     for (uint i = 0; i < kNumChannels; i++) {
00101         SoundChannel *channel = _channels[i];
00102         if (channel->_type == kMusic && channel->_playing)
00103             channel->fadeOut(fadeDelay);
00104     }
00105 }
00106 
00107 void Sound::resetSoundVars() {
00108     uint32 minId = _vm->_db->getSoundIdMin();
00109     uint32 maxId = _vm->_db->getSoundIdMax();
00110 
00111     if (minId == 0 || maxId == 0) {
00112         return;
00113     }
00114 
00115     for (uint32 id = minId; id <= maxId; id++) {
00116         _vm->_state->setVar(id, 0);
00117     }
00118 }
00119 
00120 void Sound::playCue(uint32 id, uint32 volume, uint16 heading, uint16 attenuation) {
00121     SoundChannel *channel = _channels[13];
00122     channel->play(id, volume, heading, attenuation, false, kCue);
00123 }
00124 
00125 void Sound::stopCue(uint32 fadeDelay) {
00126     SoundChannel *channel = _channels[13];
00127     channel->fadeOut(fadeDelay);
00128 }
00129 
00130 SoundChannel *Sound::getChannelForSound(uint32 id, SoundType type, bool *found) {
00131     // Channel number 13 is reserved for cue sounds
00132 
00133     // if the sound is already playing, return that channel
00134     for (uint i = 0; i < kNumChannels - 1; i++)
00135         if (_channels[i]->_id == id && (_channels[i]->_type == type || type == kAny ) && _channels[i]->_playing) {
00136             if (found) *found = true;
00137             return _channels[i];
00138         }
00139 
00140     // else return the channel with the oldest sound
00141     SoundChannel *oldest = _channels[0];
00142     for (uint i = 0; i < kNumChannels - 1; i++) {
00143         if (_channels[i]->_age > oldest->_age) {
00144             oldest = _channels[i];
00145         }
00146     }
00147 
00148     if (found) *found = false;
00149 
00150     return oldest;
00151 }
00152 
00153 void Sound::update() {
00154     for (uint i = 0; i < kNumChannels; i++)
00155         _channels[i]->update();
00156 
00157     _vm->runBackgroundSoundScriptsFromNode(_vm->_state->getLocationNode());
00158     _vm->_ambient->updateCue();
00159 }
00160 
00161 void Sound::age() {
00162     for (uint i = 0; i < kNumChannels; i++)
00163         _channels[i]->age(99);
00164 }
00165 
00166 void Sound::fadeOutOldSounds(uint32 fadeDelay) {
00167     for (uint i = 0; i < kNumChannels; i++) {
00168         if (_channels[i]->_playing && _channels[i]->_type == kAmbient && _channels[i]->_age == 1) {
00169             uint32 delay = _channels[i]->_ambientFadeOutDelay;
00170             if (_vm->_state->getAmbientOverrideFadeOutDelay() || delay == 0)
00171                 delay = fadeDelay;
00172             _channels[i]->fadeOut(delay);
00173 
00174         }
00175     }
00176     _vm->_state->setAmbientOverrideFadeOutDelay(false);
00177 }
00178 
00179 void Sound::compute3DVolumes(int32 heading, uint angle, int32 *left, int32 *right) {
00180     // This table contains the left and right volume values for the cardinal directions
00181     static const struct {
00182         int32 angle;
00183         int32 left;
00184         int32 right;
00185     } volumes[] = {
00186         { -180, 50,   50 },
00187         {  -90, 100,   0 },
00188         {    0, 100, 100 },
00189         {   90, 0,   100 },
00190         {  180, 50,   50 }
00191     };
00192 
00193 #if 0
00194     // This is the equivalent volume table for the xbox version, with 4.0 surround
00195     static const struct {
00196         int32 angle;
00197         int32 frontLeft;
00198         int32 frontRight;
00199         int32 backLeft;
00200         int32 backRight;
00201     } surroundVolumes[] = {
00202         { -180,   0,   0, 100, 100 },
00203         { -135,   0,   0, 100,   0 },
00204         {  -90, 100,   0, 100,   0 },
00205         {  -40, 100,   0,   0,   0 },
00206         {    0, 100, 100,   0,   0 },
00207         {   40,   0, 100,   0,   0 },
00208         {   90,   0, 100,   0, 100 },
00209         {  135,   0,   0,   0, 100 },
00210         {  180,   0,   0, 100, 100 },
00211     };
00212 #endif
00213 
00214     if (angle) {
00215         // Compute the distance to the sound source
00216         int32 headingDistance = heading - _vm->_state->getLookAtHeading();
00217 
00218         // Make sure to use the shortest direction
00219         while (ABS(headingDistance) > 180) {
00220             if (headingDistance > 0) {
00221                 headingDistance -= 360;
00222             } else {
00223                 headingDistance += 360;
00224             }
00225         }
00226 
00227         // Find the appropriate quadrant
00228         uint quadrant = 0;
00229         while (headingDistance < volumes[quadrant].angle || headingDistance > volumes[quadrant + 1].angle)
00230             quadrant++;
00231 
00232         float positionInQuadrant = (headingDistance - volumes[quadrant].angle)
00233                 / (float)(volumes[quadrant + 1].angle - volumes[quadrant].angle);
00234 
00235         // Compute the left and right volumes using linear interpolation from the cardinal directions
00236         *left = volumes[quadrant].left + (volumes[quadrant + 1].left - volumes[quadrant].left) * positionInQuadrant;
00237         *right = volumes[quadrant].right + (volumes[quadrant + 1].right - volumes[quadrant].right) * positionInQuadrant;
00238 
00239         // Add the base sound level
00240         *left += (100 - angle) * (100 - *left) / 100;
00241         *right += (100 - angle) * (100 - *right) / 100;
00242     } else {
00243         *left = 100;
00244         *right = 100;
00245     }
00246 }
00247 
00248 void Sound::computeVolumeBalance(int32 volume, int32 heading, uint attenuation, int32 *mixerVolume, int32 *balance) {
00249     int32 left, right;
00250     _vm->_sound->compute3DVolumes(heading, attenuation, &left, &right);
00251 
00252     *mixerVolume = MAX(left, right) * volume * Audio::Mixer::kMaxChannelVolume / 100 / 100;
00253 
00254     // Compute balance from the left and right volumes
00255     if (left == right) {
00256         *balance = 0;
00257     } else if (left > right) {
00258         *balance = -127 * (left - right) / left;
00259     } else {
00260         *balance = 127 * (right - left) / right;
00261     }
00262 }
00263 
00264 int32 Sound::playedFrames(uint32 id) {
00265     bool soundPlaying;
00266     SoundChannel *channel = getChannelForSound(id, kAny, &soundPlaying);
00267 
00268     if (!soundPlaying) {
00269         return -1;
00270     }
00271 
00272     return channel->playedFrames();
00273 }
00274 
00275 bool Sound::isPlaying(uint32 id) {
00276     bool soundPlaying;
00277     getChannelForSound(id, kAny, &soundPlaying);
00278     return soundPlaying;
00279 }
00280 
00281 void Sound::setupNextSound(SoundNextCommand command, int16 controlVar, int16 startSoundId, int16 soundCount,
00282         int32 soundMinDelay, int32 soundMaxDelay, int32 controlSoundId, int32 controlSoundMaxPosition) {
00283 
00284     bool playSeveralSounds = _vm->_state->getSoundNextMultipleSounds();
00285 
00286     _vm->_state->setSoundNextMultipleSounds(false);
00287     _vm->_state->setSoundNextIsChoosen(false);
00288     _vm->_state->setSoundNextId(0);
00289     _vm->_state->setSoundNextIsLast(false);
00290 
00291     uint32 controlLastTick = _vm->_state->getVar(controlVar);
00292     int32 playingSoundId = _vm->_state->getVar(controlVar + 1) >> 16;
00293     int32 soundDelay = _vm->_state->getVar(controlVar + 1) & 0xFFFF;
00294 
00295     if (!controlLastTick) {
00296         if (!playSeveralSounds) {
00297             for (int16 i = startSoundId; i < startSoundId + soundCount; i++) {
00298                 int16 soundVarValue = _vm->_state->getVar(i);
00299                 if (soundVarValue)
00300                     return;
00301             }
00302         }
00303 
00304         soundDelay = _vm->_rnd->getRandomNumberRng(soundMinDelay, soundMaxDelay);
00305 
00306         _vm->_state->setVar(controlVar, 1);
00307         _vm->_state->setVar(controlVar + 1, soundDelay | (playingSoundId << 16));
00308         return;
00309     }
00310 
00311     uint currentTick = _vm->_state->getTickCount();
00312     if (currentTick == controlLastTick) {
00313         return;
00314     }
00315 
00316     if (currentTick < controlLastTick) {
00317         soundDelay = 0;
00318     } else if (currentTick > controlLastTick + 10) {
00319         soundDelay -= 10;
00320     } else {
00321         soundDelay -= currentTick - controlLastTick;
00322     }
00323 
00324     if (soundDelay < 0) {
00325         soundDelay = 0;
00326     }
00327 
00328     if (soundDelay) {
00329         _vm->_state->setVar(controlVar, currentTick);
00330         _vm->_state->setVar(controlVar + 1, soundDelay | (playingSoundId << 16));
00331         return;
00332     }
00333 
00334     bool shouldPlaySound;
00335     if (command == kRandom || command == kNext) {
00336         shouldPlaySound = true;
00337     } else {
00338         int32 controlSoundPosition = playedFrames(controlSoundId);
00339 
00340         shouldPlaySound = controlSoundPosition >= 0 && controlSoundPosition <= controlSoundMaxPosition;
00341     }
00342 
00343     if (!shouldPlaySound) {
00344         return;
00345     }
00346 
00347     switch (command) {
00348     case kRandom:
00349     case kRandomIfOtherStarting: {
00350         if (soundCount == 1) {
00351             playingSoundId = startSoundId;
00352         } else {
00353             int32 newSoundId;
00354             do {
00355                 newSoundId = _vm->_rnd->getRandomNumberRng(startSoundId, startSoundId + soundCount - 1);
00356             } while (newSoundId == playingSoundId);
00357             playingSoundId = newSoundId;
00358         }
00359     }
00360     break;
00361     case kNext:
00362     case kNextIfOtherStarting: {
00363         if (!playingSoundId) {
00364             playingSoundId = startSoundId;
00365         } else {
00366             playingSoundId++;
00367         }
00368 
00369         if (playingSoundId == startSoundId + soundCount - 1) {
00370             _vm->_state->setSoundNextIsLast(true);
00371         }
00372 
00373         if (playingSoundId >= startSoundId + soundCount)
00374             playingSoundId = startSoundId;
00375     }
00376     break;
00377     }
00378 
00379     _vm->_state->setVar(controlVar, 0);
00380     _vm->_state->setVar(controlVar + 1, soundDelay | (playingSoundId << 16));
00381 
00382     _vm->_state->setVar(playingSoundId, 2);
00383 
00384     _vm->_state->setSoundNextIsChoosen(true);
00385     _vm->_state->setSoundNextId(playingSoundId);
00386 }
00387 
00388 SoundChannel::SoundChannel(Myst3Engine *vm) :
00389         _vm(vm),
00390         _playing(false),
00391         _fading(false),
00392         _id(0),
00393         _stream(0),
00394         _age(0),
00395         _ambientFadeOutDelay(0),
00396         _volume(0),
00397         _heading(0),
00398         _headingAngle(0),
00399         _fadeLastTick(0),
00400         _fadeDuration(0),
00401         _fadeTargetVolume(0),
00402         _fadeSourceVolume(0),
00403         _fadeTargetAttenuation(0),
00404         _fadeSourceAttenuation(0),
00405         _fadeTargetHeading(0),
00406         _fadeSourceHeading(0),
00407         _stopWhenSilent(true),
00408         _hasFadeArray(false),
00409         _fadeArrayPosition(0),
00410         _fadePosition(0),
00411         _type(kAny) {
00412 }
00413 
00414 SoundChannel::~SoundChannel() {
00415 }
00416 
00417 void SoundChannel::play(uint32 id, uint32 volume, uint16 heading, uint16 attenuation, bool loop, SoundType type) {
00418     stop();
00419 
00420     // Load the name of the sound from its id
00421     _name = _vm->_db->getSoundName(id);
00422 
00423     // Set the sound type
00424     if (_vm->_state->getVar(id) != 2) {
00425         _type = type;
00426     } else {
00427         _type = kMusic;
00428     }
00429 
00430     // Set the sound parameters
00431     _volume = adjustVolume(volume);
00432     _heading = heading;
00433     _headingAngle = attenuation;
00434 
00435     // Open the file to a stream
00436     Audio::RewindableAudioStream *plainStream = makeAudioStream(_name);
00437 
00438     if (!plainStream)
00439         return;
00440 
00441     // Get the sound's length
00442     Audio::SeekableAudioStream *seekableStream = dynamic_cast<Audio::SeekableAudioStream *>(plainStream);
00443     if (seekableStream) {
00444         _length = seekableStream->getLength();
00445     }
00446 
00447     _stream = Audio::makeLoopingAudioStream(plainStream, loop ? 0 : 1);
00448 
00449     // Play the sound
00450     g_system->getMixer()->playStream(mixerSoundType(), &_handle, _stream);
00451     setVolume3D(volume, heading, attenuation);
00452 
00453     // Update state
00454     _id = id;
00455     _age = 0;
00456     _playing = true;
00457     _stopWhenSilent = false;
00458     _vm->_state->setVar(id, 1);
00459 }
00460 
00461 Audio::Mixer::SoundType SoundChannel::mixerSoundType() {
00462     switch (_type) {
00463     case kCue:
00464     case kEffect:
00465         return Audio::Mixer::kSFXSoundType;
00466     case kAmbient:
00467     case kMusic:
00468         return  Audio::Mixer::kMusicSoundType;
00469     default:
00470         error("Impossible");
00471     }
00472 }
00473 
00474 uint32 SoundChannel::adjustVolume(uint32 volume) {
00475     if (_type == kMusic)
00476         return volume * 100 / 75;
00477     else
00478         return volume;
00479 }
00480 
00481 Audio::RewindableAudioStream *SoundChannel::makeAudioStream(const Common::String &name) const {
00482     Common::String folder = Common::String(name.c_str(), 4);
00483     Common::String filename = Common::String::format("M3Data/%s/%s", folder.c_str(), name.c_str());
00484 
00485     Common::SeekableReadStream *s = SearchMan.createReadStreamForMember(filename);
00486 
00487     bool isMP3 = false;
00488     bool isWMA = false;
00489 
00490     if (!s)
00491         s = SearchMan.createReadStreamForMember(filename + ".wav");
00492 
00493     if (!s) {
00494         s = SearchMan.createReadStreamForMember(filename + ".mp3");
00495         if (s) isMP3 = true;
00496     }
00497 
00498     if (!s) {
00499         s = SearchMan.createReadStreamForMember(filename + ".wma");
00500         if (s) isWMA = true;
00501     }
00502 
00503     if (!s)
00504         error("Unable to open sound file '%s'", filename.c_str());
00505 
00506     if (isMP3) {
00507 #ifdef USE_MAD
00508         return Audio::makeMP3Stream(s, DisposeAfterUse::YES);
00509 #else
00510         warning("Unable to play sound '%s', MP3 support is not compiled in.", filename.c_str());
00511         delete s;
00512         return NULL;
00513 #endif
00514     } else if (isWMA) {
00515         return Audio::makeASFStream(s, DisposeAfterUse::YES);
00516     } else {
00517         return Audio::makeWAVStream(s, DisposeAfterUse::YES);
00518     }
00519 }
00520 
00521 void SoundChannel::update() {
00522     if (!_playing)
00523         return; // Nothing to update
00524 
00525     if (!_fading)
00526         setVolume3D(_volume, _heading, _headingAngle);
00527     else
00528         updateFading();
00529 
00530     _playing = g_system->getMixer()->isSoundHandleActive(_handle);
00531 
00532     if (!_playing || (_stopWhenSilent && !_volume)) {
00533         stop();
00534     }
00535 
00536     if (!_playing)
00537         return;
00538 }
00539 
00540 void SoundChannel::stop() {
00541     _playing = g_system->getMixer()->isSoundHandleActive(_handle);
00542 
00543     if (_playing) {
00544         g_system->getMixer()->stopHandle(_handle);
00545         _playing = false;
00546     }
00547 
00548     if (_id != 0) {
00549         _vm->_state->setVar(_id, 0);
00550         _id = 0;
00551     }
00552 
00553     _age = 99;
00554     _fading = false;
00555     _stopWhenSilent = true;
00556     _hasFadeArray = false;
00557 
00558     _stream = 0;
00559     _length = Audio::Timestamp();
00560 }
00561 
00562 void SoundChannel::setVolume3D(uint32 volume, uint16 heading, uint16 attenuation) {
00563     int32 mixerVolume, balance;
00564     _vm->_sound->computeVolumeBalance(volume, heading, attenuation, &mixerVolume, &balance);
00565 
00566     g_system->getMixer()->setChannelVolume(_handle, mixerVolume);
00567     g_system->getMixer()->setChannelBalance(_handle, balance);
00568 }
00569 
00570 void SoundChannel::fadeOut(uint32 fadeDelay) {
00571     if (fadeDelay == 0) {
00572         stop();
00573     } else {
00574         fade(0, -1, 0, fadeDelay);
00575     }
00576 }
00577 
00578 void SoundChannel::fade(uint32 targetVolume, int32 targetHeading, int32 targetAttenuation, uint32 fadeDelay) {
00579     _fading = true;
00580     _hasFadeArray = false;
00581     _fadeDuration = fadeDelay;
00582     _fadePosition = 0;
00583     _fadeLastTick = 0;
00584 
00585     _fadeSourceVolume = _volume;
00586     _fadeTargetVolume = targetVolume;
00587     if (!targetVolume)
00588         _stopWhenSilent = true;
00589 
00590     if (targetHeading < 0) {
00591         _fadeSourceHeading = _heading;
00592         _fadeTargetHeading = _heading;
00593         _fadeSourceAttenuation = _headingAngle;
00594         _fadeTargetAttenuation = _headingAngle;
00595     } else {
00596         _fadeSourceAttenuation = _headingAngle;
00597         _fadeTargetAttenuation = targetAttenuation;
00598 
00599         _fadeSourceHeading = _heading;
00600         _fadeTargetHeading = targetHeading;
00601 
00602         _fadeSourceHeading -= 360;
00603 
00604         while (ABS(targetHeading - _fadeSourceHeading) > 180) {
00605             _fadeSourceHeading += 360;
00606         }
00607     }
00608 }
00609 
00610 void SoundChannel::age(uint32 maxAge) {
00611     _age++;
00612     _age = CLIP<uint32>(_age, 0, maxAge);
00613 }
00614 
00615 void SoundChannel::updateFading() {
00616     uint tick = _vm->_state->getTickCount();
00617     if (tick == _fadeLastTick) {
00618         return; // We already updated fading this tick
00619     }
00620 
00621     _fadeLastTick = tick;
00622     _fadePosition++;
00623 
00624     if (_fadePosition <= _fadeDuration) {
00625         // Fading in progress, compute the new channel parameters
00626         _volume = _fadeSourceVolume + _fadePosition * (_fadeTargetVolume - _fadeSourceVolume) / _fadeDuration;
00627         _heading = _fadeSourceHeading + _fadePosition * (_fadeTargetHeading - _fadeSourceHeading) / _fadeDuration;
00628         _headingAngle = _fadeSourceAttenuation + _fadePosition * (_fadeTargetAttenuation - _fadeSourceAttenuation) / _fadeDuration;
00629     } else {
00630         if (!_hasFadeArray) {
00631             // The fading is complete
00632             _fading = false;
00633         } else {
00634             // This step of the fade array is complete, find the next one
00635             do {
00636                 _fadeArrayPosition++;
00637             } while (_fadeArrayPosition < 4 && !_fadeDurations[_fadeArrayPosition]);
00638 
00639             if (_fadeArrayPosition < 4) {
00640                 // Setup the new fading step
00641                 _fadePosition = 0;
00642                 _fadeDuration = _fadeDurations[_fadeArrayPosition];
00643 
00644                 _fadeSourceVolume = _volume;
00645                 _fadeTargetVolume = _fadeVolumes[_fadeArrayPosition];
00646 
00647                 if (!_fadeTargetVolume) {
00648                     _stopWhenSilent = true;
00649                 }
00650             } else {
00651                 // No more steps
00652                 _hasFadeArray = false;
00653                 _fading = false;
00654                 _stopWhenSilent = true;
00655                 _volume = 0;
00656             }
00657         }
00658     }
00659     setVolume3D(_volume, _heading, _headingAngle);
00660 }
00661 
00662 uint32 SoundChannel::playedFrames() {
00663     uint32 length = _length.msecs();
00664     if (!length) {
00665         warning("Unable to retrieve length for sound %d", _id);
00666         return 0;
00667     }
00668 
00669     uint32 elapsed = g_system->getMixer()->getSoundElapsedTime(_handle);
00670 
00671     // Don't count completed loops in
00672     while (elapsed > length) {
00673         elapsed -= length;
00674     }
00675 
00676     return elapsed * 30 / 1000;
00677 }
00678 
00679 } // End of namespace Myst3


Generated on Sat Feb 16 2019 05:01:04 for ResidualVM by doxygen 1.7.1
curved edge   curved edge