SoundSource.cpp 34 KB

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