diff --git a/src/d_netcmd.c b/src/d_netcmd.c index bd7f16228..534408aec 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1034,6 +1034,13 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_soundtest); + CV_RegisterVar(&cv_invincmusicfade); + CV_RegisterVar(&cv_growmusicfade); + + CV_RegisterVar(&cv_resetspecialmusic); + + CV_RegisterVar(&cv_resume); + // ingame object placing COM_AddCommand("objectplace", Command_ObjectPlace_f); COM_AddCommand("writethings", Command_Writethings_f); diff --git a/src/doomstat.h b/src/doomstat.h index 952586231..9464385ea 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -34,6 +34,7 @@ extern INT16 gamemap; extern char mapmusname[7]; extern UINT16 mapmusflags; extern UINT32 mapmusposition; +extern UINT32 mapmusresume; #define MUSIC_TRACKMASK 0x0FFF // ----************ #define MUSIC_RELOADRESET 0x8000 // *--------------- #define MUSIC_FORCERESET 0x4000 // -*-------------- diff --git a/src/g_game.c b/src/g_game.c index 684e73492..a97143d21 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -81,6 +81,7 @@ static void G_DoStartVote(void); char mapmusname[7]; // Music name UINT16 mapmusflags; // Track and reset bit UINT32 mapmusposition; // Position to jump to +UINT32 mapmusresume; INT16 gamemap = 1; INT16 maptol; @@ -526,6 +527,12 @@ consvar_t cv_fireaxis4 = {"joyaxis4_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NU consvar_t cv_driftaxis4 = {"joyaxis4_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_deadzone4 = {"joy4_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_invincmusicfade = {"invincmusicfade", "300", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_growmusicfade = {"growmusicfade", "500", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_resetspecialmusic = {"resetspecialmusic", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_resume = {"resume", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; #if MAXPLAYERS > 16 #error "please update player_name table using the new value for MAXPLAYERS" @@ -2742,11 +2749,13 @@ void G_PlayerReborn(INT32 player) mapmusname[6] = 0; mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); mapmusposition = mapheaderinfo[gamemap-1]->muspos; + mapmusresume = 0; songcredit = true; } } P_RestoreMusic(p); + if (songcredit) S_ShowMusicCredit(); diff --git a/src/g_game.h b/src/g_game.h index 08af3a2b5..2a517777a 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -118,6 +118,13 @@ extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4,cv_deadzone4; extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff; +extern consvar_t cv_invincmusicfade; +extern consvar_t cv_growmusicfade; + +extern consvar_t cv_resetspecialmusic; + +extern consvar_t cv_resume; + typedef enum { AXISNONE = 0, diff --git a/src/i_sound.h b/src/i_sound.h index 9a5c2930a..93e3f6dd0 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -158,6 +158,9 @@ UINT32 I_GetSongLoopPoint(void); boolean I_SetSongPosition(UINT32 position); UINT32 I_GetSongPosition(void); +void I_UpdateSongLagThreshold (void); +void I_UpdateSongLagConditions (void); + /// ------------------------ // MUSIC PLAYBACK /// ------------------------ diff --git a/src/k_kart.c b/src/k_kart.c index e7faed5b0..236bbd862 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7349,9 +7349,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetScale(overlay, player->mo->scale); } player->kartstuff[k_invincibilitytimer] = itemtime+(2*TICRATE); // 10 seconds + if (P_IsDisplayPlayer(player)) + S_ChangeMusicSpecial("kinvnc"); + else + S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kinvnc)); P_RestoreMusic(player); - if (!P_IsDisplayPlayer(player)) - S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc)); K_PlayPowerGloatSound(player->mo); player->kartstuff[k_itemamount]--; } @@ -7551,9 +7553,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (cv_kartdebugshrink.value && !modeattacking && !player->bot) player->mo->destscale = (6*player->mo->destscale)/8; player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds - P_RestoreMusic(player); - if (!P_IsDisplayPlayer(player)) + if (P_IsDisplayPlayer(player)) + S_ChangeMusicSpecial("kgrow"); + else S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); + P_RestoreMusic(player); S_StartSound(player->mo, sfx_kc5a); } player->kartstuff[k_itemamount]--; diff --git a/src/p_spec.c b/src/p_spec.c index ad711fb8b..f1fba7d90 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2518,6 +2518,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) mapmusflags |= MUSIC_FORCERESET; mapmusposition = position; + mapmusresume = 0; S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position, !(line->flags & ML_EFFECT2) ? prefadems : 0, diff --git a/src/p_user.c b/src/p_user.c index 5358df1fe..c84fa61af 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1188,6 +1188,8 @@ boolean P_EndingMusic(player_t *player) // void P_RestoreMusic(player_t *player) { + UINT32 position; + if (!P_IsLocalPlayer(player)) // Only applies to a local player return; @@ -1244,10 +1246,16 @@ void P_RestoreMusic(player_t *player) // Item - Grow if (wantedmus == 2) + { S_ChangeMusicInternal("kgrow", true); + S_SetRestoreMusicFadeInCvar(&cv_growmusicfade); + } // Item - Invincibility else if (wantedmus == 1) + { S_ChangeMusicInternal("kinvnc", true); + S_SetRestoreMusicFadeInCvar(&cv_invincmusicfade); + } else { #if 0 @@ -1256,7 +1264,15 @@ void P_RestoreMusic(player_t *player) if (G_RaceGametype() && player->laps >= (UINT8)(cv_numlaps.value)) S_SpeedMusic(1.2f); #endif - S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); + if (mapmusresume && cv_resume.value) + position = mapmusresume; + else + position = mapmusposition; + + S_ChangeMusicEx(mapmusname, mapmusflags, true, position, 0, + S_GetRestoreMusicFadeIn()); + S_ClearRestoreMusicFadeInCvar(); + mapmusresume = 0; } } } diff --git a/src/s_sound.c b/src/s_sound.c index 82435d3dc..28ceff30e 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -120,6 +120,16 @@ consvar_t cv_gamesounds = {"sounds", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, consvar_t cv_playmusicifunfocused = {"playmusicifunfocused", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, PlayMusicIfUnfocused_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_playsoundifunfocused = {"playsoundsifunfocused", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, PlaySoundIfUnfocused_OnChange, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t music_resync_threshold_cons_t[] = { + {0, "MIN"}, + {1000, "MAX"}, + + {0} +}; +consvar_t cv_music_resync_threshold = {"music_resync_threshold", "100", CV_SAVE|CV_CALL, music_resync_threshold_cons_t, I_UpdateSongLagThreshold, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_music_resync_powerups_only = {"music_resync_powerups_only", "No", CV_SAVE|CV_CALL, CV_YesNo, I_UpdateSongLagConditions, 0, NULL, NULL, 0, 0, NULL}; + #define S_MAX_VOLUME 127 // when to clip out sounds @@ -283,6 +293,9 @@ void S_RegisterSoundStuff(void) CV_RegisterVar(&cv_playmusicifunfocused); CV_RegisterVar(&cv_playsoundifunfocused); + CV_RegisterVar(&cv_music_resync_threshold); + CV_RegisterVar(&cv_music_resync_powerups_only); + COM_AddCommand("tunes", Command_Tunes_f); COM_AddCommand("restartaudio", Command_RestartAudio_f); @@ -1550,6 +1563,8 @@ static char music_name[7]; // up to 6-character name static void *music_data; static UINT16 music_flags; static boolean music_looping; +static consvar_t *music_refade_cv; +static int music_usage; static char queue_name[7]; static UINT16 queue_flags; @@ -1933,6 +1948,9 @@ static void S_UnloadMusic(void) music_name[0] = 0; music_flags = 0; music_looping = false; + + music_refade_cv = 0; + music_usage = 0; } static boolean S_PlayMusic(boolean looping, UINT32 fadeinms) @@ -1940,6 +1958,8 @@ static boolean S_PlayMusic(boolean looping, UINT32 fadeinms) if (S_MusicDisabled()) return false; + I_UpdateSongLagConditions(); + if ((!fadeinms && !I_PlaySong(looping)) || (fadeinms && !I_FadeInPlaySong(fadeinms, looping))) { @@ -2050,6 +2070,15 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 } } +void +S_ChangeMusicSpecial (const char *mmusic) +{ + if (cv_resetspecialmusic.value) + S_ChangeMusic(mmusic, MUSIC_FORCERESET, true); + else + S_ChangeMusicInternal(mmusic, true); +} + void S_StopMusic(void) { if (!I_SongPlaying() @@ -2057,6 +2086,9 @@ void S_StopMusic(void) || demo.title) // SRB2Kart: Demos don't interrupt title screen music return; + if (strcasecmp(music_name, mapmusname) == 0) + mapmusresume = I_GetSongPosition(); + if (I_SongPaused()) I_ResumeSong(); @@ -2154,6 +2186,34 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) } } +void +S_SetRestoreMusicFadeInCvar (consvar_t *cv) +{ + music_refade_cv = cv; +} + +int +S_GetRestoreMusicFadeIn (void) +{ + if (music_refade_cv) + return music_refade_cv->value; + else + return 0; +} + +void +S_SetMusicUsage (int type) +{ + music_usage = type; + I_UpdateSongLagConditions(); +} + +int +S_MusicUsage (void) +{ + return music_usage; +} + /// ------------------------ /// Music Fading /// ------------------------ @@ -2198,6 +2258,7 @@ void S_Start(void) mapmusname[6] = 0; mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); mapmusposition = mapheaderinfo[gamemap-1]->muspos; + mapmusresume = 0; } //if (cv_resetmusic.value) // Starting ambience should always be restarted @@ -2272,6 +2333,7 @@ static void Command_Tunes_f(void) mapmusname[6] = 0; mapmusflags = (track & MUSIC_TRACKMASK); mapmusposition = position; + mapmusresume = 0; S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); diff --git a/src/s_sound.h b/src/s_sound.h index 2a904faff..0aa93c623 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -36,6 +36,9 @@ extern consvar_t cv_gamesounds; extern consvar_t cv_playmusicifunfocused; extern consvar_t cv_playsoundifunfocused; +extern consvar_t cv_music_resync_threshold; +extern consvar_t cv_music_resync_powerups_only; + #ifdef SNDSERV extern consvar_t sndserver_cmd, sndserver_arg; #endif @@ -176,6 +179,11 @@ UINT32 S_GetMusicPosition(void); // Music Playback // +enum +{ + MUS_SPECIAL = 1,/* powerups--invincibility, grow */ +}; + // Start music track, arbitrary, given its name, and set whether looping // note: music flags 12 bits for tracknum (gme, other formats with more than one track) // 13-15 aren't used yet @@ -184,6 +192,16 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 #define S_ChangeMusicInternal(a,b) S_ChangeMusicEx(a,0,b,0,0,0) #define S_ChangeMusic(a,b,c) S_ChangeMusicEx(a,b,c,0,0,0) +void S_ChangeMusicSpecial (const char *mmusic); + +void S_SetRestoreMusicFadeInCvar (consvar_t *cvar); +#define S_ClearRestoreMusicFadeInCvar() \ + S_SetRestoreMusicFadeInCvar(0) +int S_GetRestoreMusicFadeIn (void); + +void S_SetMusicUsage (int type); +int S_MusicUsage (void); + // Stops the music. void S_StopMusic(void); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 1617da2a3..77fcc0914 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -13,6 +13,12 @@ #if defined(HAVE_SDL) && defined(HAVE_MIXER) && SOUND==SOUND_MIXER +/* +Just for hu_stopped. I promise I didn't +write netcode into the sound code, OKAY? +*/ +#include "../d_clisrv.h" + #include "../sounds.h" #include "../s_sound.h" #include "../i_sound.h" @@ -74,12 +80,17 @@ UINT8 sound_started = false; +static UINT32 stutter_threshold_user; +static UINT32 stutter_threshold; + static Mix_Music *music; static UINT8 music_volume, sfx_volume, internal_volume; static float loop_point; static float song_length; // length in seconds static boolean songpaused; +static UINT32 music_end_bytes; static UINT32 music_bytes; +static UINT32 music_stutter_bytes; static boolean is_looping; // fading @@ -101,6 +112,8 @@ static void var_cleanup(void) loop_point = song_length =\ music_bytes = fading_source = fading_target =\ fading_timer = fading_duration = 0; + music_end_bytes = 0; + music_stutter_bytes = 0; songpaused = is_looping =\ is_fading = false; @@ -552,6 +565,35 @@ static void do_fading_callback(void) /// Music Hooks /// ------------------------ +static void +Countstutter (int len) +{ + UINT32 bytes; + + if (hu_stopped) + { + music_stutter_bytes += len; + } + else if (stutter_threshold) + { + if (music_stutter_bytes >= stutter_threshold) + { + /* + This would be after looping. If we're too near to the start of the + file, subtracting the delta will just underflow. + */ + if (music_stutter_bytes > music_bytes) + { + /* We already know where the end is because we looped. */ + bytes = ( music_end_bytes - ( music_stutter_bytes - music_bytes )); + } + else + bytes = ( music_bytes - music_stutter_bytes ); + I_SetSongPosition((int)( bytes/4/44100.0*1000 )); + } + } +} + static void count_music_bytes(int chan, void *stream, int len, void *udata) { (void)chan; @@ -561,12 +603,16 @@ static void count_music_bytes(int chan, void *stream, int len, void *udata) if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID) return; music_bytes += len; + + if (gamestate == GS_LEVEL) + Countstutter(len); } static void music_loop(void) { if (is_looping) { + music_end_bytes = music_bytes; Mix_PlayMusic(music, 0); Mix_SetMusicPosition(loop_point); music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) @@ -848,6 +894,8 @@ boolean I_SetSongPosition(UINT32 position) // NOT if position input is greater than song length. music_bytes = 0; + music_stutter_bytes = 0; + return true; } } @@ -892,6 +940,22 @@ UINT32 I_GetSongPosition(void) // 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4 } +void +I_UpdateSongLagThreshold (void) +{ + stutter_threshold_user = cv_music_resync_threshold.value/1000.0*(4*44100); + I_UpdateSongLagConditions(); +} + +void +I_UpdateSongLagConditions (void) +{ + if (! cv_music_resync_powerups_only.value || S_MusicUsage() == MUS_SPECIAL) + stutter_threshold = stutter_threshold_user; + else + stutter_threshold = 0; +} + /// ------------------------ /// Music Playback /// ------------------------