# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

ps_sound.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/ps_sound.h"
00029 #include "3d/particle_system.h"
00030 #include "nel/3d/u_ps_sound_interface.h"
00031 #include "3d/ps_attrib_maker.h"
00032 
00033 
00034 namespace NL3D 
00035 {
00036 
00037 
00038 // we batch computation of Gains and frequencies. Here is the buffer size:
00039 static const uint SoundBufSize = 1024;
00040 
00041 
00042 CPSSound::CPSSound() : _Gain(1.f),
00043                                            _GainScheme(NULL),
00044                                            _Pitch(1.f),
00045                                            _PitchScheme(NULL),
00046                                            _EmissionPercent(1),
00047                                            _SpawnSounds(false),
00048                                            _Mute(false),
00049                                            _SoundStopped(false),
00050                                            _SoundReactivated(false)
00051 {
00052         _Name = std::string("sound");
00053 }
00054 
00055 
00056 
00057 void    CPSSound::stopSound()
00058 {
00059 
00060         if (_SoundStopped) return;
00061         CPSAttrib<UPSSoundInstance *>::iterator it = _Sounds.begin()
00062                                                                                                 , endIt = _Sounds.end();
00063         while (it != endIt)
00064         {
00065                 if (*it)
00066                 {
00067                         (*it)->stop();
00068                 }
00069                 ++it;
00070         }
00071         _SoundStopped = true;
00072 }
00073 
00074 void    CPSSound::reactivateSound()
00075 {
00076         //if (!_SoundStopped) return;   
00077         _SoundReactivated  = true;
00078 }
00079 
00080 void CPSSound::removeAllSources(void)
00081 {
00082         const sint32 size = _Sounds.getSize();
00083         // delete all sounds, and rebuild them all                                              
00084         for (sint32 k = size - 1; k >= 0; --k)
00085         {
00086                 deleteElement(k);
00087         }
00088 }
00089 
00090 CPSSound::~CPSSound()
00091 {
00092         removeAllSources();
00093         delete _GainScheme;     
00094         delete _PitchScheme;    
00095 }
00096 
00097 uint32                  CPSSound::getType(void) const
00098 { 
00099         return PSSound; 
00100 }
00101 
00102 void                    CPSSound::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEt)
00103 {
00104         if (pass != PSMotion) return;
00105         const uint32 size = _Owner->getSize();  
00106         if (!size) return;
00107 
00108         
00109 
00110         
00111         if (_SoundStopped && !_SoundReactivated)
00112         {
00113                 return;
00114         }
00115         
00116         if (_SoundReactivated)
00117         {
00118                 _SoundStopped = false;
00119                 _SoundReactivated = false;
00120                 if (!_Mute)
00121                 {
00122                         sint32 k;
00123                         // delete all sounds, and rebuild them all                                              
00124                         removeAllSources();                     
00125                         for (k = 0; k < (sint32) size; ++k)
00126                         {
00127                                 newElement(NULL, 0);
00128                         }
00129                         
00130                 }
00131         }
00132 
00133         
00134                 
00135 
00136         nlassert(_Owner);       
00137         uint32 toProcess, leftToDo = size;
00138 
00139         float   Gains[SoundBufSize];
00140         float   frequencies[SoundBufSize];
00141 
00142         uint    GainPtInc    = _GainScheme ? 1 : 0;
00143         uint    frequencyPtInc = _PitchScheme ? 1 : 0;
00144         float   *currVol, *currFrequency;
00145         
00146 
00147         CPSAttrib<UPSSoundInstance *>::iterator it = _Sounds.begin()
00148                                                                                                 , endIt = _Sounds.end();
00149 
00150         CPSAttrib<NLMISC::CVector>::const_iterator posIt = _Owner->getPos().begin();
00151         CPSAttrib<NLMISC::CVector>::const_iterator speedIt = _Owner->getSpeed().begin();
00152 
00153         do
00154         {
00155                 toProcess = leftToDo > SoundBufSize ? SoundBufSize : leftToDo;
00156                 // compute Gain         
00157                 currVol = _GainScheme ? (float *) _GainScheme->make(getOwner(), size - leftToDo, Gains, sizeof(float), toProcess, true)
00158                                                                 : &_Gain;
00159                 // compute frequency
00160                 currFrequency = _PitchScheme ? (float *) _PitchScheme->make(getOwner(), size - leftToDo, frequencies, sizeof(float), toProcess, true)
00161                                                                 : &_Pitch;
00162 
00163                 endIt = it + toProcess;
00164 
00165                 if (!_Owner->isInSystemBasis())
00166                 {
00167                         do
00168                         {
00169                                 if (*it) // was this sound instanciated?
00170                                 {                                                       
00171                                         (*it)->setSoundParams(*currVol
00172                                                                                   , *posIt
00173                                                                                   , *speedIt
00174                                                                                   , *currFrequency);                                              
00175                                 }
00176                                 currVol += GainPtInc;
00177                                 currFrequency += frequencyPtInc;
00178                                 ++posIt;
00179                                 ++speedIt;
00180                                 ++it;
00181                         }
00182                         while (it != endIt);
00183                 }
00184                 else
00185                 {
00186                         const NLMISC::CMatrix m = _Owner->getOwner()->getSysMat();
00187                         do
00188                         {
00189                                 if (*it) // was this sound instanciated?
00190                                 {
00191                                         (*it)->setSoundParams(*currVol
00192                                                                                   , m * *posIt
00193                                                                                   , *speedIt
00194                                                                                   , *currFrequency);                                              
00195                                 }
00196                                 currVol += GainPtInc;
00197                                 currFrequency += frequencyPtInc;
00198                                 ++posIt;
00199                                 ++speedIt;
00200                                 ++it;
00201                         }
00202                         while (it != endIt);
00203                 }
00204 
00205                 
00206                 leftToDo -= toProcess;
00207         }
00208         while (leftToDo);
00209 
00210 }
00211 
00212 void    CPSSound::setGain(float Gain)
00213 {
00214         delete _GainScheme;
00215         _GainScheme = NULL;
00216         _Gain = Gain;   
00217 }
00218 
00219 
00220 void    CPSSound::setGainScheme(CPSAttribMaker<float> *Gain)
00221 {
00222         delete _GainScheme;
00223         _GainScheme = Gain;     
00224 }
00225 
00226 
00227 
00228 
00229 void    CPSSound::setPitch(float pitch)
00230 {
00231         delete _PitchScheme;
00232         _PitchScheme = NULL;
00233         _Pitch = pitch;
00234 }
00235 
00236 void    CPSSound::setPitchScheme(CPSAttribMaker<float> *pitch)
00237 {
00238         delete _PitchScheme;    
00239         _PitchScheme = pitch;
00240 }
00241 
00242         
00243         
00244 
00245 void                    CPSSound::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00246 {
00247         CPSLocatedBindable::serial(f);
00248         sint ver = f.serialVersion(2);
00249         f.serial(_SoundName);
00250         sint32 nbSounds;
00251         bool hasScheme;
00252         if (f.isReading())
00253         {               
00254                 f.serial(nbSounds); // we are very unlikely to save a system with sounds being played in it,
00255                                                         // but we need to keep datas coherency.
00256                 if (_Owner)
00257                 {
00258                         _Sounds.resize(_Owner->getMaxSize());
00259                 }
00260         }
00261         else
00262         {
00263                 nbSounds = _Sounds.getSize(); // number of used sound
00264                 f.serial(nbSounds);             
00265         }
00266 
00267 
00268         if (f.isReading())
00269         {
00270                 delete _GainScheme;
00271                 _GainScheme = NULL;
00272                 delete _PitchScheme;
00273                 _PitchScheme = NULL;
00274         }
00275         // save Gain infos
00276         hasScheme = _GainScheme != NULL;
00277         f.serial(hasScheme);
00278         if (hasScheme)
00279         {
00280                 f.serialPolyPtr(_GainScheme);
00281         }
00282         else
00283         {
00284                 f.serial(_Gain);
00285         }
00286         // save frequency infos
00287         hasScheme = _PitchScheme != NULL;
00288         f.serial(hasScheme);
00289         if (hasScheme)
00290         {
00291                 f.serialPolyPtr(_PitchScheme);
00292         }
00293         else
00294         {
00295                 f.serial(_Pitch);
00296         }       
00297         
00298         if (f.isReading())
00299         {
00300                 _SoundStopped = false;
00301         }
00302         
00303 
00304         if (ver > 1)
00305         {
00306                 f.serial(_EmissionPercent);
00307                 f.serial(_SpawnSounds);
00308         }       
00309 
00310         if (f.isReading())
00311         {               
00312                 for (sint k = 0; k < nbSounds; ++k)
00313                 {
00314                         newElement(NULL, 0);                    
00315                 }               
00316         }
00317 }
00318         
00319 
00320 void                    CPSSound::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
00321 {
00322         nlassert(_Owner);
00323         if (_GainScheme && _GainScheme->hasMemory()) _GainScheme->newElement(emitterLocated, emitterIndex);
00324         if (_PitchScheme && _PitchScheme->hasMemory()) _PitchScheme->newElement(emitterLocated, emitterIndex);
00325         // if there's a sound server, we generate a new sound instance
00326         if (!_Mute && !_SoundStopped && CParticleSystem::getSoundServer())
00327         {
00328                 if ((rand() % 99) * 0.01f < _EmissionPercent)
00329                 {
00330                         uint32 index = _Sounds.insert(CParticleSystem::getSoundServer()->createSound(_SoundName, _SpawnSounds));
00332                 
00333                         if (_Sounds[index])
00334                         {                       
00335                                 const NLMISC::CMatrix &mat = _Owner->isInSystemBasis() ? _Owner->getOwner()->getSysMat() : NLMISC::CMatrix::Identity;
00336                                 _Sounds[index]->setSoundParams(
00337                                         _GainScheme ? _GainScheme->get(getOwner(), 0) : 0,
00338                                         mat * _Owner->getPos()[index], 
00339                                         _Owner->getSpeed()[index], 
00340                                         _PitchScheme ? _PitchScheme->get(getOwner(), 0) : 1 );
00341                                 _Sounds[index]->play();
00342                         }
00343                 }
00344                 else
00345                 {
00346                         _Sounds.insert(NULL);
00347                 }
00348         }
00349         else
00350         {
00351                 _Sounds.insert(NULL);
00352         }
00353 }
00354 
00355 void                    CPSSound::deleteElement(uint32 index)
00356 {
00357         if (_GainScheme && _GainScheme->hasMemory()) _GainScheme->deleteElement(index);
00358         if (_PitchScheme && _PitchScheme->hasMemory()) _PitchScheme->deleteElement(index);
00359         if (_Sounds[index])
00360         {
00361                 _Sounds[index]->release();
00362         }
00363         _Sounds.remove(index);
00364 }
00365 
00366 void                    CPSSound::resize(uint32 size)
00367 {
00368         nlassert(size < (1 << 16));
00369         if (_GainScheme && _GainScheme->hasMemory()) _GainScheme->resize(size, getOwner()->getSize());
00370         if (_PitchScheme && _PitchScheme->hasMemory()) _PitchScheme->resize(size, getOwner()->getSize());
00371         _Sounds.resize(size);
00372 }
00373 
00374 } // NL3D