📄 music.c
字号:
Mix_Music *Mix_LoadMUS(const char *file){ FILE *fp; char *ext; Uint8 magic[5], moremagic[9]; Mix_Music *music; /* Figure out what kind of file this is */ fp = fopen(file, "rb"); if ( (fp == NULL) || !fread(magic, 4, 1, fp) ) { if ( fp != NULL ) { fclose(fp); } Mix_SetError("Couldn't read from '%s'", file); return(NULL); } if (!fread(moremagic, 8, 1, fp)) { Mix_SetError("Couldn't read from '%s'", file); return(NULL); } magic[4] = '\0'; moremagic[8] = '\0'; fclose(fp); /* Figure out the file extension, so we can determine the type */ ext = strrchr(file, '.'); if ( ext ) ++ext; /* skip the dot in the extension */ /* Allocate memory for the music structure */ music = (Mix_Music *)malloc(sizeof(Mix_Music)); if ( music == NULL ) { Mix_SetError("Out of memory"); return(NULL); } music->error = 0;#ifdef CMD_MUSIC if ( music_cmd ) { music->type = MUS_CMD; music->data.cmd = MusicCMD_LoadSong(music_cmd, file); if ( music->data.cmd == NULL ) { music->error = 1; } } else#endif#ifdef WAV_MUSIC /* WAVE files have the magic four bytes "RIFF" AIFF files have the magic 12 bytes "FORM" XXXX "AIFF" */ if ( (ext && MIX_string_equals(ext, "WAV")) || ((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) || (strcmp((char *)magic, "FORM") == 0) ) { music->type = MUS_WAV; music->data.wave = WAVStream_LoadSong(file, (char *)magic); if ( music->data.wave == NULL ) { Mix_SetError("Unable to load WAV file"); music->error = 1; } } else#endif#ifdef MID_MUSIC /* MIDI files have the magic four bytes "MThd" */ if ( (ext && MIX_string_equals(ext, "MID")) || (ext && MIX_string_equals(ext, "MIDI")) || strcmp((char *)magic, "MThd") == 0 || ( strcmp((char *)magic, "RIFF") == 0 && strcmp((char *)(moremagic+4), "RMID") == 0 ) ) { music->type = MUS_MID;#ifdef USE_NATIVE_MIDI if ( native_midi_ok ) { music->data.nativemidi = native_midi_loadsong((char *)file); if ( music->data.nativemidi == NULL ) { Mix_SetError("%s", native_midi_error()); music->error = 1; } } MIDI_ELSE#endif#ifdef USE_TIMIDITY_MIDI if ( timidity_ok ) { music->data.midi = Timidity_LoadSong((char *)file); if ( music->data.midi == NULL ) { Mix_SetError("%s", Timidity_Error()); music->error = 1; } } else { Mix_SetError("%s", Timidity_Error()); music->error = 1; }#endif } else#endif#ifdef OGG_MUSIC /* Ogg Vorbis files have the magic four bytes "OggS" */ if ( (ext && MIX_string_equals(ext, "OGG")) || strcmp((char *)magic, "OggS") == 0 ) { music->type = MUS_OGG; music->data.ogg = OGG_new(file); if ( music->data.ogg == NULL ) { music->error = 1; } } else#endif#ifdef MP3_MUSIC if ( (ext && MIX_string_equals(ext, "MPG")) || (ext && MIX_string_equals(ext, "MP3")) || (ext && MIX_string_equals(ext, "MPEG")) || (magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) ) { if ( Mix_InitMP3() == 0 ) { SMPEG_Info info; music->type = MUS_MP3; music->data.mp3 = smpeg.SMPEG_new(file, &info, 0); if ( !info.has_audio ) { Mix_SetError("MPEG file does not have any audio stream."); music->error = 1; } else { smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer); } } else { music->error = 1; } } else#endif#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) if ( 1 ) { music->type = MUS_MOD; music->data.module = MikMod_LoadSong((char *)file, 64); if ( music->data.module == NULL ) { Mix_SetError("%s", MikMod_strerror(MikMod_errno)); music->error = 1; } else { /* Stop implicit looping, fade out and other flags. */ music->data.module->extspd = 1; music->data.module->panflag = 1; music->data.module->wrap = 0; music->data.module->loop = 1;#if 0 /* Don't set fade out by default - unfortunately there's no real way to query the status of the song or set trigger actions. Hum. */ music->data.module->fadeout = 1;#endif } } else#endif { Mix_SetError("Unrecognized music format"); music->error = 1; } if ( music->error ) { free(music); music = NULL; } return(music);}/* Free a music chunk previously loaded */void Mix_FreeMusic(Mix_Music *music){ if ( music ) { /* Stop the music if it's currently playing */ SDL_LockAudio(); if ( music == music_playing ) { /* Wait for any fade out to finish */ while ( music->fading == MIX_FADING_OUT ) { SDL_UnlockAudio(); SDL_Delay(100); SDL_LockAudio(); } if ( music == music_playing ) { music_internal_halt(); } } SDL_UnlockAudio(); switch (music->type) {#ifdef CMD_MUSIC case MUS_CMD: MusicCMD_FreeSong(music->data.cmd); break;#endif#ifdef WAV_MUSIC case MUS_WAV: WAVStream_FreeSong(music->data.wave); break;#endif#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) case MUS_MOD: MikMod_FreeSong(music->data.module); break;#endif#ifdef MID_MUSIC case MUS_MID:#ifdef USE_NATIVE_MIDI if ( native_midi_ok ) { native_midi_freesong(music->data.nativemidi); } MIDI_ELSE#endif#ifdef USE_TIMIDITY_MIDI if ( timidity_ok ) { Timidity_FreeSong(music->data.midi); }#endif break;#endif#ifdef OGG_MUSIC case MUS_OGG: OGG_delete(music->data.ogg); break;#endif#ifdef MP3_MUSIC case MUS_MP3: smpeg.SMPEG_delete(music->data.mp3); Mix_QuitMP3(); break;#endif default: /* Unknown music type?? */ break; } free(music); }}/* Find out the music format of a mixer music, or the currently playing music, if 'music' is NULL.*/Mix_MusicType Mix_GetMusicType(const Mix_Music *music){ Mix_MusicType type = MUS_NONE; if ( music ) { type = music->type; } else { SDL_LockAudio(); if ( music_playing ) { type = music_playing->type; } SDL_UnlockAudio(); } return(type);}/* Play a music chunk. Returns 0, or -1 if there was an error. */static int music_internal_play(Mix_Music *music, double position){ int retval = 0; /* Note the music we're playing */ if ( music_playing ) { music_internal_halt(); } music_playing = music; /* Set the initial volume */ if ( music->type != MUS_MOD ) { music_internal_initialize_volume(); } /* Set up for playback */ switch (music->type) {#ifdef CMD_MUSIC case MUS_CMD: MusicCMD_Start(music->data.cmd); break;#endif#ifdef WAV_MUSIC case MUS_WAV: WAVStream_Start(music->data.wave); break;#endif#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) case MUS_MOD: Player_Start(music->data.module); /* Player_SetVolume() does nothing before Player_Start() */ music_internal_initialize_volume(); break;#endif#ifdef MID_MUSIC case MUS_MID:#ifdef USE_NATIVE_MIDI if ( native_midi_ok ) { native_midi_start(music->data.nativemidi); } MIDI_ELSE#endif#ifdef USE_TIMIDITY_MIDI if ( timidity_ok ) { Timidity_Start(music->data.midi); }#endif break;#endif#ifdef OGG_MUSIC case MUS_OGG: OGG_play(music->data.ogg); break;#endif#ifdef MP3_MUSIC case MUS_MP3: smpeg.SMPEG_enableaudio(music->data.mp3,1); smpeg.SMPEG_enablevideo(music->data.mp3,0); smpeg.SMPEG_play(music_playing->data.mp3); break;#endif default: Mix_SetError("Can't play unknown music type"); retval = -1; break; } /* Set the playback position, note any errors if an offset is used */ if ( retval == 0 ) { if ( position > 0.0 ) { if ( music_internal_position(position) < 0 ) { Mix_SetError("Position not implemented for music type"); retval = -1; } } else { music_internal_position(0.0); } } /* If the setup failed, we're not playing any music anymore */ if ( retval < 0 ) { music_playing = NULL; } return(retval);}int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position){ int retval; /* Don't play null pointers :-) */ if ( music == NULL ) { Mix_SetError("music parameter was NULL"); return(-1); } /* Setup the data */ if ( ms ) { music->fading = MIX_FADING_IN; } else { music->fading = MIX_NO_FADING; } music->fade_step = 0; music->fade_steps = ms/ms_per_step; /* Play the puppy */ SDL_LockAudio(); /* If the current music is fading out, wait for the fade to complete */ while ( music_playing && (music_playing->fading == MIX_FADING_OUT) ) { SDL_UnlockAudio(); SDL_Delay(100); SDL_LockAudio(); } music_active = 1; music_loops = loops; retval = music_internal_play(music, position); SDL_UnlockAudio(); return(retval);}int Mix_FadeInMusic(Mix_Music *music, int loops, int ms){ return Mix_FadeInMusicPos(music, loops, ms, 0.0);}int Mix_PlayMusic(Mix_Music *music, int loops){ return Mix_FadeInMusicPos(music, loops, 0, 0.0);}/* Set the playing music position */int music_internal_position(double position){ int retval = 0; switch (music_playing->type) {#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) case MUS_MOD: Player_SetPosition((UWORD)position); break;#endif#ifdef OGG_MUSIC case MUS_OGG: OGG_jump_to_time(music_playing->data.ogg, position); break;#endif#ifdef MP3_MUSIC case MUS_MP3: if ( position > 0.0 ) { smpeg.SMPEG_skip(music_playing->data.mp3, (float)position); } else { smpeg.SMPEG_rewind(music_playing->data.mp3); smpeg.SMPEG_play(music_playing->data.mp3); } break;#endif default: /* TODO: Implement this for other music backends */ retval = -1; break; } return(retval);}int Mix_SetMusicPosition(double position){ int retval; SDL_LockAudio(); if ( music_playing ) { retval = music_internal_position(position); if ( retval < 0 ) { Mix_SetError("Position not implemented for music type"); } } else { Mix_SetError("Music isn't playing"); retval = -1; } SDL_UnlockAudio(); return(retval);}/* Set the music's initial volume */static void music_internal_initialize_volume(void){ if ( music_playing->fading == MIX_FADING_IN ) { music_internal_volume(0); } else { music_internal_volume(music_volume); }}/* Set the music volume */static void music_internal_volume(int volume){ switch (music_playing->type) {#ifdef CMD_MUSIC case MUS_CMD: MusicCMD_SetVolume(volume); break;#endif#ifdef WAV_MUSIC case MUS_WAV: WAVStream_SetVolume(volume); break;#endif#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) case MUS_MOD: Player_SetVolume((SWORD)volume); break;#endif#ifdef MID_MUSIC case MUS_MID:#ifdef USE_NATIVE_MIDI if ( native_midi_ok ) { native_midi_setvolume(volume); } MIDI_ELSE#endif#ifdef USE_TIMIDITY_MIDI if ( timidity_ok ) { Timidity_SetVolume(volume); }#endif break;#endif#ifdef OGG_MUSIC case MUS_OGG: OGG_setvolume(music_playing->data.ogg, volume); break;#endif#ifdef MP3_MUSIC case MUS_MP3: smpeg.SMPEG_setvolume(music_playing->data.mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0)); break;#endif default: /* Unknown music type?? */ break; }}int Mix_VolumeMusic(int volume){ int prev_volume; prev_volume = music_volume; if ( volume < 0 ) { return prev_volume; } if ( volume > SDL_MIX_MAXVOLUME ) { volume = SDL_MIX_MAXVOLUME;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -