music_sound_manager.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000-2004 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "stdsound.h"
00025 
00026 #include "audio_mixer_user.h"
00027 #include "music_sound_manager.h"
00028 #include "music_sound.h"
00029 #include "music_source.h"
00030 
00031 
00032 using namespace NLMISC;
00033 using namespace std;
00034 
00035 
00036 namespace NLSOUND {
00037 
00038 
00039 // ***************************************************************************
00040 CMusicSoundManager::CMusicSoundManager()
00041 {
00042     _Enabled= true;
00043     _CurrentMusicPlaying= NULL;
00044     _PlayStartTime= INT_MIN;
00045     _TimeConstraintEnabled= true;
00046 }
00047 
00048 // ***************************************************************************
00049 void        CMusicSoundManager::addMusicSourcePlaying(CMusicSource *musicSource)
00050 {
00051     if(!musicSource)
00052         return;
00053     _Sources.insert(musicSource);
00054 }
00055 
00056 // ***************************************************************************
00057 void        CMusicSoundManager::removeMusicSourcePlaying(CMusicSource *musicSource)
00058 {
00059     _Sources.erase(musicSource);
00060     // may remove from the already played source
00061     _AlreadyPlayedSources.erase(musicSource);
00062 }
00063 
00064 // ***************************************************************************
00065 void        CMusicSoundManager::update()
00066 {
00067     // if disabled, then just quit
00068     if(!_Enabled)
00069         return;
00070 
00071     // update playing music each frame
00072     NLMISC::TTime       currentTime= CTime::getLocalTime();
00073     CAudioMixerUser     *mixer= CAudioMixerUser::instance();
00074 
00075     // **** First, see if the current music played is cut-able
00076     bool    canPlayNewMusic= true;
00077     // if the current played music has not ended his "minimum play time"
00078     if(_TimeConstraintEnabled && _CurrentMusicPlaying && currentTime<=_PlayStartTime+_CurrentMusicPlaying->getMinimumPlayTime())
00079         canPlayNewMusic= false;
00080 
00081     // if cannot play new music, continue the current one
00082     if(!canPlayNewMusic)
00083         return;
00084 
00085     // **** Search a music to replace the currently played one
00086     CMusicSound     *bestSound= _CurrentMusicPlaying;
00087     CMusicSource    *bestSource= NULL;
00088     std::set<CMusicSource*>::iterator   it= _Sources.begin();
00089     // for all possibles music sources
00090     for(;it!=_Sources.end();it++)
00091     {
00092         CMusicSource    *src= *it;
00093         CMusicSound     *snd= dynamic_cast<CMusicSound*>(src->getSound());
00094         // error, -> skip
00095         if(!snd)
00096             continue;
00097         // If the source was already played (this is not a loop sound), skip it
00098         // NB: It may be the current one but in this case it doesn't matters....
00099         if(_AlreadyPlayedSources.find(src)!=_AlreadyPlayedSources.end())
00100             continue;
00101         // verify that this sound can be played again from the last time it has been played
00102         if(_TimeConstraintEnabled && snd->LastStopTime>INT_MIN && currentTime<=snd->LastStopTime+snd->getTimeBeforeCanReplay())
00103             continue;
00104         // if no sound yet, take it
00105         if(!bestSound)
00106         {
00107             bestSource= src;
00108             bestSound= snd;
00109         }
00110         // else compare sound
00111         else
00112         {
00113             // take the higher priority (priority value is inversed: 0 is the best priority)
00114             if(snd->getPriority()<bestSound->getPriority())
00115             {
00116                 bestSound= snd;
00117                 bestSource= src;
00118             }
00119             // else, other criteria
00120             else if(snd->getPriority()==bestSound->getPriority())
00121             {
00122                 /* if the new sound is not looping and the best is, consider the new sound as an "instant sound"
00123                     which is prioritary
00124                 */
00125                 if(!snd->getLooping() && bestSound->getLooping())
00126                 {
00127                     bestSound= snd;
00128                     bestSource= src;
00129                 }
00130                 else if(snd->getLooping() == bestSound->getLooping())
00131                 {
00132                     // if the bestSound is the current sound played, prefer to not change the sound
00133                     if(bestSound!=_CurrentMusicPlaying)
00134                     {
00135                         /* NB: here, bestSound can be != from _CurrentMusicPlaying in the following cases:
00136                             - _CurrentMusicPlaying= NULL
00137                             - bestSound was assigned to a higher priority sound than _CurrentMusicPlaying
00138                                 thereFore snd should be different from _CurrentMusicPlaying, since this one is of
00139                                 lower priority...
00140                          */
00141                         // compare name to avoid full random jitter
00142                         string  snd0= CStringMapper::unmap(bestSound->getFileName());
00143                         string  snd1= CStringMapper::unmap(snd->getFileName());
00144                         if(snd1>snd0)
00145                         {
00146                             bestSound= snd;
00147                             bestSource= src;
00148                         }
00149                     }
00150                 }
00151             }
00152         }
00153     }
00154 
00155     // if some new music found (different from the currently played one)
00156     if(bestSound && bestSound!= _CurrentMusicPlaying)
00157     {
00158         // then launch the new music
00159         startMusic(bestSound, bestSource);
00160     }
00161     // else, no new music found => if the music is currently playing
00162     else if(_CurrentMusicPlaying)
00163     {
00164         // if the music has ended (and not loop), stop
00165         if(_CurrentMusicPlaying->getLooping()==false && mixer->isMusicEnded())
00166         {
00167             // without fade (no need since ended)
00168             stopMusic(false);
00169         }
00170         else
00171         {
00172             // verify that a source with this sound still exist. If not, we have to cut this sound too
00173             bool    found= false;
00174             std::set<CMusicSource*>::iterator   it= _Sources.begin();
00175             for(;it!=_Sources.end();it++)
00176             {
00177                 CMusicSource    *src= *it;
00178                 CMusicSound     *snd= dynamic_cast<CMusicSound*>(src->getSound());
00179                 if(snd && snd==_CurrentMusicPlaying)
00180                 {
00181                     found= true;
00182                     break;
00183                 }
00184             }
00185             // if not found, cut the music
00186             if(!found)
00187             {
00188                 // with fade
00189                 stopMusic(true);
00190             }
00191         }
00192     }
00193 }
00194 
00195 // ***************************************************************************
00196 void        CMusicSoundManager::enable(bool enable)
00197 {
00198     // if disabled, stop any music (without any fade)
00199     if(!enable)
00200         stopMusic(false);
00201 
00202     _Enabled= enable;
00203 }
00204 
00205 // ***************************************************************************
00206 void    CMusicSoundManager::startMusic(CMusicSound *newMs, CMusicSource *newSrc)
00207 {
00208     nlassert(newMs && newSrc);
00209     // fade with the current. Take the min of new FadeIn and old FadeOut
00210     sint32  xFade= newMs->getFadeInLength();
00211     if(_CurrentMusicPlaying)
00212         xFade= min(xFade, _CurrentMusicPlaying->getFadeOutLength());
00213 
00214     // start play the new music, xFade with the old
00215     CAudioMixerUser::instance()->playMusic(CStringMapper::unmap(newMs->getFileName()), uint(xFade), true, newMs->getLooping());
00216 
00217     // Mark the old one as stoped
00218     if(_CurrentMusicPlaying)
00219     {
00220         _CurrentMusicPlaying->LastStopTime= CTime::getLocalTime();
00221     }
00222 
00223     // update markers
00224     _CurrentMusicPlaying= newMs;
00225     _PlayStartTime= CTime::getLocalTime();
00226 
00227     // The source is played this time. Avoid replay it for infinite time if the player stay in the zone
00228     if(!newMs->getLooping())
00229         _AlreadyPlayedSources.insert(newSrc);
00230 }
00231 
00232 // ***************************************************************************
00233 void    CMusicSoundManager::stopMusic(bool allowFade)
00234 {
00235     if(_CurrentMusicPlaying)
00236     {
00237         // stop with or without fadeout
00238         if(allowFade)
00239             CAudioMixerUser::instance()->stopMusic(_CurrentMusicPlaying->getFadeOutLength());
00240         else
00241             CAudioMixerUser::instance()->stopMusic(0);
00242         // Mark the last stop time
00243         _CurrentMusicPlaying->LastStopTime= CTime::getLocalTime();
00244         // no more music playing
00245         _CurrentMusicPlaying= NULL;
00246     }
00247 }
00248 
00249 
00250 } // NLSOUND

Generated on Thu Jan 7 08:26:38 2010 for NeL by  doxygen 1.6.1