i_sound.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. /* Emacs style mode select -*- C++ -*-
  2. *-----------------------------------------------------------------------------
  3. *
  4. *
  5. * PrBoom: a Doom port merged with LxDoom and LSDLDoom
  6. * based on BOOM, a modified and improved DOOM engine
  7. * Copyright (C) 1999 by
  8. * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
  9. * Copyright (C) 1999-2000 by
  10. * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
  11. * Copyright 2005, 2006 by
  12. * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  27. * 02111-1307, USA.
  28. *
  29. * DESCRIPTION:
  30. * System interface for sound.
  31. *
  32. *-----------------------------------------------------------------------------
  33. */
  34. #ifdef HAVE_CONFIG_H
  35. #include "config.h"
  36. #endif
  37. #ifdef HAVE_LIBSDL_MIXER
  38. #define HAVE_MIXER
  39. #endif
  40. #include <math.h>
  41. #ifdef HAVE_UNISTD_H
  42. #include <unistd.h>
  43. #endif
  44. // I'm hacking back in the MIDI music support. At this time, I only want
  45. // music-related functions, so I'm adding this macro to remove sfx-related
  46. // functions.
  47. #define ID_DISABLE_SDL_SOUND 1
  48. #ifndef ID_DISABLE_SDL_SOUND
  49. #include "SDL.h"
  50. #include "SDL_audio.h"
  51. #include "SDL_mutex.h"
  52. #include "SDL_byteorder.h"
  53. #include "SDL_version.h"
  54. #endif // ID_DISABLE_SDL_SOUND
  55. #ifdef HAVE_MIXER
  56. #include "SDL_mixer.h"
  57. #endif
  58. #include "z_zone.h"
  59. #include "m_swap.h"
  60. #include "i_sound.h"
  61. #include "m_argv.h"
  62. #include "m_misc.h"
  63. #include "w_wad.h"
  64. #include "lprintf.h"
  65. #include "s_sound.h"
  66. #include "doomdef.h"
  67. #include "doomstat.h"
  68. #include "doomtype.h"
  69. #include "d_main.h"
  70. // The number of internal mixing channels,
  71. // the samples calculated for each mixing step,
  72. // the size of the 16bit, 2 hardware channel (stereo)
  73. // mixing buffer, and the samplerate of the raw data.
  74. // Variables used by Boom from Allegro
  75. // created here to avoid changes to core Boom files
  76. int snd_card = 1;
  77. int mus_card = 1;
  78. int detect_voices = 0; // God knows
  79. static boolean sound_inited = false;
  80. static boolean first_sound_init = true;
  81. // Needed for calling the actual sound output.
  82. static int SAMPLECOUNT= 512;
  83. #define MAX_CHANNELS 32
  84. // MWM 2000-01-08: Sample rate in samples/second
  85. int snd_samplerate=11025;
  86. // The actual output device.
  87. int audio_fd;
  88. typedef struct {
  89. // SFX id of the playing sound effect.
  90. // Used to catch duplicates (like chainsaw).
  91. int id;
  92. // The channel step amount...
  93. unsigned int step;
  94. // ... and a 0.16 bit remainder of last step.
  95. unsigned int stepremainder;
  96. unsigned int samplerate;
  97. // The channel data pointers, start and end.
  98. const unsigned char* data;
  99. const unsigned char* enddata;
  100. // Time/gametic that the channel started playing,
  101. // used to determine oldest, which automatically
  102. // has lowest priority.
  103. // In case number of active sounds exceeds
  104. // available channels.
  105. int starttime;
  106. // Hardware left and right channel volume lookup.
  107. int *leftvol_lookup;
  108. int *rightvol_lookup;
  109. } channel_info_t;
  110. channel_info_t channelinfo[MAX_CHANNELS];
  111. // Pitch to stepping lookup, unused.
  112. int steptable[256];
  113. // Volume lookups.
  114. int vol_lookup[128*256];
  115. #ifndef ID_DISABLE_SDL_SOUND
  116. /* cph
  117. * stopchan
  118. * Stops a sound, unlocks the data
  119. */
  120. static void stopchan(int i)
  121. {
  122. if (channelinfo[i].data) /* cph - prevent excess unlocks */
  123. {
  124. channelinfo[i].data=NULL;
  125. W_UnlockLumpNum(S_sfx[channelinfo[i].id].lumpnum);
  126. }
  127. }
  128. //
  129. // This function adds a sound to the
  130. // list of currently active sounds,
  131. // which is maintained as a given number
  132. // (eight, usually) of internal channels.
  133. // Returns a handle.
  134. //
  135. static int addsfx(int sfxid, int channel, const unsigned char* data, size_t len)
  136. {
  137. stopchan(channel);
  138. channelinfo[channel].data = data;
  139. /* Set pointer to end of raw data. */
  140. channelinfo[channel].enddata = channelinfo[channel].data + len - 1;
  141. channelinfo[channel].samplerate = (channelinfo[channel].data[3]<<8)+channelinfo[channel].data[2];
  142. channelinfo[channel].data += 8; /* Skip header */
  143. channelinfo[channel].stepremainder = 0;
  144. // Should be gametic, I presume.
  145. channelinfo[channel].starttime = gametic;
  146. // Preserve sound SFX id,
  147. // e.g. for avoiding duplicates of chainsaw.
  148. channelinfo[channel].id = sfxid;
  149. return channel;
  150. }
  151. static void updateSoundParams(int handle, int volume, int seperation, int pitch)
  152. {
  153. int slot = handle;
  154. int rightvol;
  155. int leftvol;
  156. int step = steptable[pitch];
  157. #ifdef RANGECHECK
  158. if ((handle < 0) || (handle >= MAX_CHANNELS))
  159. I_Error("I_UpdateSoundParams: handle out of range");
  160. #endif
  161. // Set stepping
  162. // MWM 2000-12-24: Calculates proportion of channel samplerate
  163. // to global samplerate for mixing purposes.
  164. // Patched to shift left *then* divide, to minimize roundoff errors
  165. // as well as to use SAMPLERATE as defined above, not to assume 11025 Hz
  166. if (pitched_sounds)
  167. channelinfo[slot].step = step + (((channelinfo[slot].samplerate<<16)/snd_samplerate)-65536);
  168. else
  169. channelinfo[slot].step = ((channelinfo[slot].samplerate<<16)/snd_samplerate);
  170. // Separation, that is, orientation/stereo.
  171. // range is: 1 - 256
  172. seperation += 1;
  173. // Per left/right channel.
  174. // x^2 seperation,
  175. // adjust volume properly.
  176. leftvol = volume - ((volume*seperation*seperation) >> 16);
  177. seperation = seperation - 257;
  178. rightvol= volume - ((volume*seperation*seperation) >> 16);
  179. // Sanity check, clamp volume.
  180. if (rightvol < 0 || rightvol > 127)
  181. I_Error("rightvol out of bounds");
  182. if (leftvol < 0 || leftvol > 127)
  183. I_Error("leftvol out of bounds");
  184. // Get the proper lookup table piece
  185. // for this volume level???
  186. channelinfo[slot].leftvol_lookup = &vol_lookup[leftvol*256];
  187. channelinfo[slot].rightvol_lookup = &vol_lookup[rightvol*256];
  188. }
  189. void I_UpdateSoundParams(int handle, int volume, int seperation, int pitch)
  190. {
  191. SDL_LockAudio();
  192. updateSoundParams(handle, volume, seperation, pitch);
  193. SDL_UnlockAudio();
  194. }
  195. //
  196. // SFX API
  197. // Note: this was called by S_Init.
  198. // However, whatever they did in the
  199. // old DPMS based DOS version, this
  200. // were simply dummies in the Linux
  201. // version.
  202. // See soundserver initdata().
  203. //
  204. void I_SetChannels(void)
  205. {
  206. // Init internal lookups (raw data, mixing buffer, channels).
  207. // This function sets up internal lookups used during
  208. // the mixing process.
  209. int i;
  210. int j;
  211. int* steptablemid = steptable + 128;
  212. // Okay, reset internal mixing channels to zero.
  213. for (i=0; i<MAX_CHANNELS; i++)
  214. {
  215. memset(&channelinfo[i],0,sizeof(channel_info_t));
  216. }
  217. // This table provides step widths for pitch parameters.
  218. // I fail to see that this is currently used.
  219. for (i=-128 ; i<128 ; i++)
  220. steptablemid[i] = (int)(pow(1.2, ((double)i/(64.0*snd_samplerate/11025)))*65536.0);
  221. // Generates volume lookup tables
  222. // which also turn the unsigned samples
  223. // into signed samples.
  224. for (i=0 ; i<128 ; i++)
  225. for (j=0 ; j<256 ; j++)
  226. {
  227. // proff - made this a little bit softer, because with
  228. // full volume the sound clipped badly
  229. vol_lookup[i*256+j] = (i*(j-128)*256)/191;
  230. //vol_lookup[i*256+j] = (i*(j-128)*256)/127;
  231. }
  232. }
  233. //
  234. // Retrieve the raw data lump index
  235. // for a given SFX name.
  236. //
  237. int I_GetSfxLumpNum(sfxinfo_t* sfx)
  238. {
  239. char namebuf[9];
  240. sprintf(namebuf, "ds%s", sfx->name);
  241. return W_GetNumForName(namebuf);
  242. }
  243. //
  244. // Starting a sound means adding it
  245. // to the current list of active sounds
  246. // in the internal channels.
  247. // As the SFX info struct contains
  248. // e.g. a pointer to the raw data,
  249. // it is ignored.
  250. // As our sound handling does not handle
  251. // priority, it is ignored.
  252. // Pitching (that is, increased speed of playback)
  253. // is set, but currently not used by mixing.
  254. //
  255. int I_StartSound(int id, int channel, int vol, int sep, int pitch, int priority)
  256. {
  257. const unsigned char* data;
  258. int lump;
  259. size_t len;
  260. if ((channel < 0) || (channel >= MAX_CHANNELS))
  261. #ifdef RANGECHECK
  262. I_Error("I_StartSound: handle out of range");
  263. #else
  264. return -1;
  265. #endif
  266. lump = S_sfx[id].lumpnum;
  267. // We will handle the new SFX.
  268. // Set pointer to raw data.
  269. len = W_LumpLength(lump);
  270. // e6y: Crash with zero-length sounds.
  271. // Example wad: dakills (http://www.doomworld.com/idgames/index.php?id=2803)
  272. // The entries DSBSPWLK, DSBSPACT, DSSWTCHN and DSSWTCHX are all zero-length sounds
  273. if (len<=8) return -1;
  274. /* Find padded length */
  275. len -= 8;
  276. // do the lump caching outside the SDL_LockAudio/SDL_UnlockAudio pair
  277. // use locking which makes sure the sound data is in a malloced area and
  278. // not in a memory mapped one
  279. data = W_LockLumpNum(lump);
  280. SDL_LockAudio();
  281. // Returns a handle (not used).
  282. addsfx(id, channel, data, len);
  283. updateSoundParams(channel, vol, sep, pitch);
  284. SDL_UnlockAudio();
  285. return channel;
  286. }
  287. void I_StopSound (int handle)
  288. {
  289. #ifdef RANGECHECK
  290. if ((handle < 0) || (handle >= MAX_CHANNELS))
  291. I_Error("I_StopSound: handle out of range");
  292. #endif
  293. SDL_LockAudio();
  294. stopchan(handle);
  295. SDL_UnlockAudio();
  296. }
  297. boolean I_SoundIsPlaying(int handle)
  298. {
  299. #ifdef RANGECHECK
  300. if ((handle < 0) || (handle >= MAX_CHANNELS))
  301. I_Error("I_SoundIsPlaying: handle out of range");
  302. #endif
  303. return channelinfo[handle].data != NULL;
  304. }
  305. boolean I_AnySoundStillPlaying(void)
  306. {
  307. boolean result = false;
  308. int i;
  309. for (i=0; i<MAX_CHANNELS; i++)
  310. result |= channelinfo[i].data != NULL;
  311. return result;
  312. }
  313. #endif // ID_DISABLE_SDL_SOUND
  314. //
  315. // This function loops all active (internal) sound
  316. // channels, retrieves a given number of samples
  317. // from the raw sound data, modifies it according
  318. // to the current (internal) channel parameters,
  319. // mixes the per channel samples into the given
  320. // mixing buffer, and clamping it to the allowed
  321. // range.
  322. //
  323. // This function currently supports only 16bit.
  324. //
  325. static void I_UpdateSound(void *unused, uint8_t *stream, int len)
  326. {
  327. #ifdef IPHONE
  328. return;
  329. #endif
  330. #ifndef IPHONE
  331. // Mix current sound data.
  332. // Data, from raw sound, for right and left.
  333. register unsigned char sample;
  334. register int dl;
  335. register int dr;
  336. // Pointers in audio stream, left, right, end.
  337. signed short* leftout;
  338. signed short* rightout;
  339. signed short* leftend;
  340. // Step in stream, left and right, thus two.
  341. int step;
  342. // Mixing channel index.
  343. int chan;
  344. // Left and right channel
  345. // are in audio stream, alternating.
  346. leftout = (signed short *)stream;
  347. rightout = ((signed short *)stream)+1;
  348. step = 2;
  349. // Determine end, for left channel only
  350. // (right channel is implicit).
  351. leftend = leftout + (len/4)*step;
  352. // Mix sounds into the mixing buffer.
  353. // Loop over step*SAMPLECOUNT,
  354. // that is 512 values for two channels.
  355. while (leftout != leftend)
  356. {
  357. // Reset left/right value.
  358. //dl = 0;
  359. //dr = 0;
  360. dl = *leftout;
  361. dr = *rightout;
  362. // Love thy L2 chache - made this a loop.
  363. // Now more channels could be set at compile time
  364. // as well. Thus loop those channels.
  365. for ( chan = 0; chan < numChannels; chan++ )
  366. {
  367. // Check channel, if active.
  368. if (channelinfo[chan].data)
  369. {
  370. // Get the raw data from the channel.
  371. // no filtering
  372. // sample = *channelinfo[chan].data;
  373. // linear filtering
  374. sample = (((unsigned int)channelinfo[chan].data[0] * (0x10000 - channelinfo[chan].stepremainder))
  375. + ((unsigned int)channelinfo[chan].data[1] * (channelinfo[chan].stepremainder))) >> 16;
  376. // Add left and right part
  377. // for this channel (sound)
  378. // to the current data.
  379. // Adjust volume accordingly.
  380. dl += channelinfo[chan].leftvol_lookup[sample];
  381. dr += channelinfo[chan].rightvol_lookup[sample];
  382. // Increment index ???
  383. channelinfo[chan].stepremainder += channelinfo[chan].step;
  384. // MSB is next sample???
  385. channelinfo[chan].data += channelinfo[chan].stepremainder >> 16;
  386. // Limit to LSB???
  387. channelinfo[chan].stepremainder &= 0xffff;
  388. // Check whether we are done.
  389. if (channelinfo[chan].data >= channelinfo[chan].enddata)
  390. stopchan(chan);
  391. }
  392. }
  393. // Clamp to range. Left hardware channel.
  394. // Has been char instead of short.
  395. // if (dl > 127) *leftout = 127;
  396. // else if (dl < -128) *leftout = -128;
  397. // else *leftout = dl;
  398. if (dl > SHRT_MAX)
  399. *leftout = SHRT_MAX;
  400. else if (dl < SHRT_MIN)
  401. *leftout = SHRT_MIN;
  402. else
  403. *leftout = (signed short)dl;
  404. // Same for right hardware channel.
  405. if (dr > SHRT_MAX)
  406. *rightout = SHRT_MAX;
  407. else if (dr < SHRT_MIN)
  408. *rightout = SHRT_MIN;
  409. else
  410. *rightout = (signed short)dr;
  411. // Increment current pointers in stream
  412. leftout += step;
  413. rightout += step;
  414. }
  415. #endif
  416. }
  417. void I_ShutdownSound(void)
  418. {
  419. if (sound_inited) {
  420. lprintf(LO_INFO, "I_ShutdownSound: ");
  421. #ifdef HAVE_MIXER
  422. Mix_CloseAudio();
  423. #else
  424. SDL_CloseAudio();
  425. #endif
  426. lprintf(LO_INFO, "\n");
  427. sound_inited = false;
  428. }
  429. }
  430. //static SDL_AudioSpec audio;
  431. // Hack! Fix this if real SDL sound is reintroduced.
  432. #define AUDIO_S16MSB 0
  433. #define AUDIO_S16LSB 0
  434. void I_InitSound(void)
  435. {
  436. #ifdef HAVE_MIXER
  437. int audio_rate;
  438. uint16_t audio_format;
  439. int audio_channels;
  440. int audio_buffers;
  441. if (sound_inited)
  442. I_ShutdownSound();
  443. // Secure and configure sound device first.
  444. lprintf(LO_INFO,"I_InitSound: ");
  445. /* Initialize variables */
  446. audio_rate = snd_samplerate;
  447. #if ( SDL_BYTEORDER == SDL_BIG_ENDIAN )
  448. audio_format = AUDIO_S16MSB;
  449. #else
  450. audio_format = AUDIO_S16LSB;
  451. #endif
  452. audio_channels = 2;
  453. SAMPLECOUNT = 512;
  454. audio_buffers = SAMPLECOUNT*snd_samplerate/11025;
  455. if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) {
  456. lprintf(LO_INFO,"couldn't open audio with desired format\n");
  457. return;
  458. }
  459. sound_inited = true;
  460. SAMPLECOUNT = audio_buffers;
  461. Mix_SetPostMix(I_UpdateSound, NULL);
  462. lprintf(LO_INFO," configured audio device with %d samples/slice\n", SAMPLECOUNT);
  463. #else
  464. SDL_AudioSpec audio;
  465. // Secure and configure sound device first.
  466. lprintf(LO_INFO,"I_InitSound: ");
  467. // Open the audio device
  468. audio.freq = snd_samplerate;
  469. #if ( SDL_BYTEORDER == SDL_BIG_ENDIAN )
  470. audio.format = AUDIO_S16MSB;
  471. #else
  472. audio.format = AUDIO_S16LSB;
  473. #endif
  474. audio.channels = 2;
  475. audio.samples = SAMPLECOUNT*snd_samplerate/11025;
  476. audio.callback = I_UpdateSound;
  477. if ( SDL_OpenAudio(&audio, NULL) < 0 ) {
  478. lprintf(LO_INFO,"couldn't open audio with desired format\n");
  479. return;
  480. }
  481. SAMPLECOUNT = audio.samples;
  482. lprintf(LO_INFO," configured audio device with %d samples/slice\n", SAMPLECOUNT);
  483. #endif
  484. if (first_sound_init) {
  485. atexit(I_ShutdownSound);
  486. first_sound_init = false;
  487. }
  488. if (!nomusicparm)
  489. I_InitMusic();
  490. // Finished initialization.
  491. lprintf(LO_INFO,"I_InitSound: sound module ready\n");
  492. #ifndef HAVE_MIXER
  493. SDL_PauseAudio(0);
  494. #endif
  495. }
  496. //
  497. // MUSIC API.
  498. //
  499. #ifndef HAVE_OWN_MUSIC
  500. #ifdef HAVE_MIXER
  501. #include "SDL_mixer.h"
  502. #include "mmus2mid.h"
  503. static Mix_Music *music[2] = { NULL, NULL };
  504. char* music_tmp = NULL; /* cph - name of music temporary file */
  505. #endif
  506. void I_ShutdownMusic(void)
  507. {
  508. #ifdef HAVE_MIXER
  509. if (music_tmp) {
  510. //unlink(music_tmp);
  511. //lprintf(LO_DEBUG, "I_ShutdownMusic: removing %s\n", music_tmp);
  512. free(music_tmp);
  513. music_tmp = NULL;
  514. }
  515. #endif
  516. }
  517. #ifdef IPHONE
  518. const char * SysIphoneGetTempDir();
  519. static char iphoneMusicPath[PATH_MAX];
  520. #endif
  521. void I_InitMusic(void)
  522. {
  523. // Since we can load different IWADs in the same run of the iOS game, we need to clear
  524. // the cached lumpnums for all the music, since they differ in different IWADs.
  525. for ( int i = 0; i < NUMMUSIC; ++i ) {
  526. S_music[i].lumpnum = 0;
  527. }
  528. #ifdef HAVE_MIXER
  529. if (!music_tmp) {
  530. #ifndef _WIN32
  531. #ifdef IPHONE
  532. iphoneMusicPath[0] = '\0';
  533. strcat( iphoneMusicPath, SysIphoneGetTempDir() );
  534. strcat( iphoneMusicPath, "prboom-music-XXXXXX" );
  535. music_tmp = strdup(iphoneMusicPath);
  536. #else
  537. music_tmp = strdup("/tmp/prboom-music-XXXXXX");
  538. #endif
  539. {
  540. int fd = mkstemp(music_tmp);
  541. if (fd<0) {
  542. lprintf(LO_ERROR, "I_InitMusic: failed to create music temp file %s", music_tmp);
  543. free(music_tmp); return;
  544. } else
  545. close(fd);
  546. }
  547. #else /* !_WIN32 */
  548. music_tmp = strdup("doom.tmp");
  549. #endif
  550. atexit(I_ShutdownMusic);
  551. }
  552. #endif
  553. }
  554. extern int mus_pause_opt; // From m_misc.c
  555. extern bool mus_on;
  556. void I_PlaySong(int handle, int looping)
  557. {
  558. #ifdef HAVE_MIXER
  559. if ( music[handle] && mus_on ) {
  560. Mix_FadeInMusic(music[handle], looping ? -1 : 0, 500);
  561. }
  562. #endif
  563. }
  564. void I_PauseSong (int handle)
  565. {
  566. #ifdef HAVE_MIXER
  567. switch(mus_pause_opt) {
  568. case 0:
  569. I_StopSong(handle);
  570. break;
  571. case 1:
  572. Mix_PauseMusic();
  573. break;
  574. }
  575. #endif
  576. // Default - let music continue
  577. }
  578. void I_ResumeSong (int handle)
  579. {
  580. #ifdef HAVE_MIXER
  581. switch(mus_pause_opt) {
  582. case 0:
  583. I_PlaySong(handle,1);
  584. break;
  585. case 1:
  586. Mix_ResumeMusic();
  587. break;
  588. }
  589. #endif
  590. /* Otherwise, music wasn't stopped */
  591. }
  592. void I_StopSong(int handle)
  593. {
  594. #ifdef HAVE_MIXER
  595. Mix_FadeOutMusic(500);
  596. #endif
  597. }
  598. void I_UnRegisterSong(int handle)
  599. {
  600. #ifdef HAVE_MIXER
  601. if ( music[handle] ) {
  602. Mix_FreeMusic(music[handle]);
  603. music[handle] = NULL;
  604. }
  605. #endif
  606. }
  607. int I_RegisterSong(const void *data, size_t len)
  608. {
  609. #ifdef HAVE_MIXER
  610. MIDI *mididata;
  611. FILE *midfile;
  612. if ( len < 32 )
  613. return 0; // the data should at least as big as the MUS header
  614. if ( music_tmp == NULL )
  615. return 0;
  616. midfile = fopen(music_tmp, "wb");
  617. if ( midfile == NULL ) {
  618. lprintf(LO_ERROR,"Couldn't write MIDI to %s\n", music_tmp);
  619. return 0;
  620. }
  621. /* Convert MUS chunk to MIDI? */
  622. if ( memcmp(data, "MUS", 3) == 0 )
  623. {
  624. UBYTE *mid;
  625. int midlen;
  626. mididata = malloc(sizeof(MIDI));
  627. int musResult = mmus2mid(data, mididata, 89, 0);
  628. if ( musResult != 0 ) {
  629. printf( "Failed to conver MUS to MIDI: %s\n", music_tmp );
  630. }
  631. MIDIToMidi(mididata,&mid,&midlen);
  632. M_WriteFile(music_tmp,mid,midlen);
  633. free(mid);
  634. free_mididata(mididata);
  635. free(mididata);
  636. } else {
  637. fwrite(data, len, 1, midfile);
  638. }
  639. fclose(midfile);
  640. music[0] = Mix_LoadMUS(music_tmp);
  641. if ( music[0] == NULL ) {
  642. lprintf(LO_ERROR,"Couldn't load MIDI from %s: %s\n", music_tmp, Mix_GetError());
  643. }
  644. #endif
  645. return (0);
  646. }
  647. // cournia - try to load a music file into SDL_Mixer
  648. // returns true if could not load the file
  649. int I_RegisterMusic( const char* filename, musicinfo_t *song )
  650. {
  651. #ifdef HAVE_MIXER
  652. if (!filename) return 1;
  653. if (!song) return 1;
  654. music[0] = Mix_LoadMUS(filename);
  655. if (music[0] == NULL)
  656. {
  657. lprintf(LO_WARN,"Couldn't load music from %s: %s\nAttempting to load default MIDI music.\n", filename, Mix_GetError());
  658. return 1;
  659. }
  660. else
  661. {
  662. song->data = 0;
  663. song->handle = 0;
  664. song->lumpnum = 0;
  665. return 0;
  666. }
  667. #else
  668. return 1;
  669. #endif
  670. }
  671. void I_SetMusicVolume(int volume)
  672. {
  673. #ifdef HAVE_MIXER
  674. Mix_VolumeMusic(volume*8);
  675. #endif
  676. }
  677. #endif /* HAVE_OWN_MUSIC */