Advertisement
Guest User

Untitled

a guest
Oct 30th, 2012
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.41 KB | None | 0 0
  1. // Emacs style mode select -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // Copyright(C) 1993-1996 Id Software, Inc.
  5. // Copyright(C) 2005 Simon Howard
  6. //
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the GNU General Public License
  9. // as published by the Free Software Foundation; either version 2
  10. // of the License, or (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program; if not, write to the Free Software
  19. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  20. // 02111-1307, USA.
  21. //
  22. // DESCRIPTION: none
  23. //
  24. //-----------------------------------------------------------------------------
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28.  
  29. #include "i_system.h"
  30.  
  31. #include "doomfeatures.h"
  32. #include "deh_main.h"
  33.  
  34. #include "doomstat.h"
  35. #include "doomdef.h"
  36.  
  37. #include "sounds.h"
  38. #include "s_sound.h"
  39.  
  40. #include "m_random.h"
  41. #include "m_argv.h"
  42.  
  43. #include "p_local.h"
  44. #include "w_wad.h"
  45. #include "z_zone.h"
  46.  
  47. // when to clip out sounds
  48. // Does not fit the large outdoor areas.
  49.  
  50. #define S_CLIPPING_DIST (1200 * FRACUNIT)
  51.  
  52. // Distance tp origin when sounds should be maxed out.
  53. // This should relate to movement clipping resolution
  54. // (see BLOCKMAP handling).
  55. // In the source code release: (160*FRACUNIT). Changed back to the
  56. // Vanilla value of 200 (why was this changed?)
  57.  
  58. #define S_CLOSE_DIST (200 * FRACUNIT)
  59.  
  60. // The range over which sound attenuates
  61.  
  62. #define S_ATTENUATOR ((S_CLIPPING_DIST - S_CLOSE_DIST) >> FRACBITS)
  63.  
  64. // Stereo separation
  65.  
  66. #define S_STEREO_SWING (96 * FRACUNIT)
  67.  
  68. #define NORM_PITCH 128
  69. #define NORM_PRIORITY 64
  70. #define NORM_SEP 128
  71.  
  72. typedef struct
  73. {
  74. // sound information (if null, channel avail.)
  75. sfxinfo_t *sfxinfo;
  76.  
  77. // origin of sound
  78. mobj_t *origin;
  79.  
  80. // handle of the sound being played
  81. int handle;
  82.  
  83. } channel_t;
  84.  
  85. // Low-level sound and music modules we are using
  86.  
  87. static sound_module_t *sound_module;
  88. static music_module_t *music_module;
  89.  
  90. // The set of channels available
  91.  
  92. static channel_t *channels;
  93.  
  94. // Maximum volume of a sound effect.
  95. // Internal default is max out of 0-15.
  96.  
  97. int sfxVolume = 8;
  98.  
  99. // Maximum volume of music.
  100.  
  101. int musicVolume = 8;
  102.  
  103. // Sound sample rate to use for digital output (Hz)
  104.  
  105. int snd_samplerate = 44100;
  106.  
  107. // Internal volume level, ranging from 0-127
  108.  
  109. static int snd_SfxVolume;
  110.  
  111. // Whether songs are mus_paused
  112.  
  113. static boolean mus_paused;
  114.  
  115. // Music currently being played
  116.  
  117. static musicinfo_t *mus_playing = NULL;
  118.  
  119. // Number of channels to use
  120.  
  121. int numChannels = 8;
  122.  
  123. int snd_musicdevice = SNDDEVICE_GENMIDI;
  124. int snd_sfxdevice = SNDDEVICE_SB;
  125.  
  126. // Sound modules
  127.  
  128. extern sound_module_t sound_sdl_module;
  129. extern sound_module_t sound_pcsound_module;
  130. extern music_module_t music_sdl_module;
  131. extern music_module_t music_opl_module;
  132.  
  133. // Compiled-in sound modules:
  134.  
  135. static sound_module_t *sound_modules[] =
  136. {
  137. #ifdef FEATURE_SOUND
  138. &sound_sdl_module,
  139. &sound_pcsound_module,
  140. #endif
  141. NULL,
  142. };
  143.  
  144. // Compiled-in music modules:
  145.  
  146. static music_module_t *music_modules[] =
  147. {
  148. #ifdef FEATURE_SOUND
  149. &music_sdl_module,
  150. &music_opl_module,
  151. #endif
  152. NULL,
  153. };
  154.  
  155. // Check if a sound device is in the given list of devices
  156.  
  157. static boolean SndDeviceInList(snddevice_t device, snddevice_t *list,
  158. int len)
  159. {
  160. int i;
  161.  
  162. for (i=0; i<len; ++i)
  163. {
  164. if (device == list[i])
  165. {
  166. return true;
  167. }
  168. }
  169.  
  170. return false;
  171. }
  172.  
  173. // Find and initialize a sound_module_t appropriate for the setting
  174. // in snd_sfxdevice.
  175.  
  176. static void InitSfxModule(void)
  177. {
  178. int i;
  179.  
  180. sound_module = NULL;
  181.  
  182. for (i=0; sound_modules[i] != NULL; ++i)
  183. {
  184. // Is the sfx device in the list of devices supported by
  185. // this module?
  186.  
  187. if (SndDeviceInList(snd_sfxdevice,
  188. sound_modules[i]->sound_devices,
  189. sound_modules[i]->num_sound_devices))
  190. {
  191. // Initialize the module
  192.  
  193. if (sound_modules[i]->Init())
  194. {
  195. sound_module = sound_modules[i];
  196. return;
  197. }
  198. }
  199. }
  200. }
  201.  
  202. // Initialize music according to snd_musicdevice.
  203.  
  204. static void InitMusicModule(void)
  205. {
  206. int i;
  207.  
  208. music_module = NULL;
  209.  
  210. for (i=0; music_modules[i] != NULL; ++i)
  211. {
  212. // Is the music device in the list of devices supported
  213. // by this module?
  214.  
  215. if (SndDeviceInList(snd_musicdevice,
  216. music_modules[i]->sound_devices,
  217. music_modules[i]->num_sound_devices))
  218. {
  219. // Initialize the module
  220.  
  221. if (music_modules[i]->Init())
  222. {
  223. music_module = music_modules[i];
  224. return;
  225. }
  226. }
  227. }
  228. }
  229.  
  230. //
  231. // Initializes sound stuff, including volume
  232. // Sets channels, SFX and music volume,
  233. // allocates channel buffer, sets S_sfx lookup.
  234. //
  235.  
  236. void S_Init(int sfxVolume, int musicVolume)
  237. {
  238. boolean nosound, nosfx, nomusic;
  239. int i;
  240.  
  241. //!
  242. // @vanilla
  243. //
  244. // Disable all sound output.
  245. //
  246.  
  247. nosound = M_CheckParm("-nosound") > 0;
  248.  
  249. //!
  250. // @vanilla
  251. //
  252. // Disable sound effects.
  253. //
  254.  
  255. nosfx = M_CheckParm("-nosfx") > 0;
  256.  
  257. //!
  258. // @vanilla
  259. //
  260. // Disable music.
  261. //
  262.  
  263. nomusic = M_CheckParm("-nomusic") > 0;
  264.  
  265. // Initialize the sound and music subsystems.
  266.  
  267. if (!nosound && !screensaver_mode)
  268. {
  269. if (!nosfx)
  270. {
  271. InitSfxModule();
  272. }
  273.  
  274. if (!nomusic)
  275. {
  276. InitMusicModule();
  277. }
  278. }
  279.  
  280. S_SetSfxVolume(sfxVolume);
  281. S_SetMusicVolume(musicVolume);
  282.  
  283. // Allocating the internal channels for mixing
  284. // (the maximum numer of sounds rendered
  285. // simultaneously) within zone memory.
  286. channels = Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0);
  287.  
  288. // Free all channels for use
  289. for (i=0 ; i<numChannels ; i++)
  290. {
  291. channels[i].sfxinfo = 0;
  292. }
  293.  
  294. // no sounds are playing, and they are not mus_paused
  295. mus_paused = 0;
  296.  
  297. // Note that sounds have not been cached (yet).
  298. for (i=1 ; i<NUMSFX ; i++)
  299. {
  300. S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
  301. }
  302. }
  303.  
  304. void S_Shutdown(void)
  305. {
  306. if (sound_module != NULL)
  307. {
  308. sound_module->Shutdown();
  309. }
  310.  
  311. if (music_module != NULL)
  312. {
  313. music_module->Shutdown();
  314. }
  315. }
  316.  
  317. static void S_StopChannel(int cnum)
  318. {
  319. int i;
  320. channel_t *c;
  321.  
  322. c = &channels[cnum];
  323.  
  324. if (c->sfxinfo)
  325. {
  326. // stop the sound playing
  327.  
  328. if (sound_module != NULL)
  329. {
  330. if (sound_module->SoundIsPlaying(c->handle))
  331. {
  332. sound_module->StopSound(c->handle);
  333. }
  334. }
  335.  
  336. // check to see if other channels are playing the sound
  337.  
  338. for (i=0; i<numChannels; i++)
  339. {
  340. if (cnum != i && c->sfxinfo == channels[i].sfxinfo)
  341. {
  342. break;
  343. }
  344. }
  345.  
  346. // degrade usefulness of sound data
  347.  
  348. c->sfxinfo->usefulness--;
  349. c->sfxinfo = NULL;
  350. }
  351. }
  352.  
  353. //
  354. // Per level startup code.
  355. // Kills playing sounds at start of level,
  356. // determines music if any, changes music.
  357. //
  358.  
  359. void S_Start(void)
  360. {
  361. int cnum;
  362. int mnum;
  363.  
  364. // kill all playing sounds at start of level
  365. // (trust me - a good idea)
  366. for (cnum=0 ; cnum<numChannels ; cnum++)
  367. {
  368. if (channels[cnum].sfxinfo)
  369. {
  370. S_StopChannel(cnum);
  371. }
  372. }
  373.  
  374. // start new music for the level
  375. mus_paused = 0;
  376.  
  377. if (gamemode == commercial)
  378. {
  379. mnum = mus_runnin + gamemap - 1;
  380. }
  381. else
  382. {
  383. int spmus[]=
  384. {
  385. // Song - Who? - Where?
  386.  
  387. mus_e3m4, // American e4m1
  388. mus_e3m2, // Romero e4m2
  389. mus_e3m3, // Shawn e4m3
  390. mus_e1m5, // American e4m4
  391. mus_e2m7, // Tim e4m5
  392. mus_e2m4, // Romero e4m6
  393. mus_e2m6, // J.Anderson e4m7 CHIRON.WAD
  394. mus_e2m5, // Shawn e4m8
  395. mus_e1m9, // Tim e4m9
  396. };
  397.  
  398. if (gameepisode < 4)
  399. {
  400. mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1;
  401. }
  402. else
  403. {
  404. mnum = spmus[gamemap-1];
  405. }
  406. }
  407.  
  408. S_ChangeMusic(mnum, true);
  409. }
  410.  
  411. void S_StopSound(mobj_t *origin)
  412. {
  413. int cnum;
  414.  
  415. for (cnum=0 ; cnum<numChannels ; cnum++)
  416. {
  417. if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
  418. {
  419. S_StopChannel(cnum);
  420. break;
  421. }
  422. }
  423. }
  424.  
  425. //
  426. // S_GetChannel :
  427. // If none available, return -1. Otherwise channel #.
  428. //
  429.  
  430. static int S_GetChannel(mobj_t *origin, sfxinfo_t *sfxinfo)
  431. {
  432. // channel number to use
  433. int cnum;
  434.  
  435. channel_t* c;
  436.  
  437. // Find an open channel
  438. for (cnum=0 ; cnum<numChannels ; cnum++)
  439. {
  440. if (!channels[cnum].sfxinfo)
  441. {
  442. break;
  443. }
  444. else if (origin && channels[cnum].origin == origin)
  445. {
  446. S_StopChannel(cnum);
  447. break;
  448. }
  449. }
  450.  
  451. // None available
  452. if (cnum == numChannels)
  453. {
  454. // Look for lower priority
  455. for (cnum=0 ; cnum<numChannels ; cnum++)
  456. {
  457. if (channels[cnum].sfxinfo->priority >= sfxinfo->priority)
  458. {
  459. break;
  460. }
  461. }
  462.  
  463. if (cnum == numChannels)
  464. {
  465. // FUCK! No lower priority. Sorry, Charlie.
  466. return -1;
  467. }
  468. else
  469. {
  470. // Otherwise, kick out lower priority.
  471. S_StopChannel(cnum);
  472. }
  473. }
  474.  
  475. c = &channels[cnum];
  476.  
  477. // channel is decided to be cnum.
  478. c->sfxinfo = sfxinfo;
  479. c->origin = origin;
  480.  
  481. return cnum;
  482. }
  483.  
  484. //
  485. // Changes volume, stereo-separation, and pitch variables
  486. // from the norm of a sound effect to be played.
  487. // If the sound is not audible, returns a 0.
  488. // Otherwise, modifies parameters and returns 1.
  489. //
  490.  
  491. static int S_AdjustSoundParams(mobj_t *listener, mobj_t *source,
  492. int *vol, int *sep, int *pitch)
  493. {
  494. fixed_t approx_dist;
  495. fixed_t adx;
  496. fixed_t ady;
  497. angle_t angle;
  498.  
  499. // calculate the distance to sound origin
  500. // and clip it if necessary
  501. adx = abs(listener->x - source->x);
  502. ady = abs(listener->y - source->y);
  503.  
  504. // From _GG1_ p.428. Appox. eucledian distance fast.
  505. approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
  506.  
  507. if (gamemap != 8 && approx_dist > S_CLIPPING_DIST)
  508. {
  509. return 0;
  510. }
  511.  
  512. // angle of source to listener
  513. angle = R_PointToAngle2(listener->x,
  514. listener->y,
  515. source->x,
  516. source->y);
  517.  
  518. if (angle > listener->angle)
  519. {
  520. angle = angle - listener->angle;
  521. }
  522. else
  523. {
  524. angle = angle + (0xffffffff - listener->angle);
  525. }
  526.  
  527. angle >>= ANGLETOFINESHIFT;
  528.  
  529. // stereo separation
  530. *sep = 128 - (FixedMul(S_STEREO_SWING, finesine[angle]) >> FRACBITS);
  531.  
  532. // volume calculation
  533. if (approx_dist < S_CLOSE_DIST)
  534. {
  535. *vol = snd_SfxVolume;
  536. }
  537. else if (gamemap == 8)
  538. {
  539. if (approx_dist > S_CLIPPING_DIST)
  540. {
  541. approx_dist = S_CLIPPING_DIST;
  542. }
  543.  
  544. *vol = 15+ ((snd_SfxVolume-15)
  545. *((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  546. / S_ATTENUATOR;
  547. }
  548. else
  549. {
  550. // distance effect
  551. *vol = (snd_SfxVolume
  552. * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  553. / S_ATTENUATOR;
  554. }
  555.  
  556. return (*vol > 0);
  557. }
  558.  
  559. void S_StartSound(void *origin_p, int sfx_id)
  560. {
  561. sfxinfo_t *sfx;
  562. mobj_t *origin;
  563. int rc;
  564. int sep;
  565. int pitch;
  566. int priority;
  567. int cnum;
  568. int volume;
  569.  
  570. origin = (mobj_t *) origin_p;
  571. volume = snd_SfxVolume;
  572.  
  573. // check for bogus sound #
  574. if (sfx_id < 1 || sfx_id > NUMSFX)
  575. {
  576. I_Error("Bad sfx #: %d", sfx_id);
  577. }
  578.  
  579. sfx = &S_sfx[sfx_id];
  580.  
  581. // Initialize sound parameters
  582. if (sfx->link)
  583. {
  584. pitch = sfx->pitch;
  585. priority = sfx->priority;
  586. volume += sfx->volume;
  587.  
  588. if (volume < 1)
  589. {
  590. return;
  591. }
  592.  
  593. if (volume > snd_SfxVolume)
  594. {
  595. volume = snd_SfxVolume;
  596. }
  597. }
  598. else
  599. {
  600. pitch = NORM_PITCH;
  601. priority = NORM_PRIORITY;
  602. }
  603.  
  604.  
  605. // Check to see if it is audible,
  606. // and if not, modify the params
  607. if (origin && origin != players[consoleplayer].mo)
  608. {
  609. rc = S_AdjustSoundParams(players[consoleplayer].mo,
  610. origin,
  611. &volume,
  612. &sep,
  613. &pitch);
  614.  
  615. if (origin->x == players[consoleplayer].mo->x
  616. && origin->y == players[consoleplayer].mo->y)
  617. {
  618. sep = NORM_SEP;
  619. }
  620.  
  621. if (!rc)
  622. {
  623. return;
  624. }
  625. }
  626. else
  627. {
  628. sep = NORM_SEP;
  629. }
  630.  
  631. // hacks to vary the sfx pitches
  632. if (sfx_id >= sfx_sawup
  633. && sfx_id <= sfx_sawhit)
  634. {
  635. pitch += 8 - (M_Random()&15);
  636.  
  637. if (pitch < 0)
  638. {
  639. pitch = 0;
  640. }
  641. else if (pitch > 255)
  642. {
  643. pitch = 255;
  644. }
  645. }
  646. else if (sfx_id != sfx_itemup
  647. && sfx_id != sfx_tink)
  648. {
  649. pitch += 16 - (M_Random()&31);
  650.  
  651. if (pitch < 0)
  652. {
  653. pitch = 0;
  654. }
  655. else if (pitch > 255)
  656. {
  657. pitch = 255;
  658. }
  659. }
  660.  
  661. // kill old sound
  662. S_StopSound(origin);
  663.  
  664. // try to find a channel
  665. cnum = S_GetChannel(origin, sfx);
  666.  
  667. if (cnum < 0)
  668. {
  669. return;
  670. }
  671.  
  672. // increase the usefulness
  673. if (sfx->usefulness++ < 0)
  674. {
  675. sfx->usefulness = 1;
  676. }
  677.  
  678. if (sound_module != NULL)
  679. {
  680. // Get lumpnum if necessary
  681.  
  682. if (sfx->lumpnum < 0)
  683. {
  684. sfx->lumpnum = sound_module->GetSfxLumpNum(sfx);
  685. }
  686.  
  687. // Assigns the handle to one of the channels in the
  688. // mix/output buffer.
  689.  
  690. channels[cnum].handle = sound_module->StartSound(sfx_id,
  691. cnum,
  692. volume,
  693. sep,
  694. pitch,
  695. priority);
  696. }
  697. }
  698.  
  699. //
  700. // Stop and resume music, during game PAUSE.
  701. //
  702.  
  703. void S_PauseSound(void)
  704. {
  705. if (mus_playing && !mus_paused)
  706. {
  707. if (music_module != NULL)
  708. {
  709. music_module->PauseMusic();
  710. }
  711. mus_paused = true;
  712. }
  713. }
  714.  
  715. void S_ResumeSound(void)
  716. {
  717. if (mus_playing && mus_paused)
  718. {
  719. if (music_module != NULL)
  720. {
  721. music_module->ResumeMusic();
  722. }
  723. mus_paused = false;
  724. }
  725. }
  726.  
  727. //
  728. // Updates music & sounds
  729. //
  730.  
  731. void S_UpdateSounds(mobj_t *listener)
  732. {
  733. int audible;
  734. int cnum;
  735. int volume;
  736. int sep;
  737. int pitch;
  738. sfxinfo_t* sfx;
  739. channel_t* c;
  740.  
  741. for (cnum=0; cnum<numChannels; cnum++)
  742. {
  743. c = &channels[cnum];
  744. sfx = c->sfxinfo;
  745.  
  746. if (c->sfxinfo)
  747. {
  748. if (sound_module != NULL && sound_module->SoundIsPlaying(c->handle))
  749. {
  750. // initialize parameters
  751. volume = snd_SfxVolume;
  752. pitch = NORM_PITCH;
  753. sep = NORM_SEP;
  754.  
  755. if (sfx->link)
  756. {
  757. pitch = sfx->pitch;
  758. volume += sfx->volume;
  759. if (volume < 1)
  760. {
  761. S_StopChannel(cnum);
  762. continue;
  763. }
  764. else if (volume > snd_SfxVolume)
  765. {
  766. volume = snd_SfxVolume;
  767. }
  768. }
  769.  
  770. // check non-local sounds for distance clipping
  771. // or modify their params
  772. if (c->origin && listener != c->origin)
  773. {
  774. audible = S_AdjustSoundParams(listener,
  775. c->origin,
  776. &volume,
  777. &sep,
  778. &pitch);
  779.  
  780. if (!audible)
  781. {
  782. S_StopChannel(cnum);
  783. }
  784. else
  785. {
  786. I_UpdateSoundParams(c->handle, volume, sep, pitch);
  787. }
  788. }
  789. }
  790. else
  791. {
  792. // if channel is allocated but sound has stopped,
  793. // free it
  794. S_StopChannel(cnum);
  795. }
  796. }
  797. }
  798. }
  799.  
  800. void S_SetMusicVolume(int volume)
  801. {
  802. if (volume < 0 || volume > 127)
  803. {
  804. I_Error("Attempt to set music volume at %d",
  805. volume);
  806. }
  807.  
  808. if (music_module != NULL)
  809. {
  810. music_module->SetMusicVolume(volume);
  811. }
  812. }
  813.  
  814. void S_SetSfxVolume(int volume)
  815. {
  816. if (volume < 0 || volume > 127)
  817. {
  818. I_Error("Attempt to set sfx volume at %d", volume);
  819. }
  820.  
  821. snd_SfxVolume = volume;
  822. }
  823.  
  824. //
  825. // Starts some music with the music id found in sounds.h.
  826. //
  827.  
  828. void S_StartMusic(int m_id)
  829. {
  830. S_ChangeMusic(m_id, false);
  831. }
  832.  
  833. void S_ChangeMusic(int musicnum, int looping)
  834. {
  835. musicinfo_t *music = NULL;
  836. char namebuf[9];
  837. void *handle;
  838.  
  839. // The Doom IWAD file has two versions of the intro music: d_intro
  840. // and d_introa. The latter is used for OPL playback.
  841.  
  842. if (musicnum == mus_intro && (snd_musicdevice == SNDDEVICE_ADLIB
  843. || snd_musicdevice == SNDDEVICE_SB))
  844. {
  845. musicnum = mus_introa;
  846. }
  847.  
  848. if (musicnum <= mus_None || musicnum >= NUMMUSIC)
  849. {
  850. I_Error("Bad music number %d", musicnum);
  851. }
  852. else
  853. {
  854. music = &S_music[musicnum];
  855. }
  856.  
  857. if (mus_playing == music)
  858. {
  859. return;
  860. }
  861.  
  862. // shutdown old music
  863. S_StopMusic();
  864.  
  865. // get lumpnum if neccessary
  866. if (!music->lumpnum)
  867. {
  868. sprintf(namebuf, "d_%s", DEH_String(music->name));
  869. music->lumpnum = W_GetNumForName(namebuf);
  870. }
  871.  
  872. if (music_module != NULL)
  873. {
  874. // Load & register it
  875.  
  876. music->data = W_CacheLumpNum(music->lumpnum, PU_STATIC);
  877. handle = music_module->RegisterSong(music->data,
  878. W_LumpLength(music->lumpnum));
  879. music->handle = handle;
  880.  
  881. // Play it
  882.  
  883. music_module->PlaySong(handle, looping);
  884. }
  885.  
  886. mus_playing = music;
  887. }
  888.  
  889. boolean S_MusicPlaying(void)
  890. {
  891. if (music_module != NULL)
  892. {
  893. return music_module->MusicIsPlaying();
  894. }
  895. else
  896. {
  897. return false;
  898. }
  899. }
  900.  
  901. void S_StopMusic(void)
  902. {
  903. if (mus_playing)
  904. {
  905. if (music_module != NULL)
  906. {
  907. if (mus_paused)
  908. {
  909. music_module->ResumeMusic();
  910. }
  911.  
  912. music_module->StopSong();
  913. music_module->UnRegisterSong(mus_playing->handle);
  914. W_ReleaseLumpNum(mus_playing->lumpnum);
  915.  
  916. mus_playing->data = NULL;
  917. }
  918.  
  919. mus_playing = NULL;
  920. }
  921. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement