diff --git a/src/s_sound.c b/src/s_sound.c
index 6938fd639b84504e8c0e58ddc51d0de8cd901194..8b9927e9af9c74855af41c629744f209ab85d603 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -62,6 +62,8 @@ static void GameDigiMusic_OnChange(void);
 
 static void ModFilter_OnChange(void);
 
+static lumpnum_t S_GetMusicLumpNum(const char *mname);
+
 // commands for music and sound servers
 #ifdef MUSSERV
 consvar_t musserver_cmd = {"musserver_cmd", "musserver", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -1584,6 +1586,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi
 		music_stacks->position = (status == JT_MASTER ? position : S_GetMusicPosition());
 		music_stacks->tic = gametic;
 		music_stacks->status = JT_MASTER;
+		music_stacks->mlumpnum = S_GetMusicLumpNum(music_stacks->musname);
 
 		if (status == JT_MASTER)
 			return; // we just added the user's entry here
@@ -1601,6 +1604,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi
 	new_mst->position = position;
 	new_mst->tic = gametic;
 	new_mst->status = status;
+	new_mst->mlumpnum = S_GetMusicLumpNum(new_mst->musname);
 
 	mst->next = new_mst;
 	new_mst->prev = mst;
@@ -1707,6 +1711,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
 		entry->position = mapmusposition;
 		entry->tic = gametic;
 		entry->status = JT_MASTER;
+		entry->mlumpnum = S_GetMusicLumpNum(entry->musname);
 	}
 
 	if (entry->status == JT_MASTER)
@@ -1730,7 +1735,10 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
 			if (!music_stack_noposition) // HACK: Global boolean to toggle position resuming, e.g., de-superize
 				newpos = entry->position + (S_GetMusicLength() ? (UINT32)((float)(gametic - entry->tic)/(float)TICRATE*(float)MUSICRATE) : 0);
 
-			if (newpos > 0 && S_MusicPlaying())
+			// If the newly recalled music lumpnum does not match the lumpnum that we stored in stack,
+			// then discard the new position. That way, we will not recall an invalid position
+			// when the music is replaced or digital/MIDI is toggled.
+			if (newpos > 0 && S_MusicPlaying() && S_GetMusicLumpNum(entry->musname) == entry->mlumpnum)
 				S_SetMusicPosition(newpos);
 			else
 			{
@@ -1751,33 +1759,41 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
 /// Music Playback
 /// ------------------------
 
-static boolean S_LoadMusic(const char *mname)
+static lumpnum_t S_GetMusicLumpNum(const char *mname)
 {
-	lumpnum_t mlumpnum;
-	void *mdata;
-
-	if (S_MusicDisabled())
-		return false;
-
 	if (!S_DigMusicDisabled() && S_DigExists(mname))
-		mlumpnum = W_GetNumForName(va("o_%s", mname));
+		return W_GetNumForName(va("o_%s", mname));
 	else if (!S_MIDIMusicDisabled() && S_MIDIExists(mname))
-		mlumpnum = W_GetNumForName(va("d_%s", mname));
+		return W_GetNumForName(va("d_%s", mname));
 	else if (S_DigMusicDisabled() && S_DigExists(mname))
 	{
 		CONS_Alert(CONS_NOTICE, "Digital music is disabled!\n");
-		return false;
+		return LUMPERROR;
 	}
 	else if (S_MIDIMusicDisabled() && S_MIDIExists(mname))
 	{
 		CONS_Alert(CONS_NOTICE, "MIDI music is disabled!\n");
-		return false;
+		return LUMPERROR;
 	}
 	else
 	{
 		CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), mname);
-		return false;
+		return LUMPERROR;
 	}
+}
+
+static boolean S_LoadMusic(const char *mname)
+{
+	lumpnum_t mlumpnum;
+	void *mdata;
+
+	if (S_MusicDisabled())
+		return false;
+
+	mlumpnum = S_GetMusicLumpNum(mname);
+
+	if (mlumpnum == LUMPERROR)
+		return false;
 
 	// load & register it
 	mdata = W_CacheLumpNum(mlumpnum, PU_MUSIC);
diff --git a/src/s_sound.h b/src/s_sound.h
index 2d05a055d2e585e2f57cd31657f4463ca624f433..17887ef90a47129ed5b3c4f48b8767c59216c1ea 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -193,6 +193,7 @@ typedef struct musicstack_s
 	UINT32 position;
 	tic_t tic;
 	UINT16 status;
+	lumpnum_t mlumpnum;
 
     struct musicstack_s *prev;
     struct musicstack_s *next;