SoundSource.cpp 34 KB

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