diff --git a/src/include/sound_server.h b/src/include/sound_server.h
index 6407bfb7a..552b8f7b0 100644
--- a/src/include/sound_server.h
+++ b/src/include/sound_server.h
@@ -173,10 +173,6 @@ extern unsigned AllocatedSoundMemory;
 extern unsigned CompressedSoundMemory;
 #endif
 
-#ifdef USE_SDLCD 
-    /// SDL cdrom device
-extern SDL_CD *CDRom;
-#endif 
 #if defined(USE_SDLCD) || defined(USE_LIBCDA) 
     /// cd play mode, ":off" ":random" or ":all"
 extern char *CDMode;
@@ -192,6 +188,11 @@ extern int NumCDTracks;
 --	Functions
 ----------------------------------------------------------------------------*/
 
+extern Sample* LoadFlac(const char* name);	/// Load a flac file
+extern Sample* LoadWav(const char* name);	/// Load a wav file
+extern Sample* LoadOgg(const char* name);	/// Load a ogg file
+extern Sample* LoadMp3(const char* name);	/// Load a mp3 file
+
     ///	Register a sound (can be a simple sound or a group)
 extern SoundId RegisterSound(char* file[],unsigned number);
 
diff --git a/src/sound/Makefile b/src/sound/Makefile
index 105ad13c2..ba9439d04 100644
--- a/src/sound/Makefile
+++ b/src/sound/Makefile
@@ -33,7 +33,7 @@ MODULE	= sound
 
 HDRS	= libcda.h
 
-SRCS	= sound.c sound_server.c ccl_sound.c sound_id.c \
+SRCS	= sound.c sound_server.c ccl_sound.c sound_id.c music.c \
 	  mad.c ogg.c flac.c wav.c unitsound.c libcda.c oss_audio.c sdl_audio.c
 
 OBJS	= $(addprefix $(OBJDIR), $(SRCS:.c=.$(OE)))
diff --git a/src/sound/mad.cpp b/src/sound/mad.cpp
index 50b22f6d2..04614fa3d 100644
--- a/src/sound/mad.cpp
+++ b/src/sound/mad.cpp
@@ -35,6 +35,7 @@
 #if defined(WITH_SOUND) && defined(USE_MAD)	// {
 
 #include <stdlib.h>
+#include <memory.h>
 #include "mad.h"
 
 #include "iolib.h"
@@ -50,7 +51,7 @@
 typedef struct _my_user_ {
     CLFile* File;			// File handle
     Sample* Sample;			// Sample buffer
-    char Buffer[4096];			// Decoded buffer
+    unsigned char Buffer[4096];		// Decoded buffer
 } MyUser;
 
 /*----------------------------------------------------------------------------
@@ -68,6 +69,7 @@ typedef struct _my_user_ {
 local enum mad_flow MAD_read(void *user, struct mad_stream *stream)
 {
     int i;
+    int l;
     CLFile *f;
     MyUser *u;
 
@@ -76,13 +78,21 @@ local enum mad_flow MAD_read(void *user, struct mad_stream *stream)
     u = (MyUser *) user;
     f = u->File;
 
-    if ((i = CLread(f, u->Buffer, sizeof(u->Buffer))) != sizeof(u->Buffer)) {
-	if (!i) {
-	    return MAD_FLOW_STOP;
-	}
+    l = 0;
+    // Copy remaining bytes over
+    if (stream->next_frame) {
+	memmove(u->Buffer, stream->next_frame,
+	    l = &u->Buffer[sizeof(u->Buffer)] - stream->next_frame);
     }
-    DebugLevel3Fn("%d bytes\n", i);
-    mad_stream_buffer(stream, u->Buffer, i);
+
+    i = CLread(f, u->Buffer + l, sizeof(u->Buffer) - l);
+    //if (!(l + i)) {
+    if (!i) {
+	return MAD_FLOW_STOP;
+    }
+    DebugLevel3Fn("%d bytes\n", l + i);
+    mad_stream_buffer(stream, u->Buffer, l + i);
+
     return MAD_FLOW_CONTINUE;
 }
 
diff --git a/src/sound/music.cpp b/src/sound/music.cpp
new file mode 100644
index 000000000..29da59afc
--- /dev/null
+++ b/src/sound/music.cpp
@@ -0,0 +1,355 @@
+//   ___________		     _________		      _____  __
+//   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
+//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+//    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
+//    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
+//	  \/		    \/	   \/	     \/		   \/
+//  ______________________                           ______________________
+//			  T H E   W A R   B E G I N S
+//	   FreeCraft - A free fantasy real time strategy game engine
+//
+/**@name music.c		-	Background music support */
+//
+//	(c) Copyright 2002 by Lutz Sammer
+//
+//	FreeCraft is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published
+//	by the Free Software Foundation; only version 2 of the License.
+//
+//	FreeCraft is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//	GNU General Public License for more details.
+//
+//	$Id$
+
+//@{
+
+/*----------------------------------------------------------------------------
+--	Includes
+----------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include "freecraft.h"
+
+#if defined(WITH_SOUND)	// {
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef USE_LIBMODPLUG
+#include "../libmodplug/modplug.h"
+#endif
+
+#ifdef USE_LIBCDA
+#include "libcda.h"
+#endif
+
+#ifdef USE_SDLCD
+#include <SDL.h>
+#endif
+
+#include "iolib.h"
+#include "sound.h"
+#include "sound_server.h"
+
+/*----------------------------------------------------------------------------
+--	Declaration
+----------------------------------------------------------------------------*/
+
+#define SoundFrequency	44100		// sample rate of dsp
+
+/*----------------------------------------------------------------------------
+--	Variables
+----------------------------------------------------------------------------*/
+
+#ifdef USE_LIBMODPLUG
+global ModPlugFile* ModFile;		/// Mod file loaded into memory
+#endif
+#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD)
+global Sample* MusicSample;		/// Music samples
+global int MusicIndex;			/// Music sample index
+#endif
+#if defined(USE_SDLCD) || defined(USE_LIBCDA)
+global char *CDMode = ":off";	/// cd play mode, ":off" ":random" or ":all"
+global int CDTrack;			/// Current cd track
+#endif
+#ifdef USE_SDLCD
+global SDL_CD *CDRom;			/// SDL cdrom device
+#endif
+#ifdef USE_LIBCDA
+global int NumCDTracks;			/// Number of tracks on the cd
+#endif
+
+/*----------------------------------------------------------------------------
+--	Functions
+----------------------------------------------------------------------------*/
+
+/**
+**	Stop the current playing music.
+**
+**	@todo 	FIXME: Stop the CD-PLAYER.
+*/
+global void StopMusic(void)
+{
+    if (PlayingMusic) {
+	PlayingMusic = 0;		// Callback!
+#ifdef USE_LIBMODPLUG
+	if (ModFile) {
+	    ModPlug_Unload(ModFile);
+	    ModFile = NULL;
+	    return;
+	}
+#endif
+#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD)
+	if (MusicSample) {
+	    free(MusicSample);
+	    MusicSample = NULL;
+	    MusicIndex = 0;
+	    return;
+	}
+#endif
+    }
+}
+
+#ifdef USE_LIBMODPLUG
+/**
+**	Load a mod file.
+*/
+local int LoadMod(const char* name)
+{
+    ModPlug_Settings settings;
+    CLFile* f;
+    char* buffer;
+    int size;
+    int i;
+    
+    ModPlug_GetSettings(&settings);
+    settings.mFrequency=SoundFrequency;
+#ifdef USE_LIBMODPLUG32
+    settings.mBits=32;
+#else
+    settings.mBits=16;
+#endif
+    settings.mLoopCount=0;		// Disable looping
+    ModPlug_SetSettings(&settings);
+
+    buffer=malloc(8192);
+    DebugLevel2Fn("Loading `%s'\n",name);
+
+    if( !(f=CLopen(name)) ) {
+	printf("Can't open file `%s'\n",name);
+	return 0;
+    }
+
+    size=0;
+    while( (i=CLread(f,buffer+size,8192))==8192 ) {
+	size+=8192;
+	buffer=realloc(buffer,size+8192);
+    }
+    size+=i;
+    buffer=realloc(buffer,size);
+    DebugLevel3Fn("%d\n",size);
+
+    StopMusic();			// stop music before new music
+
+    ModFile=ModPlug_Load(buffer,size);
+
+    free(buffer);
+
+    if( ModFile ) {
+	DebugLevel0Fn("Started\n");
+	PlayingMusic=1;
+	return 1;
+    }
+
+    return 0;
+}
+#endif
+
+#ifdef USE_SDLCD
+/**
+**	Play music from cdrom.
+**
+**	:all :random :off
+**
+**	@param name	Name starting with ":".
+*/
+local int PlayCDRom(const char* name)
+{
+    // Old mode off, starting cdrom play.
+    if (!strcmp(CDMode, ":off")) {
+	if (!strncmp(name, ":", 1)) {
+	    StopMusic();		// stop music before new music
+	    SDL_Init(SDL_INIT_CDROM);
+	    CDRom = SDL_CDOpen(0);
+	    SDL_CDStatus(CDRom);
+	}
+    }
+    // CDPlayer command?
+    if (!strncmp(name, ":", 1)) {
+	if (!CDRom) {
+	    fprintf(stderr, "Couldn't open cdrom drive: %s\n", SDL_GetError());
+	    return 1;
+	}
+	// if mode is play all tracks
+	if (!strcmp(name, ":all")) {
+	    CDMode = ":all";
+	    SDL_CDPlayTracks(CDRom, 0, 0, 0, 0);
+	    return 1;
+	}
+	// if mode is play random tracks
+	if (!strcmp(name, ":random")) {
+	    CDMode = ":random";
+	    CDTrack = MyRand() % CDRom->numtracks;
+	    SDL_CDPlayTracks(CDRom, CDTrack, 0, 0, 0);
+	}
+	CDMode = ":off";
+	return 1;
+    }
+
+    // FIXME: no cdrom, must stop it now!
+
+    return 0;
+}
+#endif
+
+#ifdef USE_LIBCDA
+/**
+**	Play music from cdrom.
+**
+**	:all :random :off
+**
+**	@param name	Name starting with ":".
+*/
+local int PlayCDRom(const char* name)
+{
+    if (!strcmp(CDMode, ":off")) {
+	if (!strncmp(name, ":", 1)) {
+	    if (cd_init() < 0) {
+		fprintf(stderr, "Error initialising libcda \n");
+		return 1;
+	    }
+	    cd_get_tracks(&CDTrack, &NumCDTracks);
+	    if (NumCDTracks == 0) {
+		return 1;
+	    }
+	    --CDTrack;
+	}
+    }
+
+    if (!strncmp(name, ":", 1)) {
+
+	// if mode is play all tracks
+	if (!strcmp(name, ":all")) {
+	    CDMode = ":all";
+	    do {
+		if (CDTrack > NumCDTracks)
+		    CDTrack = 1;
+	    } while (cd_is_audio(++CDTrack) < 1);
+	    cd_play(CDTrack);
+	    return 1;
+	}
+	// if mode is play random tracks
+	if (!strcmp(name, ":random")) {
+	    CDMode = ":random";
+	    do {
+		CDTrack = MyRand() % NumCDTracks;
+	    } while (cd_is_audio(CDTrack) < 1);
+	    cd_play(CDTrack);
+	    return 1;
+	}
+	CDMode = ":off";
+	return 1;
+    }
+
+    // FIXME: no cdrom, must stop it now!
+
+    return 0;
+}
+#endif
+
+/**
+**	Play a music file.
+**	Currently supported are .mod, .it, .s3m, .wav, .xm.
+**	Optional .ogg, mp3 and cdrom.
+**
+**	Some quick hacks for mods.
+**
+**	@param name	Name of sound file, format is automatic detected.
+**			Names starting with ':' control the cdrom.
+*/
+global void PlayMusic(const char* name)
+{
+    char buffer[1024];
+    Sample *sample;
+
+#ifdef USE_SDLCD
+    if (PlayCDRom(name)) {
+	return;
+    }
+#endif
+#ifdef USE_LIBCDA
+    if (PlayCDRom(name)) {
+	return;
+    }
+#endif
+    name = LibraryFileName(name, buffer);
+#ifdef USE_OGG
+    if ((sample = LoadOgg(name))) {
+	if( sample->Channels!=2
+		|| sample->SampleSize!=16
+		|| sample->Frequency!=SoundFrequency ) {
+	    DebugLevel0Fn("Not supported music format\n");
+	    free(sample);
+	    return;
+	}
+	StopMusic();
+	MusicSample = sample;
+	MusicIndex = 0;
+	PlayingMusic = 1;
+	return;
+    }
+#endif
+#ifdef USE_MAD
+    if ((sample = LoadMp3(name))) {
+	if( sample->Channels!=2
+		|| sample->SampleSize!=16
+		|| sample->Frequency!=SoundFrequency ) {
+	    DebugLevel0Fn("Not supported music format\n");
+	    free(sample);
+	    return;
+	}
+	StopMusic();
+	MusicSample = sample;
+	MusicIndex = 0;
+	PlayingMusic = 1;
+	return;
+    }
+#endif
+#ifdef USE_FLAC
+    if ((sample = LoadFlac(name))) {
+	if( sample->Channels!=2
+		|| sample->SampleSize!=16
+		|| sample->Frequency!=SoundFrequency ) {
+	    DebugLevel0Fn("Not supported music format\n");
+	    free(sample);
+	    return;
+	}
+	StopMusic();
+	MusicSample = sample;
+	MusicIndex = 0;
+	PlayingMusic = 1;
+	return;
+    }
+#endif
+#ifdef USE_LIBMODPLUG
+    if (LoadMod(name)) {
+	return;
+    }
+#endif
+}
+
+#endif	// } WITH_SOUND
+
+//@}
diff --git a/src/sound/sound_server.cpp b/src/sound/sound_server.cpp
index 570896d18..3d849545e 100644
--- a/src/sound/sound_server.cpp
+++ b/src/sound/sound_server.cpp
@@ -93,11 +93,6 @@
 #include <SDL.h>
 #endif
 
-extern Sample* LoadFlac(const char* name);	/// Load a flac file
-extern Sample* LoadWav(const char* name);	/// Load a wav file
-extern Sample* LoadOgg(const char* name);	/// Load a ogg file
-extern Sample* LoadMp3(const char* name);	/// Load a mp3 file
-
 /*----------------------------------------------------------------------------
 --	Defines
 ----------------------------------------------------------------------------*/
@@ -141,165 +136,21 @@ global int WithSoundThread;		/// FIXME: docu
 global int SoundThreadRunning;		/// FIXME: docu
 
 #ifdef USE_SDLCD
-global SDL_CD *CDRom;
-#endif
-#if defined(USE_SDLCD) || defined(USE_LIBCDA)
-global char *CDMode = ":off";
-global int CDTrack;
-#endif
-#ifdef USE_LIBCDA
-global int NumCDTracks;
+global SDL_CD *CDRom;			/// SDL cdrom device
 #endif
 
 /*----------------------------------------------------------------------------
 --	Functions
 ----------------------------------------------------------------------------*/
 
-#ifdef USE_LIBMODPLUG
-local ModPlugFile* ModFile;		/// Mod file loaded into memory
-
-/**
-**	Play a music file. Currently supported are .mod, .it, .s3m, .wav, .xm.
-**
-**	Some quick hacks for mods.
-**
-**	@param name	Name of sound file, format is automatic detected.
-*/
-global void PlayMusic(const char* name)
-{
-    ModPlug_Settings settings;
-    CLFile* f;
-    char* buffer;
-    int size;
-    int i;
-    
-    ModPlug_GetSettings(&settings);
-    settings.mFrequency=SoundFrequency;
-#ifdef USE_LIBMODPLUG32
-    settings.mBits=32;
-#else
-    settings.mBits=16;
+#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD)
+extern Sample* MusicSample;		/// Music samples
+extern int MusicIndex;			/// Music sample index
 #endif
 
-    settings.mLoopCount=0;		// Disable looping
-    ModPlug_SetSettings(&settings);
-    
-#ifdef USE_SDLCD
-    if (!strcmp(CDMode,":off")) {
-	if (!strncmp(name,":",1)) {
-	    SDL_Init(SDL_INIT_CDROM);
-	    CDRom = SDL_CDOpen(0);
-	    SDL_CDStatus(CDRom);
-	}
-    }
-    
-    if (!strncmp(name,":",1)) {
-	if (!CDRom) {
-	    fprintf(stderr, "Couldn't open cdrom drive: %s\n", SDL_GetError());
-	    return;
-	}
+#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD) || defined(USE_LIBMODPLUG)
 
-	// if mode is play all tracks
-	if (!strcmp(name, ":all")) {
-	    CDMode = ":all";
-	    SDL_CDPlayTracks(CDRom, 0, 0, 0, 0);
-	    return;
-	}
-	
-	// if mode is play random tracks
-	if (!strcmp(name, ":random")) {
-	    CDMode = ":random";
-	    CDTrack = MyRand() % CDRom->numtracks;
-	    SDL_CDPlayTracks(CDRom, CDTrack, 0, 0, 0);
-	    return;
-	}
-	return;
-    }
-#endif
-
-#ifdef USE_LIBCDA
-    if (!strcmp(CDMode,":off")) {
-	if (!strncmp(name,":",1)) {
-	    if (cd_init() < 0) {
-		fprintf(stderr,"Error initialising libcda \n");
-		return;
-	    }
-	    cd_get_tracks(&CDTrack, &NumCDTracks);
-	    if (NumCDTracks == 0)
-		return;
-	    --CDTrack;
-	}
-    }
-
-    if (!strncmp(name,":",1)) {
-
-        // if mode is play all tracks
-	if (!strcmp(name, ":all")) {
-	    CDMode = ":all";
-	    do {
-		if (CDTrack > NumCDTracks)
-		    CDTrack = 1;
-	    } while (cd_is_audio(++CDTrack) < 1);
-	    cd_play(CDTrack);
-	    return;
-	}
-	
-	// if mode is play random tracks
-	if (!strcmp(name, ":random")) {
-	    CDMode = ":random";
-	    do {
-		CDTrack = MyRand() % NumCDTracks;
-	    } while (cd_is_audio(CDTrack) < 1);
-	    cd_play(CDTrack);
-	    return;
-	}
-    }
-#endif
-
-    buffer=malloc(8192);
-    name=LibraryFileName(name,buffer);
-
-    DebugLevel2Fn("Loading `%s'\n",name);
-
-    if( !(f=CLopen(name)) ) {
-	printf("Can't open file `%s'\n",name);
-	return;
-    }
-
-    size=0;
-    while( (i=CLread(f,buffer+size,8192))==8192 ) {
-	size+=8192;
-	buffer=realloc(buffer,size+8192);
-    }
-    size+=i;
-    buffer=realloc(buffer,size);
-    DebugLevel0Fn("%d\n",size);
-
-    StopMusic();			// stop music before new music
-
-    ModFile=ModPlug_Load(buffer,size);
-
-    free(buffer);
-
-    if( ModFile ) {
-	DebugLevel0Fn("Started\n");
-	PlayingMusic=1;
-    }
-}
-
-/**
-**	Stop the current playing music.
-*/
-global void StopMusic(void)
-{
-    if( PlayingMusic ) {
-	PlayingMusic=0;			// Callback!
-	if( ModFile ) {
-	    ModPlug_Unload(ModFile);
-	    ModFile=NULL;
-	}
-    }
-}
+extern ModPlugFile* ModFile;		/// Mod file loaded into memory
 
 /**
 **	Mix music to stereo 32 bit.
@@ -307,49 +158,72 @@ global void StopMusic(void)
 **	@param buffer	Buffer for mixed samples.
 **	@param size	Number of samples that fits into buffer.
 */
-local void MixMusicToStereo32(int* buffer,int size)
+local void MixMusicToStereo32(int* buffer, int size)
 {
-#ifdef USE_LIBMODPLUG32
-    long* buf;
-#else
-    short* buf;
-#endif
     int i;
     int n;
-    
 
-    if( PlayingMusic ) {
-	DebugCheck( !ModFile );
-
-	buf=alloca(size*sizeof(*buf));
-
-	n=ModPlug_Read(ModFile,buf,size*sizeof(*buf));
-
-	for( i=0; i<n/sizeof(*buf); ++i ) {	// Add to our samples
+    if (PlayingMusic) {
+	n = 0;
+#ifdef USE_LIBMODPLUG
+	if (ModFile) {
 #ifdef USE_LIBMODPLUG32
-	    buffer[i]+=((buf[i]>>16)*MusicVolume)/256;
+	    long *buf;
 #else
-	    buffer[i]+=(buf[i]*MusicVolume)/256;
+	    short *buf;
 #endif
-	}
+	    buf = alloca(size * sizeof(*buf));
 
-	if( n!=size*sizeof(*buf) ) {		// End reached
-	    SCM cb;
+	    n = ModPlug_Read(ModFile, buf, size * sizeof(*buf));
 
-	    DebugLevel2Fn("End of music %d\n",i);
-	    PlayingMusic=0;
-	    if( ModFile ) {
-		ModPlug_Unload(ModFile);
+	    for (i = 0; i < n / sizeof(*buf); ++i) {	// Add to our samples
+#ifdef USE_LIBMODPLUG32
+		buffer[i] += ((buf[i] >> 16) * MusicVolume) / 256;
+#else
+		buffer[i] += (buf[i] * MusicVolume) / 256;
+#endif
 	    }
 
-	    if( CallbackMusic ) {
-		cb=gh_symbol2scm("music-stopped");
-		if( !gh_null_p(symbol_boundp(cb,NIL)) ) {
+	    n = n != size * sizeof(*buf);	// End reached?
+	}
+#endif
+#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD)
+	if (MusicSample) {
+	    short *buf;
+
+	    buf = (short *)(MusicSample->Data + MusicIndex);
+	    if (size * 2 > MusicSample->Length - MusicIndex) {
+		n = MusicSample->Length - MusicIndex;
+	    } else {
+		n = size * 2;
+	    }
+	    n >>= 1;
+	    for (i = 0; i < n; ++i) {	// Add to our samples
+		buffer[i] += (buf[i] * MusicVolume) / 256;
+	    }
+	    MusicIndex += i * 2;
+
+	    n = MusicIndex == MusicSample->Length;
+	}
+#endif
+
+	if (n) {			// End reached
+	    SCM cb;
+
+	    DebugLevel3Fn("End of music %d\n", i);
+	    PlayingMusic = 0;
+	    if (ModFile) {
+		ModPlug_Unload(ModFile);
+	    }
+	    // FIXME: we are inside the SDL callback!
+	    if (CallbackMusic) {
+		cb = gh_symbol2scm("music-stopped");
+		if (!gh_null_p(symbol_boundp(cb, NIL))) {
 		    SCM value;
 
-		    value=symbol_value(cb,NIL);
-		    if( !gh_null_p(value) ) {
-			gh_apply(value,NIL);
+		    value = symbol_value(cb, NIL);
+		    if (!gh_null_p(value)) {
+			gh_apply(value, NIL);
 		    }
 		}
 	    }
@@ -371,6 +245,11 @@ global void StopMusic(void)
 
 #endif
 
+/**
+**	Check cdrom.
+**
+**	Perodic called from the main loop.
+*/
 global void CDRomCheck(void)
 {
 #ifdef USE_SDLCD
@@ -394,8 +273,9 @@ global void CDRomCheck(void)
     } else {
 	DebugLevel0Fn("get track\n");
         CDTrack = cd_current_track() + 1;
-	if (CDTrack > NumCDTracks)
+	if (CDTrack > NumCDTracks) {
 	    CDTrack = 1;
+	}
     }
 #endif
 }