00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
00077 _SoundReactivated = true;
00078 }
00079
00080 void CPSSound::removeAllSources(void)
00081 {
00082 const sint32 size = _Sounds.getSize();
00083
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
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
00157 currVol = _GainScheme ? (float *) _GainScheme->make(getOwner(), size - leftToDo, Gains, sizeof(float), toProcess, true)
00158 : &_Gain;
00159
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)
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)
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);
00255
00256 if (_Owner)
00257 {
00258 _Sounds.resize(_Owner->getMaxSize());
00259 }
00260 }
00261 else
00262 {
00263 nbSounds = _Sounds.getSize();
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
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
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
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 }