diff --git a/src/i_sound.h b/src/i_sound.h
index 98cc7523c561adc4c899575800e199d8b54c0284..71d3a8c2486b83cd6cb05ebb06feb6cc1c4c7f3a 100644
--- a/src/i_sound.h
+++ b/src/i_sound.h
@@ -18,6 +18,21 @@
 #include "sounds.h"
 #include "command.h"
 
+// copied from SDL mixer, plus GME
+typedef enum {
+    MU_NONE,
+    MU_CMD,
+    MU_WAV,
+    MU_MOD,
+    MU_MID,
+    MU_OGG,
+    MU_MP3,
+    MU_MP3_MAD_UNUSED, // use MU_MP3 instead
+    MU_FLAC,
+    MU_MODPLUG_UNUSED, // use MU_MOD instead
+	MU_GME
+} musictype_t;
+
 /**	\brief Sound subsystem runing and waiting
 */
 extern UINT8 sound_started;
@@ -150,6 +165,8 @@ boolean I_MusicPlaying(void);
 */
 boolean I_MusicPaused(void);
 
+musictype_t I_MusicType(void);
+
 //
 //  MIDI I/O
 //
diff --git a/src/s_sound.c b/src/s_sound.c
index 16d808f630189523a288eca89a2e9aa0478825c7..f288819868ceb2ccac5ff197269ef336b24e0c59 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -1412,6 +1412,11 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
 	I_SetSongTrack(mflags & MUSIC_TRACKMASK);
 }
 
+musictype_t S_MusicType()
+{
+	return I_MusicType();
+}
+
 boolean S_SpeedMusic(float speed)
 {
 	return I_SetSongSpeed(speed);
diff --git a/src/s_sound.h b/src/s_sound.h
index 94b12ba0b02635f065c034b150ac9a8270955da5..e73e8c909c07cce7b5356c3c930969cedd1ce078 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -14,6 +14,7 @@
 #ifndef __S_SOUND__
 #define __S_SOUND__
 
+#include "i_sound.h"
 #include "sounds.h"
 #include "m_fixed.h"
 #include "command.h"
@@ -132,6 +133,9 @@ void S_StopSound(void *origin);
 #define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b)
 void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping);
 
+// Get music type
+musictype_t S_MusicType();
+
 // Set Speed of Music
 boolean S_SpeedMusic(float speed);
 
diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c
index 012c3fffb77beb6261707329a0a5b5b4ef8e1074..43060db88709d883d07afff949db1a90079a43a2 100644
--- a/src/sdl/mixer_sound.c
+++ b/src/sdl/mixer_sound.c
@@ -441,9 +441,25 @@ void I_SetSfxVolume(UINT8 volume)
 // Music
 //
 
+musictype_t I_MusicType(void)
+{
+	if (gme)
+		return MU_GME;
+	else if (midimode)
+		return MU_MID;
+	else if (!music)
+		return MU_NONE;
+	else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED)
+		return MU_MOD;
+	else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED)
+		return MU_MP3;
+	else
+		return (musictype_t)Mix_GetMusicType(music);
+}
+
 static void count_music_bytes(int chan, void *stream, int len, void *udata)
 {
-	if(midimode || !music)
+	if (gme || midimode || !music || I_MusicType() == MU_MOD)
 		return;
 	music_bytes += len;
 }
@@ -797,17 +813,24 @@ boolean I_StartDigSong(const char *musicname, boolean looping)
 		}
 	}
 
-	if (Mix_PlayMusic(music, 0) == -1)
+	if (I_MusicType() != MU_MOD && Mix_PlayMusic(music, 0) == -1)
 	{
 		CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
 		return true;
 	}
+	else if ((I_MusicType() == MU_MOD) && Mix_PlayMusic(music, -1) == -1) // if MOD, loop forever
+	{
+		CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
+		return true;
+	}
+
 	Mix_VolumeMusic((UINT32)music_volume*128/31);
 
-	Mix_HookMusicFinished(music_loop);
+	if (I_MusicType() != MU_MOD)
+		Mix_HookMusicFinished(music_loop); // don't bother counting if MOD
 
 	music_bytes = 0;
-	if(!Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL))
+	if(I_MusicType() != MU_MOD && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL))
 		CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError());
 
 	return true;
@@ -893,15 +916,17 @@ UINT32 I_GetMusicLength(void)
 		gme_free_info(info);
 		return max(length, 0);
 	}
-	else if (midimode || !music)
+	else if (midimode || !music || I_MusicType() == MU_MOD)
 		return 0;
-
-	// VERY IMPORTANT to set your LENGTHMS= in your song files, folks!
-	// SDL mixer can't read music length itself.
-	length = (UINT32)(music_length*1000);
-	if (!length)
-		CONS_Debug(DBG_BASIC, "Getting music length: music is missing LENGTHMS= in music tag.\n");
-	return length;
+	else
+	{
+		// VERY IMPORTANT to set your LENGTHMS= in your song files, folks!
+		// SDL mixer can't read music length itself.
+		length = (UINT32)(music_length*1000);
+		if (!length)
+			CONS_Debug(DBG_BASIC, "Getting music length: music is missing LENGTHMS= in music tag.\n");
+		return length;
+	}
 }
 
 boolean I_SetMusicPosition(UINT32 position)
@@ -929,22 +954,27 @@ boolean I_SetMusicPosition(UINT32 position)
 	}
 	else if (midimode || !music)
 		return false;
-
-	// Because SDL mixer can't identify song length, if you have
-	// a position input greater than the real length, then
-	// music_bytes becomes inaccurate.
-	length = I_GetMusicLength(); // get it in MS
-	if (length)
-		position %= length;
-
-	Mix_RewindMusic(); // needed for mp3
-	if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0)
-		music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition)
+	else if (I_MusicType() == MU_MOD)
+		// Goes by channels
+		return Mix_SetMusicPosition(position);
 	else
-		// NOTE: This block fires on incorrect song format,
-		// NOT if position input is greater than song length.
-		music_bytes = 0;
-	return true;
+	{
+		// Because SDL mixer can't identify song length, if you have
+		// a position input greater than the real length, then
+		// music_bytes becomes inaccurate.
+		length = I_GetMusicLength(); // get it in MS
+		if (length)
+			position %= length;
+
+		Mix_RewindMusic(); // needed for mp3
+		if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0)
+			music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition)
+		else
+			// NOTE: This block fires on incorrect song format,
+			// NOT if position input is greater than song length.
+			music_bytes = 0;
+		return true;
+	}
 }
 
 UINT32 I_GetMusicPosition(void)
@@ -977,11 +1007,11 @@ UINT32 I_GetMusicPosition(void)
 	}
 	else if (midimode || !music)
 		return 0;
-
-	return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz
-	// 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel)
-	// This is hardcoded in I_StartupSound. Other formats for factor:
-	// 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4
+	else
+		return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz
+		// 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel)
+		// This is hardcoded in I_StartupSound. Other formats for factor:
+		// 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4
 }
 
 boolean I_SetSongTrack(int track)
@@ -1010,7 +1040,10 @@ boolean I_SetSongTrack(int track)
 		SDL_UnlockAudio();
 		return false;
 	}
+	else
 #endif
+	if (I_MusicType() == MU_MOD)
+		Mix_SetMusicPosition(track);
 	(void)track;
 	return false;
 }