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
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 #include <math.h>
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 #ifdef HAVE_LIBSDL_MIXER
43 #define HAVE_MIXER
44 #endif
45
46 #include "SDL.h"
47 #include "SDL_audio.h"
48 #include "SDL_mutex.h"
49
50 #if SDL_VERSION_ATLEAST(1, 3, 0)
51 #include "SDL_endian.h"
52 #else
53 #include "SDL_byteorder.h"
54 #endif
55
56 #include "SDL_version.h"
57 #include "SDL_thread.h"
58 #ifdef HAVE_MIXER
59 #define USE_RWOPS
60 #include "SDL_mixer.h"
61 #endif
62
63 #include "z_zone.h"
64
65 #include "m_swap.h"
66 #include "i_sound.h"
67 #include "m_argv.h"
68 #include "m_misc.h"
69 #include "w_wad.h"
70 #include "lprintf.h"
71 #include "s_sound.h"
72
73 #include "doomdef.h"
74 #include "doomstat.h"
75 #include "doomtype.h"
76
77 #include "d_main.h"
78
79 //e6y
80 #include "i_pcsound.h"
81 #include "e6y.h"
82
83 int snd_pcspeaker;
84
85 // The number of internal mixing channels,
86 // the samples calculated for each mixing step,
87 // the size of the 16bit, 2 hardware channel (stereo)
88 // mixing buffer, and the samplerate of the raw data.
89
90 // Variables used by Boom from Allegro
91 // created here to avoid changes to core Boom files
92 int snd_card = 1;
93 int mus_card = 1;
94 int detect_voices = 0; // God knows
95
96 static dboolean sound_inited = false;
97 static dboolean first_sound_init = true;
98
99 // Needed for calling the actual sound output.
100 static int SAMPLECOUNT = 512;
101 #define MAX_CHANNELS 32
102
103 // MWM 2000-01-08: Sample rate in samples/second
104 int snd_samplerate = 11025;
105
106 // The actual output device.
107 int audio_fd;
108
109 typedef struct
110 {
111 // SFX id of the playing sound effect.
112 // Used to catch duplicates (like chainsaw).
113 int id;
114 // The channel step amount...
115 unsigned int step;
116 // ... and a 0.16 bit remainder of last step.
117 unsigned int stepremainder;
118 unsigned int samplerate;
119 // The channel data pointers, start and end.
120 const unsigned char *data;
121 const unsigned char *enddata;
122 // Time/gametic that the channel started playing,
123 // used to determine oldest, which automatically
124 // has lowest priority.
125 // In case number of active sounds exceeds
126 // available channels.
127 int starttime;
128 // left and right channel volume (0-127)
129 int leftvol;
130 int rightvol;
131 } channel_info_t;
132
133 channel_info_t channelinfo[MAX_CHANNELS];
134
135 // Pitch to stepping lookup, unused.
136 int steptable[256];
137
138 // Volume lookups.
139 //int vol_lookup[128 * 256];
140
141 // NSM
142 static int dumping_sound = 0;
143
144
145 // lock for updating any params related to sfx
146 SDL_mutex *sfxmutex;
147 // lock for updating any params related to music
148 SDL_mutex *musmutex;
149
150
151 /* cph
152 * stopchan
153 * Stops a sound, unlocks the data
154 */
155
stopchan(int i)156 static void stopchan(int i)
157 {
158 if (channelinfo[i].data) /* cph - prevent excess unlocks */
159 {
160 channelinfo[i].data = NULL;
161 W_UnlockLumpNum(S_sfx[channelinfo[i].id].lumpnum);
162 }
163 }
164
165 //
166 // This function adds a sound to the
167 // list of currently active sounds,
168 // which is maintained as a given number
169 // (eight, usually) of internal channels.
170 // Returns a handle.
171 //
addsfx(int sfxid,int channel,const unsigned char * data,size_t len)172 static int addsfx(int sfxid, int channel, const unsigned char *data, size_t len)
173 {
174 stopchan(channel);
175
176 channelinfo[channel].data = data;
177 /* Set pointer to end of raw data. */
178 channelinfo[channel].enddata = channelinfo[channel].data + len - 1;
179 channelinfo[channel].samplerate = (channelinfo[channel].data[3] << 8) + channelinfo[channel].data[2];
180 channelinfo[channel].data += 8; /* Skip header */
181
182 channelinfo[channel].stepremainder = 0;
183 // Should be gametic, I presume.
184 channelinfo[channel].starttime = gametic;
185
186 // Preserve sound SFX id,
187 // e.g. for avoiding duplicates of chainsaw.
188 channelinfo[channel].id = sfxid;
189
190 return channel;
191 }
192
updateSoundParams(int handle,int volume,int seperation,int pitch)193 static void updateSoundParams(int handle, int volume, int seperation, int pitch)
194 {
195 int slot = handle;
196 int rightvol;
197 int leftvol;
198 int step = steptable[pitch];
199
200 #ifdef RANGECHECK
201 if ((handle < 0) || (handle >= MAX_CHANNELS))
202 I_Error("I_UpdateSoundParams: handle out of range");
203 #endif
204
205 if (snd_pcspeaker)
206 return;
207
208 // Set stepping
209 // MWM 2000-12-24: Calculates proportion of channel samplerate
210 // to global samplerate for mixing purposes.
211 // Patched to shift left *then* divide, to minimize roundoff errors
212 // as well as to use SAMPLERATE as defined above, not to assume 11025 Hz
213 if (pitched_sounds)
214 channelinfo[slot].step = step + (((channelinfo[slot].samplerate << 16) / snd_samplerate) - 65536);
215 else
216 channelinfo[slot].step = ((channelinfo[slot].samplerate << 16) / snd_samplerate);
217
218 // Separation, that is, orientation/stereo.
219 // range is: 1 - 256
220 seperation += 1;
221
222 // Per left/right channel.
223 // x^2 seperation,
224 // adjust volume properly.
225 leftvol = volume - ((volume * seperation * seperation) >> 16);
226 seperation = seperation - 257;
227 rightvol = volume - ((volume * seperation * seperation) >> 16);
228
229 // Sanity check, clamp volume.
230 if (rightvol < 0 || rightvol > 127)
231 I_Error("rightvol out of bounds");
232
233 if (leftvol < 0 || leftvol > 127)
234 I_Error("leftvol out of bounds");
235
236 // Get the proper lookup table piece
237 // for this volume level???
238 channelinfo[slot].leftvol = leftvol;
239 channelinfo[slot].rightvol = rightvol;
240 }
241
I_UpdateSoundParams(int handle,int volume,int seperation,int pitch)242 void I_UpdateSoundParams(int handle, int volume, int seperation, int pitch)
243 {
244 SDL_LockMutex (sfxmutex);
245 updateSoundParams(handle, volume, seperation, pitch);
246 SDL_UnlockMutex (sfxmutex);
247 }
248
249 //
250 // SFX API
251 // Note: this was called by S_Init.
252 // However, whatever they did in the
253 // old DPMS based DOS version, this
254 // were simply dummies in the Linux
255 // version.
256 // See soundserver initdata().
257 //
I_SetChannels(void)258 void I_SetChannels(void)
259 {
260 // Init internal lookups (raw data, mixing buffer, channels).
261 // This function sets up internal lookups used during
262 // the mixing process.
263 int i;
264 //int j;
265
266 int *steptablemid = steptable + 128;
267
268 // Okay, reset internal mixing channels to zero.
269 for (i = 0; i < MAX_CHANNELS; i++)
270 {
271 memset(&channelinfo[i], 0, sizeof(channel_info_t));
272 }
273
274 // This table provides step widths for pitch parameters.
275 // I fail to see that this is currently used.
276 for (i = -128 ; i < 128 ; i++)
277 steptablemid[i] = (int)(pow(1.2, ((double)i / (64.0 * snd_samplerate / 11025))) * 65536.0);
278
279
280 // Generates volume lookup tables
281 // which also turn the unsigned samples
282 // into signed samples.
283 /*
284 for (i = 0 ; i < 128 ; i++)
285 for (j = 0 ; j < 256 ; j++)
286 {
287 // proff - made this a little bit softer, because with
288 // full volume the sound clipped badly
289 vol_lookup[i * 256 + j] = (i * (j - 128) * 256) / 191;
290 //vol_lookup[i*256+j] = (i*(j-128)*256)/127;
291 }
292 */
293 }
294
295 //
296 // Retrieve the raw data lump index
297 // for a given SFX name.
298 //
I_GetSfxLumpNum(sfxinfo_t * sfx)299 int I_GetSfxLumpNum(sfxinfo_t *sfx)
300 {
301 char namebuf[9];
302 const char *prefix;
303
304 // Different prefix for PC speaker sound effects.
305 prefix = (snd_pcspeaker ? "dp" : "ds");
306
307 sprintf(namebuf, "%s%s", prefix, sfx->name);
308 return W_SafeGetNumForName(namebuf); //e6y: make missing sounds non-fatal
309 }
310
311 //
312 // Starting a sound means adding it
313 // to the current list of active sounds
314 // in the internal channels.
315 // As the SFX info struct contains
316 // e.g. a pointer to the raw data,
317 // it is ignored.
318 // As our sound handling does not handle
319 // priority, it is ignored.
320 // Pitching (that is, increased speed of playback)
321 // is set, but currently not used by mixing.
322 //
I_StartSound(int id,int channel,int vol,int sep,int pitch,int priority)323 int I_StartSound(int id, int channel, int vol, int sep, int pitch, int priority)
324 {
325 const unsigned char *data;
326 int lump;
327 size_t len;
328
329 if ((channel < 0) || (channel >= MAX_CHANNELS))
330 #ifdef RANGECHECK
331 I_Error("I_StartSound: handle out of range");
332 #else
333 return -1;
334 #endif
335
336 if (snd_pcspeaker)
337 return I_PCS_StartSound(id, channel, vol, sep, pitch, priority);
338
339 lump = S_sfx[id].lumpnum;
340
341 // We will handle the new SFX.
342 // Set pointer to raw data.
343 len = W_LumpLength(lump);
344
345 // e6y: Crash with zero-length sounds.
346 // Example wad: dakills (http://www.doomworld.com/idgames/index.php?id=2803)
347 // The entries DSBSPWLK, DSBSPACT, DSSWTCHN and DSSWTCHX are all zero-length sounds
348 if (len <= 8) return -1;
349
350 /* Find padded length */
351 len -= 8;
352 // do the lump caching outside the SDL_LockAudio/SDL_UnlockAudio pair
353 // use locking which makes sure the sound data is in a malloced area and
354 // not in a memory mapped one
355 data = W_LockLumpNum(lump);
356
357 SDL_LockMutex (sfxmutex);
358
359 // Returns a handle (not used).
360 addsfx(id, channel, data, len);
361 updateSoundParams(channel, vol, sep, pitch);
362
363 SDL_UnlockMutex (sfxmutex);
364
365
366 return channel;
367 }
368
369
370
I_StopSound(int handle)371 void I_StopSound (int handle)
372 {
373 #ifdef RANGECHECK
374 if ((handle < 0) || (handle >= MAX_CHANNELS))
375 I_Error("I_StopSound: handle out of range");
376 #endif
377
378 if (snd_pcspeaker)
379 {
380 I_PCS_StopSound(handle);
381 return;
382 }
383
384 SDL_LockMutex (sfxmutex);
385 stopchan(handle);
386 SDL_UnlockMutex (sfxmutex);
387 }
388
389
I_SoundIsPlaying(int handle)390 dboolean I_SoundIsPlaying(int handle)
391 {
392 #ifdef RANGECHECK
393 if ((handle < 0) || (handle >= MAX_CHANNELS))
394 I_Error("I_SoundIsPlaying: handle out of range");
395 #endif
396
397 if (snd_pcspeaker)
398 return I_PCS_SoundIsPlaying(handle);
399
400 return channelinfo[handle].data != NULL;
401 }
402
403
I_AnySoundStillPlaying(void)404 dboolean I_AnySoundStillPlaying(void)
405 {
406 dboolean result = false;
407 int i;
408
409 if (snd_pcspeaker)
410 return false;
411
412 for (i = 0; i < MAX_CHANNELS; i++)
413 result |= channelinfo[i].data != NULL;
414
415 return result;
416 }
417
418
419 //
420 // This function loops all active (internal) sound
421 // channels, retrieves a given number of samples
422 // from the raw sound data, modifies it according
423 // to the current (internal) channel parameters,
424 // mixes the per channel samples into the given
425 // mixing buffer, and clamping it to the allowed
426 // range.
427 //
428 // This function currently supports only 16bit.
429 //
430
431 #ifndef HAVE_OWN_MUSIC
432 static void Exp_UpdateMusic (void *buff, unsigned nsamp);
433 #endif
434
435 // from pcsound_sdl.c
436 void PCSound_Mix_Callback(void *udata, Uint8 *stream, int len);
437
I_UpdateSound(void * unused,Uint8 * stream,int len)438 static void I_UpdateSound(void *unused, Uint8 *stream, int len)
439 {
440 // Mix current sound data.
441 // Data, from raw sound, for right and left.
442 // register unsigned char sample;
443 register int dl;
444 register int dr;
445
446 // Pointers in audio stream, left, right, end.
447 signed short *leftout;
448 signed short *rightout;
449 signed short *leftend;
450 // Step in stream, left and right, thus two.
451 int step;
452
453 // Mixing channel index.
454 int chan;
455
456 // NSM: when dumping sound, ignore the callback calls and only
457 // service dumping calls
458 if (dumping_sound && unused != (void *) 0xdeadbeef)
459 return;
460
461 #ifndef HAVE_OWN_MUSIC
462 // do music update
463 if (use_experimental_music)
464 {
465 SDL_LockMutex (musmutex);
466 Exp_UpdateMusic (stream, len / 4);
467 SDL_UnlockMutex (musmutex);
468 }
469 #endif
470
471 if (snd_pcspeaker)
472 {
473 PCSound_Mix_Callback (NULL, stream, len);
474 // no sfx mixing
475 return;
476 }
477
478 SDL_LockMutex (sfxmutex);
479 // Left and right channel
480 // are in audio stream, alternating.
481 leftout = (signed short *)stream;
482 rightout = ((signed short *)stream) + 1;
483 step = 2;
484
485 // Determine end, for left channel only
486 // (right channel is implicit).
487 leftend = leftout + (len / 4) * step;
488
489 // Mix sounds into the mixing buffer.
490 // Loop over step*SAMPLECOUNT,
491 // that is 512 values for two channels.
492 while (leftout != leftend)
493 {
494 // Reset left/right value.
495 //dl = 0;
496 //dr = 0;
497 dl = *leftout;
498 dr = *rightout;
499
500 // Love thy L2 chache - made this a loop.
501 // Now more channels could be set at compile time
502 // as well. Thus loop those channels.
503 for ( chan = 0; chan < numChannels; chan++ )
504 {
505 // Check channel, if active.
506 if (channelinfo[chan].data)
507 {
508 // Get the raw data from the channel.
509 // no filtering
510 //int s = channelinfo[chan].data[0] * 0x10000 - 0x800000;
511
512 // linear filtering
513 // the old SRC did linear interpolation back into 8 bit, and then expanded to 16 bit.
514 // this does interpolation and 8->16 at same time, allowing slightly higher quality
515 int s = ((unsigned int)channelinfo[chan].data[0] * (0x10000 - channelinfo[chan].stepremainder))
516 + ((unsigned int)channelinfo[chan].data[1] * (channelinfo[chan].stepremainder))
517 - 0x800000; // convert to signed
518
519
520 // Add left and right part
521 // for this channel (sound)
522 // to the current data.
523 // Adjust volume accordingly.
524
525 // full loudness (vol=127) is actually 127/191
526
527 dl += channelinfo[chan].leftvol * s / 49152; // >> 15;
528 dr += channelinfo[chan].rightvol * s / 49152; // >> 15;
529
530 // Increment index ???
531 channelinfo[chan].stepremainder += channelinfo[chan].step;
532 // MSB is next sample???
533 channelinfo[chan].data += channelinfo[chan].stepremainder >> 16;
534 // Limit to LSB???
535 channelinfo[chan].stepremainder &= 0xffff;
536
537 // Check whether we are done.
538 if (channelinfo[chan].data >= channelinfo[chan].enddata)
539 stopchan(chan);
540 }
541 }
542
543 // Clamp to range. Left hardware channel.
544 // Has been char instead of short.
545 // if (dl > 127) *leftout = 127;
546 // else if (dl < -128) *leftout = -128;
547 // else *leftout = dl;
548
549 if (dl > SHRT_MAX)
550 *leftout = SHRT_MAX;
551 else if (dl < SHRT_MIN)
552 *leftout = SHRT_MIN;
553 else
554 *leftout = (signed short)dl;
555
556 // Same for right hardware channel.
557 if (dr > SHRT_MAX)
558 *rightout = SHRT_MAX;
559 else if (dr < SHRT_MIN)
560 *rightout = SHRT_MIN;
561 else
562 *rightout = (signed short)dr;
563
564 // Increment current pointers in stream
565 leftout += step;
566 rightout += step;
567 }
568 SDL_UnlockMutex (sfxmutex);
569 }
570
I_ShutdownSound(void)571 void I_ShutdownSound(void)
572 {
573 if (sound_inited)
574 {
575 lprintf(LO_INFO, "I_ShutdownSound: ");
576 #ifdef HAVE_MIXER
577 Mix_CloseAudio();
578 #endif
579 SDL_CloseAudio();
580 lprintf(LO_INFO, "\n");
581 sound_inited = false;
582
583 if (sfxmutex)
584 {
585 SDL_DestroyMutex (sfxmutex);
586 sfxmutex = NULL;
587 }
588 }
589 }
590
591 //static SDL_AudioSpec audio;
592
I_InitSound(void)593 void I_InitSound(void)
594 {
595 int audio_rate;
596 int audio_channels;
597 int audio_buffers;
598 SDL_AudioSpec audio;
599
600 // haleyjd: the docs say we should do this
601 if (SDL_InitSubSystem(SDL_INIT_AUDIO))
602 {
603 lprintf(LO_INFO, "Couldn't initialize SDL audio (%s))\n", SDL_GetError());
604 nosfxparm = true;
605 nomusicparm = true;
606 return;
607 }
608 if (sound_inited)
609 I_ShutdownSound();
610
611 // Secure and configure sound device first.
612 lprintf(LO_INFO, "I_InitSound: ");
613
614 if (!use_experimental_music)
615 {
616 #ifdef HAVE_MIXER
617
618 /* Initialize variables */
619 audio_rate = snd_samplerate;
620 audio_channels = 2;
621 SAMPLECOUNT = 512;
622 audio_buffers = SAMPLECOUNT*snd_samplerate/11025;
623
624 if (Mix_OpenAudio(audio_rate, MIX_DEFAULT_FORMAT, audio_channels, audio_buffers) < 0)
625 {
626 lprintf(LO_INFO,"couldn't open audio with desired format (%s)\n", SDL_GetError());
627 nosfxparm = true;
628 nomusicparm = true;
629 return;
630 }
631 sound_inited_once = true;//e6y
632 sound_inited = true;
633 SAMPLECOUNT = audio_buffers;
634 Mix_SetPostMix(I_UpdateSound, NULL);
635 lprintf(LO_INFO," configured audio device with %d samples/slice\n", SAMPLECOUNT);
636 }
637 else
638 #else // HAVE_MIXER
639 }
640 #endif // HAVE_MIXER
641 {
642 // Open the audio device
643 audio.freq = snd_samplerate;
644 #if ( SDL_BYTEORDER == SDL_BIG_ENDIAN )
645 audio.format = AUDIO_S16MSB;
646 #else
647 audio.format = AUDIO_S16LSB;
648 #endif
649 audio.channels = 2;
650 audio.samples = SAMPLECOUNT * snd_samplerate / 11025;
651 audio.callback = I_UpdateSound;
652 if ( SDL_OpenAudio(&audio, NULL) < 0 )
653 {
654 lprintf(LO_INFO, "couldn't open audio with desired format (%s))\n", SDL_GetError());
655 nosfxparm = true;
656 nomusicparm = true;
657 return;
658 }
659 sound_inited_once = true;//e6y
660 sound_inited = true;
661 SAMPLECOUNT = audio.samples;
662 lprintf(LO_INFO, " configured audio device with %d samples/slice\n", SAMPLECOUNT);
663 }
664 if (first_sound_init)
665 {
666 atexit(I_ShutdownSound);
667 first_sound_init = false;
668 }
669
670 sfxmutex = SDL_CreateMutex ();
671
672 // If we are using the PC speaker, we now need to initialise it.
673 if (snd_pcspeaker)
674 I_PCS_InitSound();
675
676 if (!nomusicparm)
677 I_InitMusic();
678
679 // Finished initialization.
680 lprintf(LO_INFO, "I_InitSound: sound module ready\n");
681 SDL_PauseAudio(0);
682 }
683
684
685 // NSM sound capture routines
686
687 // silences sound output, and instead allows sound capture to work
688 // call this before sound startup
I_SetSoundCap(void)689 void I_SetSoundCap (void)
690 {
691 dumping_sound = 1;
692 }
693
694 // grabs len samples of audio (16 bit interleaved)
I_GrabSound(int len)695 unsigned char *I_GrabSound (int len)
696 {
697 static unsigned char *buffer = NULL;
698 static size_t buffer_size = 0;
699 size_t size;
700
701 if (!dumping_sound)
702 return NULL;
703
704 size = len * 4;
705 if (!buffer || size > buffer_size)
706 {
707 buffer_size = size * 4;
708 buffer = realloc (buffer, buffer_size);
709 }
710
711 if (buffer)
712 {
713 memset (buffer, 0, size);
714 I_UpdateSound ((void *) 0xdeadbeef, buffer, size);
715 }
716 return buffer;
717 }
718
719
720
721
722 // NSM helper routine for some of the streaming audio
I_ResampleStream(void * dest,unsigned nsamp,void (* proc)(void * dest,unsigned nsamp),unsigned sratein,unsigned srateout)723 void I_ResampleStream (void *dest, unsigned nsamp, void (*proc) (void *dest, unsigned nsamp), unsigned sratein, unsigned srateout)
724 { // assumes 16 bit signed interleaved stereo
725
726 unsigned i;
727 int j = 0;
728
729 short *sout = dest;
730
731 static short *sin = NULL;
732 static unsigned sinsamp = 0;
733
734 static unsigned remainder = 0;
735 unsigned step = (sratein << 16) / (unsigned) srateout;
736
737 unsigned nreq = (step * nsamp + remainder) >> 16;
738
739 if (nreq > sinsamp)
740 {
741 sin = realloc (sin, (nreq + 1) * 4);
742 if (!sinsamp) // avoid pop when first starting stream
743 sin[0] = sin[1] = 0;
744 sinsamp = nreq;
745 }
746
747 proc (sin + 2, nreq);
748
749 for (i = 0; i < nsamp; i++)
750 {
751 *sout++ = ((unsigned) sin[j + 0] * (0x10000 - remainder) +
752 (unsigned) sin[j + 2] * remainder) >> 16;
753 *sout++ = ((unsigned) sin[j + 1] * (0x10000 - remainder) +
754 (unsigned) sin[j + 3] * remainder) >> 16;
755 remainder += step;
756 j += remainder >> 16 << 1;
757 remainder &= 0xffff;
758 }
759 sin[0] = sin[nreq * 2];
760 sin[1] = sin[nreq * 2 + 1];
761 }
762
763
764 #ifndef HAVE_OWN_MUSIC
765
766 //
767 // MUSIC API.
768 //
769
770 int use_experimental_music = -1;
771
772 static void Exp_UpdateMusic (void *buff, unsigned nsamp);
773 static int Exp_RegisterMusic (const char *filename, musicinfo_t *song);
774 static int Exp_RegisterSong (const void *data, size_t len);
775 static int Exp_RegisterSongEx (const void *data, size_t len, int try_mus2mid);
776 static void Exp_SetMusicVolume (int volume);
777 static void Exp_UnRegisterSong(int handle);
778 static void Exp_StopSong(int handle);
779 static void Exp_ResumeSong (int handle);
780 static void Exp_PauseSong (int handle);
781 static void Exp_PlaySong(int handle, int looping);
782 static void Exp_InitMusic(void);
783 static void Exp_ShutdownMusic(void);
784
785
786
787
788
789 #ifdef HAVE_MIXER
790
791 #include "mus2mid.h"
792
793
794 static Mix_Music *music[2] = { NULL, NULL };
795
796 // Some tracks are directly streamed from the RWops;
797 // we need to free them in the end
798 static SDL_RWops *rw_midi = NULL;
799
800 static char *music_tmp = NULL; /* cph - name of music temporary file */
801
802 // List of extensions that can be appended to music_tmp. First must be "".
803 static const char *music_tmp_ext[] = { "", ".mp3", ".ogg" };
804 #define MUSIC_TMP_EXT (sizeof(music_tmp_ext)/sizeof(*music_tmp_ext))
805
806 #endif
807
I_ShutdownMusic(void)808 void I_ShutdownMusic(void)
809 {
810 if (use_experimental_music)
811 {
812 Exp_ShutdownMusic ();
813 return;
814 }
815 #ifdef HAVE_MIXER
816 if (music_tmp) {
817 int i;
818 char *name;
819
820 S_StopMusic();
821 for (i = 0; i < MUSIC_TMP_EXT; i++)
822 {
823 name = malloc(strlen(music_tmp) + strlen(music_tmp_ext[i]) + 1);
824 sprintf(name, "%s%s", music_tmp, music_tmp_ext[i]);
825 if (!unlink(name))
826 lprintf(LO_DEBUG, "I_ShutdownMusic: removed %s\n", name);
827 free(name);
828 }
829 free(music_tmp);
830 music_tmp = NULL;
831 }
832 #endif
833 }
834
I_InitMusic(void)835 void I_InitMusic(void)
836 {
837 if (use_experimental_music)
838 {
839 Exp_InitMusic ();
840 return;
841 }
842 #ifdef HAVE_MIXER
843 if (!music_tmp) {
844 #ifndef _WIN32
845 music_tmp = strdup("/tmp/"PACKAGE"-music-XXXXXX");
846 {
847 int fd = mkstemp(music_tmp);
848 if (fd<0) {
849 lprintf(LO_ERROR, "I_InitMusic: failed to create music temp file %s", music_tmp);
850 free(music_tmp); music_tmp = NULL; return;
851 } else
852 close(fd);
853 }
854 #else /* !_WIN32 */
855 music_tmp = strdup("doom.tmp");
856 #endif
857 atexit(I_ShutdownMusic);
858 }
859 return;
860 #endif
861 lprintf (LO_INFO, "I_InitMusic: Was compiled without SDL_Mixer support. You should enable experimental music.\n");
862 }
863
I_PlaySong(int handle,int looping)864 void I_PlaySong(int handle, int looping)
865 {
866 if (use_experimental_music)
867 {
868 Exp_PlaySong (handle, looping);
869 return;
870 }
871 #ifdef HAVE_MIXER
872 if ( music[handle] ) {
873 //Mix_FadeInMusic(music[handle], looping ? -1 : 0, 500);
874 Mix_PlayMusic(music[handle], looping ? -1 : 0);
875
876 // haleyjd 10/28/05: make sure volume settings remain consistent
877 I_SetMusicVolume(snd_MusicVolume);
878 }
879 #endif
880 }
881
882 extern int mus_pause_opt; // From m_misc.c
883
I_PauseSong(int handle)884 void I_PauseSong (int handle)
885 {
886 if (use_experimental_music)
887 {
888 Exp_PauseSong (handle);
889 return;
890 }
891 #ifdef HAVE_MIXER
892 switch(mus_pause_opt) {
893 case 0:
894 I_StopSong(handle);
895 break;
896 case 1:
897 switch (Mix_GetMusicType(NULL))
898 {
899 case MUS_NONE:
900 break;
901 case MUS_MID:
902 // SDL_mixer's native MIDI music playing does not pause properly.
903 // As a workaround, set the volume to 0 when paused.
904 I_SetMusicVolume(0);
905 break;
906 default:
907 Mix_PauseMusic();
908 break;
909 }
910 break;
911 }
912 #endif
913 // Default - let music continue
914 }
915
I_ResumeSong(int handle)916 void I_ResumeSong (int handle)
917 {
918 if (use_experimental_music)
919 {
920 Exp_ResumeSong (handle);
921 return;
922 }
923 #ifdef HAVE_MIXER
924 switch(mus_pause_opt) {
925 case 0:
926 I_PlaySong(handle,1);
927 break;
928 case 1:
929 switch (Mix_GetMusicType(NULL))
930 {
931 case MUS_NONE:
932 break;
933 case MUS_MID:
934 I_SetMusicVolume(snd_MusicVolume);
935 break;
936 default:
937 Mix_ResumeMusic();
938 break;
939 }
940 break;
941 }
942 #endif
943 /* Otherwise, music wasn't stopped */
944 }
945
I_StopSong(int handle)946 void I_StopSong(int handle)
947 {
948 if (use_experimental_music)
949 {
950 Exp_StopSong (handle);
951 return;
952 }
953 #ifdef HAVE_MIXER
954 // halt music playback
955 Mix_HaltMusic();
956 #endif
957 }
958
I_UnRegisterSong(int handle)959 void I_UnRegisterSong(int handle)
960 {
961 if (use_experimental_music)
962 {
963 Exp_UnRegisterSong (handle);
964 return;
965 }
966 #ifdef HAVE_MIXER
967 if ( music[handle] ) {
968 Mix_FreeMusic(music[handle]);
969 music[handle] = NULL;
970
971 // Free RWops
972 if (rw_midi != NULL)
973 {
974 //SDL_FreeRW(rw_midi);
975 rw_midi = NULL;
976 }
977 }
978 #endif
979 }
980
I_RegisterSong(const void * data,size_t len)981 int I_RegisterSong(const void *data, size_t len)
982 {
983 int i;
984 char *name;
985 dboolean io_errors = false;
986
987
988 if (use_experimental_music)
989 {
990 return Exp_RegisterSong (data, len);
991 }
992 #ifdef HAVE_MIXER
993
994 if (music_tmp == NULL)
995 return 0;
996
997 // e6y: new logic by me
998 // Now you can hear title music in deca.wad
999 // http://www.doomworld.com/idgames/index.php?id=8808
1000 // Ability to use mp3 and ogg as inwad lump
1001
1002 music[0] = NULL;
1003
1004 if (len > 4 && memcmp(data, "MUS", 3) != 0)
1005 {
1006 // The header has no MUS signature
1007 // Let's try to load this song with SDL
1008 for (i = 0; i < MUSIC_TMP_EXT; i++)
1009 {
1010 // Current SDL_mixer (up to 1.2.8) cannot load some MP3 and OGG
1011 // without proper extension
1012 name = malloc(strlen(music_tmp) + strlen(music_tmp_ext[i]) + 1);
1013 sprintf(name, "%s%s", music_tmp, music_tmp_ext[i]);
1014
1015 if (strlen(music_tmp_ext[i]) == 0)
1016 {
1017 //midi
1018 rw_midi = SDL_RWFromConstMem(data, len);
1019 if (rw_midi)
1020 {
1021 music[0] = Mix_LoadMUS_RW(rw_midi);
1022 }
1023 }
1024
1025 if (!music[0])
1026 {
1027 io_errors = (M_WriteFile(name, data, len) == 0);
1028 if (!io_errors)
1029 {
1030 music[0] = Mix_LoadMUS(name);
1031 }
1032 }
1033
1034 free(name);
1035 if (music[0])
1036 break; // successfully loaded
1037 }
1038 }
1039
1040 // e6y: from Chocolate-Doom
1041 // Assume a MUS file and try to convert
1042 if (!music[0])
1043 {
1044 MEMFILE *instream;
1045 MEMFILE *outstream;
1046 void *outbuf;
1047 size_t outbuf_len;
1048 int result;
1049
1050 instream = mem_fopen_read(data, len);
1051 outstream = mem_fopen_write();
1052
1053 // e6y: from chocolate-doom
1054 // New mus -> mid conversion code thanks to Ben Ryves <benryves@benryves.com>
1055 // This plays back a lot of music closer to Vanilla Doom - eg. tnt.wad map02
1056 result = mus2mid(instream, outstream);
1057
1058 if (result != 0)
1059 {
1060 size_t muslen = len;
1061 const unsigned char *musptr = data;
1062
1063 // haleyjd 04/04/10: scan forward for a MUS header. Evidently DMX was
1064 // capable of doing this, and would skip over any intervening data. That,
1065 // or DMX doesn't use the MUS header at all somehow.
1066 while (musptr < (const unsigned char*)data + len - sizeof(musheader))
1067 {
1068 // if we found a likely header start, reset the mus pointer to that location,
1069 // otherwise just leave it alone and pray.
1070 if (!strncmp((const char*)musptr, "MUS\x1a", 4))
1071 {
1072 mem_fclose(instream);
1073 instream = mem_fopen_read(musptr, muslen);
1074 result = mus2mid(instream, outstream);
1075 break;
1076 }
1077
1078 musptr++;
1079 muslen--;
1080 }
1081 }
1082
1083 if (result == 0)
1084 {
1085 mem_get_buf(outstream, &outbuf, &outbuf_len);
1086
1087 rw_midi = SDL_RWFromMem(outbuf, outbuf_len);
1088 if (rw_midi)
1089 {
1090 music[0] = Mix_LoadMUS_RW(rw_midi);
1091 }
1092
1093 if (!music[0])
1094 {
1095 io_errors = M_WriteFile(music_tmp, outbuf, outbuf_len) == 0;
1096
1097 if (!io_errors)
1098 {
1099 // Load the MUS
1100 music[0] = Mix_LoadMUS(music_tmp);
1101 }
1102 }
1103 }
1104
1105 mem_fclose(instream);
1106 mem_fclose(outstream);
1107 }
1108
1109 // Failed to load
1110 if (!music[0])
1111 {
1112 // Conversion failed, free everything
1113 if (rw_midi != NULL)
1114 {
1115 //SDL_FreeRW(rw_midi);
1116 rw_midi = NULL;
1117 }
1118
1119 if (io_errors)
1120 {
1121 lprintf(LO_ERROR, "Error writing song\n");
1122 }
1123 else
1124 {
1125 lprintf(LO_ERROR, "Error loading song: %s\n", Mix_GetError());
1126 }
1127 }
1128
1129 #endif
1130 return (0);
1131 }
1132
1133 // cournia - try to load a music file into SDL_Mixer
1134 // returns true if could not load the file
I_RegisterMusic(const char * filename,musicinfo_t * song)1135 int I_RegisterMusic( const char* filename, musicinfo_t *song )
1136 {
1137 if (use_experimental_music)
1138 {
1139 return Exp_RegisterMusic (filename, song);
1140
1141 }
1142
1143
1144 #ifdef HAVE_MIXER
1145 if (!filename) return 1;
1146 if (!song) return 1;
1147 music[0] = Mix_LoadMUS(filename);
1148 if (music[0] == NULL)
1149 {
1150 lprintf(LO_WARN,"Couldn't load music from %s: %s\nAttempting to load default MIDI music.\n", filename, Mix_GetError());
1151 return 1;
1152 }
1153 else
1154 {
1155 song->data = 0;
1156 song->handle = 0;
1157 song->lumpnum = 0;
1158 return 0;
1159 }
1160 #else
1161 return 1;
1162 #endif
1163 }
1164
I_SetMusicVolume(int volume)1165 void I_SetMusicVolume(int volume)
1166 {
1167 if (use_experimental_music)
1168 {
1169 Exp_SetMusicVolume (volume);
1170 return;
1171 }
1172 #ifdef HAVE_MIXER
1173 Mix_VolumeMusic(volume*8);
1174
1175 #ifdef _WIN32
1176 // e6y: workaround
1177 if (mus_extend_volume && Mix_GetMusicType(NULL) == MUS_MID)
1178 I_midiOutSetVolumes(volume /* *8 */);
1179 #endif
1180
1181 #endif
1182 }
1183
1184
1185
1186
1187
1188
1189
1190 /********************************************************
1191
1192 experimental music API
1193
1194 ********************************************************/
1195
1196
1197
1198 // note that the "handle" passed around by s_sound is ignored
1199 // however, a handle is maintained for the individual music players
1200
1201 const char *snd_soundfont; // soundfont name for synths that use it
1202 const char *snd_mididev; // midi device to use (portmidiplayer)
1203
1204 #include "mus2mid.h"
1205
1206 #include "MUSIC/musicplayer.h"
1207
1208 #include "MUSIC/oplplayer.h"
1209 #include "MUSIC/madplayer.h"
1210 #include "MUSIC/dumbplayer.h"
1211 #include "MUSIC/flplayer.h"
1212 #include "MUSIC/vorbisplayer.h"
1213 #include "MUSIC/portmidiplayer.h"
1214
1215 // list of possible music players
1216 static const music_player_t *music_players[] =
1217 { // until some ui work is done, the order these appear is the autodetect order.
1218 // of particular importance: things that play mus have to be last, because
1219 // mus2midi very often succeeds even on garbage input
1220 &vorb_player, // vorbisplayer.h
1221 &mp_player, // madplayer.h
1222 &db_player, // dumbplayer.h
1223 &fl_player, // flplayer.h
1224 &opl_synth_player, // oplplayer.h
1225 &pm_player, // portmidiplayer.h
1226 NULL
1227 };
1228 #define NUM_MUS_PLAYERS ((int)(sizeof (music_players) / sizeof (music_player_t *) - 1))
1229
1230
1231 static int music_player_was_init[NUM_MUS_PLAYERS];
1232
1233 #define PLAYER_VORBIS "vorbis player"
1234 #define PLAYER_MAD "mad mp3 player"
1235 #define PLAYER_DUMB "dumb tracker player"
1236 #define PLAYER_FLUIDSYNTH "fluidsynth midi player"
1237 #define PLAYER_OPL2 "opl2 synth player"
1238 #define PLAYER_PORTMIDI "portmidi midi player"
1239
1240 // order in which players are to be tried
1241 char music_player_order[NUM_MUS_PLAYERS][200] =
1242 {
1243 PLAYER_VORBIS,
1244 PLAYER_MAD,
1245 PLAYER_DUMB,
1246 PLAYER_FLUIDSYNTH,
1247 PLAYER_OPL2,
1248 PLAYER_PORTMIDI,
1249 };
1250
1251 // prefered MIDI device
1252 const char *snd_midiplayer;
1253
1254 const char *midiplayers[midi_player_last + 1] = {
1255 "sdl", "fluidsynth", "opl2", "portmidi", NULL};
1256
1257 static int current_player = -1;
1258 static const void *music_handle = NULL;
1259
1260 // songs played directly from wad (no mus->mid conversion)
1261 // won't have this
1262 static void *song_data = NULL;
1263
1264
1265
1266
Exp_ShutdownMusic(void)1267 static void Exp_ShutdownMusic(void)
1268 {
1269 int i;
1270 S_StopMusic ();
1271
1272 for (i = 0; music_players[i]; i++)
1273 {
1274 if (music_player_was_init[i])
1275 music_players[i]->shutdown ();
1276 }
1277
1278 if (musmutex)
1279 {
1280 SDL_DestroyMutex (musmutex);
1281 musmutex = NULL;
1282 }
1283 }
1284
1285
Exp_InitMusic(void)1286 static void Exp_InitMusic(void)
1287 {
1288 int i;
1289 musmutex = SDL_CreateMutex ();
1290
1291
1292 // todo not so greedy
1293 for (i = 0; music_players[i]; i++)
1294 music_player_was_init[i] = music_players[i]->init (snd_samplerate);
1295 atexit(Exp_ShutdownMusic);
1296 }
1297
Exp_PlaySong(int handle,int looping)1298 static void Exp_PlaySong(int handle, int looping)
1299 {
1300 if (music_handle)
1301 {
1302 SDL_LockMutex (musmutex);
1303 music_players[current_player]->play (music_handle, looping);
1304 music_players[current_player]->setvolume (snd_MusicVolume);
1305 SDL_UnlockMutex (musmutex);
1306 }
1307
1308 }
1309
1310 extern int mus_pause_opt; // From m_misc.c
1311
Exp_PauseSong(int handle)1312 static void Exp_PauseSong (int handle)
1313 {
1314 if (!music_handle)
1315 return;
1316
1317 SDL_LockMutex (musmutex);
1318 switch (mus_pause_opt)
1319 {
1320 case 0:
1321 music_players[current_player]->stop ();
1322 break;
1323 case 1:
1324 music_players[current_player]->pause ();
1325 break;
1326 default: // Default - let music continue
1327 break;
1328 }
1329 SDL_UnlockMutex (musmutex);
1330 }
1331
Exp_ResumeSong(int handle)1332 static void Exp_ResumeSong (int handle)
1333 {
1334 if (!music_handle)
1335 return;
1336
1337 SDL_LockMutex (musmutex);
1338 switch (mus_pause_opt)
1339 {
1340 case 0: // i'm not sure why we can guarantee looping=true here,
1341 // but that's what the old code did
1342 music_players[current_player]->play (music_handle, 1);
1343 break;
1344 case 1:
1345 music_players[current_player]->resume ();
1346 break;
1347 default: // Default - music was never stopped
1348 break;
1349 }
1350 SDL_UnlockMutex (musmutex);
1351 }
1352
Exp_StopSong(int handle)1353 static void Exp_StopSong(int handle)
1354 {
1355 if (music_handle)
1356 {
1357 SDL_LockMutex (musmutex);
1358 music_players[current_player]->stop ();
1359 SDL_UnlockMutex (musmutex);
1360 }
1361 }
1362
Exp_UnRegisterSong(int handle)1363 static void Exp_UnRegisterSong(int handle)
1364 {
1365 if (music_handle)
1366 {
1367 SDL_LockMutex (musmutex);
1368 music_players[current_player]->unregistersong (music_handle);
1369 music_handle = NULL;
1370 if (song_data)
1371 {
1372 free (song_data);
1373 song_data = NULL;
1374 }
1375 SDL_UnlockMutex (musmutex);
1376 }
1377 }
1378
Exp_SetMusicVolume(int volume)1379 static void Exp_SetMusicVolume (int volume)
1380 {
1381 if (music_handle)
1382 {
1383 SDL_LockMutex (musmutex);
1384 music_players[current_player]->setvolume (volume);
1385 SDL_UnlockMutex (musmutex);
1386 }
1387 }
1388
1389 // returns 1 on success, 0 on failure
Exp_RegisterSongEx(const void * data,size_t len,int try_mus2mid)1390 static int Exp_RegisterSongEx (const void *data, size_t len, int try_mus2mid)
1391 {
1392 int i, j;
1393 dboolean io_errors = false;
1394
1395 MEMFILE *instream;
1396 MEMFILE *outstream;
1397 void *outbuf;
1398 size_t outbuf_len;
1399 int result;
1400
1401 //try_mus2mid = 0; // debug: supress mus2mid conversion completely
1402
1403
1404 if (music_handle)
1405 Exp_UnRegisterSong (0);
1406
1407
1408 // e6y: new logic by me
1409 // Now you can hear title music in deca.wad
1410 // http://www.doomworld.com/idgames/index.php?id=8808
1411 // Ability to use mp3 and ogg as inwad lump
1412
1413 if (len > 4 && memcmp(data, "MUS", 3) != 0)
1414 {
1415 // The header has no MUS signature
1416 // Let's try to load this song directly
1417
1418 // go through music players in order
1419 int found = 0;
1420
1421 for (j = 0; j < NUM_MUS_PLAYERS; j++)
1422 {
1423 found = 0;
1424 for (i = 0; music_players[i]; i++)
1425 {
1426 if (strcmp (music_players[i]->name (), music_player_order[j]) == 0)
1427 {
1428 found = 1;
1429 if (music_player_was_init[i])
1430 {
1431 const void *temp_handle = music_players[i]->registersong (data, len);
1432 if (temp_handle)
1433 {
1434 SDL_LockMutex (musmutex);
1435 current_player = i;
1436 music_handle = temp_handle;
1437 SDL_UnlockMutex (musmutex);
1438 lprintf (LO_INFO, "Exp_RegisterSongEx: Using player %s\n", music_players[i]->name ());
1439 return 1;
1440 }
1441 }
1442 else
1443 lprintf (LO_INFO, "Exp_RegisterSongEx: Music player %s on preferred list but it failed to init\n", music_players[i]-> name ());
1444 }
1445 }
1446 if (!found)
1447 lprintf (LO_INFO, "Exp_RegisterSongEx: Couldn't find preferred music player %s in list\n (typo or support not included at compile time)\n", music_player_order[j]);
1448 }
1449 // load failed
1450 }
1451
1452
1453
1454
1455 // load failed? try mus2mid
1456 if (try_mus2mid)
1457 {
1458
1459 instream = mem_fopen_read (data, len);
1460 outstream = mem_fopen_write ();
1461
1462 // e6y: from chocolate-doom
1463 // New mus -> mid conversion code thanks to Ben Ryves <benryves@benryves.com>
1464 // This plays back a lot of music closer to Vanilla Doom - eg. tnt.wad map02
1465 result = mus2mid(instream, outstream);
1466 if (result != 0)
1467 {
1468 size_t muslen = len;
1469 const unsigned char *musptr = data;
1470
1471 // haleyjd 04/04/10: scan forward for a MUS header. Evidently DMX was
1472 // capable of doing this, and would skip over any intervening data. That,
1473 // or DMX doesn't use the MUS header at all somehow.
1474 while (musptr < (const unsigned char*)data + len - sizeof(musheader))
1475 {
1476 // if we found a likely header start, reset the mus pointer to that location,
1477 // otherwise just leave it alone and pray.
1478 if (!strncmp ((const char*) musptr, "MUS\x1a", 4))
1479 {
1480 mem_fclose (instream);
1481 instream = mem_fopen_read (musptr, muslen);
1482 result = mus2mid (instream, outstream);
1483 break;
1484 }
1485
1486 musptr++;
1487 muslen--;
1488 }
1489 }
1490 if (result == 0)
1491 {
1492 mem_get_buf(outstream, &outbuf, &outbuf_len);
1493
1494 // recopy so we can free the MEMFILE
1495 song_data = malloc (outbuf_len);
1496 if (song_data)
1497 memcpy (song_data, outbuf, outbuf_len);
1498
1499 mem_fclose(instream);
1500 mem_fclose(outstream);
1501
1502 if (song_data)
1503 {
1504 return Exp_RegisterSongEx (song_data, outbuf_len, 0);
1505 }
1506 }
1507 }
1508
1509 lprintf (LO_ERROR, "Exp_RegisterSongEx: Failed\n");
1510 return 0;
1511 }
1512
1513
Exp_RegisterSong(const void * data,size_t len)1514 static int Exp_RegisterSong (const void *data, size_t len)
1515 {
1516 Exp_RegisterSongEx (data, len, 1);
1517 return 0;
1518 }
1519
1520 // try register external music file (not in WAD)
1521
Exp_RegisterMusic(const char * filename,musicinfo_t * song)1522 static int Exp_RegisterMusic (const char *filename, musicinfo_t *song)
1523 {
1524 int len;
1525
1526 len = M_ReadFile (filename, (byte **) &song_data);
1527
1528 if (len == -1)
1529 {
1530 lprintf (LO_WARN, "Couldn't read %s\nAttempting to load default MIDI music.\n", filename);
1531 return 1;
1532 }
1533
1534 if (!Exp_RegisterSongEx (song_data, len, 1))
1535 {
1536 free (song_data);
1537 song_data = NULL;
1538 lprintf(LO_WARN, "Couldn't load music from %s\nAttempting to load default MIDI music.\n", filename);
1539 return 1; // failure
1540 }
1541
1542 song->data = 0;
1543 song->handle = 0;
1544 song->lumpnum = 0;
1545 return 0;
1546 }
1547
Exp_UpdateMusic(void * buff,unsigned nsamp)1548 static void Exp_UpdateMusic (void *buff, unsigned nsamp)
1549 {
1550
1551 if (!music_handle)
1552 {
1553 memset (buff, 0, nsamp * 4);
1554 return;
1555 }
1556
1557
1558 music_players[current_player]->render (buff, nsamp);
1559 }
1560
M_ChangeMIDIPlayer(void)1561 void M_ChangeMIDIPlayer(void)
1562 {
1563 int experimental_music;
1564
1565 #ifdef HAVE_OWN_MUSIC
1566 // do not bother about small memory leak
1567 snd_midiplayer = strdup(midiplayers[midi_player_sdl]);
1568 use_experimental_music = 0;
1569 return;
1570 #endif
1571
1572 if (!strcasecmp(snd_midiplayer, midiplayers[midi_player_sdl]))
1573 {
1574 experimental_music = false;
1575 }
1576 else
1577 {
1578 experimental_music = true;
1579
1580 if (!strcasecmp(snd_midiplayer, midiplayers[midi_player_fluidsynth]))
1581 {
1582 strcpy(music_player_order[3], PLAYER_FLUIDSYNTH);
1583 strcpy(music_player_order[4], PLAYER_OPL2);
1584 strcpy(music_player_order[5], PLAYER_PORTMIDI);
1585 }
1586 else if (!strcasecmp(snd_midiplayer, midiplayers[midi_player_opl2]))
1587 {
1588 strcpy(music_player_order[3], PLAYER_OPL2);
1589 strcpy(music_player_order[4], PLAYER_FLUIDSYNTH);
1590 strcpy(music_player_order[5], PLAYER_PORTMIDI);
1591 }
1592 else if (!strcasecmp(snd_midiplayer, midiplayers[midi_player_portmidi]))
1593 {
1594 strcpy(music_player_order[3], PLAYER_PORTMIDI);
1595 strcpy(music_player_order[4], PLAYER_FLUIDSYNTH);
1596 strcpy(music_player_order[5], PLAYER_OPL2);
1597 }
1598 }
1599
1600 #if 1
1601 if (use_experimental_music == -1)
1602 {
1603 use_experimental_music = experimental_music;
1604 }
1605 else
1606 {
1607 if (experimental_music && use_experimental_music)
1608 {
1609 S_StopMusic();
1610 S_RestartMusic();
1611 }
1612 }
1613 #else
1614 S_StopMusic();
1615
1616 if (use_experimental_music != experimental_music)
1617 {
1618 I_ShutdownMusic();
1619
1620 S_Stop();
1621 I_ShutdownSound();
1622
1623 use_experimental_music = experimental_music;
1624
1625 I_InitSound();
1626 }
1627
1628 S_RestartMusic();
1629 #endif
1630 }
1631
1632 #endif
1633