snd_emitter.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "snd_local.h"
  23. /*
  24. ===================
  25. idSoundFade::Clear
  26. ===================
  27. */
  28. void idSoundFade::Clear() {
  29. fadeStart44kHz = 0;
  30. fadeEnd44kHz = 0;
  31. fadeStartVolume = 0;
  32. fadeEndVolume = 0;
  33. }
  34. /*
  35. ===================
  36. idSoundFade::FadeDbAt44kHz
  37. ===================
  38. */
  39. float idSoundFade::FadeDbAt44kHz( int current44kHz ) {
  40. float fadeDb;
  41. if ( current44kHz >= fadeEnd44kHz ) {
  42. fadeDb = fadeEndVolume;
  43. } else if ( current44kHz > fadeStart44kHz ) {
  44. float fraction = ( fadeEnd44kHz - fadeStart44kHz );
  45. float over = ( current44kHz - fadeStart44kHz );
  46. fadeDb = fadeStartVolume + ( fadeEndVolume - fadeStartVolume ) * over / fraction;
  47. } else {
  48. fadeDb = fadeStartVolume;
  49. }
  50. return fadeDb;
  51. }
  52. //========================================================================
  53. /*
  54. =======================
  55. GeneratePermutedList
  56. Fills in elements[0] .. elements[numElements-1] with a permutation of
  57. 0 .. numElements-1 based on the permute parameter
  58. numElements == 3
  59. maxPermute = 6
  60. permute 0 = 012
  61. permute 1 = 021
  62. permute 2 = 102
  63. permute 3 = 120
  64. permute 4 = 201
  65. permute 5 = 210
  66. =======================
  67. */
  68. void PermuteList_r( int *list, int listLength, int permute, int maxPermute ) {
  69. if ( listLength < 2 ) {
  70. return;
  71. }
  72. permute %= maxPermute;
  73. int swap = permute * listLength / maxPermute;
  74. int old = list[swap];
  75. list[swap] = list[0];
  76. list[0] = old;
  77. maxPermute /= listLength;
  78. PermuteList_r( list + 1, listLength - 1, permute, maxPermute );
  79. }
  80. int Factorial( int val ) {
  81. int fact = val;
  82. while ( val > 1 ) {
  83. val--;
  84. fact *= val;
  85. }
  86. return fact;
  87. }
  88. void GeneratePermutedList( int *list, int listLength, int permute ) {
  89. for ( int i = 0 ; i < listLength ; i++ ) {
  90. list[i] = i;
  91. }
  92. // we can't calculate > 12 factorial, so we can't easily build a permuted list
  93. if ( listLength > 12 ) {
  94. return;
  95. }
  96. // calculate listLength factorial
  97. int maxPermute = Factorial( listLength );
  98. // recursively permute
  99. PermuteList_r( list, listLength, permute, maxPermute );
  100. }
  101. void TestPermutations( void ) {
  102. int list[SOUND_MAX_LIST_WAVS];
  103. for ( int len = 1 ; len < 5 ; len++ ) {
  104. common->Printf( "list length: %i\n", len );
  105. int max = Factorial( len );
  106. for ( int j = 0 ; j < max * 2 ; j++ ) {
  107. GeneratePermutedList( list, len, j );
  108. common->Printf( "%4i : ", j );
  109. for ( int k = 0 ; k < len ; k++ ) {
  110. common->Printf( "%i", list[k] );
  111. }
  112. common->Printf( "\n" );
  113. }
  114. }
  115. }
  116. //=====================================================================================
  117. /*
  118. ===================
  119. idSoundChannel::idSoundChannel
  120. ===================
  121. */
  122. idSoundChannel::idSoundChannel( void ) {
  123. decoder = NULL;
  124. Clear();
  125. }
  126. /*
  127. ===================
  128. idSoundChannel::~idSoundChannel
  129. ===================
  130. */
  131. idSoundChannel::~idSoundChannel( void ) {
  132. Clear();
  133. }
  134. /*
  135. ===================
  136. idSoundChannel::Clear
  137. ===================
  138. */
  139. void idSoundChannel::Clear( void ) {
  140. int j;
  141. Stop();
  142. soundShader = NULL;
  143. lastVolume = 0.0f;
  144. triggerChannel = SCHANNEL_ANY;
  145. channelFade.Clear();
  146. diversity = 0.0f;
  147. leadinSample = NULL;
  148. trigger44kHzTime = 0;
  149. for( j = 0; j < 6; j++ ) {
  150. lastV[j] = 0.0f;
  151. }
  152. memset( &parms, 0, sizeof(parms) );
  153. triggered = false;
  154. openalSource = NULL;
  155. openalStreamingOffset = 0;
  156. openalStreamingBuffer[0] = openalStreamingBuffer[1] = openalStreamingBuffer[2] = 0;
  157. lastopenalStreamingBuffer[0] = lastopenalStreamingBuffer[1] = lastopenalStreamingBuffer[2] = 0;
  158. }
  159. /*
  160. ===================
  161. idSoundChannel::Start
  162. ===================
  163. */
  164. void idSoundChannel::Start( void ) {
  165. triggerState = true;
  166. if ( decoder == NULL ) {
  167. decoder = idSampleDecoder::Alloc();
  168. }
  169. }
  170. /*
  171. ===================
  172. idSoundChannel::Stop
  173. ===================
  174. */
  175. void idSoundChannel::Stop( void ) {
  176. triggerState = false;
  177. if ( decoder != NULL ) {
  178. idSampleDecoder::Free( decoder );
  179. decoder = NULL;
  180. }
  181. }
  182. /*
  183. ===================
  184. idSoundChannel::ALStop
  185. ===================
  186. */
  187. void idSoundChannel::ALStop( void ) {
  188. if ( idSoundSystemLocal::useOpenAL ) {
  189. if ( alIsSource( openalSource ) ) {
  190. alSourceStop( openalSource );
  191. alSourcei( openalSource, AL_BUFFER, 0 );
  192. soundSystemLocal.FreeOpenALSource( openalSource );
  193. }
  194. if ( openalStreamingBuffer[0] && openalStreamingBuffer[1] && openalStreamingBuffer[2] ) {
  195. alGetError();
  196. alDeleteBuffers( 3, &openalStreamingBuffer[0] );
  197. if ( alGetError() == AL_NO_ERROR ) {
  198. openalStreamingBuffer[0] = openalStreamingBuffer[1] = openalStreamingBuffer[2] = 0;
  199. }
  200. }
  201. if ( lastopenalStreamingBuffer[0] && lastopenalStreamingBuffer[1] && lastopenalStreamingBuffer[2] ) {
  202. alGetError();
  203. alDeleteBuffers( 3, &lastopenalStreamingBuffer[0] );
  204. if ( alGetError() == AL_NO_ERROR ) {
  205. lastopenalStreamingBuffer[0] = lastopenalStreamingBuffer[1] = lastopenalStreamingBuffer[2] = 0;
  206. }
  207. }
  208. }
  209. }
  210. /*
  211. ===================
  212. idSoundChannel::GatherChannelSamples
  213. Will always return 44kHz samples for the given range, even if it deeply looped or
  214. out of the range of the unlooped samples. Handles looping between multiple different
  215. samples and leadins
  216. ===================
  217. */
  218. void idSoundChannel::GatherChannelSamples( int sampleOffset44k, int sampleCount44k, float *dest ) const {
  219. float *dest_p = dest;
  220. int len;
  221. //Sys_DebugPrintf( "msec:%i sample:%i : %i : %i\n", Sys_Milliseconds(), soundSystemLocal.GetCurrent44kHzTime(), sampleOffset44k, sampleCount44k ); //!@#
  222. // negative offset times will just zero fill
  223. if ( sampleOffset44k < 0 ) {
  224. len = -sampleOffset44k;
  225. if ( len > sampleCount44k ) {
  226. len = sampleCount44k;
  227. }
  228. memset( dest_p, 0, len * sizeof( dest_p[0] ) );
  229. dest_p += len;
  230. sampleCount44k -= len;
  231. sampleOffset44k += len;
  232. }
  233. // grab part of the leadin sample
  234. idSoundSample *leadin = leadinSample;
  235. if ( !leadin || sampleOffset44k < 0 || sampleCount44k <= 0 ) {
  236. memset( dest_p, 0, sampleCount44k * sizeof( dest_p[0] ) );
  237. return;
  238. }
  239. if ( sampleOffset44k < leadin->LengthIn44kHzSamples() ) {
  240. len = leadin->LengthIn44kHzSamples() - sampleOffset44k;
  241. if ( len > sampleCount44k ) {
  242. len = sampleCount44k;
  243. }
  244. // decode the sample
  245. decoder->Decode( leadin, sampleOffset44k, len, dest_p );
  246. dest_p += len;
  247. sampleCount44k -= len;
  248. sampleOffset44k += len;
  249. }
  250. // if not looping, zero fill any remaining spots
  251. if ( !soundShader || !( parms.soundShaderFlags & SSF_LOOPING ) ) {
  252. memset( dest_p, 0, sampleCount44k * sizeof( dest_p[0] ) );
  253. return;
  254. }
  255. // fill the remainder with looped samples
  256. idSoundSample *loop = soundShader->entries[0];
  257. if ( !loop ) {
  258. memset( dest_p, 0, sampleCount44k * sizeof( dest_p[0] ) );
  259. return;
  260. }
  261. sampleOffset44k -= leadin->LengthIn44kHzSamples();
  262. while( sampleCount44k > 0 ) {
  263. int totalLen = loop->LengthIn44kHzSamples();
  264. sampleOffset44k %= totalLen;
  265. len = totalLen - sampleOffset44k;
  266. if ( len > sampleCount44k ) {
  267. len = sampleCount44k;
  268. }
  269. // decode the sample
  270. decoder->Decode( loop, sampleOffset44k, len, dest_p );
  271. dest_p += len;
  272. sampleCount44k -= len;
  273. sampleOffset44k += len;
  274. }
  275. }
  276. //=====================================================================================
  277. /*
  278. ===============
  279. idSoundEmitterLocal::idSoundEmitterLocal
  280. ===============
  281. */
  282. idSoundEmitterLocal::idSoundEmitterLocal( void ) {
  283. soundWorld = NULL;
  284. Clear();
  285. }
  286. /*
  287. ===============
  288. idSoundEmitterLocal::~idSoundEmitterLocal
  289. ===============
  290. */
  291. idSoundEmitterLocal::~idSoundEmitterLocal( void ) {
  292. Clear();
  293. }
  294. /*
  295. ===============
  296. idSoundEmitterLocal::Clear
  297. ===============
  298. */
  299. void idSoundEmitterLocal::Clear( void ) {
  300. int i;
  301. for( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  302. channels[i].ALStop();
  303. channels[i].Clear();
  304. }
  305. removeStatus = REMOVE_STATUS_SAMPLEFINISHED;
  306. distance = 0.0f;
  307. lastValidPortalArea = -1;
  308. playing = false;
  309. hasShakes = false;
  310. ampTime = 0; // last time someone queried
  311. amplitude = 0;
  312. maxDistance = 10.0f; // meters
  313. spatializedOrigin.Zero();
  314. memset( &parms, 0, sizeof( parms ) );
  315. }
  316. /*
  317. ==================
  318. idSoundEmitterLocal::OverrideParms
  319. ==================
  320. */
  321. void idSoundEmitterLocal::OverrideParms( const soundShaderParms_t *base,
  322. const soundShaderParms_t *over, soundShaderParms_t *out ) {
  323. if ( !over ) {
  324. *out = *base;
  325. return;
  326. }
  327. if ( over->minDistance ) {
  328. out->minDistance = over->minDistance;
  329. } else {
  330. out->minDistance = base->minDistance;
  331. }
  332. if ( over->maxDistance ) {
  333. out->maxDistance = over->maxDistance;
  334. } else {
  335. out->maxDistance = base->maxDistance;
  336. }
  337. if ( over->shakes ) {
  338. out->shakes = over->shakes;
  339. } else {
  340. out->shakes = base->shakes;
  341. }
  342. if ( over->volume ) {
  343. out->volume = over->volume;
  344. } else {
  345. out->volume = base->volume;
  346. }
  347. if ( over->soundClass ) {
  348. out->soundClass = over->soundClass;
  349. } else {
  350. out->soundClass = base->soundClass;
  351. }
  352. out->soundShaderFlags = base->soundShaderFlags | over->soundShaderFlags;
  353. }
  354. /*
  355. ==================
  356. idSoundEmitterLocal::CheckForCompletion
  357. Checks to see if all the channels have completed, clearing the playing flag if necessary.
  358. Sets the playing and shakes bools.
  359. ==================
  360. */
  361. void idSoundEmitterLocal::CheckForCompletion( int current44kHzTime ) {
  362. bool hasActive;
  363. int i;
  364. hasActive = false;
  365. hasShakes = false;
  366. if ( playing ) {
  367. for ( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  368. idSoundChannel *chan = &channels[i];
  369. if ( !chan->triggerState ) {
  370. continue;
  371. }
  372. const idSoundShader *shader = chan->soundShader;
  373. if ( !shader ) {
  374. continue;
  375. }
  376. // see if this channel has completed
  377. if ( !( chan->parms.soundShaderFlags & SSF_LOOPING ) ) {
  378. ALint state = AL_PLAYING;
  379. if ( idSoundSystemLocal::useOpenAL && alIsSource( chan->openalSource ) ) {
  380. alGetSourcei( chan->openalSource, AL_SOURCE_STATE, &state );
  381. }
  382. idSlowChannel slow = GetSlowChannel( chan );
  383. if ( soundWorld->slowmoActive && slow.IsActive() ) {
  384. if ( slow.GetCurrentPosition().time >= chan->leadinSample->LengthIn44kHzSamples() / 2 ) {
  385. chan->Stop();
  386. // if this was an onDemand sound, purge the sample now
  387. if ( chan->leadinSample->onDemand ) {
  388. chan->leadinSample->PurgeSoundSample();
  389. }
  390. continue;
  391. }
  392. } else if ( ( chan->trigger44kHzTime + chan->leadinSample->LengthIn44kHzSamples() < current44kHzTime ) || ( state == AL_STOPPED ) ) {
  393. chan->Stop();
  394. // free hardware resources
  395. chan->ALStop();
  396. // if this was an onDemand sound, purge the sample now
  397. if ( chan->leadinSample->onDemand ) {
  398. chan->leadinSample->PurgeSoundSample();
  399. }
  400. continue;
  401. }
  402. }
  403. // free decoder memory if no sound was decoded for a while
  404. if ( chan->decoder != NULL && chan->decoder->GetLastDecodeTime() < current44kHzTime - SOUND_DECODER_FREE_DELAY ) {
  405. chan->decoder->ClearDecoder();
  406. }
  407. hasActive = true;
  408. if ( chan->parms.shakes > 0.0f ) {
  409. hasShakes = true;
  410. }
  411. }
  412. }
  413. // mark the entire sound emitter as non-playing if there aren't any active channels
  414. if ( !hasActive ) {
  415. playing = false;
  416. if ( removeStatus == REMOVE_STATUS_WAITSAMPLEFINISHED ) {
  417. // this can now be reused by the next request for a new soundEmitter
  418. removeStatus = REMOVE_STATUS_SAMPLEFINISHED;
  419. }
  420. }
  421. }
  422. /*
  423. ===================
  424. idSoundEmitterLocal::Spatialize
  425. Called once each sound frame by the main thread from idSoundWorldLocal::PlaceOrigin
  426. ===================
  427. */
  428. void idSoundEmitterLocal::Spatialize( idVec3 listenerPos, int listenerArea, idRenderWorld *rw ) {
  429. int i;
  430. bool hasActive = false;
  431. //
  432. // work out the maximum distance of all the playing channels
  433. //
  434. maxDistance = 0;
  435. for ( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  436. idSoundChannel *chan = &channels[i];
  437. if ( !chan->triggerState ) {
  438. continue;
  439. }
  440. if ( chan->parms.maxDistance > maxDistance ) {
  441. maxDistance = chan->parms.maxDistance;
  442. }
  443. }
  444. //
  445. // work out where the sound comes from
  446. //
  447. idVec3 realOrigin = origin * DOOM_TO_METERS;
  448. idVec3 len = listenerPos - realOrigin;
  449. realDistance = len.LengthFast();
  450. if ( realDistance >= maxDistance ) {
  451. // no way to possibly hear it
  452. distance = realDistance;
  453. return;
  454. }
  455. //
  456. // work out virtual origin and distance, which may be from a portal instead of the actual origin
  457. //
  458. distance = maxDistance * METERS_TO_DOOM;
  459. if ( listenerArea == -1 ) { // listener is outside the world
  460. return;
  461. }
  462. if ( rw ) {
  463. // we have a valid renderWorld
  464. int soundInArea = rw->PointInArea( origin );
  465. if ( soundInArea == -1 ) {
  466. if ( lastValidPortalArea == -1 ) { // sound is outside the world
  467. distance = realDistance;
  468. spatializedOrigin = origin; // sound is in our area
  469. return;
  470. }
  471. soundInArea = lastValidPortalArea;
  472. }
  473. lastValidPortalArea = soundInArea;
  474. if ( soundInArea == listenerArea ) {
  475. distance = realDistance;
  476. spatializedOrigin = origin; // sound is in our area
  477. return;
  478. }
  479. soundWorld->ResolveOrigin( 0, NULL, soundInArea, 0.0f, origin, this );
  480. distance /= METERS_TO_DOOM;
  481. } else {
  482. // no portals available
  483. distance = realDistance;
  484. spatializedOrigin = origin; // sound is in our area
  485. }
  486. }
  487. /*
  488. ===========================================================================================
  489. PUBLIC FUNCTIONS
  490. ===========================================================================================
  491. */
  492. /*
  493. =====================
  494. idSoundEmitterLocal::UpdateEmitter
  495. =====================
  496. */
  497. void idSoundEmitterLocal::UpdateEmitter( const idVec3 &origin, int listenerId, const soundShaderParms_t *parms ) {
  498. if ( !parms ) {
  499. common->Error( "idSoundEmitterLocal::UpdateEmitter: NULL parms" );
  500. }
  501. if ( soundWorld && soundWorld->writeDemo ) {
  502. soundWorld->writeDemo->WriteInt( DS_SOUND );
  503. soundWorld->writeDemo->WriteInt( SCMD_UPDATE );
  504. soundWorld->writeDemo->WriteInt( index );
  505. soundWorld->writeDemo->WriteVec3( origin );
  506. soundWorld->writeDemo->WriteInt( listenerId );
  507. soundWorld->writeDemo->WriteFloat( parms->minDistance );
  508. soundWorld->writeDemo->WriteFloat( parms->maxDistance );
  509. soundWorld->writeDemo->WriteFloat( parms->volume );
  510. soundWorld->writeDemo->WriteFloat( parms->shakes );
  511. soundWorld->writeDemo->WriteInt( parms->soundShaderFlags );
  512. soundWorld->writeDemo->WriteInt( parms->soundClass );
  513. }
  514. this->origin = origin;
  515. this->listenerId = listenerId;
  516. this->parms = *parms;
  517. // FIXME: change values on all channels?
  518. }
  519. /*
  520. =====================
  521. idSoundEmitterLocal::Free
  522. They are never truly freed, just marked so they can be reused by the soundWorld
  523. =====================
  524. */
  525. void idSoundEmitterLocal::Free( bool immediate ) {
  526. if ( removeStatus != REMOVE_STATUS_ALIVE ) {
  527. return;
  528. }
  529. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  530. common->Printf( "FreeSound (%i,%i)\n", index, (int)immediate );
  531. }
  532. if ( soundWorld && soundWorld->writeDemo ) {
  533. soundWorld->writeDemo->WriteInt( DS_SOUND );
  534. soundWorld->writeDemo->WriteInt( SCMD_FREE );
  535. soundWorld->writeDemo->WriteInt( index );
  536. soundWorld->writeDemo->WriteInt( immediate );
  537. }
  538. if ( !immediate ) {
  539. removeStatus = REMOVE_STATUS_WAITSAMPLEFINISHED;
  540. } else {
  541. Clear();
  542. }
  543. }
  544. /*
  545. =====================
  546. idSoundEmitterLocal::StartSound
  547. returns the length of the started sound in msec
  548. =====================
  549. */
  550. int idSoundEmitterLocal::StartSound( const idSoundShader *shader, const s_channelType channel, float diversity, int soundShaderFlags, bool allowSlow ) {
  551. int i;
  552. if ( !shader ) {
  553. return 0;
  554. }
  555. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  556. common->Printf( "StartSound %ims (%i,%i,%s) = ", soundWorld->gameMsec, index, (int)channel, shader->GetName() );
  557. }
  558. if ( soundWorld && soundWorld->writeDemo ) {
  559. soundWorld->writeDemo->WriteInt( DS_SOUND );
  560. soundWorld->writeDemo->WriteInt( SCMD_START );
  561. soundWorld->writeDemo->WriteInt( index );
  562. soundWorld->writeDemo->WriteHashString( shader->GetName() );
  563. soundWorld->writeDemo->WriteInt( channel );
  564. soundWorld->writeDemo->WriteFloat( diversity );
  565. soundWorld->writeDemo->WriteInt( soundShaderFlags );
  566. }
  567. // build the channel parameters by taking the shader parms and optionally overriding
  568. soundShaderParms_t chanParms;
  569. chanParms = shader->parms;
  570. OverrideParms( &chanParms, &this->parms, &chanParms );
  571. chanParms.soundShaderFlags |= soundShaderFlags;
  572. if ( chanParms.shakes > 0.0f ) {
  573. shader->CheckShakesAndOgg();
  574. }
  575. // this is the sample time it will be first mixed
  576. int start44kHz;
  577. if ( soundWorld->fpa[0] ) {
  578. // if we are recording an AVI demo, don't use hardware time
  579. start44kHz = soundWorld->lastAVI44kHz + MIXBUFFER_SAMPLES;
  580. } else {
  581. start44kHz = soundSystemLocal.GetCurrent44kHzTime() + MIXBUFFER_SAMPLES;
  582. }
  583. //
  584. // pick which sound to play from the shader
  585. //
  586. if ( !shader->numEntries ) {
  587. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  588. common->Printf( "no samples in sound shader\n" );
  589. }
  590. return 0; // no sounds
  591. }
  592. int choice;
  593. // pick a sound from the list based on the passed diversity
  594. choice = (int)(diversity * shader->numEntries);
  595. if ( choice < 0 || choice >= shader->numEntries ) {
  596. choice = 0;
  597. }
  598. // bump the choice if the exact sound was just played and we are NO_DUPS
  599. if ( chanParms.soundShaderFlags & SSF_NO_DUPS ) {
  600. idSoundSample *sample;
  601. if ( shader->leadins[ choice ] ) {
  602. sample = shader->leadins[ choice ];
  603. } else {
  604. sample = shader->entries[ choice ];
  605. }
  606. for( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  607. idSoundChannel *chan = &channels[i];
  608. if ( chan->leadinSample == sample ) {
  609. choice = ( choice + 1 ) % shader->numEntries;
  610. break;
  611. }
  612. }
  613. }
  614. // PLAY_ONCE sounds will never be restarted while they are running
  615. if ( chanParms.soundShaderFlags & SSF_PLAY_ONCE ) {
  616. for( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  617. idSoundChannel *chan = &channels[i];
  618. if ( chan->triggerState && chan->soundShader == shader ) {
  619. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  620. common->Printf( "PLAY_ONCE not restarting\n" );
  621. }
  622. return 0;
  623. }
  624. }
  625. }
  626. // never play the same sound twice with the same starting time, even
  627. // if they are on different channels
  628. for( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  629. idSoundChannel *chan = &channels[i];
  630. if ( chan->triggerState && chan->soundShader == shader && chan->trigger44kHzTime == start44kHz ) {
  631. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  632. common->Printf( "already started this frame\n" );
  633. }
  634. return 0;
  635. }
  636. }
  637. Sys_EnterCriticalSection();
  638. // kill any sound that is currently playing on this channel
  639. if ( channel != SCHANNEL_ANY ) {
  640. for( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  641. idSoundChannel *chan = &channels[i];
  642. if ( chan->triggerState && chan->soundShader && chan->triggerChannel == channel ) {
  643. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  644. common->Printf( "(override %s)", chan->soundShader->base->GetName() );
  645. }
  646. chan->Stop();
  647. // if this was an onDemand sound, purge the sample now
  648. if ( chan->leadinSample->onDemand ) {
  649. chan->ALStop();
  650. chan->leadinSample->PurgeSoundSample();
  651. }
  652. break;
  653. }
  654. }
  655. }
  656. // find a free channel to play the sound on
  657. idSoundChannel *chan;
  658. for( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  659. chan = &channels[i];
  660. if ( !chan->triggerState ) {
  661. break;
  662. }
  663. }
  664. if ( i == SOUND_MAX_CHANNELS ) {
  665. // we couldn't find a channel for it
  666. Sys_LeaveCriticalSection();
  667. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  668. common->Printf( "no channels available\n" );
  669. }
  670. return 0;
  671. }
  672. chan = &channels[i];
  673. if ( shader->leadins[ choice ] ) {
  674. chan->leadinSample = shader->leadins[ choice ];
  675. } else {
  676. chan->leadinSample = shader->entries[ choice ];
  677. }
  678. // if the sample is onDemand (voice mails, etc), load it now
  679. if ( chan->leadinSample->purged ) {
  680. int start = Sys_Milliseconds();
  681. chan->leadinSample->Load();
  682. int end = Sys_Milliseconds();
  683. session->TimeHitch( end - start );
  684. // recalculate start44kHz, because loading may have taken a fair amount of time
  685. if ( !soundWorld->fpa[0] ) {
  686. start44kHz = soundSystemLocal.GetCurrent44kHzTime() + MIXBUFFER_SAMPLES;
  687. }
  688. }
  689. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  690. common->Printf( "'%s'\n", chan->leadinSample->name.c_str() );
  691. }
  692. if ( idSoundSystemLocal::s_skipHelltimeFX.GetBool() ) {
  693. chan->disallowSlow = true;
  694. } else {
  695. chan->disallowSlow = !allowSlow;
  696. }
  697. ResetSlowChannel( chan );
  698. // the sound will start mixing in the next async mix block
  699. chan->triggered = true;
  700. chan->openalStreamingOffset = 0;
  701. chan->trigger44kHzTime = start44kHz;
  702. chan->parms = chanParms;
  703. chan->triggerGame44kHzTime = soundWorld->game44kHz;
  704. chan->soundShader = shader;
  705. chan->triggerChannel = channel;
  706. chan->Start();
  707. // we need to start updating the def and mixing it in
  708. playing = true;
  709. // spatialize it immediately, so it will start the next mix block
  710. // even if that happens before the next PlaceOrigin()
  711. Spatialize( soundWorld->listenerPos, soundWorld->listenerArea, soundWorld->rw );
  712. // return length of sound in milliseconds
  713. int length = chan->leadinSample->LengthIn44kHzSamples();
  714. if ( chan->leadinSample->objectInfo.nChannels == 2 ) {
  715. length /= 2; // stereo samples
  716. }
  717. // adjust the start time based on diversity for looping sounds, so they don't all start
  718. // at the same point
  719. if ( chan->parms.soundShaderFlags & SSF_LOOPING && !chan->leadinSample->LengthIn44kHzSamples() ) {
  720. chan->trigger44kHzTime -= diversity * length;
  721. chan->trigger44kHzTime &= ~7; // so we don't have to worry about the 22kHz and 11kHz expansions
  722. // starting in fractional samples
  723. chan->triggerGame44kHzTime -= diversity * length;
  724. chan->triggerGame44kHzTime &= ~7;
  725. }
  726. length *= 1000 / (float)PRIMARYFREQ;
  727. Sys_LeaveCriticalSection();
  728. return length;
  729. }
  730. /*
  731. ===================
  732. idSoundEmitterLocal::ModifySound
  733. ===================
  734. */
  735. void idSoundEmitterLocal::ModifySound( const s_channelType channel, const soundShaderParms_t *parms ) {
  736. if ( !parms ) {
  737. common->Error( "idSoundEmitterLocal::ModifySound: NULL parms" );
  738. }
  739. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  740. common->Printf( "ModifySound(%i,%i)\n", index, channel );
  741. }
  742. if ( soundWorld && soundWorld->writeDemo ) {
  743. soundWorld->writeDemo->WriteInt( DS_SOUND );
  744. soundWorld->writeDemo->WriteInt( SCMD_MODIFY );
  745. soundWorld->writeDemo->WriteInt( index );
  746. soundWorld->writeDemo->WriteInt( channel );
  747. soundWorld->writeDemo->WriteFloat( parms->minDistance );
  748. soundWorld->writeDemo->WriteFloat( parms->maxDistance );
  749. soundWorld->writeDemo->WriteFloat( parms->volume );
  750. soundWorld->writeDemo->WriteFloat( parms->shakes );
  751. soundWorld->writeDemo->WriteInt( parms->soundShaderFlags );
  752. soundWorld->writeDemo->WriteInt( parms->soundClass );
  753. }
  754. for ( int i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  755. idSoundChannel *chan = &channels[i];
  756. if ( !chan->triggerState ) {
  757. continue;
  758. }
  759. if ( channel != SCHANNEL_ANY && chan->triggerChannel != channel ) {
  760. continue;
  761. }
  762. OverrideParms( &chan->parms, parms, &chan->parms );
  763. if ( chan->parms.shakes > 0.0f && chan->soundShader != NULL ) {
  764. chan->soundShader->CheckShakesAndOgg();
  765. }
  766. }
  767. }
  768. /*
  769. ===================
  770. idSoundEmitterLocal::StopSound
  771. can pass SCHANNEL_ANY
  772. ===================
  773. */
  774. void idSoundEmitterLocal::StopSound( const s_channelType channel ) {
  775. int i;
  776. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  777. common->Printf( "StopSound(%i,%i)\n", index, channel );
  778. }
  779. if ( soundWorld && soundWorld->writeDemo ) {
  780. soundWorld->writeDemo->WriteInt( DS_SOUND );
  781. soundWorld->writeDemo->WriteInt( SCMD_STOP );
  782. soundWorld->writeDemo->WriteInt( index );
  783. soundWorld->writeDemo->WriteInt( channel );
  784. }
  785. Sys_EnterCriticalSection();
  786. for( i = 0; i < SOUND_MAX_CHANNELS; i++ ) {
  787. idSoundChannel *chan = &channels[i];
  788. if ( !chan->triggerState ) {
  789. continue;
  790. }
  791. if ( channel != SCHANNEL_ANY && chan->triggerChannel != channel ) {
  792. continue;
  793. }
  794. // stop it
  795. chan->Stop();
  796. // free hardware resources
  797. chan->ALStop();
  798. // if this was an onDemand sound, purge the sample now
  799. if ( chan->leadinSample->onDemand ) {
  800. chan->leadinSample->PurgeSoundSample();
  801. }
  802. chan->leadinSample = NULL;
  803. chan->soundShader = NULL;
  804. }
  805. Sys_LeaveCriticalSection();
  806. }
  807. /*
  808. ===================
  809. idSoundEmitterLocal::FadeSound
  810. to is in Db (sigh), over is in seconds
  811. ===================
  812. */
  813. void idSoundEmitterLocal::FadeSound( const s_channelType channel, float to, float over ) {
  814. if ( idSoundSystemLocal::s_showStartSound.GetInteger() ) {
  815. common->Printf( "FadeSound(%i,%i,%f,%f )\n", index, channel, to, over );
  816. }
  817. if ( !soundWorld ) {
  818. return;
  819. }
  820. if ( soundWorld->writeDemo ) {
  821. soundWorld->writeDemo->WriteInt( DS_SOUND );
  822. soundWorld->writeDemo->WriteInt( SCMD_FADE );
  823. soundWorld->writeDemo->WriteInt( index );
  824. soundWorld->writeDemo->WriteInt( channel );
  825. soundWorld->writeDemo->WriteFloat( to );
  826. soundWorld->writeDemo->WriteFloat( over );
  827. }
  828. int start44kHz;
  829. if ( soundWorld->fpa[0] ) {
  830. // if we are recording an AVI demo, don't use hardware time
  831. start44kHz = soundWorld->lastAVI44kHz + MIXBUFFER_SAMPLES;
  832. } else {
  833. start44kHz = soundSystemLocal.GetCurrent44kHzTime() + MIXBUFFER_SAMPLES;
  834. }
  835. int length44kHz = soundSystemLocal.MillisecondsToSamples( over * 1000 );
  836. for( int i = 0; i < SOUND_MAX_CHANNELS ; i++ ) {
  837. idSoundChannel *chan = &channels[i];
  838. if ( !chan->triggerState ) {
  839. continue;
  840. }
  841. if ( channel != SCHANNEL_ANY && chan->triggerChannel != channel ) {
  842. continue;
  843. }
  844. // if it is already fading to this volume at this rate, don't change it
  845. if ( chan->channelFade.fadeEndVolume == to &&
  846. chan->channelFade.fadeEnd44kHz - chan->channelFade.fadeStart44kHz == length44kHz ) {
  847. continue;
  848. }
  849. // fade it
  850. chan->channelFade.fadeStartVolume = chan->channelFade.FadeDbAt44kHz( start44kHz );
  851. chan->channelFade.fadeStart44kHz = start44kHz;
  852. chan->channelFade.fadeEnd44kHz = start44kHz + length44kHz;
  853. chan->channelFade.fadeEndVolume = to;
  854. }
  855. }
  856. /*
  857. ===================
  858. idSoundEmitterLocal::CurrentlyPlaying
  859. ===================
  860. */
  861. bool idSoundEmitterLocal::CurrentlyPlaying( void ) const {
  862. return playing;
  863. }
  864. /*
  865. ===================
  866. idSoundEmitterLocal::Index
  867. ===================
  868. */
  869. int idSoundEmitterLocal::Index( void ) const {
  870. return index;
  871. }
  872. /*
  873. ===================
  874. idSoundEmitterLocal::CurrentAmplitude
  875. this is called from the main thread by the material shader system
  876. to allow lights and surface flares to vary with the sound amplitude
  877. ===================
  878. */
  879. float idSoundEmitterLocal::CurrentAmplitude( void ) {
  880. if ( idSoundSystemLocal::s_constantAmplitude.GetFloat() >= 0.0f ) {
  881. return idSoundSystemLocal::s_constantAmplitude.GetFloat();
  882. }
  883. if ( removeStatus > REMOVE_STATUS_WAITSAMPLEFINISHED ) {
  884. return 0.0;
  885. }
  886. int localTime = soundSystemLocal.GetCurrent44kHzTime();
  887. // see if we can use our cached value
  888. if ( ampTime == localTime ) {
  889. return amplitude;
  890. }
  891. // calculate a new value
  892. ampTime = localTime;
  893. amplitude = soundWorld->FindAmplitude( this, localTime, NULL, SCHANNEL_ANY, false );
  894. return amplitude;
  895. }
  896. /*
  897. ===================
  898. idSoundEmitterLocal::GetSlowChannel
  899. ===================
  900. */
  901. idSlowChannel idSoundEmitterLocal::GetSlowChannel( const idSoundChannel *chan ) {
  902. return slowChannels[chan - channels];
  903. }
  904. /*
  905. ===================
  906. idSoundEmitterLocal::SetSlowChannel
  907. ===================
  908. */
  909. void idSoundEmitterLocal::SetSlowChannel( const idSoundChannel *chan, idSlowChannel slow ) {
  910. slowChannels[chan - channels] = slow;
  911. }
  912. /*
  913. ===================
  914. idSoundEmitterLocal::ResetSlowChannel
  915. ===================
  916. */
  917. void idSoundEmitterLocal::ResetSlowChannel( const idSoundChannel *chan ) {
  918. int index = chan - channels;
  919. slowChannels[index].Reset();
  920. }
  921. /*
  922. ===================
  923. idSlowChannel::Reset
  924. ===================
  925. */
  926. void idSlowChannel::Reset() {
  927. memset( this, 0, sizeof( *this ) );
  928. this->chan = chan;
  929. curPosition.Set( 0 );
  930. newPosition.Set( 0 );
  931. curSampleOffset = -10000;
  932. newSampleOffset = -10000;
  933. triggerOffset = 0;
  934. }
  935. /*
  936. ===================
  937. idSlowChannel::AttachSoundChannel
  938. ===================
  939. */
  940. void idSlowChannel::AttachSoundChannel( const idSoundChannel *chan ) {
  941. this->chan = chan;
  942. }
  943. /*
  944. ===================
  945. idSlowChannel::GetSlowmoSpeed
  946. ===================
  947. */
  948. float idSlowChannel::GetSlowmoSpeed() {
  949. idSoundWorldLocal *sw = static_cast<idSoundWorldLocal*>( soundSystemLocal.GetPlayingSoundWorld() );
  950. if ( sw ) {
  951. return sw->slowmoSpeed;
  952. } else {
  953. return 0;
  954. }
  955. }
  956. /*
  957. ===================
  958. idSlowChannel::GenerateSlowChannel
  959. ===================
  960. */
  961. void idSlowChannel::GenerateSlowChannel( FracTime& playPos, int sampleCount44k, float* finalBuffer ) {
  962. idSoundWorldLocal *sw = static_cast<idSoundWorldLocal*>( soundSystemLocal.GetPlayingSoundWorld() );
  963. float in[MIXBUFFER_SAMPLES+3], out[MIXBUFFER_SAMPLES+3], *src, *spline, slowmoSpeed;
  964. int i, neededSamples, orgTime, zeroedPos, count = 0;
  965. src = in + 2;
  966. spline = out + 2;
  967. if ( sw ) {
  968. slowmoSpeed = sw->slowmoSpeed;
  969. }
  970. else {
  971. slowmoSpeed = 1;
  972. }
  973. neededSamples = sampleCount44k * slowmoSpeed + 4;
  974. orgTime = playPos.time;
  975. // get the channel's samples
  976. chan->GatherChannelSamples( playPos.time * 2, neededSamples, src );
  977. for ( i = 0; i < neededSamples >> 1; i++ ) {
  978. spline[i] = src[i*2];
  979. }
  980. // interpolate channel
  981. zeroedPos = playPos.time;
  982. playPos.time = 0;
  983. for ( i = 0; i < sampleCount44k >> 1; i++, count += 2 ) {
  984. float val;
  985. val = spline[playPos.time];
  986. src[i] = val;
  987. playPos.Increment( slowmoSpeed );
  988. }
  989. // lowpass filter
  990. float *in_p = in + 2, *out_p = out + 2;
  991. int numSamples = sampleCount44k >> 1;
  992. lowpass.GetContinuitySamples( in_p[-1], in_p[-2], out_p[-1], out_p[-2] );
  993. lowpass.SetParms( slowmoSpeed * 15000, 1.2f );
  994. for ( int i = 0, count = 0; i < numSamples; i++, count += 2 ) {
  995. lowpass.ProcessSample( in_p + i, out_p + i );
  996. finalBuffer[count] = finalBuffer[count+1] = out[i];
  997. }
  998. lowpass.SetContinuitySamples( in_p[numSamples-2], in_p[numSamples-3], out_p[numSamples-2], out_p[numSamples-3] );
  999. playPos.time += zeroedPos;
  1000. }
  1001. /*
  1002. ===================
  1003. idSlowChannel::GatherChannelSamples
  1004. ===================
  1005. */
  1006. void idSlowChannel::GatherChannelSamples( int sampleOffset44k, int sampleCount44k, float *dest ) {
  1007. int state = 0;
  1008. // setup chan
  1009. active = true;
  1010. newSampleOffset = sampleOffset44k >> 1;
  1011. // set state
  1012. if ( newSampleOffset < curSampleOffset ) {
  1013. state = PLAYBACK_RESET;
  1014. } else if ( newSampleOffset > curSampleOffset ) {
  1015. state = PLAYBACK_ADVANCING;
  1016. }
  1017. if ( state == PLAYBACK_RESET ) {
  1018. curPosition.Set( newSampleOffset );
  1019. }
  1020. // set current vars
  1021. curSampleOffset = newSampleOffset;
  1022. newPosition = curPosition;
  1023. // do the slow processing
  1024. GenerateSlowChannel( newPosition, sampleCount44k, dest );
  1025. // finish off
  1026. if ( state == PLAYBACK_ADVANCING )
  1027. curPosition = newPosition;
  1028. }