1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: i_sound.c 1524 2020-05-09 12:07:09Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 2000-2016 by Doom Legacy team
8 //
9 // This source is available for distribution and/or modification
10 // only under the terms of the DOOM Source Code License as
11 // published by id Software. All rights reserved.
12 //
13 // The source is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
16 // for more details.
17 //
18 // $Log: i_sound.c,v $
19 // Revision 1.14 2007/01/28 14:45:01 chiphog
20 // This patch addresses 2 issues:
21 // * Separated the SDL and HAVE_MIXER assumptions. We can now compile with
22 // SDL=1 but without specifying HAVE_MIXER=1.
23 // * Fixed the playing of MIDI (from MUS) music under SDL. One needs to
24 // compile with SDL=1 and HAVE_MIXER=1 to get SDL music. This involved
25 // two things:
26 // + Removed/replaced the conflicting functions explained here:
27 // http://jonatkins.org/SDL_mixer/SDL_mixer.html#SEC5
28 // + Backported some SDL mixer mystery magic from legacy-2
29 // This patch has been tested on linux with:
30 // - make LINUX=1 # you get sound, but it ain't SDL
31 // - make LINUX=1 SDL=1 # you get SDL sound but no music
32 // - make LINUX=1 SDL=1 HAVE_MIXER=1 # you get SDL sound and SDL music
33 // Compiling with HAVE_MIXER=1 but without SDL=1 will fail.
34 //
35 // Revision 1.13 2006/07/22 15:38:07 hurdler
36 // Quick fix for SDL_mixer compiling issue
37 //
38 // Revision 1.12 2004/04/18 12:53:42 hurdler
39 // fix Heretic issue with SDL and OS/2
40 //
41 // Revision 1.11 2003/07/13 13:16:15 hurdler
42 // Revision 1.10 2001/08/20 20:40:42 metzgermeister
43 //
44 // Revision 1.9 2001/05/16 22:33:35 bock
45 // Initial FreeBSD support.
46 //
47 // Revision 1.8 2001/05/14 19:02:58 metzgermeister
48 // * Fixed floor not moving up with player on E3M1
49 // * Fixed crash due to oversized string in screen message ... bad bug!
50 // * Corrected some typos
51 // * fixed sound bug in SDL
52 //
53 // Revision 1.7 2001/04/14 14:15:14 metzgermeister
54 // fixed bug no sound device
55 //
56 // Revision 1.6 2001/04/09 20:21:56 metzgermeister
57 // dummy for I_FreeSfx
58 //
59 // Revision 1.5 2001/03/25 18:11:24 metzgermeister
60 // * SDL sound bug with swapped stereo channels fixed
61 // * separate hw_trick.c now for HW_correctSWTrick(.)
62 //
63 // Revision 1.4 2001/03/09 21:53:56 metzgermeister
64 // Revision 1.3 2000/11/02 19:49:40 bpereira
65 // Revision 1.2 2000/09/10 10:56:00 metzgermeister
66 // Revision 1.1 2000/08/21 21:17:32 metzgermeister
67 // Initial import to CVS
68 //
69 //
70 // DESCRIPTION:
71 // System interface for sound.
72 //
73 //-----------------------------------------------------------------------------
74
75 #include <math.h>
76 #include <unistd.h>
77
78 #include <SDL.h>
79 #include <SDL_audio.h>
80 #include <SDL_mutex.h>
81 #include <SDL_version.h>
82 #if ((SDL_MAJOR_VERSION*100)+(SDL_MINOR_VERSION*10)) < 120
83 # include <SDL_byteorder.h>
84 #else
85 # include <SDL_endian.h>
86 #endif
87
88 #ifdef HAVE_MIXER
89 # define USE_RWOPS
90 # include <SDL_mixer.h>
91 #endif
92
93 #include "doomincl.h"
94 #include "doomstat.h"
95
96 #include "i_system.h"
97 #include "i_sound.h"
98 #include "m_argv.h"
99 #include "m_misc.h"
100 #include "m_swap.h"
101 #include "w_wad.h"
102
103 #include "s_sound.h"
104
105 #include "d_main.h"
106 #include "z_zone.h"
107
108 #include "qmus2mid.h"
109
110
111
112 // MIDI music buffer
113 #define MIDBUFFERSIZE (128*1024)
114
115 #define MUSIC_FADE_TIME 400 // ms
116
117 // The number of internal mixing channels,
118 // mixing buffer, and the samplerate of the raw data.
119
120 // Doom sound effects
121 #define DOOM_SAMPLERATE 11025 // Hz
122
123 // Needed for calling the actual sound output.
124 // max. number of simultaneous sounds
125 #define NUM_CHANNELS 16
126 #define CHANNEL_NUM_MASK (NUM_CHANNELS-1)
127 #define SAMPLERATE 22050 // Hz
128 // requested audio buffer size (512 means about 46 ms at 11 kHz)
129 #define SAMPLECOUNT 512
130
131 typedef struct {
132
133 // The channel data pointers, start and end.
134 byte * data_ptr; // NULL when inactive
135 byte * data_end;
136
137 unsigned int step; // The channel step amount...
138 unsigned int step_remainder; // ... and a 0.16 bit remainder of last step.
139
140 // When the channel starts playing, and there are too many sounds,
141 // determine which to kill by oldest and priority.
142 unsigned int age_priority;
143
144 // The data sample rate
145 unsigned int samplerate;
146
147 // The sound in channel handles,
148 // determined on registration,
149 // might be used to unregister/stop/modify,
150 // Lowest bits are the channel num.
151 int handle;
152
153 // SFX id of the playing sound effect.
154 // Used to catch duplicates (like chainsaw).
155 int sfxid;
156
157 // Hardware left and right channel volume lookup.
158 int * leftvol_lookup;
159 int * rightvol_lookup;
160
161 #ifdef SURROUND_SOUND
162 byte invert_right;
163 #endif
164
165 } mix_channel_t;
166
167 static mix_channel_t mix_channel[ NUM_CHANNELS ]; // channel
168
169
170 // Pitch to stepping lookup, 16.16 fixed point
171 static Sint32 steptable[256];
172
173 // Volume lookups.
174 static int vol_lookup[128 * 256];
175
176 // Buffer for MIDI
177 static byte *midi_buffer;
178
179 // Flags for the -nosound and -nomusic options
180 extern boolean nosoundfx;
181 extern boolean nomusic;
182
183 static boolean musicStarted = false;
184 static boolean soundStarted = false;
185
186 static unsigned int sound_age = 1000; // age counter
187
188
189 //
190 // SFX API
191 // Note: this was called by S_Init.
192 // However, whatever they did in the
193 // old DPMS based DOS version, this
194 // were simply dummies in the Linux version.
195 // See soundserver initdata().
196 //
197 // Well... To keep compatibility with legacy doom, I have to call this in
198 // I_InitSound since it is not called in S_Init... (emanne@absysteme.fr)
199
I_SetChannels(void)200 static void I_SetChannels(void)
201 {
202 // Init internal lookups (raw data, mixing buffer, channels).
203 // This function sets up internal lookups used during
204 // the mixing process.
205 int i, j;
206
207 if (nosoundfx)
208 return;
209
210 double base_step = (double)DOOM_SAMPLERATE / (double)SAMPLERATE;
211
212 // This table provides step widths for pitch parameters.
213 for (i = 0; i < 256; i++)
214 {
215 steptable[i] = (Sint32)(base_step * pow(2.0, ((i-128) / 64.0)) * 65536.0);
216 }
217
218 // Generates volume lookup tables
219 // which also turn the u8 samples into s16 samples.
220 for (i = 0; i < 128; i++)
221 {
222 for (j = 0; j < 256; j++)
223 {
224 vol_lookup[i * 256 + j] = (i * (j - 128) * 256) / 127;
225 }
226 }
227 }
228
I_SetSfxVolume(int volume)229 void I_SetSfxVolume(int volume)
230 {
231 // Can use mix_sfxvolume (0..31), or set local volume vars.
232 // mix_sfxvolume = volume;
233 }
234
235
I_GetSfx(sfxinfo_t * sfx)236 void I_GetSfx(sfxinfo_t * sfx)
237 {
238 S_GetSfxLump( sfx ); // lump to sfx
239 // [WDJ] If save sfx->data += 8 to skip header,
240 // then would need to undo it to Free the mem. Caused Z_Free failure.
241 if( sfx->length > 8 )
242 {
243 sfx->length -= 8; // length of sound
244 }
245 }
246
I_FreeSfx(sfxinfo_t * sfx)247 void I_FreeSfx(sfxinfo_t * sfx)
248 {
249 // normal Z_Free in S_FreeSfx
250 }
251
252 #if 0
253 // cleanly stop a channel
254 static void stop_channel( mix_channel_t * chanp )
255 {
256 chanp->data_ptr = NULL;
257 // Do not release sound lump, it gets used too often,
258 // and would have to check for other sound channels using it.
259 }
260 #endif
261
262
263 //
264 // Starting a sound means adding it
265 // to the current list of active sounds in the internal channels.
266 // Pitching (that is, increased speed of playback)
267 // is set, but currently not used by mixing.
268 //
269 // vol : volume, 0..255
270 // sep : separation, +/- 127, SURROUND_SEP special operation
271 // Return a channel handle.
I_StartSound(sfxid_t sfxid,int vol,int sep,int pitch,int priority)272 int I_StartSound(sfxid_t sfxid, int vol, int sep, int pitch, int priority)
273 {
274 int handle;
275 mix_channel_t * chanp;
276 int i;
277 int slot;
278
279 if (nosoundfx)
280 return 0;
281
282 #ifndef HAVE_MIXER
283 SDL_LockAudio();
284 #endif
285
286 // Chainsaw troubles.
287 // Play these sound effects only one at a time.
288 if (S_sfx[sfxid].flags & SFX_single)
289 {
290 // Loop all channels, check.
291 for (i = 0; i < NUM_CHANNELS; i++)
292 {
293 chanp = & mix_channel[i];
294 // if Active, and using the same SFX
295 if ((chanp->data_ptr) && (chanp->sfxid == sfxid))
296 {
297 if( S_sfx[sfxid].flags & SFX_id_fin )
298 return chanp->handle; // already have one
299 // Kill, Reset.
300 chanp->data_ptr = 0;
301 break;
302 }
303 }
304 }
305
306 // Loop all channels to find unused channel, or oldest SFX.
307 slot = 0; // default
308 int oldest = -1;
309 for (i = 0; (i < NUM_CHANNELS); i++)
310 {
311 if (! mix_channel[i].data_ptr ) // unused
312 {
313 slot = i;
314 break;
315 }
316 // handles sound_age wrap, by considering only diff
317 register unsigned int agpr = sound_age - mix_channel[i].age_priority;
318 if (agpr > oldest) // older
319 {
320 slot = i;
321 oldest = agpr;
322 }
323 }
324
325 chanp = & mix_channel[slot]; // channel to use
326
327 // Preserve sound SFX id,
328 // e.g. for avoiding duplicates of chainsaw.
329 chanp->sfxid = sfxid;
330
331 byte * header = S_sfx[sfxid].data;
332 // Okay, in the less recent channel,
333 // we will handle the new SFX.
334 // Set pointer to raw data, skipping header.
335 chanp->data_ptr = (unsigned char *) S_sfx[sfxid].data + 8;
336 // chanp->data_ptr = & header[8];
337 // Set pointer to end of raw data.
338 chanp->data_end = chanp->data_ptr + S_sfx[sfxid].length;
339
340 // Get samplerate from the sfx header, 16 bit, big endian
341 chanp->samplerate = (header[3] << 8) + header[2];
342
343 // Set stepping
344 chanp->step = steptable[pitch] * chanp->samplerate / DOOM_SAMPLERATE;
345 // 16.16 fixed point
346 chanp->step_remainder = 0;
347 // balanced between age and priority
348 // low priority (higher value) increases age
349 chanp->age_priority = sound_age - priority; // age at start
350 sound_age += 16; // vrs priority 0..256
351
352 // Per left/right channel.
353 // x^2 seperation,
354 // adjust volume properly.
355 // vol *= 8;
356
357 // vol : range 0..255
358 // mix_sfxvolume : range 0..31
359 vol = (vol * mix_sfxvolume) >> 7;
360 // Notice : sdldoom replaced all the calls to avoid this conversion
361
362 int leftvol, rightvol;
363
364 #ifdef SURROUND_SOUND
365 chanp->invert_right = 0;
366 if( sep == SURROUND_SEP )
367 {
368 // Use a normal sound data for the left channel (with pan left)
369 // and an inverted sound data for the right channel (with pan right)
370 leftvol = rightvol = (vol * (224 * 224)) >> 16; // slight reduction going through panning
371 chanp->invert_right = 1; // invert right channel
372 }
373 else
374 #endif
375 {
376 // Separation, that is, orientation/stereo.
377 // sep : +/- 127, <0 is left, >0 is right
378 sep += 129; // 129 +/- 127 ; ( 1 - 256 )
379 leftvol = vol - ((vol * sep * sep) >> 16);
380 sep = 258 - sep; // 129 +/- 127
381 rightvol = vol - ((vol * sep * sep) >> 16);
382 }
383
384 // Sanity check, clamp volume.
385 if (rightvol < 0 || rightvol > 127)
386 {
387 I_SoftError("rightvol out of bounds\n");
388 rightvol = ( rightvol < 0 ) ? 0 : 127;
389 }
390
391 if (leftvol < 0 || leftvol > 127)
392 {
393 I_SoftError("leftvol out of bounds\n");
394 leftvol = ( leftvol < 0 ) ? 0 : 127;
395 }
396
397 // Get the proper lookup table piece
398 // for this volume level
399 chanp->leftvol_lookup = &vol_lookup[leftvol * 256];
400 chanp->rightvol_lookup = &vol_lookup[rightvol * 256];
401
402 // Assign current handle number.
403 // Preserved so sounds could be stopped.
404 handle = slot | ((chanp->handle + NUM_CHANNELS) & ~CHANNEL_NUM_MASK);
405 chanp->handle = handle;
406
407 #ifndef HAVE_MIXER
408 SDL_UnlockAudio();
409 #endif
410
411 // Returns a handle
412 return handle;
413 }
414
415
416 // handle : the handle returned by StartSound.
417 // vol : volume, 0..255
418 // sep : separation, +/- 127
I_UpdateSoundParams(int handle,int vol,int sep,int pitch)419 void I_UpdateSoundParams(int handle, int vol, int sep, int pitch)
420 {
421 int slot = handle & CHANNEL_NUM_MASK;
422
423 if( mix_channel[slot].handle == handle )
424 {
425 mix_channel_t * chanp = & mix_channel[slot]; // channel to use
426
427 // Per left/right channel.
428 // x^2 seperation,
429 // adjust volume properly.
430 // vol *= 8;
431 // vol : range 0..255
432 // mix_sfxvolume : range 0..31
433 vol = (vol * mix_sfxvolume) >> 7;
434
435 int leftvol, rightvol;
436
437 #ifdef SURROUND_SOUND
438 chanp->invert_right = 0;
439 if( sep == SURROUND_SEP )
440 {
441 // Use normal sound data for the left channel (pan left)
442 // and inverted sound data for the right channel (pan right).
443 leftvol = rightvol = (vol * (224 * 224)) >> 16; // slight reduction going through panning
444 chanp->invert_right = 1; // invert right channel
445 }
446 else
447 #endif
448 {
449 // Separation, that is, orientation/stereo.
450 // sep : +/- 127, <0 is left, >0 is right
451 sep += 129; // 129 +/- 127 ; ( 1 - 256 )
452 leftvol = vol - ((vol * sep * sep) >> 16);
453 sep = 258 - sep; // -129 +/- 127
454 rightvol = vol - ((vol * sep * sep) >> 16);
455 }
456
457 // Sanity check, clamp volume.
458 if (rightvol < 0 || rightvol > 127)
459 {
460 I_SoftError("rightvol out of bounds\n");
461 rightvol = ( rightvol < 0 ) ? 0 : 127;
462 }
463
464 if (leftvol < 0 || leftvol > 127)
465 {
466 I_SoftError("leftvol out of bounds\n");
467 leftvol = ( leftvol < 0 ) ? 0 : 127;
468 }
469
470 // Get the proper lookup table piece
471 // for this volume level
472 chanp->leftvol_lookup = &vol_lookup[leftvol * 256];
473 chanp->rightvol_lookup = &vol_lookup[rightvol * 256];
474
475 // Set stepping
476 // chanp->step = steptable[pitch];
477 chanp->step = steptable[pitch] * chanp->samplerate / DOOM_SAMPLERATE;
478 }
479 }
480
481
482 // handle : the handle returned by StartSound.
I_StopSound(int handle)483 void I_StopSound(int handle)
484 {
485 int slot = handle & CHANNEL_NUM_MASK;
486 if( mix_channel[slot].handle == handle )
487 {
488 // outside caller should lock
489 #ifndef HAVE_MIXER
490 SDL_LockAudio();
491 #endif
492
493 mix_channel[slot].data_ptr = NULL;
494 // stop_channel( & mix_channel[slot] );
495
496 #ifndef HAVE_MIXER
497 SDL_UnlockAudio();
498 #endif
499 }
500 }
501
502 // handle : the handle returned by StartSound.
I_SoundIsPlaying(int handle)503 int I_SoundIsPlaying(int handle)
504 {
505 int slot = handle & CHANNEL_NUM_MASK;
506 if( mix_channel[slot].handle == handle )
507 {
508 return mix_channel[slot].data_ptr != NULL;
509 }
510 return 0;
511 }
512
513 //
514 // Not used by SDL version
515 //
I_SubmitSound(void)516 void I_SubmitSound(void)
517 {
518 }
519
520 //
521 // This function loops all active (internal) sound
522 // channels, retrieves a given number of samples
523 // from the raw sound data, modifies it according
524 // to the current (internal) channel parameters,
525 // mixes the per channel samples into the given
526 // mixing buffer, and clamping it to the allowed
527 // range.
528 //
529 // This function currently supports only 16bit.
530 //
I_UpdateSound(void)531 void I_UpdateSound(void)
532 {
533 /*
534 Pour une raison que j'ignore, la version SDL n'appelle jamais
535 ce truc directement. Fonction vide pour garder une compatibilit�
536 avec le point de vue de legacy...
537 */
538
539 // Himmel, Arsch und Zwirn
540 }
541
I_UpdateSound_sdl(void * unused,Uint8 * stream,int len)542 static void I_UpdateSound_sdl(void *unused, Uint8 *stream, int len)
543 {
544 int chan;
545 // Mix current sound data.
546 // Data, from raw sound, for right and left.
547 if (nosoundfx)
548 return;
549
550 // Pointers in audio stream, left, right, end.
551 // Left and right channels are multiplexed in the audio stream, alternating.
552 Sint16 *leftout = (Sint16 *)stream;
553 Sint16 *rightout = leftout + 1;
554
555 // Step in stream, left and right channels, thus two.
556 int step = 2;
557
558 // first Sint16 at least partially outside the buffer
559 Sint16 *buffer_end = ((Sint16 *)stream) +len/sizeof(Sint16);
560
561 // Mix sounds into the mixing buffer.
562 while (rightout < buffer_end)
563 {
564 // take the current audio output (incl. music) and mix (add) in our sfx
565 register int dl = *leftout;
566 register int dr = *rightout;
567
568 // Love thy L2 chache - made this a loop.
569 // Now more channels could be set at compile time
570 // as well. Thus loop those channels.
571 // Mixing channel index.
572 register mix_channel_t * chanp = & mix_channel[ 0 ];
573 for (chan = NUM_CHANNELS; chan > 0; chan--)
574 {
575 register byte * chan_data_ptr = chanp->data_ptr;
576 // Check channel, if active.
577 if ( chan_data_ptr )
578 {
579 // Get the raw data from the channel.
580 register unsigned int sample = * chan_data_ptr;
581 // Add left and right part for this channel (sound)
582 // to the current data.
583 // Adjust volume accordingly.
584 dl += chanp->leftvol_lookup[sample];
585 #ifdef SURROUND_SOUND
586 if( chanp->invert_right )
587 dr -= chanp->rightvol_lookup[sample];
588 else
589 dr += chanp->rightvol_lookup[sample];
590 #else
591 dr += chanp->rightvol_lookup[sample];
592 #endif
593 // 16.16 fixed point step forward in the sound data
594 chanp->step_remainder += chanp->step;
595 // take full steps
596 chan_data_ptr += chanp->step_remainder >> 16;
597 // remainder, save for next round
598 chanp->step_remainder &= 0xFFFF;
599
600 // Check whether we are done.
601 if (chan_data_ptr >= chanp->data_end)
602 chan_data_ptr = NULL;
603
604 chanp->data_ptr = chan_data_ptr;
605 }
606 chanp ++; // next channel
607 }
608
609 // Clamp to range. Left hardware channel.
610 // Has been char instead of short.
611
612 if (dl > 0x7fff)
613 *leftout = 0x7fff;
614 else if (dl < -0x8000)
615 *leftout = -0x8000;
616 else
617 *leftout = dl;
618
619 // Same for right hardware channel.
620 if (dr > 0x7fff)
621 *rightout = 0x7fff;
622 else if (dr < -0x8000)
623 *rightout = -0x8000;
624 else
625 *rightout = dr;
626
627 // Increment current pointers in stream
628 leftout += step;
629 rightout += step;
630 }
631 }
632
633
634
635
636 //
637 // MUSIC API.
638 //
639
640 #ifdef HAVE_MIXER
641 /// the "registered" piece of music
642 static struct music_channel_t
643 {
644 Mix_Music *mus;
645 SDL_RWops *rwop; ///< must not be freed before music is halted
646 } music = { NULL, NULL };
647
648
649 #if ((SDL_MIXER_MAJOR_VERSION*100)+(SDL_MIXER_MINOR_VERSION*10)+SDL_MIXER_PATCHLEVEL) < 127
650 // Older SDL without RWOPS
651 #define OLD_SDL_MIXER
652
653 #ifdef SMIF_PC_DOS
654 static char * midiname = "DoomMUS.mid";
655 #else
656 static char midiname[24] = "/tmp/DoomMUSXXXXXX";
657 #endif
658 FILE * midifile;
659
Init_OLD_SDL_MIXER(void)660 void Init_OLD_SDL_MIXER( void )
661 {
662 #ifndef SMIF_PC_DOS
663 // Make temp file name
664 mkstemp( midiname );
665 // strcat( midiname, ".mid" );
666 #endif
667 // fprintf( stderr, "Midiname= %s\n", midiname );
668 }
669
Free_OLD_SDL_MIXER(void)670 void Free_OLD_SDL_MIXER( void )
671 {
672 // delete the temp file
673 remove( midiname );
674 }
675
676
677 #include <errno.h>
678 extern int errno;
679
Midifile_OLD_SDL_MIXER(byte * midibuf,unsigned long midilength)680 void Midifile_OLD_SDL_MIXER( byte* midibuf, unsigned long midilength )
681 {
682 midifile = fopen( midiname, "wb" );
683 if( midifile )
684 {
685 fwrite( midibuf, midilength, 1, midifile );
686 fclose( midifile );
687 if(verbose)
688 fprintf( stderr, "Midifile written: %s size=%li\n", midiname, midilength );
689
690 // wants file to have .MID extension, but mkstemp file cannot have extension
691 music.mus = Mix_LoadMUS( midiname );
692 if( music.mus == NULL )
693 {
694 I_SoftError("Music load file failed\n");
695 perror( "Mix_LoadMUS fails when not cd to doomlegacy directory" );
696 }
697 }
698 }
699 #endif
700 #endif
701
702
I_PlaySong(int handle,byte looping)703 void I_PlaySong(int handle, byte looping)
704 {
705 #ifdef HAVE_MIXER
706 if (nomusic)
707 return;
708
709 if (music.mus)
710 {
711 Mix_FadeInMusic(music.mus, looping ? -1 : 1, MUSIC_FADE_TIME);
712 }
713 #endif
714 }
715
I_PauseSong(int handle)716 void I_PauseSong(int handle)
717 {
718 #ifdef HAVE_MIXER
719 if (nomusic)
720 return;
721
722 Mix_PauseMusic();
723 #endif
724 }
725
I_ResumeSong(int handle)726 void I_ResumeSong(int handle)
727 {
728 #ifdef HAVE_MIXER
729 if (nomusic)
730 return;
731
732 Mix_ResumeMusic();
733 #endif
734 }
735
I_StopSong(int handle)736 void I_StopSong(int handle)
737 {
738 #ifdef HAVE_MIXER
739 if (nomusic)
740 return;
741
742 Mix_FadeOutMusic(MUSIC_FADE_TIME);
743 #endif
744 }
745
746
I_UnRegisterSong(int handle)747 void I_UnRegisterSong(int handle)
748 {
749 #ifdef HAVE_MIXER
750 if (nomusic)
751 return;
752
753 if (music.mus)
754 {
755 Mix_FreeMusic(music.mus);
756 music.mus = NULL;
757 music.rwop = NULL;
758 }
759 #endif
760 }
761
762
763 // return handle (always 0)
764 // data : ptr to lump data
765 // len : length of data
I_RegisterSong(void * data,int len)766 int I_RegisterSong( void* data, int len )
767 {
768 #ifdef HAVE_MIXER
769 if (nomusic)
770 return 0;
771
772 if (music.mus)
773 {
774 I_SoftError("Two registered pieces of music simultaneously!\n");
775 return 0;
776 }
777
778 if (memcmp(data, MUSHEADER, 4) == 0)
779 {
780 unsigned long midilength; // per qmus2mid, SDL_RWFromConstMem wants int
781 // convert mus to mid in memory with a wonderful function
782 // thanks to S.Bacquet for the source of qmus2mid
783 int err = qmus2mid(data, len, 89, 0, MIDBUFFERSIZE,
784 /*INOUT*/ midi_buffer, &midilength);
785 if ( err != QM_success )
786 {
787 I_SoftError("Cannot convert MUS to MIDI: error %d.\n", err);
788 return 0;
789 }
790 #ifdef OLD_SDL_MIXER
791 Midifile_OLD_SDL_MIXER( midi_buffer, midilength );
792 #else
793 music.rwop = SDL_RWFromConstMem(midi_buffer, midilength);
794 #endif
795 }
796 else
797 {
798 // MIDI, MP3, Ogg Vorbis, various module formats
799 #ifdef OLD_SDL_MIXER
800 Midifile_OLD_SDL_MIXER( data, len );
801 #else
802 music.rwop = SDL_RWFromConstMem(data, len);
803 #endif
804 }
805
806 #ifdef OLD_SDL_MIXER
807 // In old mixer Mix_LoadMUS_RW does not work.
808 #else
809 // SDL_mixer automatically frees the rwop when the music is stopped.
810 music.mus = Mix_LoadMUS_RW(music.rwop);
811 #endif
812 if (!music.mus)
813 {
814 I_SoftError("Couldn't load music lump: %s\n", Mix_GetError());
815 music.rwop = NULL;
816 }
817
818 // debug_Printf("register song\n"); // [WDJ] debug
819 #endif
820
821 return 0;
822 }
823
824
I_SetMusicVolume(int volume)825 void I_SetMusicVolume(int volume)
826 {
827 // volume: 0--31
828 #ifdef HAVE_MIXER
829 if (nomusic)
830 return;
831
832 Mix_VolumeMusic((MIX_MAX_VOLUME * volume) / 32);
833 #endif
834 }
835
836
837
838
I_StartupSound(void)839 void I_StartupSound(void)
840 {
841 static SDL_AudioSpec audspec; // [WDJ] desc name, too many audio in this file
842
843 if( nosoundfx )
844 {
845 nomusic = true;
846 return;
847 }
848
849 // Configure sound device
850 CONS_Printf("I_InitSound: ");
851
852 // Open the audio device
853 audspec.freq = SAMPLERATE;
854 audspec.format = AUDIO_S16SYS;
855 audspec.channels = 2;
856 // From eternity, adjust for new samplerate
857 audspec.samples = SAMPLECOUNT * SAMPLERATE / DOOM_SAMPLERATE;
858 audspec.callback = I_UpdateSound_sdl;
859 I_SetChannels();
860
861 #ifndef HAVE_MIXER
862 // no mixer, no music
863 nomusic = true;
864
865 // Open the audio device
866 if (SDL_OpenAudio(&audspec, NULL) < 0)
867 {
868 CONS_Printf("Couldn't open audio with desired format.\n");
869 SDL_CloseAudio();
870 nosoundfx = nomusic = true;
871 return;
872 }
873
874 SDL_PauseAudio(0);
875 #else
876 // use SDL_mixer for music
877
878 // because we use SDL_mixer, audio is opened here.
879 if (Mix_OpenAudio(audspec.freq, audspec.format, audspec.channels, audspec.samples) < 0)
880 {
881 // [WDJ] On sound cards without midi ports, opening audio will block music.
882 // When midi music is played through Timidity, it will also try to use the
883 // dsp port, which is already in use. Need to use a mixer on sound
884 // effect and Timidity output. Some sound cards have two dsp ports.
885
886 CONS_Printf("Unable to open audio: %s\n", Mix_GetError());
887 nosoundfx = nomusic = true;
888 return;
889 }
890
891 int number_channels; // for QuerySpec
892 if (!Mix_QuerySpec(&audspec.freq, &audspec.format, &number_channels))
893 {
894 CONS_Printf("Mix_QuerySpec: %s\n", Mix_GetError());
895 nosoundfx = nomusic = true;
896 return;
897 }
898
899 Mix_SetPostMix(audspec.callback, NULL); // after mixing music, add sound fx
900 Mix_Resume(-1); // start all sound channels (although they are not used)
901 #endif
902
903 CONS_Printf("Audio device initialized: %d Hz, %d samples/slice.\n",
904 audspec.freq, audspec.samples);
905
906 #ifdef HAVE_MIXER
907 if (!nomusic)
908 {
909 Mix_ResumeMusic(); // start music playback
910 midi_buffer = (byte *)Z_Malloc(MIDBUFFERSIZE, PU_STATIC, NULL);
911
912 #ifdef OLD_SDL_MIXER
913 Init_OLD_SDL_MIXER();
914 #endif
915
916 CONS_Printf(" Music initialized.\n");
917 musicStarted = true;
918 }
919 #endif
920
921 // Finished initialization.
922 CONS_Printf("I_InitSound: sound module ready.\n");
923 soundStarted = true;
924
925 CONS_Printf(" done.\n");
926 }
927
928
I_ShutdownSound(void)929 void I_ShutdownSound(void)
930 {
931 if (nosoundfx || !soundStarted)
932 return;
933
934 CONS_Printf("I_ShutdownSound: ");
935
936 #ifdef HAVE_MIXER
937 Mix_CloseAudio();
938 #else
939 SDL_CloseAudio();
940 #endif
941
942 CONS_Printf("shut down\n");
943 soundStarted = false;
944
945 // music
946 if (musicStarted)
947 {
948 Z_Free(midi_buffer);
949
950 #ifdef OLD_SDL_MIXER
951 Free_OLD_SDL_MIXER();
952 #endif
953
954 musicStarted = false;
955 }
956 }
957