s_sound.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition 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 BFG Edition 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 "Precompiled.h"
  21. #include "globaldata.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include "i_system.h"
  25. #include "i_sound.h"
  26. #include "sounds.h"
  27. #include "s_sound.h"
  28. #include "z_zone.h"
  29. #include "m_random.h"
  30. #include "w_wad.h"
  31. #include "doomdef.h"
  32. #include "p_local.h"
  33. #include "doomstat.h"
  34. #include "Main.h"
  35. // Purpose?
  36. const char snd_prefixen[]
  37. = { 'P', 'P', 'A', 'S', 'S', 'S', 'M', 'M', 'M', 'S', 'S', 'S' };
  38. // when to clip out sounds
  39. // Does not fit the large outdoor areas.
  40. // Distance tp origin when sounds should be maxed out.
  41. // This should relate to movement clipping resolution
  42. // (see BLOCKMAP handling).
  43. // Originally: (200*0x10000).
  44. // Adjustable by menu.
  45. // percent attenuation from front to back
  46. // Current music/sfx card - index useless
  47. // w/o a reference LUT in a sound module.
  48. // Config file? Same disclaimer as above.
  49. // the set of ::g->channels available
  50. // These are not used, but should be (menu).
  51. // Maximum volume of a sound effect.
  52. // Internal default is max out of 0-15.
  53. // Maximum volume of music. Useless so far.
  54. // whether songs are ::g->mus_paused
  55. // music currently being played
  56. // following is set
  57. // by the defaults code in M_misc:
  58. // number of ::g->channels available
  59. //
  60. // Internals.
  61. //
  62. int
  63. S_getChannel
  64. ( void* origin,
  65. sfxinfo_t* sfxinfo );
  66. int
  67. S_AdjustSoundParams
  68. ( mobj_t* listener,
  69. mobj_t* source,
  70. int* vol,
  71. int* sep,
  72. int* pitch );
  73. void S_StopChannel(int cnum);
  74. //
  75. // Initializes sound stuff, including volume
  76. // Sets ::g->channels, SFX and music volume,
  77. // allocates channel buffer, sets S_sfx lookup.
  78. //
  79. void S_Init
  80. ( int sfxVolume,
  81. int musicVolume )
  82. {
  83. int i;
  84. // Whatever these did with DMX, these are rather dummies now.
  85. I_SetChannels();
  86. S_SetSfxVolume(sfxVolume);
  87. S_SetMusicVolume(musicVolume);
  88. // Allocating the internal ::g->channels for mixing
  89. // (the maximum numer of sounds rendered
  90. // simultaneously) within zone memory.
  91. ::g->channels =
  92. (channel_t *) DoomLib::Z_Malloc(::g->numChannels*sizeof(channel_t), PU_STATIC, 0);
  93. // Free all ::g->channels for use
  94. for (i=0 ; i < ::g->numChannels ; i++)
  95. ::g->channels[i].sfxinfo = 0;
  96. // no sounds are playing, and they are not ::g->mus_paused
  97. ::g->mus_paused = 0;
  98. ::g->mus_looping = 0;
  99. // Note that sounds have not been cached (yet).
  100. for (i=1 ; i<NUMSFX ; i++)
  101. S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
  102. }
  103. //
  104. // Per level startup code.
  105. // Kills playing sounds at start of level,
  106. // determines music if any, changes music.
  107. //
  108. void S_Start(void)
  109. {
  110. int cnum;
  111. int mnum;
  112. // kill all playing sounds at start of level
  113. // (trust me - a good idea)
  114. if( ::g->channels ) {
  115. for (cnum=0 ; cnum < ::g->numChannels ; cnum++)
  116. if (::g->channels[cnum].sfxinfo)
  117. S_StopChannel(cnum);
  118. }
  119. // start new music for the level
  120. ::g->mus_paused = 0;
  121. if (::g->gamemode == commercial) {
  122. mnum = mus_runnin + ::g->gamemap - 1;
  123. /*
  124. Is this necessary?
  125. if ( ::g->gamemission == 0 ) {
  126. mnum = mus_runnin + ::g->gamemap - 1;
  127. }
  128. else {
  129. mnum = mus_runnin + ( gameLocal->GetMissionData( ::g->gamemission )->mapMusic[ ::g->gamemap-1 ] - 1 );
  130. }
  131. */
  132. }
  133. else
  134. {
  135. int spmus[] = {
  136. // Song - Who? - Where?
  137. mus_e3m4, // American e4m1
  138. mus_e3m2, // Romero e4m2
  139. mus_e3m3, // Shawn e4m3
  140. mus_e1m5, // American e4m4
  141. mus_e2m7, // Tim e4m5
  142. mus_e2m4, // Romero e4m6
  143. mus_e2m6, // J.Anderson e4m7 CHIRON.WAD
  144. mus_e2m5, // Shawn e4m8
  145. mus_e1m9 // Tim e4m9
  146. };
  147. if (::g->gameepisode < 4)
  148. mnum = mus_e1m1 + (::g->gameepisode-1)*9 + ::g->gamemap-1;
  149. else
  150. mnum = spmus[::g->gamemap-1];
  151. }
  152. S_StopMusic();
  153. S_ChangeMusic(mnum, true);
  154. ::g->nextcleanup = 15;
  155. }
  156. void
  157. S_StartSoundAtVolume
  158. ( void* origin_p,
  159. int sfx_id,
  160. int volume )
  161. {
  162. int rc;
  163. int sep;
  164. int pitch;
  165. int priority;
  166. sfxinfo_t* sfx;
  167. int cnum;
  168. mobj_t* origin = (mobj_t *) origin_p;
  169. // Debug.
  170. /*I_PrintfE
  171. "S_StartSoundAtVolume: playing sound %d (%s)\n",
  172. sfx_id, S_sfx[sfx_id].name );*/
  173. // check for bogus sound #
  174. if (sfx_id < 1 || sfx_id > NUMSFX)
  175. I_Error("Bad sfx #: %d", sfx_id);
  176. sfx = &S_sfx[sfx_id];
  177. // Initialize sound parameters
  178. if (sfx->link)
  179. {
  180. pitch = sfx->pitch;
  181. priority = sfx->priority;
  182. volume += sfx->volume;
  183. if (volume < 1)
  184. return;
  185. if ( volume > s_volume_sound.GetInteger() )
  186. volume = s_volume_sound.GetInteger();
  187. }
  188. else
  189. {
  190. pitch = NORM_PITCH;
  191. priority = NORM_PRIORITY;
  192. if (volume < 1)
  193. return;
  194. if ( volume > s_volume_sound.GetInteger() )
  195. volume = s_volume_sound.GetInteger();
  196. }
  197. // Check to see if it is audible,
  198. // and if not, modify the params
  199. // DHM - Nerve :: chainsaw!!!
  200. if (origin && ::g->players[::g->consoleplayer].mo && origin != ::g->players[::g->consoleplayer].mo)
  201. {
  202. rc = S_AdjustSoundParams(::g->players[::g->consoleplayer].mo,
  203. origin,
  204. &volume,
  205. &sep,
  206. &pitch);
  207. if ( origin->x == ::g->players[::g->consoleplayer].mo->x
  208. && origin->y == ::g->players[::g->consoleplayer].mo->y)
  209. {
  210. sep = NORM_SEP;
  211. }
  212. if (!rc)
  213. return;
  214. }
  215. else
  216. {
  217. sep = NORM_SEP;
  218. }
  219. // hacks to vary the sfx pitches
  220. const bool isChainsawSound = sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit;
  221. if ( !isChainsawSound && sfx_id != sfx_itemup && sfx_id != sfx_tink)
  222. {
  223. pitch += 16 - (M_Random()&31);
  224. if (pitch<0)
  225. pitch = 0;
  226. else if (pitch>255)
  227. pitch = 255;
  228. }
  229. // kill old sound
  230. //S_StopSound(origin);
  231. // try to find a channel
  232. cnum = S_getChannel(origin, sfx);
  233. if (cnum<0) {
  234. printf( "No sound channels available for sfxid %d.\n", sfx_id );
  235. return;
  236. }
  237. // get lumpnum if necessary
  238. if (sfx->lumpnum < 0)
  239. sfx->lumpnum = I_GetSfxLumpNum(sfx);
  240. // increase the usefulness
  241. if (sfx->usefulness++ < 0)
  242. sfx->usefulness = 1;
  243. // Assigns the handle to one of the ::g->channels in the
  244. // mix/output buffer.
  245. ::g->channels[cnum].handle = I_StartSound(sfx_id, origin, ::g->players[::g->consoleplayer].mo, volume, pitch, priority);
  246. }
  247. void S_StartSound ( void* origin, int sfx_id )
  248. {
  249. S_StartSoundAtVolume(origin, sfx_id, s_volume_sound.GetInteger() );
  250. }
  251. void S_StopSound(void *origin)
  252. {
  253. int cnum;
  254. for (cnum=0 ; cnum < ::g->numChannels ; cnum++)
  255. {
  256. if (::g->channels[cnum].sfxinfo && ::g->channels[cnum].origin == origin)
  257. {
  258. S_StopChannel(cnum);
  259. break;
  260. }
  261. }
  262. }
  263. //
  264. // Stop and resume music, during game PAUSE.
  265. //
  266. void S_PauseSound(void)
  267. {
  268. if (::g->mus_playing && !::g->mus_paused)
  269. {
  270. I_PauseSong(::g->mus_playing->handle);
  271. ::g->mus_paused = true;
  272. }
  273. }
  274. void S_ResumeSound(void)
  275. {
  276. if (::g->mus_playing && ::g->mus_paused)
  277. {
  278. I_ResumeSong(::g->mus_playing->handle);
  279. ::g->mus_paused = false;
  280. }
  281. }
  282. //
  283. // Updates music & sounds
  284. //
  285. void S_UpdateSounds(void* listener_p)
  286. {
  287. int audible;
  288. int cnum;
  289. int volume;
  290. int sep;
  291. int pitch;
  292. sfxinfo_t* sfx;
  293. channel_t* c;
  294. mobj_t* listener = (mobj_t*)listener_p;
  295. for (cnum=0 ; cnum < ::g->numChannels ; cnum++)
  296. {
  297. c = &::g->channels[cnum];
  298. sfx = c->sfxinfo;
  299. if(sfx)
  300. {
  301. if (I_SoundIsPlaying(c->handle))
  302. {
  303. // initialize parameters
  304. volume = s_volume_sound.GetInteger();
  305. pitch = NORM_PITCH;
  306. sep = NORM_SEP;
  307. if (sfx->link)
  308. {
  309. pitch = sfx->pitch;
  310. volume += sfx->volume;
  311. if (volume < 1) {
  312. S_StopChannel(cnum);
  313. continue;
  314. } else if ( volume > s_volume_sound.GetInteger() ) {
  315. volume = s_volume_sound.GetInteger();
  316. }
  317. }
  318. // check non-local sounds for distance clipping or modify their params
  319. if (c->origin && listener_p != c->origin)
  320. {
  321. audible = S_AdjustSoundParams(listener, (mobj_t*)c->origin, &volume, &sep, &pitch);
  322. if (!audible) {
  323. S_StopChannel(cnum);
  324. }
  325. }
  326. }
  327. else
  328. {
  329. // if channel is allocated but sound has stopped, free it
  330. S_StopChannel(cnum);
  331. }
  332. }
  333. }
  334. }
  335. void S_SetMusicVolume(int volume)
  336. {
  337. I_SetMusicVolume(volume);
  338. s_volume_midi.SetInteger( volume );
  339. }
  340. void S_SetSfxVolume(int volume)
  341. {
  342. I_SetSfxVolume(volume);
  343. s_volume_sound.SetInteger( volume );
  344. }
  345. //
  346. // Starts some music with the music id found in sounds.h.
  347. //
  348. void S_StartMusic(int m_id)
  349. {
  350. S_ChangeMusic(m_id, false);
  351. }
  352. void S_ChangeMusic ( int musicnum, int looping )
  353. {
  354. #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING
  355. if (gameLocal->IsSplitscreen() && DoomLib::GetPlayer() > 0 )
  356. {
  357. // we aren't the key player... we have no control over music
  358. return;
  359. }
  360. #endif
  361. musicinfo_t* music = NULL;
  362. if ( (musicnum <= mus_None)
  363. || (musicnum >= NUMMUSIC) )
  364. {
  365. I_Error("Bad music number %d", musicnum);
  366. }
  367. else
  368. music = &::g->S_music[musicnum];
  369. if (::g->mus_playing == music)
  370. return;
  371. //I_Printf("S_ChangeMusic: Playing new track: '%s'\n", music->name);
  372. I_PlaySong( music->name, looping );
  373. ::g->mus_playing = music;
  374. }
  375. void S_StopMusic(void)
  376. {
  377. if (::g->doomcom.consoleplayer)
  378. {
  379. // we aren't the key player... we have no control over music
  380. return;
  381. }
  382. if (::g->mus_playing)
  383. {
  384. if (::g->mus_paused)
  385. I_ResumeSong(::g->mus_playing->handle);
  386. I_StopSong(::g->mus_playing->handle);
  387. I_UnRegisterSong(::g->mus_playing->handle);
  388. //Z_FreeTags( PU_MUSIC_SHARED, PU_MUSIC_SHARED );
  389. ::g->mus_playing->data = 0;
  390. ::g->mus_playing = 0;
  391. }
  392. }
  393. void S_StopChannel(int cnum)
  394. {
  395. int i;
  396. channel_t* c = &::g->channels[cnum];
  397. if (c->sfxinfo)
  398. {
  399. // stop the sound playing
  400. if (I_SoundIsPlaying(c->handle))
  401. {
  402. #ifdef SAWDEBUG
  403. if (c->sfxinfo == &S_sfx[sfx_sawful])
  404. I_PrintfE( "stopped\n");
  405. #endif
  406. I_StopSound(c->handle);
  407. }
  408. // check to see
  409. // if other ::g->channels are playing the sound
  410. for (i=0 ; i < ::g->numChannels ; i++)
  411. {
  412. if (cnum != i
  413. && c->sfxinfo == ::g->channels[i].sfxinfo)
  414. {
  415. break;
  416. }
  417. }
  418. // degrade usefulness of sound data
  419. c->sfxinfo->usefulness--;
  420. c->sfxinfo = 0;
  421. }
  422. }
  423. //
  424. // Changes volume, stereo-separation, and pitch variables
  425. // from the norm of a sound effect to be played.
  426. // If the sound is not audible, returns a 0.
  427. // Otherwise, modifies parameters and returns 1.
  428. //
  429. int S_AdjustSoundParams( mobj_t* listener, mobj_t* source, int* vol, int* sep, int* pitch ) {
  430. fixed_t approx_dist;
  431. fixed_t adx;
  432. fixed_t ady;
  433. // DHM - Nerve :: Could happen in multiplayer if a player exited the level holding the chainsaw
  434. if ( listener == NULL || source == NULL ) {
  435. return 0;
  436. }
  437. // calculate the distance to sound origin
  438. // and clip it if necessary
  439. adx = abs(listener->x - source->x);
  440. ady = abs(listener->y - source->y);
  441. // From _GG1_ p.428. Appox. eucledian distance fast.
  442. approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
  443. if ( approx_dist > S_CLIPPING_DIST) {
  444. return 0;
  445. }
  446. // angle of source to listener
  447. *sep = NORM_SEP;
  448. // volume calculation
  449. if (approx_dist < S_CLOSE_DIST) {
  450. *vol = s_volume_sound.GetInteger();
  451. }
  452. else {
  453. // distance effect
  454. *vol = ( s_volume_sound.GetInteger()
  455. * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  456. / S_ATTENUATOR;
  457. }
  458. return (*vol > 0);
  459. }
  460. //
  461. // S_getChannel :
  462. // If none available, return -1. Otherwise channel #.
  463. //
  464. int
  465. S_getChannel
  466. ( void* origin,
  467. sfxinfo_t* sfxinfo )
  468. {
  469. // channel number to use
  470. int cnum;
  471. channel_t* c;
  472. // Find an open channel
  473. for (cnum=0 ; cnum < ::g->numChannels ; cnum++)
  474. {
  475. if (!::g->channels[cnum].sfxinfo)
  476. break;
  477. else if ( origin && ::g->channels[cnum].origin == origin &&
  478. (::g->channels[cnum].handle == sfx_sawidl || ::g->channels[cnum].handle == sfx_sawful) )
  479. {
  480. S_StopChannel(cnum);
  481. break;
  482. }
  483. }
  484. // None available
  485. if (cnum == ::g->numChannels)
  486. {
  487. // Look for lower priority
  488. for (cnum=0 ; cnum < ::g->numChannels ; cnum++)
  489. if (::g->channels[cnum].sfxinfo->priority >= sfxinfo->priority) break;
  490. if (cnum == ::g->numChannels)
  491. {
  492. // FUCK! No lower priority. Sorry, Charlie.
  493. return -1;
  494. }
  495. else
  496. {
  497. // Otherwise, kick out lower priority.
  498. S_StopChannel(cnum);
  499. }
  500. }
  501. c = &::g->channels[cnum];
  502. // channel is decided to be cnum.
  503. c->sfxinfo = sfxinfo;
  504. c->origin = origin;
  505. return cnum;
  506. }