SoundSource.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2012 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Audio.h"
  25. #include "Context.h"
  26. #include "ResourceCache.h"
  27. #include "Sound.h"
  28. #include "SoundSource.h"
  29. #include <cstring>
  30. #include "DebugNew.h"
  31. #define INC_POS_LOOPED() \
  32. pos += intAdd; \
  33. fractPos += fractAdd; \
  34. if (fractPos > 65535) \
  35. { \
  36. fractPos &= 65535; \
  37. ++pos; \
  38. } \
  39. while (pos >= end) \
  40. pos -= (end - repeat); \
  41. #define INC_POS_ONESHOT() \
  42. pos += intAdd; \
  43. fractPos += fractAdd; \
  44. if (fractPos > 65535) \
  45. { \
  46. fractPos &= 65535; \
  47. ++pos; \
  48. } \
  49. if (pos >= end) \
  50. { \
  51. pos = 0; \
  52. break; \
  53. } \
  54. #define INC_POS_STEREO_LOOPED() \
  55. pos += (intAdd << 1); \
  56. fractPos += fractAdd; \
  57. if (fractPos > 65535) \
  58. { \
  59. fractPos &= 65535; \
  60. pos += 2; \
  61. } \
  62. while (pos >= end) \
  63. pos -= (end - repeat); \
  64. #define INC_POS_STEREO_ONESHOT() \
  65. pos += (intAdd << 1); \
  66. fractPos += fractAdd; \
  67. if (fractPos > 65535) \
  68. { \
  69. fractPos &= 65535; \
  70. pos += 2; \
  71. } \
  72. if (pos >= end) \
  73. { \
  74. pos = 0; \
  75. break; \
  76. } \
  77. #define GET_IP_SAMPLE() (((((int)pos[1] - (int)pos[0]) * fractPos) / 65536) + (int)pos[0])
  78. #define GET_IP_SAMPLE_LEFT() (((((int)pos[2] - (int)pos[0]) * fractPos) / 65536) + (int)pos[0])
  79. #define GET_IP_SAMPLE_RIGHT() (((((int)pos[3] - (int)pos[1]) * fractPos) / 65536) + (int)pos[1])
  80. static const String typeNames[] =
  81. {
  82. "Master",
  83. "Effect",
  84. "Music",
  85. "Voice",
  86. ""
  87. };
  88. static const float AUTOREMOVE_DELAY = 0.25f;
  89. OBJECTTYPESTATIC(SoundSource);
  90. SoundSource::SoundSource(Context* context) :
  91. Component(context),
  92. position_(0),
  93. fractPosition_(0),
  94. timePosition_(0.0f),
  95. soundType_(SOUND_EFFECT),
  96. frequency_(0.0f),
  97. gain_(1.0f),
  98. attenuation_(1.0f),
  99. panning_(0.0f),
  100. autoRemoveTimer_(0.0f),
  101. autoRemove_(false),
  102. decoder_(0),
  103. decodePosition_(0)
  104. {
  105. audio_ = GetSubsystem<Audio>();
  106. if (audio_)
  107. audio_->AddSoundSource(this);
  108. }
  109. SoundSource::~SoundSource()
  110. {
  111. if (audio_)
  112. audio_->RemoveSoundSource(this);
  113. FreeDecoder();
  114. }
  115. void SoundSource::RegisterObject(Context* context)
  116. {
  117. context->RegisterFactory<SoundSource>();
  118. ENUM_ATTRIBUTE(SoundSource, "Sound Type", soundType_, typeNames, SOUND_EFFECT, AM_DEFAULT);
  119. ATTRIBUTE(SoundSource, VAR_FLOAT, "Frequency", frequency_, 0.0f, AM_DEFAULT);
  120. ATTRIBUTE(SoundSource, VAR_FLOAT, "Gain", gain_, 1.0f, AM_DEFAULT);
  121. ATTRIBUTE(SoundSource, VAR_FLOAT, "Attenuation", attenuation_, 1.0f, AM_DEFAULT);
  122. ATTRIBUTE(SoundSource, VAR_FLOAT, "Panning", panning_, 0.0f, AM_DEFAULT);
  123. ATTRIBUTE(SoundSource, VAR_BOOL, "Autoremove on Stop", autoRemove_, false, AM_FILE);
  124. ACCESSOR_ATTRIBUTE(SoundSource, VAR_RESOURCEREF, "Sound", GetSoundAttr, SetSoundAttr, ResourceRef, ResourceRef(Sound::GetTypeStatic()), AM_DEFAULT);
  125. ACCESSOR_ATTRIBUTE(SoundSource, VAR_INT, "Play Position", GetPositionAttr, SetPositionAttr, int, 0, AM_FILE);
  126. }
  127. void SoundSource::Play(Sound* sound)
  128. {
  129. if (!audio_)
  130. return;
  131. // If no frequency set yet, set from the sound's default
  132. if (frequency_ == 0.0f && sound)
  133. SetFrequency(sound->GetFrequency());
  134. // If sound source is currently playing, have to lock the audio mutex
  135. if (position_)
  136. {
  137. MutexLock lock(audio_->GetMutex());
  138. PlayLockless(sound);
  139. }
  140. else
  141. PlayLockless(sound);
  142. }
  143. void SoundSource::Play(Sound* sound, float frequency)
  144. {
  145. SetFrequency(frequency);
  146. Play(sound);
  147. }
  148. void SoundSource::Play(Sound* sound, float frequency, float gain)
  149. {
  150. SetFrequency(frequency);
  151. SetGain(gain);
  152. Play(sound);
  153. }
  154. void SoundSource::Play(Sound* sound, float frequency, float gain, float panning)
  155. {
  156. SetFrequency(frequency);
  157. SetGain(gain);
  158. SetPanning(panning);
  159. Play(sound);
  160. }
  161. void SoundSource::Stop()
  162. {
  163. if (!audio_)
  164. return;
  165. // If sound source is currently playing, have to lock the audio mutex
  166. if (position_)
  167. {
  168. MutexLock lock(audio_->GetMutex());
  169. StopLockless();
  170. }
  171. // Free the compressed sound decoder now if any
  172. FreeDecoder();
  173. sound_.Reset();
  174. }
  175. void SoundSource::SetSoundType(SoundType type)
  176. {
  177. if (type == SOUND_MASTER || type >= MAX_SOUND_TYPES)
  178. return;
  179. soundType_ = type;
  180. }
  181. void SoundSource::SetFrequency(float frequency)
  182. {
  183. frequency_ = Clamp(frequency, 0.0f, 535232.0f);
  184. }
  185. void SoundSource::SetGain(float gain)
  186. {
  187. gain_ = Max(gain, 0.0f);
  188. }
  189. void SoundSource::SetAttenuation(float attenuation)
  190. {
  191. attenuation_ = Clamp(attenuation, 0.0f, 1.0f);
  192. }
  193. void SoundSource::SetPanning(float panning)
  194. {
  195. panning_ = Clamp(panning, -1.0f, 1.0f);
  196. }
  197. void SoundSource::SetAutoRemove(bool enable)
  198. {
  199. autoRemove_ = enable;
  200. }
  201. bool SoundSource::IsPlaying() const
  202. {
  203. return sound_.Get() != 0;
  204. }
  205. void SoundSource::SetPlayPosition(signed char* pos)
  206. {
  207. if (!audio_ || !sound_)
  208. return;
  209. MutexLock lock(audio_->GetMutex());
  210. SetPlayPositionLockless(pos);
  211. }
  212. void SoundSource::PlayLockless(Sound* sound)
  213. {
  214. // Reset the time position in any case
  215. timePosition_ = 0.0f;
  216. if (sound)
  217. {
  218. if (!sound->IsCompressed())
  219. {
  220. // Uncompressed sound start
  221. signed char* start = sound->GetStart();
  222. if (start)
  223. {
  224. // Free Decoder in case previous sound was compressed
  225. FreeDecoder();
  226. sound_ = sound;
  227. position_ = start;
  228. fractPosition_ = 0;
  229. return;
  230. }
  231. }
  232. else
  233. {
  234. // Compressed sound start
  235. if (sound == sound_)
  236. {
  237. // If same compressed sound is already playing, rewind the Decoder
  238. sound_->RewindDecoder(decoder_);
  239. return;
  240. }
  241. else
  242. {
  243. // Else just set the new sound with a dummy start position. The mixing routine will allocate the new Decoder
  244. FreeDecoder();
  245. sound_ = sound;
  246. position_ = sound->GetStart();
  247. return;
  248. }
  249. }
  250. }
  251. // If sound pointer is null or if sound has no data, stop playback
  252. FreeDecoder();
  253. sound_.Reset();
  254. position_ = 0;
  255. }
  256. void SoundSource::StopLockless()
  257. {
  258. position_ = 0;
  259. timePosition_ = 0.0f;
  260. }
  261. void SoundSource::SetPlayPositionLockless(signed char* pos)
  262. {
  263. // Setting position on a compressed sound is not supported
  264. if (!sound_ || sound_->IsCompressed())
  265. return;
  266. signed char* start = sound_->GetStart();
  267. signed char* end = sound_->GetEnd();
  268. if (pos < start)
  269. pos = start;
  270. if (sound_->IsSixteenBit() && (pos - start) & 1)
  271. ++pos;
  272. if (pos > end)
  273. pos = end;
  274. position_ = pos;
  275. timePosition_ = (float)((int)pos - (int)sound_->GetStart()) / (sound_->GetSampleSize() * sound_->GetFrequency());
  276. }
  277. void SoundSource::Update(float timeStep)
  278. {
  279. if (!audio_)
  280. return;
  281. // If there is no actual audio output, perform fake mixing into a nonexistent buffer to check stopping/looping
  282. if (!audio_->IsInitialized())
  283. MixNull(timeStep);
  284. // Free the sound if playback has stopped
  285. if (sound_ && !position_)
  286. {
  287. FreeDecoder();
  288. sound_.Reset();
  289. }
  290. // Check for autoremove
  291. if (autoRemove_)
  292. {
  293. if (!IsPlaying())
  294. {
  295. autoRemoveTimer_ += timeStep;
  296. if (autoRemoveTimer_ > AUTOREMOVE_DELAY)
  297. {
  298. Remove();
  299. // Note: this object is now deleted, so only returning immediately is safe
  300. return;
  301. }
  302. }
  303. else
  304. autoRemoveTimer_ = 0.0f;
  305. }
  306. }
  307. void SoundSource::Mix(int* dest, unsigned samples, int mixRate, bool stereo, bool interpolate)
  308. {
  309. if (!position_ || !sound_)
  310. return;
  311. if (sound_->IsCompressed())
  312. {
  313. if (decoder_)
  314. {
  315. // If Decoder already exists, Decode new compressed audio
  316. bool eof = false;
  317. unsigned currentPos = position_ - decodeBuffer_->GetStart();
  318. if (currentPos != decodePosition_)
  319. {
  320. // If buffer has wrapped, Decode first to the end
  321. if (currentPos < decodePosition_)
  322. {
  323. unsigned bytes = decodeBuffer_->GetDataSize() - decodePosition_;
  324. unsigned outBytes = sound_->Decode(decoder_, decodeBuffer_->GetStart() + decodePosition_, bytes);
  325. // If produced less output, end of sound encountered. Fill rest with zero
  326. if (outBytes < bytes)
  327. {
  328. memset(decodeBuffer_->GetStart() + decodePosition_ + outBytes, 0, bytes - outBytes);
  329. eof = true;
  330. }
  331. decodePosition_ = 0;
  332. }
  333. if (currentPos > decodePosition_)
  334. {
  335. unsigned bytes = currentPos - decodePosition_;
  336. unsigned outBytes = sound_->Decode(decoder_, decodeBuffer_->GetStart() + decodePosition_, bytes);
  337. // If produced less output, end of sound encountered. Fill rest with zero
  338. if (outBytes < bytes)
  339. {
  340. memset(decodeBuffer_->GetStart() + decodePosition_ + outBytes, 0, bytes - outBytes);
  341. if (sound_->IsLooped())
  342. eof = true;
  343. }
  344. // If wrote to buffer start, correct interpolation wraparound
  345. if (!decodePosition_)
  346. decodeBuffer_->FixInterpolation();
  347. }
  348. }
  349. // If end of stream encountered, check whether we should rewind or stop
  350. if (eof)
  351. {
  352. if (sound_->IsLooped())
  353. {
  354. sound_->RewindDecoder(decoder_);
  355. timePosition_ = 0.0f;
  356. }
  357. else
  358. decodeBuffer_->SetLooped(false); // Stop after the current decode buffer has been played
  359. }
  360. decodePosition_ = currentPos;
  361. }
  362. else
  363. {
  364. // Setup the decoder and decode buffer
  365. decoder_ = sound_->AllocateDecoder();
  366. unsigned sampleSize = sound_->GetSampleSize();
  367. unsigned DecodeBufferSize = sampleSize * sound_->GetIntFrequency() * DECODE_BUFFER_LENGTH / 1000;
  368. decodeBuffer_ = new Sound(context_);
  369. decodeBuffer_->SetSize(DecodeBufferSize);
  370. decodeBuffer_->SetFormat(sound_->GetIntFrequency(), true, sound_->IsStereo());
  371. // Clear the decode buffer, then fill with initial audio data and set it to loop
  372. memset(decodeBuffer_->GetStart(), 0, DecodeBufferSize);
  373. sound_->Decode(decoder_, decodeBuffer_->GetStart(), DecodeBufferSize);
  374. decodeBuffer_->SetLooped(true);
  375. decodePosition_ = 0;
  376. // Start playing the decode buffer
  377. position_ = decodeBuffer_->GetStart();
  378. fractPosition_ = 0;
  379. }
  380. }
  381. // If compressed, play the decode buffer. Otherwise play the original sound
  382. Sound* sound = sound_->IsCompressed() ? decodeBuffer_ : sound_;
  383. if (!sound)
  384. return;
  385. // Choose the correct mixing routine
  386. if (!sound->IsStereo())
  387. {
  388. if (interpolate)
  389. {
  390. if (stereo)
  391. MixMonoToStereoIP(sound, dest, samples, mixRate);
  392. else
  393. MixMonoToMonoIP(sound, dest, samples, mixRate);
  394. }
  395. else
  396. {
  397. if (stereo)
  398. MixMonoToStereo(sound, dest, samples, mixRate);
  399. else
  400. MixMonoToMono(sound, dest, samples, mixRate);
  401. }
  402. }
  403. else
  404. {
  405. if (interpolate)
  406. {
  407. if (stereo)
  408. MixStereoToStereoIP(sound, dest, samples, mixRate);
  409. else
  410. MixStereoToMonoIP(sound, dest, samples, mixRate);
  411. }
  412. else
  413. {
  414. if (stereo)
  415. MixStereoToStereo(sound, dest, samples, mixRate);
  416. else
  417. MixStereoToMono(sound, dest, samples, mixRate);
  418. }
  419. }
  420. // Update the time position
  421. if (!sound_->IsCompressed())
  422. timePosition_ = (float)((int)position_ - (int)sound_->GetStart()) / (sound_->GetSampleSize() * sound_->GetFrequency());
  423. else
  424. timePosition_ += ((float)samples / (float)mixRate) * frequency_ / sound_->GetFrequency();
  425. }
  426. void SoundSource::SetSoundAttr(ResourceRef value)
  427. {
  428. ResourceCache* cache = GetSubsystem<ResourceCache>();
  429. Play(cache->GetResource<Sound>(value.id_));
  430. }
  431. void SoundSource::SetPositionAttr(int value)
  432. {
  433. if (sound_)
  434. SetPlayPosition(sound_->GetStart() + value);
  435. }
  436. ResourceRef SoundSource::GetSoundAttr() const
  437. {
  438. return GetResourceRef(sound_, Sound::GetTypeStatic());
  439. }
  440. int SoundSource::GetPositionAttr() const
  441. {
  442. if (sound_)
  443. return (int)(GetPlayPosition() - sound_->GetStart());
  444. else
  445. return 0;
  446. }
  447. void SoundSource::MixMonoToMono(Sound* sound, int* dest, unsigned samples, int mixRate)
  448. {
  449. float totalGain = audio_->GetSoundSourceMasterGain(soundType_) * attenuation_ * gain_;
  450. int vol = (int)(256.0f * totalGain + 0.5f);
  451. if (!vol)
  452. {
  453. MixZeroVolume(sound, samples, mixRate);
  454. return;
  455. }
  456. float add = frequency_ / (float)mixRate;
  457. int intAdd = (int)add;
  458. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  459. int fractPos = fractPosition_;
  460. if (sound->IsSixteenBit())
  461. {
  462. short* pos = (short*)position_;
  463. short* end = (short*)sound->GetEnd();
  464. short* repeat = (short*)sound->GetRepeat();
  465. if (sound->IsLooped())
  466. {
  467. while (--samples)
  468. {
  469. *dest = *dest + (*pos * vol) / 256;
  470. ++dest;
  471. INC_POS_LOOPED();
  472. }
  473. position_ = (signed char*)pos;
  474. }
  475. else
  476. {
  477. while (--samples)
  478. {
  479. *dest = *dest + (*pos * vol) / 256;
  480. ++dest;
  481. INC_POS_ONESHOT();
  482. }
  483. position_ = (signed char*)pos;
  484. }
  485. }
  486. else
  487. {
  488. signed char* pos = (signed char*)position_;
  489. signed char* end = sound->GetEnd();
  490. signed char* repeat = sound->GetRepeat();
  491. if (sound->IsLooped())
  492. {
  493. while (--samples)
  494. {
  495. *dest = *dest + *pos * vol;
  496. ++dest;
  497. INC_POS_LOOPED();
  498. }
  499. position_ = pos;
  500. }
  501. else
  502. {
  503. while (--samples)
  504. {
  505. *dest = *dest + *pos * vol;
  506. ++dest;
  507. INC_POS_ONESHOT();
  508. }
  509. position_ = pos;
  510. }
  511. }
  512. fractPosition_ = fractPos;
  513. }
  514. void SoundSource::MixMonoToStereo(Sound* sound, int* dest, unsigned samples, int mixRate)
  515. {
  516. float totalGain = audio_->GetSoundSourceMasterGain(soundType_) * attenuation_ * gain_;
  517. int leftVol = (int)((-panning_ + 1.0f) * (256.0f * totalGain + 0.5f));
  518. int rightVol = (int)((panning_ + 1.0f) * (256.0f * totalGain + 0.5f));
  519. if (!leftVol && !rightVol)
  520. {
  521. MixZeroVolume(sound, samples, mixRate);
  522. return;
  523. }
  524. float add = frequency_ / (float)mixRate;
  525. int intAdd = (int)add;
  526. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  527. int fractPos = fractPosition_;
  528. if (sound->IsSixteenBit())
  529. {
  530. short* pos = (short*)position_;
  531. short* end = (short*)sound->GetEnd();
  532. short* repeat = (short*)sound->GetRepeat();
  533. if (sound->IsLooped())
  534. {
  535. while (--samples)
  536. {
  537. *dest = *dest + (*pos * leftVol) / 256;
  538. ++dest;
  539. *dest = *dest + (*pos * rightVol) / 256;
  540. ++dest;
  541. INC_POS_LOOPED();
  542. }
  543. position_ = (signed char*)pos;
  544. }
  545. else
  546. {
  547. while (--samples)
  548. {
  549. *dest = *dest + (*pos * leftVol) / 256;
  550. ++dest;
  551. *dest = *dest + (*pos * rightVol) / 256;
  552. ++dest;
  553. INC_POS_ONESHOT();
  554. }
  555. position_ = (signed char*)pos;
  556. }
  557. }
  558. else
  559. {
  560. signed char* pos = (signed char*)position_;
  561. signed char* end = sound->GetEnd();
  562. signed char* repeat = sound->GetRepeat();
  563. if (sound->IsLooped())
  564. {
  565. while (--samples)
  566. {
  567. *dest = *dest + *pos * leftVol;
  568. ++dest;
  569. *dest = *dest + *pos * rightVol;
  570. ++dest;
  571. INC_POS_LOOPED();
  572. }
  573. position_ = pos;
  574. }
  575. else
  576. {
  577. while (--samples)
  578. {
  579. *dest = *dest + *pos * leftVol;
  580. ++dest;
  581. *dest = *dest + *pos * rightVol;
  582. ++dest;
  583. INC_POS_ONESHOT();
  584. }
  585. position_ = pos;
  586. }
  587. }
  588. fractPosition_ = fractPos;
  589. }
  590. void SoundSource::MixMonoToMonoIP(Sound* sound, int* dest, unsigned samples, int mixRate)
  591. {
  592. float totalGain = audio_->GetSoundSourceMasterGain(soundType_) * attenuation_ * gain_;
  593. int vol = (int)(256.0f * totalGain + 0.5f);
  594. if (!vol)
  595. {
  596. MixZeroVolume(sound, samples, mixRate);
  597. return;
  598. }
  599. float add = frequency_ / (float)mixRate;
  600. int intAdd = (int)add;
  601. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  602. int fractPos = fractPosition_;
  603. if (sound->IsSixteenBit())
  604. {
  605. short* pos = (short*)position_;
  606. short* end = (short*)sound->GetEnd();
  607. short* repeat = (short*)sound->GetRepeat();
  608. if (sound->IsLooped())
  609. {
  610. while (--samples)
  611. {
  612. *dest = *dest + (GET_IP_SAMPLE() * vol) / 256;
  613. ++dest;
  614. INC_POS_LOOPED();
  615. }
  616. position_ = (signed char*)pos;
  617. }
  618. else
  619. {
  620. while (--samples)
  621. {
  622. *dest = *dest + (GET_IP_SAMPLE() * vol) / 256;
  623. ++dest;
  624. INC_POS_ONESHOT();
  625. }
  626. position_ = (signed char*)pos;
  627. }
  628. }
  629. else
  630. {
  631. signed char* pos = (signed char*)position_;
  632. signed char* end = sound->GetEnd();
  633. signed char* repeat = sound->GetRepeat();
  634. if (sound->IsLooped())
  635. {
  636. while (--samples)
  637. {
  638. *dest = *dest + GET_IP_SAMPLE() * vol;
  639. ++dest;
  640. INC_POS_LOOPED();
  641. }
  642. position_ = pos;
  643. }
  644. else
  645. {
  646. while (--samples)
  647. {
  648. *dest = *dest + GET_IP_SAMPLE() * vol;
  649. ++dest;
  650. INC_POS_ONESHOT();
  651. }
  652. position_ = pos;
  653. }
  654. }
  655. fractPosition_ = fractPos;
  656. }
  657. void SoundSource::MixMonoToStereoIP(Sound* sound, int* dest, unsigned samples, int mixRate)
  658. {
  659. float totalGain = audio_->GetSoundSourceMasterGain(soundType_) * attenuation_ * gain_;
  660. int leftVol = (int)((-panning_ + 1.0f) * (256.0f * totalGain + 0.5f));
  661. int rightVol = (int)((panning_ + 1.0f) * (256.0f * totalGain + 0.5f));
  662. if (!leftVol && !rightVol)
  663. {
  664. MixZeroVolume(sound, samples, mixRate);
  665. return;
  666. }
  667. float add = frequency_ / (float)mixRate;
  668. int intAdd = (int)add;
  669. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  670. int fractPos = fractPosition_;
  671. if (sound->IsSixteenBit())
  672. {
  673. short* pos = (short*)position_;
  674. short* end = (short*)sound->GetEnd();
  675. short* repeat = (short*)sound->GetRepeat();
  676. if (sound->IsLooped())
  677. {
  678. while (--samples)
  679. {
  680. int s = GET_IP_SAMPLE();
  681. *dest = *dest + (s * leftVol) / 256;
  682. ++dest;
  683. *dest = *dest + (s * rightVol) / 256;
  684. ++dest;
  685. INC_POS_LOOPED();
  686. }
  687. position_ = (signed char*)pos;
  688. }
  689. else
  690. {
  691. while (--samples)
  692. {
  693. int s = GET_IP_SAMPLE();
  694. *dest = *dest + (s * leftVol) / 256;
  695. ++dest;
  696. *dest = *dest + (s * rightVol) / 256;
  697. ++dest;
  698. INC_POS_ONESHOT();
  699. }
  700. position_ = (signed char*)pos;
  701. }
  702. }
  703. else
  704. {
  705. signed char* pos = (signed char*)position_;
  706. signed char* end = sound->GetEnd();
  707. signed char* repeat = sound->GetRepeat();
  708. if (sound->IsLooped())
  709. {
  710. while (--samples)
  711. {
  712. int s = GET_IP_SAMPLE();
  713. *dest = *dest + s * leftVol;
  714. ++dest;
  715. *dest = *dest + s * rightVol;
  716. ++dest;
  717. INC_POS_LOOPED();
  718. }
  719. position_ = pos;
  720. }
  721. else
  722. {
  723. while (--samples)
  724. {
  725. int s = GET_IP_SAMPLE();
  726. *dest = *dest + s * leftVol;
  727. ++dest;
  728. *dest = *dest + s * rightVol;
  729. ++dest;
  730. INC_POS_ONESHOT();
  731. }
  732. position_ = pos;
  733. }
  734. }
  735. fractPosition_ = fractPos;
  736. }
  737. void SoundSource::MixStereoToMono(Sound* sound, int* dest, unsigned samples, int mixRate)
  738. {
  739. float totalGain = audio_->GetSoundSourceMasterGain(soundType_) * attenuation_ * gain_;
  740. int vol = (int)(256.0f * totalGain + 0.5f);
  741. if (!vol)
  742. {
  743. MixZeroVolume(sound, samples, mixRate);
  744. return;
  745. }
  746. float add = frequency_ / (float)mixRate;
  747. int intAdd = (int)add;
  748. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  749. int fractPos = fractPosition_;
  750. if (sound->IsSixteenBit())
  751. {
  752. short* pos = (short*)position_;
  753. short* end = (short*)sound->GetEnd();
  754. short* repeat = (short*)sound->GetRepeat();
  755. if (sound->IsLooped())
  756. {
  757. while (--samples)
  758. {
  759. int s = ((int)pos[0] + (int)pos[1]) / 2;
  760. *dest = *dest + (s * vol) / 256;
  761. ++dest;
  762. INC_POS_STEREO_LOOPED();
  763. }
  764. position_ = (signed char*)pos;
  765. }
  766. else
  767. {
  768. while (--samples)
  769. {
  770. int s = ((int)pos[0] + (int)pos[1]) / 2;
  771. *dest = *dest + (s * vol) / 256;
  772. ++dest;
  773. INC_POS_STEREO_ONESHOT();
  774. }
  775. position_ = (signed char*)pos;
  776. }
  777. }
  778. else
  779. {
  780. signed char* pos = (signed char*)position_;
  781. signed char* end = sound->GetEnd();
  782. signed char* repeat = sound->GetRepeat();
  783. if (sound->IsLooped())
  784. {
  785. while (--samples)
  786. {
  787. int s = ((int)pos[0] + (int)pos[1]) / 2;
  788. *dest = *dest + s * vol;
  789. ++dest;
  790. INC_POS_STEREO_LOOPED();
  791. }
  792. position_ = pos;
  793. }
  794. else
  795. {
  796. while (--samples)
  797. {
  798. int s = ((int)pos[0] + (int)pos[1]) / 2;
  799. *dest = *dest + s * vol;
  800. ++dest;
  801. INC_POS_STEREO_ONESHOT();
  802. }
  803. position_ = pos;
  804. }
  805. }
  806. fractPosition_ = fractPos;
  807. }
  808. void SoundSource::MixStereoToStereo(Sound* sound, int* dest, unsigned samples, int mixRate)
  809. {
  810. float totalGain = audio_->GetSoundSourceMasterGain(soundType_) * attenuation_ * gain_;
  811. int vol = (int)(256.0f * totalGain + 0.5f);
  812. if (!vol)
  813. {
  814. MixZeroVolume(sound, samples, mixRate);
  815. return;
  816. }
  817. float add = frequency_ / (float)mixRate;
  818. int intAdd = (int)add;
  819. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  820. int fractPos = fractPosition_;
  821. if (sound->IsSixteenBit())
  822. {
  823. short* pos = (short*)position_;
  824. short* end = (short*)sound->GetEnd();
  825. short* repeat = (short*)sound->GetRepeat();
  826. if (sound->IsLooped())
  827. {
  828. while (--samples)
  829. {
  830. *dest = *dest + (pos[0] * vol) / 256;
  831. ++dest;
  832. *dest = *dest + (pos[1] * vol) / 256;
  833. ++dest;
  834. INC_POS_STEREO_LOOPED();
  835. }
  836. position_ = (signed char*)pos;
  837. }
  838. else
  839. {
  840. while (--samples)
  841. {
  842. *dest = *dest + (pos[0] * vol) / 256;
  843. ++dest;
  844. *dest = *dest + (pos[1] * vol) / 256;
  845. ++dest;
  846. INC_POS_STEREO_ONESHOT();
  847. }
  848. position_ = (signed char*)pos;
  849. }
  850. }
  851. else
  852. {
  853. signed char* pos = (signed char*)position_;
  854. signed char* end = sound->GetEnd();
  855. signed char* repeat = sound->GetRepeat();
  856. if (sound->IsLooped())
  857. {
  858. while (--samples)
  859. {
  860. *dest = *dest + pos[0] * vol;
  861. ++dest;
  862. *dest = *dest + pos[1] * vol;
  863. ++dest;
  864. INC_POS_STEREO_LOOPED();
  865. }
  866. position_ = pos;
  867. }
  868. else
  869. {
  870. while (--samples)
  871. {
  872. *dest = *dest + pos[0] * vol;
  873. ++dest;
  874. *dest = *dest + pos[1] * vol;
  875. ++dest;
  876. INC_POS_STEREO_ONESHOT();
  877. }
  878. position_ = pos;
  879. }
  880. }
  881. fractPosition_ = fractPos;
  882. }
  883. void SoundSource::MixStereoToMonoIP(Sound* sound, int* dest, unsigned samples, int mixRate)
  884. {
  885. float totalGain = audio_->GetSoundSourceMasterGain(soundType_) * attenuation_ * gain_;
  886. int vol = (int)(256.0f * totalGain + 0.5f);
  887. if (!vol)
  888. {
  889. MixZeroVolume(sound, samples, mixRate);
  890. return;
  891. }
  892. float add = frequency_ / (float)mixRate;
  893. int intAdd = (int)add;
  894. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  895. int fractPos = fractPosition_;
  896. if (sound->IsSixteenBit())
  897. {
  898. short* pos = (short*)position_;
  899. short* end = (short*)sound->GetEnd();
  900. short* repeat = (short*)sound->GetRepeat();
  901. if (sound->IsLooped())
  902. {
  903. while (--samples)
  904. {
  905. int s = (GET_IP_SAMPLE_LEFT() + GET_IP_SAMPLE_RIGHT()) / 2;
  906. *dest = *dest + (s * vol) / 256;
  907. ++dest;
  908. INC_POS_STEREO_LOOPED();
  909. }
  910. position_ = (signed char*)pos;
  911. }
  912. else
  913. {
  914. while (--samples)
  915. {
  916. int s = (GET_IP_SAMPLE_LEFT() + GET_IP_SAMPLE_RIGHT()) / 2;
  917. *dest = *dest + (s * vol) / 256;
  918. ++dest;
  919. INC_POS_STEREO_ONESHOT();
  920. }
  921. position_ = (signed char*)pos;
  922. }
  923. }
  924. else
  925. {
  926. signed char* pos = (signed char*)position_;
  927. signed char* end = sound->GetEnd();
  928. signed char* repeat = sound->GetRepeat();
  929. if (sound->IsLooped())
  930. {
  931. while (--samples)
  932. {
  933. int s = (GET_IP_SAMPLE_LEFT() + GET_IP_SAMPLE_RIGHT()) / 2;
  934. *dest = *dest + s * vol;
  935. ++dest;
  936. INC_POS_STEREO_LOOPED();
  937. }
  938. position_ = pos;
  939. }
  940. else
  941. {
  942. while (--samples)
  943. {
  944. int s = (GET_IP_SAMPLE_LEFT() + GET_IP_SAMPLE_RIGHT()) / 2;
  945. *dest = *dest + s * vol;
  946. ++dest;
  947. INC_POS_STEREO_ONESHOT();
  948. }
  949. position_ = pos;
  950. }
  951. }
  952. fractPosition_ = fractPos;
  953. }
  954. void SoundSource::MixStereoToStereoIP(Sound* sound, int* dest, unsigned samples, int mixRate)
  955. {
  956. float totalGain = audio_->GetSoundSourceMasterGain(soundType_) * attenuation_ * gain_;
  957. int vol = (int)(256.0f * totalGain + 0.5f);
  958. if (!vol)
  959. {
  960. MixZeroVolume(sound, samples, mixRate);
  961. return;
  962. }
  963. float add = frequency_ / (float)mixRate;
  964. int intAdd = (int)add;
  965. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  966. int fractPos = fractPosition_;
  967. if (sound->IsSixteenBit())
  968. {
  969. short* pos = (short*)position_;
  970. short* end = (short*)sound->GetEnd();
  971. short* repeat = (short*)sound->GetRepeat();
  972. if (sound->IsLooped())
  973. {
  974. while (--samples)
  975. {
  976. *dest = *dest + (GET_IP_SAMPLE_LEFT() * vol) / 256;
  977. ++dest;
  978. *dest = *dest + (GET_IP_SAMPLE_RIGHT() * vol) / 256;
  979. ++dest;
  980. INC_POS_STEREO_LOOPED();
  981. }
  982. position_ = (signed char*)pos;
  983. }
  984. else
  985. {
  986. while (--samples)
  987. {
  988. *dest = *dest + (GET_IP_SAMPLE_LEFT() * vol) / 256;
  989. ++dest;
  990. *dest = *dest + (GET_IP_SAMPLE_RIGHT() * vol) / 256;
  991. ++dest;
  992. INC_POS_STEREO_ONESHOT();
  993. }
  994. position_ = (signed char*)pos;
  995. }
  996. }
  997. else
  998. {
  999. signed char* pos = (signed char*)position_;
  1000. signed char* end = sound->GetEnd();
  1001. signed char* repeat = sound->GetRepeat();
  1002. if (sound->IsLooped())
  1003. {
  1004. while (--samples)
  1005. {
  1006. *dest = *dest + GET_IP_SAMPLE_LEFT() * vol;
  1007. ++dest;
  1008. *dest = *dest + GET_IP_SAMPLE_RIGHT() * vol;
  1009. ++dest;
  1010. INC_POS_STEREO_LOOPED();
  1011. }
  1012. position_ = pos;
  1013. }
  1014. else
  1015. {
  1016. while (--samples)
  1017. {
  1018. *dest = *dest + GET_IP_SAMPLE_LEFT() * vol;
  1019. ++dest;
  1020. *dest = *dest + GET_IP_SAMPLE_RIGHT() * vol;
  1021. ++dest;
  1022. INC_POS_STEREO_ONESHOT();
  1023. }
  1024. position_ = pos;
  1025. }
  1026. }
  1027. fractPosition_ = fractPos;
  1028. }
  1029. void SoundSource::MixZeroVolume(Sound* sound, unsigned samples, int mixRate)
  1030. {
  1031. float add = frequency_ * (float)samples / (float)mixRate;
  1032. int intAdd = (int)add;
  1033. int fractAdd = (int)((add - floorf(add)) * 65536.0f);
  1034. unsigned sampleSize = sound->GetSampleSize();
  1035. fractPosition_ += fractAdd;
  1036. if (fractPosition_ > 65535)
  1037. {
  1038. fractPosition_ &= 65535;
  1039. position_ += sampleSize;
  1040. }
  1041. position_ += intAdd * sampleSize;
  1042. if (position_ > sound->GetEnd())
  1043. {
  1044. if (sound->IsLooped())
  1045. {
  1046. while (position_ >= sound->GetEnd())
  1047. {
  1048. position_ -= (sound->GetEnd() - sound->GetRepeat());
  1049. }
  1050. }
  1051. else
  1052. position_ = 0;
  1053. }
  1054. }
  1055. void SoundSource::MixNull(float timeStep)
  1056. {
  1057. if (!position_ || !sound_)
  1058. return;
  1059. // Advance only the time position
  1060. timePosition_ += timeStep * frequency_ / sound_->GetFrequency();
  1061. if (sound_->IsLooped())
  1062. {
  1063. // For simulated playback, simply reset the time position to zero when the sound loops
  1064. if (timePosition_ >= sound_->GetLength())
  1065. timePosition_ -= sound_->GetLength();
  1066. }
  1067. else
  1068. {
  1069. if (timePosition_ >= sound_->GetLength())
  1070. {
  1071. position_ = 0;
  1072. timePosition_ = 0.0f;
  1073. }
  1074. }
  1075. }
  1076. void SoundSource::FreeDecoder()
  1077. {
  1078. if (sound_ && decoder_)
  1079. {
  1080. sound_->FreeDecoder(decoder_);
  1081. decoder_ = 0;
  1082. }
  1083. decodeBuffer_.Reset();
  1084. }