diff --git a/src/dehacked.c b/src/dehacked.c
index e2df1114222a04018393b454048b8466809f73af..002ad8071d0055e77eabead042ff0f877d8c7e4b 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1205,6 +1205,8 @@ static void readlevelheader(MYFILE *f, INT32 num)
 				mapheaderinfo[num-1]->skynum = (INT16)i;
 			else if (fastcmp(word, "INTERSCREEN"))
 				strncpy(mapheaderinfo[num-1]->interscreen, word2, 8);
+			else if (fastcmp(word, "MUSICINTERFADEOUT"))
+				mapheaderinfo[num-1]->musicinterfadeout = (UINT32)get_number(word2);
 			else if (fastcmp(word, "PRECUTSCENENUM"))
 				mapheaderinfo[num-1]->precutscenenum = (UINT8)i;
 			else if (fastcmp(word, "CUTSCENENUM"))
diff --git a/src/doomstat.h b/src/doomstat.h
index d6fd046b4558cd12898e82a36ba864f98cc24d18..cbeb4de428c10a6e1cad5d3d47d73000785a8e18 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -246,6 +246,9 @@ typedef struct
 	UINT8 numGradedMares;   ///< Internal. For grade support.
 	nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful.
 
+	// Music stuff.
+	UINT32 musicinterfadeout;  ///< Fade out level music on intermission screen in milliseconds
+
 	// Lua stuff.
 	// (This is not ifdeffed so the map header structure can stay identical, just in case.)
 	UINT8 numCustomOptions;     ///< Internal. For Lua custom value support.
diff --git a/src/g_game.c b/src/g_game.c
index 6be4cf96e25f1e93624fae3130eaf4366c3b5fdc..0c53d17ff52bb5c5b032a750d7f2447c2ca62ced 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -3541,7 +3541,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
 	{
 		// Clear a bunch of variables
 		tokenlist = token = sstimer = redscore = bluescore = lastmap = 0;
-		countdown = countdown2 = 0;
+		countdown = countdown2 = exitfadestarted = 0;
 
 		for (i = 0; i < MAXPLAYERS; i++)
 		{
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index a1d7994bf317f55d261eaa8133d7eaa7658c81db..b68574a7fe4e94cc95a7d4a33fe3c5f08bf9ebb5 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -1211,7 +1211,9 @@ static int mapheaderinfo_get(lua_State *L)
 			if (!header->interscreen[i])
 				break;
 		lua_pushlstring(L, header->interscreen, i);
-	} else if (fastcmp(field,"runsoc"))
+	} else if (fastcmp(field,"musicinterfadeout"))
+		lua_pushinteger(L, header->musicinterfadeout);
+	else if (fastcmp(field,"runsoc"))
 		lua_pushstring(L, header->runsoc);
 	else if (fastcmp(field,"scriptname"))
 		lua_pushstring(L, header->scriptname);
diff --git a/src/p_setup.c b/src/p_setup.c
index 6c6b9153d5df381a9f40013aeb84a9180695077c..424aed5bc771e12e43c6f4f84f9a04bcd6a325b2 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -227,6 +227,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	mapheaderinfo[num]->menuflags = 0;
 	// TODO grades support for delfile (pfft yeah right)
 	P_DeleteGrades(num);
+	mapheaderinfo[num]->musicinterfadeout = 0;
 	// an even further impossibility, delfile custom opts support
 	mapheaderinfo[num]->customopts = NULL;
 	mapheaderinfo[num]->numCustomOptions = 0;
@@ -2189,7 +2190,7 @@ static void P_LevelInitStuff(void)
 			players[i].lives = cv_startinglives.value;
 		}
 
-		players[i].realtime = countdown = countdown2 = 0;
+		players[i].realtime = countdown = countdown2 = exitfadestarted = 0;
 
 		players[i].gotcontinue = false;
 
diff --git a/src/p_user.c b/src/p_user.c
index 03b037fede87b9aebc8298e1c40e8a4ed8094569..1d34ba5f1196b010a46508713e1bbda7e5376a24 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -8789,6 +8789,45 @@ void P_PlayerThink(player_t *player)
 	if (player->exiting && countdown2)
 		player->exiting = 5;
 
+	// Same check as below, just at 1 second before
+	// so we can fade music
+	if (!exitfadestarted &&
+		player->exiting <= 1*TICRATE &&
+		(!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musicinterfadeout : true) &&
+			// don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop
+		(gametype == GT_RACE || gametype == GT_COMPETITION ? countdown2 == 0 : true) && // don't fade on timeout
+		player->lives > 0 && // don't fade on game over (competition)
+		P_IsLocalPlayer(player))
+	{
+		if (cv_playersforexit.value)
+		{
+			INT32 i, total = 0, exiting = 0;
+
+			for (i = 0; i < MAXPLAYERS; i++)
+			{
+				if (!playeringame[i] || players[i].spectator || players[i].bot)
+					continue;
+				if (players[i].lives <= 0)
+					continue;
+
+				total++;
+				if (players[i].exiting && players[i].exiting < 1*TICRATE+1)
+					exiting++;
+			}
+
+			if (!total || ((4*exiting)/total) >= cv_playersforexit.value)
+			{
+				exitfadestarted = true;
+				S_FadeOutStopMusic(1*MUSICRATE);
+			}
+		}
+		else
+		{
+			exitfadestarted = true;
+			S_FadeOutStopMusic(1*MUSICRATE);
+		}
+	}
+
 	if (player->exiting == 2 || countdown2 == 2)
 	{
 		if (cv_playersforexit.value) // Count to be sure everyone's exited
diff --git a/src/s_sound.h b/src/s_sound.h
index 538707ffb14b3c95ec798b5abeb5c8350d66a964..852ed4c27126a4290379e25a8f0289e5fa4586ed 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -23,6 +23,12 @@
 // mask used to indicate sound origin is player item pickup
 #define PICKUP_SOUND 0x8000
 
+// Game state stuff
+
+boolean exitfadestarted;
+
+// Sound stuff
+
 extern consvar_t stereoreverse;
 extern consvar_t cv_soundvolume, cv_digmusicvolume, cv_midimusicvolume;
 extern consvar_t cv_numChannels;
diff --git a/src/y_inter.c b/src/y_inter.c
index e7df165bfc71e666bf5b064495f154fdaa9c53d8..1f4b49ddf60da65a3062c416ed04fae13fd0f702 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -696,7 +696,10 @@ void Y_Ticker(void)
 		boolean anybonuses = false;
 
 		if (!intertic) // first time only
-			S_ChangeMusicInternal("lclear", false); // don't loop it
+			if (mapheaderinfo[gamemap-1]->musicinterfadeout)
+				S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musicinterfadeout);
+			else
+				S_ChangeMusicInternal("_clear", false); // don't loop it
 
 		if (intertic < TICRATE) // one second pause before tally begins
 			return;
@@ -757,7 +760,10 @@ void Y_Ticker(void)
 
 		if (!intertic) // first time only
 		{
-			S_ChangeMusicInternal("lclear", false); // don't loop it
+			if (mapheaderinfo[gamemap-1]->musicinterfadeout)
+				S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musicinterfadeout);
+			else
+				S_ChangeMusicInternal("_clear", false); // don't loop it
 			tallydonetic = 0;
 		}