00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdsound.h"
00027
00028 #include "complex_source.h"
00029 #include "complex_sound.h"
00030
00031 using namespace std;
00032 using namespace NLMISC;
00033
00034 namespace NLSOUND
00035 {
00036
00037 CComplexSource::CComplexSource (CComplexSound *soundPattern, bool spawn, TSpawnEndCallback cb, void *cbUserParam)
00038 : CSourceCommon(soundPattern, spawn, cb, cbUserParam),
00039 _Source1(NULL),
00040 _Source2(NULL)
00041 {
00042 nlassert(soundPattern->getSoundType() == CSound::SOUND_COMPLEX);
00043 _PatternSound = static_cast<CComplexSound*>(soundPattern);
00044
00045
00046 _Gain = soundPattern->getGain();
00047 _Pitch = soundPattern->getPitch();
00048 _Looping = soundPattern->getLooping();
00049 _Priority = soundPattern->getPriority();
00050 _TickPerSecond = soundPattern->getTicksPerSecond();
00051 }
00052
00053 CComplexSource::~CComplexSource()
00054 {
00055 CAudioMixerUser *mixer = CAudioMixerUser::instance();
00056
00057 CAudioMixerUser::instance()->unregisterUpdate(this);
00058 CAudioMixerUser::instance()->removeEvents(this);
00059
00060 std::vector<USource *>::iterator first(_AllSources.begin()), last(_AllSources.end());
00061 for (; first != last; ++first)
00062 {
00063
00064 delete *first;
00065 }
00066 }
00067
00068
00069 void CComplexSource::setSound( TSoundId id, CSoundContext *context)
00070 {
00071 }
00072
00073 TSoundId CComplexSource::getSound()
00074 {
00075 return _PatternSound;
00076 }
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 bool CComplexSource::isPlaying()
00092 {
00093 return _Playing;
00094 }
00095
00096 void CComplexSource::play()
00097 {
00098 CAudioMixerUser *mixer = CAudioMixerUser::instance();
00099 NLMISC::TTime now = NLMISC::CTime::getLocalTime();
00100
00101 switch (_PatternSound->getPatternMode())
00102 {
00103 case CComplexSound::MODE_CHAINED:
00104 {
00105 _SoundSeqIndex = 0;
00106 const vector<uint32> &soundSeq = _PatternSound->getSoundSeq();
00107 if (!soundSeq.empty())
00108 {
00109 CSound *sound = mixer->getSoundId(_PatternSound->getSound(soundSeq[_SoundSeqIndex++]));
00110
00111 if (sound == 0)
00112 return;
00113
00114 if (_PatternSound->doFadeIn())
00115 _FadeLength = min(uint32(_PatternSound->getFadeLenght()/_TickPerSecond), sound->getDuration() /2);
00116 else
00117 _FadeLength = 0;
00118
00119 _Source2 = mixer->createSource(sound, false);
00120 if (_Source2 == NULL)
00121 return;
00122 _Source2->setRelativeGain(0);
00123 _Source2->setPos(_Position);
00124 _Source2->play();
00125 _StartTime2 = now;
00126
00127
00128 mixer->registerUpdate(this);
00129 }
00130 }
00131 break;
00132 case CComplexSound::MODE_SPARSE:
00133 {
00134
00135 _SoundSeqIndex = 0;
00136 _DelaySeqIndex = 0;
00137 const vector<uint32> &soundSeq = _PatternSound->getSoundSeq();
00138 if (!soundSeq.empty())
00139 {
00140 CSound *sound = mixer->getSoundId(_PatternSound->getSound(soundSeq[_SoundSeqIndex++]));
00141
00142 _Source1 = mixer->createSource(sound, false);
00143 if (_Source1 == NULL)
00144 return;
00145 _Source1->setRelativeGain(_Gain);
00146 _Source1->setPos(_Position);
00147 _Source1->play();
00148 _StartTime1 = now;
00149
00150
00151 const std::vector<uint32> &delaySeq = _PatternSound->getDelaySeq();
00152 if (!delaySeq.empty() && _DelaySeqIndex < delaySeq.size())
00153 {
00154 _LastSparseEvent = false;
00155
00156 mixer->addEvent(this, uint64(now + sound->getDuration() + delaySeq[_DelaySeqIndex++]/_TickPerSecond));
00157 }
00158 else
00159 {
00160 _LastSparseEvent = true;
00161
00162 mixer->addEvent(this, now + sound->getDuration());
00163 }
00164 }
00165 }
00166 break;
00167 case CComplexSound::MODE_ALL_IN_ONE:
00168 {
00169
00170 const std::vector<std::string> &sounds = _PatternSound->getSounds();
00171
00172 std::vector<std::string>::const_iterator first(sounds.begin()), last(sounds.end());
00173
00174 if (_AllSources.empty())
00175 {
00176
00177 for (; first != last; ++first)
00178 {
00179 CSound *sound = mixer->getSoundId(*first);
00180 if (sound != NULL)
00181 {
00182 USource *source = mixer->createSource(sound, false);
00183 source->setRelativeGain(_Gain);
00184 source->setPos(_Position);
00185 source->play();
00186
00187 _AllSources.push_back(source);
00188 }
00189 }
00190 }
00191 else
00192 {
00193
00194 std::vector<USource *>::iterator first(_AllSources.begin()), last(_AllSources.end());
00195
00196 for (; first != last; ++first)
00197 {
00198 (*first)->setRelativeGain(_Gain);
00199 (*first)->setPos(_Position);
00200 (*first)->play();
00201 }
00202 }
00203
00204 mixer->addEvent(this, NLMISC::CTime::getLocalTime() + _PatternSound->getDuration());
00205 }
00206 break;
00207 default:
00208 nldebug("Unknow pattern mode. Can't play.");
00209 }
00210
00211 CSourceCommon::play();
00212 }
00213 void CComplexSource::stop()
00214 {
00215 CAudioMixerUser *mixer = CAudioMixerUser::instance();
00216 if (_Source1)
00217 {
00218
00219
00220 delete _Source1;
00221
00222 _Source1 = NULL;
00223 }
00224 if (_Source2)
00225 {
00226
00227
00228 delete _Source2;
00229
00230 _Source2 = NULL;
00231 }
00232
00233 std::vector<USource *>::iterator first(_AllSources.begin()), last(_AllSources.end());
00234 for (; first != last; ++first)
00235 {
00236 if ((*first)->isPlaying())
00237 (*first)->stop();
00238 }
00239
00240 switch (_PatternSound->getPatternMode())
00241 {
00242 case CComplexSound::MODE_CHAINED:
00243 mixer->unregisterUpdate(this);
00244 mixer->removeEvents(this);
00245 break;
00246 case CComplexSound::MODE_SPARSE:
00247 case CComplexSound::MODE_ALL_IN_ONE:
00248 mixer->removeEvents(this);
00249 break;
00250 }
00251
00252 CSourceCommon::stop();
00253 }
00254
00255
00256
00257
00258
00259 void CComplexSource::setPos( const NLMISC::CVector& pos )
00260 {
00261 CSourceCommon::setPos(pos);
00262
00263 if (_Source1 != NULL)
00264 _Source1->setPos(pos);
00265 if (_Source2 != NULL)
00266 _Source2->setPos(pos);
00267
00268 std::vector<USource *>::iterator first(_AllSources.begin()), last(_AllSources.end());
00269 for (; first != last; ++first)
00270 {
00271 (*first)->setPos(pos);
00272 }
00273 }
00274
00275 void CComplexSource::setVelocity( const NLMISC::CVector& vel )
00276 {
00277 CSourceCommon::setVelocity(vel);
00278
00279 if (_Source1 != NULL)
00280 _Source1->setVelocity(vel);
00281 if (_Source2 != NULL)
00282 _Source2->setVelocity(vel);
00283
00284 std::vector<USource *>::iterator first(_AllSources.begin()), last(_AllSources.end());
00285 for (; first != last; ++first)
00286 {
00287 (*first)->setVelocity(vel);
00288 }
00289 }
00290
00291
00292
00293
00294 void CComplexSource::setDirection( const NLMISC::CVector& dir )
00295 {
00296 CSourceCommon::setDirection(dir);
00297
00298 if (_Source1 != NULL)
00299 _Source1->setDirection(dir);
00300 if (_Source2 != NULL)
00301 _Source2->setDirection(dir);
00302
00303 std::vector<USource *>::iterator first(_AllSources.begin()), last(_AllSources.end());
00304 for (; first != last; ++first)
00305 {
00306 (*first)->setDirection(dir);
00307 }
00308 }
00309
00310
00311
00312
00313
00314 void CComplexSource::setGain( float gain )
00315 {
00316 CSourceCommon::setGain(gain);
00317
00318 if (_Source1 != NULL)
00319 _Source1->setGain(gain);
00320 if (_Source2 != NULL)
00321 _Source2->setGain(gain);
00322
00323 std::vector<USource *>::iterator first(_AllSources.begin()), last(_AllSources.end());
00324 for (; first != last; ++first)
00325 {
00326 (*first)->setGain(_Gain);
00327 }
00328 }
00329
00330 void CComplexSource::setRelativeGain( float gain )
00331 {
00332 CSourceCommon::setRelativeGain(gain);
00333
00334 if (_Source1 != NULL)
00335 _Source1->setRelativeGain(gain);
00336 if (_Source2 != NULL)
00337 _Source2->setRelativeGain(gain);
00338
00339 std::vector<USource *>::iterator first(_AllSources.begin()), last(_AllSources.end());
00340 for (; first != last; ++first)
00341 {
00342 (*first)->setRelativeGain(_Gain);
00343 }
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 uint32 CComplexSource::getTime()
00366 {
00367
00368 if (!_Playing || _PlayStart == 0)
00369 return 0;
00370
00371 TTime now = NLMISC::CTime::getLocalTime();
00372
00373 TTime delta = now - _PlayStart;
00374
00375 return uint32(delta);
00376 }
00377
00378
00380 void CComplexSource::onUpdate()
00381 {
00382
00383
00384
00385
00386
00387 nlassert(_PatternSound->getPatternMode() == CComplexSound::MODE_CHAINED);
00388
00389 CAudioMixerUser *mixer = CAudioMixerUser::instance();
00390
00391
00392 TTime now = NLMISC::CTime::getLocalTime();
00393 if (_FadeLength > 0)
00394 {
00395 _FadeFactor = float((double(now) - double(_StartTime2)) / double(_FadeLength)) ;
00396
00397 }
00398 else
00399 _FadeFactor = 1.0f;
00400
00401 nldebug("Fade factor = %f", _FadeFactor);
00402 if (_FadeFactor >= 1.0)
00403 {
00404
00405 if (_Source1)
00406 {
00407
00408
00409 delete _Source1;
00410 _Source1 = NULL;
00411 }
00412 if (_Source2)
00413 {
00414
00415 _Source2->setRelativeGain(1.0f * _Gain);
00416
00417 _Source1 = _Source2;
00418 _StartTime1 = _StartTime2;
00419 _Source2 = NULL;
00420
00421 CSound *sound2 = NULL;
00422
00423 const vector<uint32> &soundSeq = _PatternSound->getSoundSeq();
00424 if (_SoundSeqIndex < soundSeq.size())
00425 {
00426 sound2 = mixer->getSoundId(_PatternSound->getSound(soundSeq[_SoundSeqIndex++]));
00427 }
00428 else if (_Looping)
00429 {
00430
00431 _SoundSeqIndex = 0;
00432 sound2 = mixer->getSoundId(_PatternSound->getSound(soundSeq[_SoundSeqIndex++]));
00433 }
00434
00435
00436 if (sound2 != NULL)
00437 {
00438 nldebug("CS : Chaining to sound %s", sound2->getName().c_str());
00439 CAudioMixerUser *mixer = CAudioMixerUser::instance();
00440
00441
00442 _FadeLength = minof<uint32>(uint32(_PatternSound->getFadeLenght()/_TickPerSecond), sound2->getDuration() / 2, _Source1->getSound()->getDuration()/2);
00443 _Source2 = mixer->createSource(sound2, false);
00444
00445 nldebug("Seting event for sound %s in %u millisec (XFade = %u).", _Source1->getSound()->getName().c_str(), _Source1->getSound()->getDuration(), _FadeLength);
00446 mixer->addEvent(this, _StartTime1 + _Source1->getSound()->getDuration() - _FadeLength);
00447 }
00448 else
00449 {
00450
00451 nldebug("Setting last event for sound %s in %u millisec.", _Source1->getSound()->getName().c_str(), _Source1->getSound()->getDuration());
00452 if (_PatternSound->doFadeOut())
00453 {
00454
00455 mixer->addEvent(this, _StartTime1 + _Source1->getSound()->getDuration() - _PatternSound->getFadeLenght());
00456 }
00457 else
00458 {
00459
00460 mixer->addEvent(this, _StartTime1 + _Source1->getSound()->getDuration());
00461 }
00462 }
00463 }
00464 else
00465 {
00466 if (_PatternSound->doFadeOut())
00467 {
00468
00469 _Playing = false;
00470 }
00471 }
00472
00473 mixer->unregisterUpdate(this);
00474 }
00475 else
00476 {
00477
00478 if (_Source1)
00479 {
00480
00481 _Source1->setRelativeGain(float(1.0 - _FadeFactor) * _Gain);
00482
00483 }
00484 if (_Source2)
00485 {
00486
00487
00488 _Source2->setRelativeGain(float(_FadeFactor) * _Gain);
00489 }
00490 }
00491 }
00493 void CComplexSource::onEvent()
00494 {
00495 CAudioMixerUser *mixer = CAudioMixerUser::instance();
00496 NLMISC::TTime now = NLMISC::CTime::getLocalTime();
00497
00498 switch (_PatternSound->getPatternMode())
00499 {
00500 case CComplexSound::MODE_CHAINED:
00501 {
00502
00503 if (_Source2 != NULL)
00504 {
00505
00506 _StartTime2 = now;
00507
00508 _Source2->setRelativeGain(0);
00509
00510 _Source2->play();
00511
00512 mixer->registerUpdate(this);
00513 }
00514 else
00515 {
00516 if (_PatternSound->doFadeOut())
00517 {
00518
00519 _StartTime2 = now;
00520 mixer->registerUpdate(this);
00521 }
00522 else
00523 {
00524
00525
00526
00527 delete _Source1;
00528 _Source1 = NULL;
00529 _Playing = false;
00530 }
00531 }
00532 }
00533 break;
00534 case CComplexSound::MODE_SPARSE:
00535 {
00536 if (_Source1 != NULL)
00537 {
00538
00539
00540 delete _Source1;
00541 _Source1 = NULL;
00542 }
00543
00544 const std::vector<uint32> &delaySeq = _PatternSound->getDelaySeq();
00545 const vector<uint32> &soundSeq = _PatternSound->getSoundSeq();
00546
00547 if (_Looping && _DelaySeqIndex >= delaySeq.size())
00548 {
00549 _DelaySeqIndex = 0;
00550 }
00551
00552 if (!soundSeq.empty() && !_LastSparseEvent)
00553 {
00554
00555 if (_SoundSeqIndex >= soundSeq.size())
00556 _SoundSeqIndex = 0;
00557
00558 CSound *sound = mixer->getSoundId(_PatternSound->getSound(soundSeq[_SoundSeqIndex++]));
00559
00560 _Source1 = mixer->createSource(sound, false);
00561 if (_Source1 == NULL)
00562 {
00563 stop();
00564 return;
00565 }
00566 _Source1->setRelativeGain(_Gain);
00567 _Source1->setPos(_Position);
00568 _Source1->play();
00569 _StartTime1 = now;
00570
00571
00572 if (!delaySeq.empty() && _DelaySeqIndex < delaySeq.size())
00573 {
00574
00575 mixer->addEvent(this, uint64(now + sound->getDuration() + delaySeq[_DelaySeqIndex++]/_TickPerSecond));
00576 }
00577 else
00578 {
00579
00580 _LastSparseEvent = true;
00581 mixer->addEvent(this, now + sound->getDuration());
00582 }
00583 }
00584 else
00585 {
00586
00587 stop();
00588 }
00589 }
00590 break;
00591 case CComplexSound::MODE_ALL_IN_ONE:
00592
00593 stop();
00594 break;
00595 default:
00596 nlassert(false);
00597 }
00598 }
00599
00600
00601
00602 }