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