s_sound.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. // Emacs style mode select -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION: none
  20. //
  21. //-----------------------------------------------------------------------------
  22. static const char
  23. rcsid[] = "$Id: s_sound.c,v 1.6 1997/02/03 22:45:12 b1 Exp $";
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include "i_system.h"
  27. #include "i_sound.h"
  28. #include "sounds.h"
  29. #include "s_sound.h"
  30. #include "z_zone.h"
  31. #include "m_random.h"
  32. #include "w_wad.h"
  33. #include "doomdef.h"
  34. #include "p_local.h"
  35. #include "doomstat.h"
  36. // Purpose?
  37. const char snd_prefixen[]
  38. = { 'P', 'P', 'A', 'S', 'S', 'S', 'M', 'M', 'M', 'S', 'S', 'S' };
  39. #define S_MAX_VOLUME 127
  40. // when to clip out sounds
  41. // Does not fit the large outdoor areas.
  42. #define S_CLIPPING_DIST (1200*0x10000)
  43. // Distance tp origin when sounds should be maxed out.
  44. // This should relate to movement clipping resolution
  45. // (see BLOCKMAP handling).
  46. // Originally: (200*0x10000).
  47. #define S_CLOSE_DIST (160*0x10000)
  48. #define S_ATTENUATOR ((S_CLIPPING_DIST-S_CLOSE_DIST)>>FRACBITS)
  49. // Adjustable by menu.
  50. #define NORM_VOLUME snd_MaxVolume
  51. #define NORM_PITCH 128
  52. #define NORM_PRIORITY 64
  53. #define NORM_SEP 128
  54. #define S_PITCH_PERTURB 1
  55. #define S_STEREO_SWING (96*0x10000)
  56. // percent attenuation from front to back
  57. #define S_IFRACVOL 30
  58. #define NA 0
  59. #define S_NUMCHANNELS 2
  60. // Current music/sfx card - index useless
  61. // w/o a reference LUT in a sound module.
  62. extern int snd_MusicDevice;
  63. extern int snd_SfxDevice;
  64. // Config file? Same disclaimer as above.
  65. extern int snd_DesiredMusicDevice;
  66. extern int snd_DesiredSfxDevice;
  67. typedef struct
  68. {
  69. // sound information (if null, channel avail.)
  70. sfxinfo_t* sfxinfo;
  71. // origin of sound
  72. void* origin;
  73. // handle of the sound being played
  74. int handle;
  75. } channel_t;
  76. // the set of channels available
  77. static channel_t* channels;
  78. // These are not used, but should be (menu).
  79. // Maximum volume of a sound effect.
  80. // Internal default is max out of 0-15.
  81. int snd_SfxVolume = 15;
  82. // Maximum volume of music. Useless so far.
  83. int snd_MusicVolume = 15;
  84. // whether songs are mus_paused
  85. static boolean mus_paused;
  86. // music currently being played
  87. static musicinfo_t* mus_playing=0;
  88. // following is set
  89. // by the defaults code in M_misc:
  90. // number of channels available
  91. int numChannels;
  92. static int nextcleanup;
  93. //
  94. // Internals.
  95. //
  96. int
  97. S_getChannel
  98. ( void* origin,
  99. sfxinfo_t* sfxinfo );
  100. int
  101. S_AdjustSoundParams
  102. ( mobj_t* listener,
  103. mobj_t* source,
  104. int* vol,
  105. int* sep,
  106. int* pitch );
  107. void S_StopChannel(int cnum);
  108. //
  109. // Initializes sound stuff, including volume
  110. // Sets channels, SFX and music volume,
  111. // allocates channel buffer, sets S_sfx lookup.
  112. //
  113. void S_Init
  114. ( int sfxVolume,
  115. int musicVolume )
  116. {
  117. int i;
  118. fprintf( stderr, "S_Init: default sfx volume %d\n", sfxVolume);
  119. // Whatever these did with DMX, these are rather dummies now.
  120. I_SetChannels();
  121. S_SetSfxVolume(sfxVolume);
  122. // No music with Linux - another dummy.
  123. S_SetMusicVolume(musicVolume);
  124. // Allocating the internal channels for mixing
  125. // (the maximum numer of sounds rendered
  126. // simultaneously) within zone memory.
  127. channels =
  128. (channel_t *) Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0);
  129. // Free all channels for use
  130. for (i=0 ; i<numChannels ; i++)
  131. channels[i].sfxinfo = 0;
  132. // no sounds are playing, and they are not mus_paused
  133. mus_paused = 0;
  134. // Note that sounds have not been cached (yet).
  135. for (i=1 ; i<NUMSFX ; i++)
  136. S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
  137. }
  138. //
  139. // Per level startup code.
  140. // Kills playing sounds at start of level,
  141. // determines music if any, changes music.
  142. //
  143. void S_Start(void)
  144. {
  145. int cnum;
  146. int mnum;
  147. // kill all playing sounds at start of level
  148. // (trust me - a good idea)
  149. for (cnum=0 ; cnum<numChannels ; cnum++)
  150. if (channels[cnum].sfxinfo)
  151. S_StopChannel(cnum);
  152. // start new music for the level
  153. mus_paused = 0;
  154. if (gamemode == commercial)
  155. mnum = mus_runnin + gamemap - 1;
  156. else
  157. {
  158. int spmus[]=
  159. {
  160. // Song - Who? - Where?
  161. mus_e3m4, // American e4m1
  162. mus_e3m2, // Romero e4m2
  163. mus_e3m3, // Shawn e4m3
  164. mus_e1m5, // American e4m4
  165. mus_e2m7, // Tim e4m5
  166. mus_e2m4, // Romero e4m6
  167. mus_e2m6, // J.Anderson e4m7 CHIRON.WAD
  168. mus_e2m5, // Shawn e4m8
  169. mus_e1m9 // Tim e4m9
  170. };
  171. if (gameepisode < 4)
  172. mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1;
  173. else
  174. mnum = spmus[gamemap-1];
  175. }
  176. // HACK FOR COMMERCIAL
  177. // if (commercial && mnum > mus_e3m9)
  178. // mnum -= mus_e3m9;
  179. S_ChangeMusic(mnum, true);
  180. nextcleanup = 15;
  181. }
  182. void
  183. S_StartSoundAtVolume
  184. ( void* origin_p,
  185. int sfx_id,
  186. int volume )
  187. {
  188. int rc;
  189. int sep;
  190. int pitch;
  191. int priority;
  192. sfxinfo_t* sfx;
  193. int cnum;
  194. mobj_t* origin = (mobj_t *) origin_p;
  195. // Debug.
  196. /*fprintf( stderr,
  197. "S_StartSoundAtVolume: playing sound %d (%s)\n",
  198. sfx_id, S_sfx[sfx_id].name );*/
  199. // check for bogus sound #
  200. if (sfx_id < 1 || sfx_id > NUMSFX)
  201. I_Error("Bad sfx #: %d", sfx_id);
  202. sfx = &S_sfx[sfx_id];
  203. // Initialize sound parameters
  204. if (sfx->link)
  205. {
  206. pitch = sfx->pitch;
  207. priority = sfx->priority;
  208. volume += sfx->volume;
  209. if (volume < 1)
  210. return;
  211. if (volume > snd_SfxVolume)
  212. volume = snd_SfxVolume;
  213. }
  214. else
  215. {
  216. pitch = NORM_PITCH;
  217. priority = NORM_PRIORITY;
  218. }
  219. // Check to see if it is audible,
  220. // and if not, modify the params
  221. if (origin && origin != players[consoleplayer].mo)
  222. {
  223. rc = S_AdjustSoundParams(players[consoleplayer].mo,
  224. origin,
  225. &volume,
  226. &sep,
  227. &pitch);
  228. if ( origin->x == players[consoleplayer].mo->x
  229. && origin->y == players[consoleplayer].mo->y)
  230. {
  231. sep = NORM_SEP;
  232. }
  233. if (!rc)
  234. return;
  235. }
  236. else
  237. {
  238. sep = NORM_SEP;
  239. }
  240. // hacks to vary the sfx pitches
  241. if (sfx_id >= sfx_sawup
  242. && sfx_id <= sfx_sawhit)
  243. {
  244. pitch += 8 - (M_Random()&15);
  245. if (pitch<0)
  246. pitch = 0;
  247. else if (pitch>255)
  248. pitch = 255;
  249. }
  250. else if (sfx_id != sfx_itemup
  251. && sfx_id != sfx_tink)
  252. {
  253. pitch += 16 - (M_Random()&31);
  254. if (pitch<0)
  255. pitch = 0;
  256. else if (pitch>255)
  257. pitch = 255;
  258. }
  259. // kill old sound
  260. S_StopSound(origin);
  261. // try to find a channel
  262. cnum = S_getChannel(origin, sfx);
  263. if (cnum<0)
  264. return;
  265. //
  266. // This is supposed to handle the loading/caching.
  267. // For some odd reason, the caching is done nearly
  268. // each time the sound is needed?
  269. //
  270. // get lumpnum if necessary
  271. if (sfx->lumpnum < 0)
  272. sfx->lumpnum = I_GetSfxLumpNum(sfx);
  273. #ifndef SNDSRV
  274. // cache data if necessary
  275. if (!sfx->data)
  276. {
  277. fprintf( stderr,
  278. "S_StartSoundAtVolume: 16bit and not pre-cached - wtf?\n");
  279. // DOS remains, 8bit handling
  280. //sfx->data = (void *) W_CacheLumpNum(sfx->lumpnum, PU_MUSIC);
  281. // fprintf( stderr,
  282. // "S_StartSoundAtVolume: loading %d (lump %d) : 0x%x\n",
  283. // sfx_id, sfx->lumpnum, (int)sfx->data );
  284. }
  285. #endif
  286. // increase the usefulness
  287. if (sfx->usefulness++ < 0)
  288. sfx->usefulness = 1;
  289. // Assigns the handle to one of the channels in the
  290. // mix/output buffer.
  291. channels[cnum].handle = I_StartSound(sfx_id,
  292. /*sfx->data,*/
  293. volume,
  294. sep,
  295. pitch,
  296. priority);
  297. }
  298. void
  299. S_StartSound
  300. ( void* origin,
  301. int sfx_id )
  302. {
  303. #ifdef SAWDEBUG
  304. // if (sfx_id == sfx_sawful)
  305. // sfx_id = sfx_itemup;
  306. #endif
  307. S_StartSoundAtVolume(origin, sfx_id, snd_SfxVolume);
  308. // UNUSED. We had problems, had we not?
  309. #ifdef SAWDEBUG
  310. {
  311. int i;
  312. int n;
  313. static mobj_t* last_saw_origins[10] = {1,1,1,1,1,1,1,1,1,1};
  314. static int first_saw=0;
  315. static int next_saw=0;
  316. if (sfx_id == sfx_sawidl
  317. || sfx_id == sfx_sawful
  318. || sfx_id == sfx_sawhit)
  319. {
  320. for (i=first_saw;i!=next_saw;i=(i+1)%10)
  321. if (last_saw_origins[i] != origin)
  322. fprintf(stderr, "old origin 0x%lx != "
  323. "origin 0x%lx for sfx %d\n",
  324. last_saw_origins[i],
  325. origin,
  326. sfx_id);
  327. last_saw_origins[next_saw] = origin;
  328. next_saw = (next_saw + 1) % 10;
  329. if (next_saw == first_saw)
  330. first_saw = (first_saw + 1) % 10;
  331. for (n=i=0; i<numChannels ; i++)
  332. {
  333. if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
  334. || channels[i].sfxinfo == &S_sfx[sfx_sawful]
  335. || channels[i].sfxinfo == &S_sfx[sfx_sawhit]) n++;
  336. }
  337. if (n>1)
  338. {
  339. for (i=0; i<numChannels ; i++)
  340. {
  341. if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
  342. || channels[i].sfxinfo == &S_sfx[sfx_sawful]
  343. || channels[i].sfxinfo == &S_sfx[sfx_sawhit])
  344. {
  345. fprintf(stderr,
  346. "chn: sfxinfo=0x%lx, origin=0x%lx, "
  347. "handle=%d\n",
  348. channels[i].sfxinfo,
  349. channels[i].origin,
  350. channels[i].handle);
  351. }
  352. }
  353. fprintf(stderr, "\n");
  354. }
  355. }
  356. }
  357. #endif
  358. }
  359. void S_StopSound(void *origin)
  360. {
  361. int cnum;
  362. for (cnum=0 ; cnum<numChannels ; cnum++)
  363. {
  364. if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
  365. {
  366. S_StopChannel(cnum);
  367. break;
  368. }
  369. }
  370. }
  371. //
  372. // Stop and resume music, during game PAUSE.
  373. //
  374. void S_PauseSound(void)
  375. {
  376. if (mus_playing && !mus_paused)
  377. {
  378. I_PauseSong(mus_playing->handle);
  379. mus_paused = true;
  380. }
  381. }
  382. void S_ResumeSound(void)
  383. {
  384. if (mus_playing && mus_paused)
  385. {
  386. I_ResumeSong(mus_playing->handle);
  387. mus_paused = false;
  388. }
  389. }
  390. //
  391. // Updates music & sounds
  392. //
  393. void S_UpdateSounds(void* listener_p)
  394. {
  395. int audible;
  396. int cnum;
  397. int volume;
  398. int sep;
  399. int pitch;
  400. sfxinfo_t* sfx;
  401. channel_t* c;
  402. mobj_t* listener = (mobj_t*)listener_p;
  403. // Clean up unused data.
  404. // This is currently not done for 16bit (sounds cached static).
  405. // DOS 8bit remains.
  406. /*if (gametic > nextcleanup)
  407. {
  408. for (i=1 ; i<NUMSFX ; i++)
  409. {
  410. if (S_sfx[i].usefulness < 1
  411. && S_sfx[i].usefulness > -1)
  412. {
  413. if (--S_sfx[i].usefulness == -1)
  414. {
  415. Z_ChangeTag(S_sfx[i].data, PU_CACHE);
  416. S_sfx[i].data = 0;
  417. }
  418. }
  419. }
  420. nextcleanup = gametic + 15;
  421. }*/
  422. for (cnum=0 ; cnum<numChannels ; cnum++)
  423. {
  424. c = &channels[cnum];
  425. sfx = c->sfxinfo;
  426. if (c->sfxinfo)
  427. {
  428. if (I_SoundIsPlaying(c->handle))
  429. {
  430. // initialize parameters
  431. volume = snd_SfxVolume;
  432. pitch = NORM_PITCH;
  433. sep = NORM_SEP;
  434. if (sfx->link)
  435. {
  436. pitch = sfx->pitch;
  437. volume += sfx->volume;
  438. if (volume < 1)
  439. {
  440. S_StopChannel(cnum);
  441. continue;
  442. }
  443. else if (volume > snd_SfxVolume)
  444. {
  445. volume = snd_SfxVolume;
  446. }
  447. }
  448. // check non-local sounds for distance clipping
  449. // or modify their params
  450. if (c->origin && listener_p != c->origin)
  451. {
  452. audible = S_AdjustSoundParams(listener,
  453. c->origin,
  454. &volume,
  455. &sep,
  456. &pitch);
  457. if (!audible)
  458. {
  459. S_StopChannel(cnum);
  460. }
  461. else
  462. I_UpdateSoundParams(c->handle, volume, sep, pitch);
  463. }
  464. }
  465. else
  466. {
  467. // if channel is allocated but sound has stopped,
  468. // free it
  469. S_StopChannel(cnum);
  470. }
  471. }
  472. }
  473. // kill music if it is a single-play && finished
  474. // if ( mus_playing
  475. // && !I_QrySongPlaying(mus_playing->handle)
  476. // && !mus_paused )
  477. // S_StopMusic();
  478. }
  479. void S_SetMusicVolume(int volume)
  480. {
  481. if (volume < 0 || volume > 127)
  482. {
  483. I_Error("Attempt to set music volume at %d",
  484. volume);
  485. }
  486. I_SetMusicVolume(127);
  487. I_SetMusicVolume(volume);
  488. snd_MusicVolume = volume;
  489. }
  490. void S_SetSfxVolume(int volume)
  491. {
  492. if (volume < 0 || volume > 127)
  493. I_Error("Attempt to set sfx volume at %d", volume);
  494. snd_SfxVolume = volume;
  495. }
  496. //
  497. // Starts some music with the music id found in sounds.h.
  498. //
  499. void S_StartMusic(int m_id)
  500. {
  501. S_ChangeMusic(m_id, false);
  502. }
  503. void
  504. S_ChangeMusic
  505. ( int musicnum,
  506. int looping )
  507. {
  508. musicinfo_t* music;
  509. char namebuf[9];
  510. if ( (musicnum <= mus_None)
  511. || (musicnum >= NUMMUSIC) )
  512. {
  513. I_Error("Bad music number %d", musicnum);
  514. }
  515. else
  516. music = &S_music[musicnum];
  517. if (mus_playing == music)
  518. return;
  519. // shutdown old music
  520. S_StopMusic();
  521. // get lumpnum if neccessary
  522. if (!music->lumpnum)
  523. {
  524. sprintf(namebuf, "d_%s", music->name);
  525. music->lumpnum = W_GetNumForName(namebuf);
  526. }
  527. // load & register it
  528. music->data = (void *) W_CacheLumpNum(music->lumpnum, PU_MUSIC);
  529. music->handle = I_RegisterSong(music->data);
  530. // play it
  531. I_PlaySong(music->handle, looping);
  532. mus_playing = music;
  533. }
  534. void S_StopMusic(void)
  535. {
  536. if (mus_playing)
  537. {
  538. if (mus_paused)
  539. I_ResumeSong(mus_playing->handle);
  540. I_StopSong(mus_playing->handle);
  541. I_UnRegisterSong(mus_playing->handle);
  542. Z_ChangeTag(mus_playing->data, PU_CACHE);
  543. mus_playing->data = 0;
  544. mus_playing = 0;
  545. }
  546. }
  547. void S_StopChannel(int cnum)
  548. {
  549. int i;
  550. channel_t* c = &channels[cnum];
  551. if (c->sfxinfo)
  552. {
  553. // stop the sound playing
  554. if (I_SoundIsPlaying(c->handle))
  555. {
  556. #ifdef SAWDEBUG
  557. if (c->sfxinfo == &S_sfx[sfx_sawful])
  558. fprintf(stderr, "stopped\n");
  559. #endif
  560. I_StopSound(c->handle);
  561. }
  562. // check to see
  563. // if other channels are playing the sound
  564. for (i=0 ; i<numChannels ; i++)
  565. {
  566. if (cnum != i
  567. && c->sfxinfo == channels[i].sfxinfo)
  568. {
  569. break;
  570. }
  571. }
  572. // degrade usefulness of sound data
  573. c->sfxinfo->usefulness--;
  574. c->sfxinfo = 0;
  575. }
  576. }
  577. //
  578. // Changes volume, stereo-separation, and pitch variables
  579. // from the norm of a sound effect to be played.
  580. // If the sound is not audible, returns a 0.
  581. // Otherwise, modifies parameters and returns 1.
  582. //
  583. int
  584. S_AdjustSoundParams
  585. ( mobj_t* listener,
  586. mobj_t* source,
  587. int* vol,
  588. int* sep,
  589. int* pitch )
  590. {
  591. fixed_t approx_dist;
  592. fixed_t adx;
  593. fixed_t ady;
  594. angle_t angle;
  595. // calculate the distance to sound origin
  596. // and clip it if necessary
  597. adx = abs(listener->x - source->x);
  598. ady = abs(listener->y - source->y);
  599. // From _GG1_ p.428. Appox. eucledian distance fast.
  600. approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
  601. if (gamemap != 8
  602. && approx_dist > S_CLIPPING_DIST)
  603. {
  604. return 0;
  605. }
  606. // angle of source to listener
  607. angle = R_PointToAngle2(listener->x,
  608. listener->y,
  609. source->x,
  610. source->y);
  611. if (angle > listener->angle)
  612. angle = angle - listener->angle;
  613. else
  614. angle = angle + (0xffffffff - listener->angle);
  615. angle >>= ANGLETOFINESHIFT;
  616. // stereo separation
  617. *sep = 128 - (FixedMul(S_STEREO_SWING,finesine[angle])>>FRACBITS);
  618. // volume calculation
  619. if (approx_dist < S_CLOSE_DIST)
  620. {
  621. *vol = snd_SfxVolume;
  622. }
  623. else if (gamemap == 8)
  624. {
  625. if (approx_dist > S_CLIPPING_DIST)
  626. approx_dist = S_CLIPPING_DIST;
  627. *vol = 15+ ((snd_SfxVolume-15)
  628. *((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  629. / S_ATTENUATOR;
  630. }
  631. else
  632. {
  633. // distance effect
  634. *vol = (snd_SfxVolume
  635. * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  636. / S_ATTENUATOR;
  637. }
  638. return (*vol > 0);
  639. }
  640. //
  641. // S_getChannel :
  642. // If none available, return -1. Otherwise channel #.
  643. //
  644. int
  645. S_getChannel
  646. ( void* origin,
  647. sfxinfo_t* sfxinfo )
  648. {
  649. // channel number to use
  650. int cnum;
  651. channel_t* c;
  652. // Find an open channel
  653. for (cnum=0 ; cnum<numChannels ; cnum++)
  654. {
  655. if (!channels[cnum].sfxinfo)
  656. break;
  657. else if (origin && channels[cnum].origin == origin)
  658. {
  659. S_StopChannel(cnum);
  660. break;
  661. }
  662. }
  663. // None available
  664. if (cnum == numChannels)
  665. {
  666. // Look for lower priority
  667. for (cnum=0 ; cnum<numChannels ; cnum++)
  668. if (channels[cnum].sfxinfo->priority >= sfxinfo->priority) break;
  669. if (cnum == numChannels)
  670. {
  671. // FUCK! No lower priority. Sorry, Charlie.
  672. return -1;
  673. }
  674. else
  675. {
  676. // Otherwise, kick out lower priority.
  677. S_StopChannel(cnum);
  678. }
  679. }
  680. c = &channels[cnum];
  681. // channel is decided to be cnum.
  682. c->sfxinfo = sfxinfo;
  683. c->origin = origin;
  684. return cnum;
  685. }