music.c
author Stephane Peter <megastep@lokigames.com>
Sat, 23 Oct 1999 03:31:21 +0000
changeset 4 5c4485704b30
parent 3 f6dabb779e45
child 7 e73da9dc4bdc
permissions -rw-r--r--
Added fading in/out of music and samples.
     1 /*
     2     MIXERLIB:  An audio mixer library based on the SDL library
     3     Copyright (C) 1997-1999  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     5635-34 Springhouse Dr.
    21     Pleasanton, CA 94588 (USA)
    22     slouken@devolution.com
    23 */
    24 
    25 #include <stdlib.h>
    26 #include <string.h>
    27 #include <SDL/SDL_endian.h>
    28 #include <SDL/SDL_audio.h>
    29 
    30 #include "mixer.h"
    31 
    32 /* The music command hack is UNIX specific */
    33 #ifndef unix
    34 #undef CMD_MUSIC
    35 #endif
    36 
    37 #ifdef CMD_MUSIC
    38 #include "music_cmd.h"
    39 #endif
    40 #ifdef WAV_MUSIC
    41 #include "wavestream.h"
    42 #endif
    43 #ifdef MOD_MUSIC
    44 #include "mikmod.h"
    45 #endif
    46 #ifdef MID_MUSIC
    47 #include "timidity.h"
    48 #endif
    49 #ifdef MP3_MUSIC
    50 #include <smpeg/smpeg.h>
    51 
    52 static SDL_AudioSpec used_mixer;
    53 #endif
    54 
    55 int music_active = 1;
    56 static int music_loops = 0;
    57 static char *music_cmd = NULL;
    58 static int samplesize;
    59 static Mix_Music *music_playing = 0;
    60 static SDL_mutex *music_lock;
    61 static int music_volume;
    62 static int music_swap8;
    63 static int music_swap16;
    64 
    65 struct _Mix_Music {
    66 	enum {
    67 		MUS_CMD,
    68 		MUS_WAV,
    69 		MUS_MOD,
    70 		MUS_MID,
    71 		MUS_MP3
    72 	} type;
    73 	union {
    74 #ifdef CMD_MUSIC
    75 		MusicCMD *cmd;
    76 #endif
    77 #ifdef WAV_MUSIC
    78 		WAVStream *wave;
    79 #endif
    80 #ifdef MOD_MUSIC
    81 		UNIMOD *module;
    82 #endif
    83 #ifdef MID_MUSIC
    84 		MidiSong *midi;
    85 #endif
    86 #ifdef MP3_MUSIC
    87 		SMPEG *mp3;
    88 #endif
    89 	} data;
    90 	Mix_Fading fading;
    91 	int fade_volume;
    92 	int fade_length;
    93 	Uint32 ticks_fade;
    94 	int error;
    95 };
    96 static int timidity_ok;
    97 
    98 /* Mixing function */
    99 void music_mixer(void *udata, Uint8 *stream, int len)
   100 {
   101 	int i;
   102 
   103 	if ( music_playing ) {
   104 		if( music_playing->fading != MIX_NO_FADING ) {
   105 			Uint32 ticks = SDL_GetTicks() - music_playing->ticks_fade;
   106 			if( ticks > music_playing->fade_length ) {
   107 				if ( music_playing->fading == MIX_FADING_OUT ) {
   108 					music_volume = music_playing->fade_volume;
   109 					music_playing->fading = MIX_NO_FADING;
   110 					Mix_HaltMusic();
   111 					return;
   112 				}
   113 				music_playing->fading = MIX_NO_FADING;
   114 			} else {
   115 				if ( music_playing->fading == MIX_FADING_OUT ) {
   116 					Mix_VolumeMusic((music_playing->fade_volume * (music_playing->fade_length-ticks)) 
   117 									/ music_playing->fade_length);
   118 				} else { /* Fading in */
   119 					Mix_VolumeMusic((music_playing->fade_volume * ticks) 
   120 									/ music_playing->fade_length);
   121 				}
   122 			}
   123 		}
   124 		switch (music_playing->type) {
   125 #ifdef CMD_MUSIC
   126 			case MUS_CMD:
   127 				/* The playing is done externally */
   128 				break;
   129 #endif
   130 #ifdef WAV_MUSIC
   131 			case MUS_WAV:
   132 				WAVStream_PlaySome(stream, len);
   133 				break;
   134 #endif
   135 #ifdef MOD_MUSIC
   136 			case MUS_MOD:
   137 				VC_WriteBytes((SBYTE *)stream, len);
   138 				if ( music_swap8 ) {
   139 					Uint8 *dst;
   140 
   141 					dst = stream;
   142 					for ( i=len; i; --i ) {
   143 						*dst++ ^= 0x80;
   144 					}
   145 				} else
   146 				if ( music_swap16 ) {
   147 					Uint8 *dst, tmp;
   148 
   149 					dst = stream;
   150 					for ( i=(len/2); i; --i ) {
   151 						tmp = dst[0];
   152 						dst[0] = dst[1];
   153 						dst[1] = tmp;
   154 						dst += 2;
   155 					}
   156 				}
   157 				break;
   158 #endif
   159 #ifdef MID_MUSIC
   160 			case MUS_MID:
   161 				Timidity_PlaySome(stream, len/samplesize);
   162 				break;
   163 #endif
   164 #ifdef MP3_MUSIC
   165 		    case MUS_MP3:
   166 			    SMPEG_playAudio(music_playing->data.mp3, stream, len);
   167 				break;
   168 #endif
   169 			default:
   170 				/* Unknown music type?? */
   171 				break;
   172 		}
   173 	}
   174 }
   175 
   176 /* Initialize the music players with a certain desired audio format */
   177 int open_music(SDL_AudioSpec *mixer)
   178 {
   179 	int music_error;
   180 
   181 	music_error = 0;
   182 #ifdef WAV_MUSIC
   183 	if ( WAVStream_Init(mixer) < 0 ) {
   184 		++music_error;
   185 	}
   186 #endif
   187 #ifdef MOD_MUSIC
   188 	/* Set the MikMod music format */
   189 	music_swap8 = 0;
   190 	music_swap16 = 0;
   191 	switch (mixer->format) {
   192 
   193 		case AUDIO_U8:
   194 		case AUDIO_S8: {
   195 			if ( mixer->format == AUDIO_S8 ) {
   196 				music_swap8 = 1;
   197 			}
   198 			md_mode = 0;
   199 		}
   200 		break;
   201 
   202 		case AUDIO_S16LSB:
   203 		case AUDIO_S16MSB: {
   204 			/* See if we need to correct MikMod mixing */
   205 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   206 			if ( mixer->format == AUDIO_S16MSB ) {
   207 #else
   208 			if ( mixer->format == AUDIO_S16LSB ) {
   209 #endif
   210 				music_swap16 = 1;
   211 			}
   212 			md_mode = DMODE_16BITS;
   213 		}
   214 		break;
   215 
   216 		default: {
   217 			SDL_SetError("Unknown hardware audio format");
   218 			++music_error;
   219 		}
   220 	}
   221 	if ( mixer->channels > 1 ) {
   222 		if ( mixer->channels > 2 ) {
   223 			SDL_SetError("Hardware uses more channels than mixer");
   224 			++music_error;
   225 		}
   226 		md_mode |= DMODE_STEREO;
   227 	}
   228 	samplesize     = mixer->size/mixer->samples;
   229 	md_mixfreq     = mixer->freq;
   230 	md_device      = 0;
   231 	md_volume      = 96;
   232 	md_musicvolume = 128;
   233 	md_sndfxvolume = 128;
   234 	md_pansep      = 128;
   235 	md_reverb      = 0;
   236 	MikMod_RegisterAllLoaders();
   237 	MikMod_RegisterAllDrivers();
   238 	if ( MikMod_Init() ) {
   239 		SDL_SetError("%s", _mm_errmsg[_mm_errno]);
   240 		++music_error;
   241 	}
   242 #endif
   243 #ifdef MID_MUSIC
   244 	if ( Timidity_Init(mixer->freq,
   245 			mixer->format, mixer->channels, mixer->samples) == 0 ) {
   246 		timidity_ok = 1;
   247 	} else {
   248 		timidity_ok = 0;
   249 	}
   250 #endif
   251 #ifdef MP3_MUSIC
   252 	/* Keep a copy of the mixer */
   253 	used_mixer = *mixer;
   254 #endif
   255 	music_playing = 0;
   256 
   257 	/* Initialize the music lock */
   258 	music_lock = SDL_CreateMutex();
   259 	if ( music_error ) {
   260 		return(-1);
   261 	}
   262 	Mix_VolumeMusic(SDL_MIX_MAXVOLUME);
   263 
   264 	return(0);
   265 }
   266 
   267 /* Load a music file */
   268 Mix_Music *Mix_LoadMUS(const char *file)
   269 {
   270 	FILE *fp;
   271 	unsigned char magic[5];
   272 	Mix_Music *music;
   273 
   274 	/* Figure out what kind of file this is */
   275 	fp = fopen(file, "rb");
   276 	if ( (fp == NULL) || !fread(magic, 4, 1, fp) ) {
   277 		if ( fp != NULL ) {
   278 			fclose(fp);
   279 		}
   280 		SDL_SetError("Couldn't read from '%s'", file);
   281 		return(NULL);
   282 	}
   283 	magic[4] = '\0';
   284 	fclose(fp);
   285 
   286 	/* Allocate memory for the music structure */
   287 	music = (Mix_Music *)malloc(sizeof(Mix_Music));
   288 	if ( music == NULL ) {
   289 		SDL_SetError("Out of memory");
   290 		return(NULL);
   291 	}
   292 	music->error = 0;
   293 
   294 #ifdef CMD_MUSIC
   295 	if ( music_cmd ) {
   296 		music->type = MUS_CMD;
   297 		music->data.cmd = MusicCMD_LoadSong(music_cmd, file);
   298 		if ( music->data.cmd == NULL ) {
   299 			music->error = 1;
   300 		}
   301 	} else
   302 #endif
   303 #ifdef WAV_MUSIC
   304 	/* WAVE files have the magic four bytes "RIFF"
   305 	   AIFF files have the magic 12 bytes "FORM" XXXX "AIFF"
   306 	 */
   307 	if ( (strcmp(magic, "RIFF") == 0) || (strcmp(magic, "FORM") == 0) ) {
   308 		music->type = MUS_WAV;
   309 		music->data.wave = WAVStream_LoadSong(file, magic);
   310 		if ( music->data.wave == NULL ) {
   311 			music->error = 1;
   312 		}
   313 	} else
   314 #endif
   315 #ifdef MID_MUSIC
   316 	/* MIDI files have the magic four bytes "MThd" */
   317 	if ( strcmp(magic, "MThd") == 0 ) {
   318 		music->type = MUS_MID;
   319 		if ( timidity_ok ) {
   320 			music->data.midi = Timidity_LoadSong((char *)file);
   321 			if ( music->data.midi == NULL ) {
   322 				SDL_SetError("%s", Timidity_Error());
   323 				music->error = 1;
   324 			}
   325 		}
   326 		else {
   327 			SDL_SetError("%s", Timidity_Error());
   328 			music->error = 1;
   329 		}
   330 	} else
   331 #endif
   332 #ifdef MP3_MUSIC
   333 	if ( magic[0]==0xFF && (magic[1]&0xF0)==0xF0) {
   334 		SMPEG_Info info;
   335 		music->type = MUS_MP3;
   336 		music->data.mp3 = SMPEG_new(file, &info, 0);
   337 		if(!info.has_audio){
   338 			SDL_SetError("MPEG file does not have any audio stream.");
   339 			music->error = 1;
   340 		}else{
   341 			SMPEG_actualSpec(music->data.mp3, &used_mixer);
   342 		}
   343 	} else
   344 #endif
   345 #ifdef MOD_MUSIC
   346 	if ( 1 ) {
   347 		music->type = MUS_MOD;
   348 		music->data.module = MikMod_LoadSong((char *)file, 64);
   349 		if ( music->data.module == NULL ) {
   350 			SDL_SetError("%s", _mm_errmsg[_mm_errno]);
   351 			music->error = 1;
   352 		}
   353 	} else
   354 #endif
   355 	{
   356 		SDL_SetError("Unrecognized music format");
   357 		music->error = 1;
   358 	}
   359 	if ( music->error ) {
   360 		free(music);
   361 		music = NULL;
   362 	}
   363 	return(music);
   364 }
   365 
   366 /* Free a music chunk previously loaded */
   367 void Mix_FreeMusic(Mix_Music *music)
   368 {
   369 	if ( music ) {
   370 		/* Caution: If music is playing, mixer will crash */
   371 		if ( music == music_playing ) {
   372 			if ( music->fading == MIX_FADING_OUT ) {
   373 				/* Wait for the fade out to finish */
   374 				while(music->fading == MIX_FADING_OUT)
   375 					SDL_Delay(100);
   376 			} else {
   377 				Mix_HaltMusic(); /* Stop it immediately */
   378 			}
   379 		}
   380 		switch (music->type) {
   381 #ifdef CMD_MUSIC
   382 			case MUS_CMD:
   383 				MusicCMD_FreeSong(music->data.cmd);
   384 				break;
   385 #endif
   386 #ifdef WAV_MUSIC
   387 			case MUS_WAV:
   388 				WAVStream_FreeSong(music->data.wave);
   389 				break;
   390 #endif
   391 #ifdef MOD_MUSIC
   392 			case MUS_MOD:
   393 				MikMod_FreeSong(music->data.module);
   394 				break;
   395 #endif
   396 #ifdef MID_MUSIC
   397 			case MUS_MID:
   398 				Timidity_FreeSong(music->data.midi);
   399 				break;
   400 #endif
   401 #ifdef MP3_MUSIC
   402 		    case MUS_MP3:
   403 				SMPEG_delete(music->data.mp3);
   404 				break;
   405 #endif
   406 			default:
   407 				/* Unknown music type?? */
   408 				break;
   409 		}
   410 		free(music);
   411 	}
   412 }
   413 
   414 /* Play a music chunk.  Returns 0, or -1 if there was an error.
   415 */
   416 int Mix_PlayMusic(Mix_Music *music, int loops)
   417 {
   418 	/* Don't play null pointers :-) */
   419 	if ( music == NULL ) {
   420 		return(-1);
   421 	}
   422 	/* If the current music is fading out, wait for the fade to complete */
   423 	while ( music_playing && music_playing->fading==MIX_FADING_OUT ) {
   424 		SDL_Delay(100);
   425 	}
   426 	switch (music->type) {
   427 #ifdef CMD_MUSIC
   428 		case MUS_CMD:
   429 			MusicCMD_SetVolume(music_volume);
   430 			MusicCMD_Start(music->data.cmd);
   431 			break;
   432 #endif
   433 #ifdef WAV_MUSIC
   434 		case MUS_WAV:
   435 			WAVStream_SetVolume(music_volume);
   436 			WAVStream_Start(music->data.wave);
   437 			break;
   438 #endif
   439 #ifdef MOD_MUSIC
   440 		case MUS_MOD:
   441 			Player_SetVolume(music_volume);
   442 			Player_Start(music->data.module);
   443 			Player_SetPosition(0);
   444 			break;
   445 #endif
   446 #ifdef MID_MUSIC
   447 		case MUS_MID:
   448 			Timidity_SetVolume(music_volume);
   449 			Timidity_Start(music->data.midi);
   450 			break;
   451 #endif
   452 #ifdef MP3_MUSIC
   453 	    case MUS_MP3:
   454 			SMPEG_enableaudio(music->data.mp3,1);
   455 			SMPEG_enablevideo(music->data.mp3,0);
   456 			SMPEG_setvolume(music->data.mp3,((float)music_volume/(float)MIX_MAX_VOLUME)*100.0);
   457 			SMPEG_loop(music->data.mp3, loops);
   458 			SMPEG_play(music->data.mp3);
   459 			break;
   460 #endif
   461 		default:
   462 			/* Unknown music type?? */
   463 			return(-1);
   464 	}
   465 	music_active = 1;
   466 	music_playing = music;
   467 	music_playing->fading = MIX_NO_FADING;
   468 	return(0);
   469 }
   470 
   471 /* Fade in a music over "ms" milliseconds */
   472 int Mix_FadeInMusic(Mix_Music *music, int loops, int ms)
   473 {
   474 	if ( music && music_volume > 0 ) { /* No need to fade if we can't hear it */
   475 		music->fade_volume = music_volume;
   476 		music_volume = 0;
   477 		if(Mix_PlayMusic(music,loops)<0)
   478 			return(-1);
   479 		music_playing->fading = MIX_FADING_IN;
   480 		music_playing->fade_length = ms;
   481 		music_playing->ticks_fade = SDL_GetTicks();
   482 	}
   483 	return(0);
   484 }
   485 
   486 /* Set the music volume */
   487 int Mix_VolumeMusic(int volume)
   488 {
   489 	int prev_volume;
   490 
   491 	prev_volume = music_volume;
   492 	if ( volume < 0 ) {
   493 		volume = 0;
   494 	}
   495 	if ( volume > SDL_MIX_MAXVOLUME ) {
   496 		volume = SDL_MIX_MAXVOLUME;
   497 	}
   498 	music_volume = volume;
   499 	if ( music_playing ) {
   500 		switch (music_playing->type) {
   501 #ifdef CMD_MUSIC
   502 		case MUS_CMD:
   503 			MusicCMD_SetVolume(music_volume);
   504 			break;
   505 #endif
   506 #ifdef WAV_MUSIC
   507 		case MUS_WAV:
   508 			WAVStream_SetVolume(music_volume);
   509 			break;
   510 #endif
   511 #ifdef MOD_MUSIC
   512 		case MUS_MOD:
   513 			Player_SetVolume(music_volume);
   514 			break;
   515 #endif
   516 #ifdef MID_MUSIC
   517 		case MUS_MID:
   518 			Timidity_SetVolume(music_volume);
   519 			break;
   520 #endif
   521 #ifdef MP3_MUSIC
   522 		case MUS_MP3:
   523 			SMPEG_setvolume(music_playing->data.mp3,((float)music_volume/(float)MIX_MAX_VOLUME)*100.0);
   524 			break;
   525 #endif
   526 		default:
   527 			/* Unknown music type?? */
   528 			break;
   529 		}
   530 	}
   531 	return(prev_volume);
   532 }
   533 
   534 /* Halt playing of music */
   535 int Mix_HaltMusic(void)
   536 {
   537 	/* This function can be called both from the main program thread
   538 	   and from the SDL audio thread (when fading), so we need to ensure 
   539 	   that only one thread is running it at once */
   540 	SDL_mutexP(music_lock);
   541 	if ( music_playing ) {
   542 		switch (music_playing->type) {
   543 #ifdef CMD_MUSIC
   544 			case MUS_CMD:
   545 				MusicCMD_Stop(music_playing->data.cmd);
   546 				break;
   547 #endif
   548 #ifdef WAV_MUSIC
   549 			case MUS_WAV:
   550 				WAVStream_Stop();
   551 				break;
   552 #endif
   553 #ifdef MOD_MUSIC
   554 			case MUS_MOD:
   555 				Player_Stop();
   556 				break;
   557 #endif
   558 #ifdef MID_MUSIC
   559 			case MUS_MID:
   560 				Timidity_Stop();
   561 				break;
   562 #endif
   563 #ifdef MP3_MUSIC
   564 		    case MUS_MP3:
   565 				SMPEG_stop(music_playing->data.mp3);
   566 				break;
   567 #endif
   568 			default:
   569 				/* Unknown music type?? */
   570 				SDL_mutexV(music_lock);
   571 				return(-1);
   572 		}
   573 		if(music_playing->fading != MIX_NO_FADING) /* Restore volume */
   574 			music_volume = music_playing->fade_volume;
   575 		music_playing->fading = MIX_NO_FADING;
   576 		music_playing = 0;
   577 	}
   578 	SDL_mutexV(music_lock);
   579 	return(0);
   580 }
   581 
   582 /* Progressively stop the music */
   583 int Mix_FadeOutMusic(int ms)
   584 {
   585 	if ( music_playing && music_playing->fading==MIX_NO_FADING ) {
   586 		if ( music_volume>0 ) {
   587 			music_playing->fading = MIX_FADING_OUT;
   588 			music_playing->fade_volume = music_volume;
   589 			music_playing->fade_length = ms;
   590 			music_playing->ticks_fade = SDL_GetTicks();
   591 			return(1);
   592 		}
   593 	}
   594 	return(0);
   595 }
   596 
   597 Mix_Fading Mix_FadingMusic(void)
   598 {
   599 	if( music_playing )
   600 		return music_playing->fading;
   601 	return MIX_NO_FADING;
   602 }
   603 
   604 /* Pause/Resume the music stream */
   605 void Mix_PauseMusic(void)
   606 {
   607 	if ( music_playing ) {
   608 		switch ( music_playing->type ) {
   609 #ifdef CMD_MUSIC
   610 		case MUS_CMD:
   611 			MusicCMD_Pause(music_playing->data.cmd);
   612 			break;
   613 #endif
   614 #ifdef MP3_MUSIC
   615 		case MUS_MP3:
   616 			SMPEG_pause(music_playing->data.mp3);
   617 			break;
   618 #endif
   619 		}
   620 	}
   621 	music_active = 0;
   622 }
   623 
   624 void Mix_ResumeMusic(void)
   625 {
   626 	if ( music_playing ) {
   627 		switch ( music_playing->type ) {
   628 #ifdef CMD_MUSIC
   629 		case MUS_CMD:
   630 			MusicCMD_Resume(music_playing->data.cmd);
   631 			break;
   632 #endif
   633 #ifdef MP3_MUSIC
   634 		case MUS_MP3:
   635 			SMPEG_pause(music_playing->data.mp3);
   636 			break;
   637 #endif
   638 		}
   639 	}
   640 	music_active = 1;
   641 }
   642 
   643 void Mix_RewindMusic(void)
   644 {
   645 	if ( music_playing ) {
   646 		switch ( music_playing->type ) {
   647 #ifdef MP3_MUSIC
   648 		case MUS_MP3:
   649 			SMPEG_rewind(music_playing->data.mp3);
   650 			break;
   651 #endif
   652 		}
   653 	}
   654 }
   655 
   656 /* Check the status of the music */
   657 int Mix_PlayingMusic(void)
   658 {
   659 	if ( music_playing ) {
   660 		switch (music_playing->type) {
   661 #ifdef CMD_MUSIC
   662 			case MUS_CMD:
   663 				if (!MusicCMD_Active(music_playing->data.cmd)) {
   664 					music_playing = 0;
   665 				}
   666 				break;
   667 #endif
   668 #ifdef WAV_MUSIC
   669 			case MUS_WAV:
   670 				if ( ! WAVStream_Active() ) {
   671 					music_playing = 0;
   672 				}
   673 				break;
   674 #endif
   675 #ifdef MOD_MUSIC
   676 			case MUS_MOD:
   677 				if ( ! Player_Active() ) {
   678 					music_playing = 0;
   679 				}
   680 				break;
   681 #endif
   682 #ifdef MID_MUSIC
   683 			case MUS_MID:
   684 				if ( ! Timidity_Active() ) {
   685 					music_playing = 0;
   686 				}
   687 				break;
   688 #endif
   689 #ifdef MP3_MUSIC
   690 			case MUS_MP3:
   691 				if(SMPEG_status(music_playing->data.mp3)!=SMPEG_PLAYING)
   692 					music_playing = 0;
   693 				break;
   694 #endif
   695 		}
   696 	}
   697 	return(music_playing ? 1 : 0);
   698 }
   699 
   700 /* Set the external music playback command */
   701 int Mix_SetMusicCMD(const char *command)
   702 {
   703 	Mix_HaltMusic();
   704 	if ( music_cmd ) {
   705 		free(music_cmd);
   706 		music_cmd = NULL;
   707 	}
   708 	if ( command ) {
   709 		music_cmd = (char *)malloc(strlen(command)+1);
   710 		if ( music_cmd == NULL ) {
   711 			return(-1);
   712 		}
   713 		strcpy(music_cmd, command);
   714 	}
   715 	return(0);
   716 }
   717 
   718 /* Uninitialize the music players */
   719 void close_music(void)
   720 {
   721 	Mix_HaltMusic();
   722 #ifdef CMD_MUSIC
   723 	Mix_SetMusicCMD(NULL);
   724 #endif
   725 #ifdef MOD_MUSIC
   726 	MikMod_Exit();
   727 #endif
   728 }
   729