diff --git a/game/engines/default/engine/Game.lua b/game/engines/default/engine/Game.lua
index 88545dfb6be89553dae5134e542628b346498f97..55c184212309c80c8e2fe5e04a15812ddbd6237e 100644
--- a/game/engines/default/engine/Game.lua
+++ b/game/engines/default/engine/Game.lua
@@ -201,6 +201,8 @@ function _M:tick()
 			print("[COROUTINE] dead", stop[i])
 		end
 	end
+
+	if self.cleanSounds then self:cleanSounds() end
 end
 
 --- Called when a zone leaves a level
diff --git a/game/engines/default/engine/interface/GameMusic.lua b/game/engines/default/engine/interface/GameMusic.lua
index df4fceda5467f3cecab2db6e4dc6d9b4b9c1d949..52d459a14a5405b0d3b52eefdcaebe7a53b31e23 100644
--- a/game/engines/default/engine/interface/GameMusic.lua
+++ b/game/engines/default/engine/interface/GameMusic.lua
@@ -37,18 +37,21 @@ end
 
 function _M:playMusic(name)
 	if not name then
-		for name, data in pairs(self.playing_musics) do self:playMusic(name, data.loop) end
+		for name, data in pairs(self.playing_musics) do self:playMusic(name) end
 		return
 	end
 	if self.loaded_musics[name] then return end
-	self.loaded_musics[name] = core.sound.load("/data/music/"..name)
+	local ok
+	ok, self.loaded_musics[name] = pcall(core.sound.load, "/data/music/"..name, false)
 	local m = self.loaded_musics[name]
-	if not m then return end
+	print("[MUSIC] loading", name, m)
+	if not ok or not m then self.loaded_musics[name] = nil return end
 
-	print("[MUSIC] playing", name, m, " :: current ? ", self.playing_music)
+	print("[MUSIC] playing", name, m)
+	m = m:use() -- Get the source
 	m:loop(true)
 	m:play()
-	self.playing_musics[name] = {loop=true}
+	self.playing_musics[name] = {source=m}
 end
 
 function _M:stopMusic(name)
@@ -58,7 +61,7 @@ function _M:stopMusic(name)
 	end
 
 	if not self.loaded_musics[name] then return end
-	self.loaded_musics[name]:stop()
+	if self.playing_musics[name].source then self.playing_musics[name].source:stop() end
 	self.loaded_musics[name] = nil
 	self.playing_musics[name] = nil
 	print("[MUSIC] stoping", name)
@@ -77,7 +80,3 @@ do return end
 	end
 	return core.sound.musicVolume(vol) or 0
 end
-
---- Called by the C core when the current music stops
-function _M:onMusicStop()
-end
diff --git a/game/engines/default/engine/interface/GameSound.lua b/game/engines/default/engine/interface/GameSound.lua
index 150b91591606b3fc1acb275a460118e6b23e9e81..871f5fb2d4e4a1a498d95cb0d49141d24d235b77 100644
--- a/game/engines/default/engine/interface/GameSound.lua
+++ b/game/engines/default/engine/interface/GameSound.lua
@@ -24,12 +24,14 @@ module(..., package.seeall, class.make)
 
 --- Initializes
 function _M:init()
+	self.playing_sounds = {}
 	self.loaded_sounds = {}
 --	setmetatable(self.loaded_sounds, {__mode="v"})
 end
 
 function _M:loaded()
 	self.loaded_sounds = self.loaded_sounds or {}
+	self.playing_sounds = {}
 --	setmetatable(self.loaded_sounds, {__mode="v"})
 end
 
@@ -42,13 +44,12 @@ function _M:playSound(name)
 			setfenv(f, setmetatable({}, {__index=_G}))
 			def = f()
 			print("[SOUND] loading from", "/data/sound/"..name..".lua", ":=:", "/data/sound/"..def.file, ":>")
-			ok, def.sample = pcall(core.sound.load, "/data/sound/"..def.file)
+			ok, def.sample = pcall(core.sound.load, "/data/sound/"..def.file, false)
 			if not ok then return end
 			print("[SOUND] :=>", def.sample)
-			if def.volume and def.sample then def.sample:volume(def.volume / 100) end
 		elseif fs.exists("/data/sound/"..name..".ogg") then
 			def = {}
-			ok, def.sample = pcall(core.sound.load, "/data/sound/"..name..".ogg")
+			ok, def.sample = pcall(core.sound.load, "/data/sound/"..name..".ogg", false)
 			if not ok then return end
 			print("[SOUND] loading from", "/data/sound/"..name..".ogg", ":=:", def.sample)
 		else
@@ -59,6 +60,19 @@ function _M:playSound(name)
 		s = self.loaded_sounds[name]
 	end
 	if not s or not s.sample then return end
-	s.sample:play(s.loop)
-	return s
+	local source = s.sample:use()
+	if s.volume then source:volume(s.volume / 100) end
+	source:play()
+	self.playing_sounds[source] = true
+	return source
+end
+
+--- Called on ticks to free up non playing sources
+function _M:cleanSounds()
+	if not self.playing_sounds then return end
+	local todel = {}
+	for s, _ in pairs(self.playing_sounds) do
+		if not s:playing() then todel[#todel+1] = s end
+	end
+	for i = 1, #todel do self.playing_sounds[todel[i]] = nil end
 end
diff --git a/game/modules/tome/data/zones/trollmire/zone.lua b/game/modules/tome/data/zones/trollmire/zone.lua
index 19f87942e5adef26581f56477fa68bdf1d29b347..1306796a7c480081bfcfebdda200bec3848074b3 100644
--- a/game/modules/tome/data/zones/trollmire/zone.lua
+++ b/game/modules/tome/data/zones/trollmire/zone.lua
@@ -86,6 +86,7 @@ return {
 		},
 		-- Hidden treasure level
 		[4] = {
+			ambient_music = {"Rainy Day.ogg", "weather/rain.ogg"},
 			generator = {
 				map = {
 					class = "engine.generator.map.Static",
diff --git a/game/modules/tome/data/zones/wilderness/zone.lua b/game/modules/tome/data/zones/wilderness/zone.lua
index f5cfc02fde81cfdb833968fc5f8f4b32cd7d9f82..b67a8063bbd710d856eeab76b645b51d2dd253b0 100644
--- a/game/modules/tome/data/zones/wilderness/zone.lua
+++ b/game/modules/tome/data/zones/wilderness/zone.lua
@@ -62,7 +62,7 @@ return {
 				if e.immediate then
 					e = e:clone()
 					e:resolve() e:resolve(nil, true)
-					for i,s in ipairs(game.level.spots) do print("=====",i,table.serialize(s,nil,true)) end FIX ME !!! angolwen?!
+					for i,s in ipairs(game.level.spots) do print("=====",i,table.serialize(s,nil,true)) end --FIX ME !!! angolwen?!
 					print("<<<", e.immediate[1], e.immediate[2])
 					local where = game.level:pickSpotRemove{type=e.immediate[1], subtype=e.immediate[2]}
 					while where and (game.level.map:checkAllEntities(where.x, where.y, "block_move") or not game.level.map:checkAllEntities(where.x, where.y, "can_encounter")) do where = game.level:pickSpotRemove{type=e.immediate[1], subtype=e.immediate[2]} end
diff --git a/src/main.c b/src/main.c
index c2f1a552ce92fc511087b72a4a36d5fab9a777b9..183da2b690f9865850db5f59f2c8de1c53539467 100644
--- a/src/main.c
+++ b/src/main.c
@@ -853,6 +853,8 @@ int main(int argc, char *argv[])
 	nb_cpus = get_number_cpus();
 	printf("[CPU] Detected %d CPUs\n", nb_cpus);
 
+	init_openal();
+
 	// RNG init
 	init_gen_rand(time(NULL));
 
@@ -915,7 +917,6 @@ int main(int argc, char *argv[])
 	boot_lua(2, FALSE, argc, argv);
 
 	pass_command_args(argc, argv);
-	init_openal();
 
 	SDL_Event event;
 	while (!exit_engine)
diff --git a/src/music.c b/src/music.c
index 6ed0b9657fcef05e8a0d8c01868570e2fb616588..8903d518acd99bd82ef2f8dfd660efca1c66c4d3 100644
--- a/src/music.c
+++ b/src/music.c
@@ -116,11 +116,11 @@ static int staticLoader(void *sound) {
 	if (data == NULL) return 1;
 	bufferSize = readSoundData((Sound *)sound, data, bufferSize);
 	alBufferData(((Sound *)sound)->buffers[0], (info->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, bufferSize, info->rate);
+//	printf("==statuic buffer : %s\n",  alGetString(alGetError()));
 	free(data);
 	ov_clear(((Sound *)sound)->vorbisFile);
 	free(((Sound *)sound)->vorbisFile);
 	((Sound *)sound)->vorbisFile = NULL;
-	alSourcei(((Sound *)sound)->source, AL_BUFFER, ((Sound *)sound)->buffers[0]);
 	return 0;
 }
 
@@ -140,7 +140,7 @@ static int streamingLoader(void *sound) {
 
 	do {
 		testRest = 1;
-		alGetSourcei(((Sound *)sound)->source, AL_BUFFERS_QUEUED, &i);
+		alGetSourcei(((Sound *)sound)->static_source, AL_BUFFERS_QUEUED, &i);
 //		printf("==1: %d\n", i);
 		if (i == 0) { /*fill and queue initial buffers*/
 			readBytes = readSoundData((Sound *)sound, data, STREAMING_BUFFER_SIZE);
@@ -149,11 +149,11 @@ static int streamingLoader(void *sound) {
 			readBytes = readSoundData((Sound *)sound, data, STREAMING_BUFFER_SIZE);
 			alBufferData(((Sound *)sound)->buffers[1], (info->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, readBytes, info->rate);
 //			printf("==read: %d : %s\n", i, alGetString(alGetError()));
-			alSourceQueueBuffers(((Sound *)sound)->source, 2, ((Sound *)sound)->buffers);
+			alSourceQueueBuffers(((Sound *)sound)->static_source, 2, ((Sound *)sound)->buffers);
 //			printf("==read: %d : %s\n", i, alGetString(alGetError()));
 		}
 		else { /*refill processed buffers*/
-			alGetSourcei(((Sound *)sound)->source, AL_BUFFERS_PROCESSED, &i);
+			alGetSourcei(((Sound *)sound)->static_source, AL_BUFFERS_PROCESSED, &i);
 			while (i-- != 0) {
 				readBytes = readSoundData((Sound *)sound, data, STREAMING_BUFFER_SIZE);
 				if (readBytes == 0) {
@@ -161,9 +161,9 @@ static int streamingLoader(void *sound) {
 					break;
 				}
 				else {
-					alSourceUnqueueBuffers(((Sound *)sound)->source, 1, &buffer);
+					alSourceUnqueueBuffers(((Sound *)sound)->static_source, 1, &buffer);
 					alBufferData(buffer, (info->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, readBytes, info->rate);
-					alSourceQueueBuffers(((Sound *)sound)->source, 1, &buffer);
+					alSourceQueueBuffers(((Sound *)sound)->static_source, 1, &buffer);
 				}
 			}
 		}
@@ -171,7 +171,7 @@ static int streamingLoader(void *sound) {
 		SDL_CondSignal(((Sound *)sound)->cond); /*tell the main thread we're done, in case it's waiting for us*/
 //		printf("==3: %d\n", i);
 		if (testRest) {
-			alGetSourcei(((Sound *)sound)->source, AL_SOURCE_STATE, &i);
+			alGetSourcei(((Sound *)sound)->static_source, AL_SOURCE_STATE, &i);
 			testRest = (i == AL_PLAYING);
 		}
 		if (testRest) {
@@ -189,6 +189,7 @@ static int streamingLoader(void *sound) {
 
 	SDL_UnlockMutex(((Sound *)sound)->mutex);
 	free(data);
+
 	return 0;
 }
 
@@ -198,9 +199,10 @@ static int loadsoundLua(lua_State *L) {
 
 	luaL_checktype(L, 1, LUA_TSTRING);
 	s = lua_tostring(L, 1);
+	bool is_stream = lua_toboolean(L, 2);
 
 	Sound *sound = (Sound*)lua_newuserdata(L, sizeof(Sound));
-	auxiliar_setclass(L, "sound{source}", -1);
+	auxiliar_setclass(L, "sound{buffer}", -1);
 	sound->type = SOUND_STATIC;
 	sound->loop = 0;
 	sound->loaderShouldExit = 0;
@@ -209,7 +211,6 @@ static int loadsoundLua(lua_State *L) {
 	sound->path = malloc(strlen(s) + 1);
 	if (sound->path == NULL) luaL_error(L, "out of memory");
 	strcpy(sound->path, s);
-	alGenSources(1, &sound->source);
 	alGenBuffers(2, sound->buffers);
 	sound->vorbisFile = malloc(sizeof(OggVorbis_File));
 	if (sound->vorbisFile == NULL) luaL_error(L, "out of memory");
@@ -227,7 +228,8 @@ static int loadsoundLua(lua_State *L) {
 
 	if (ov_streams(sound->vorbisFile) > 1) luaL_error(L, "Error loading sound \"%s\": Ogg files containing multiple logical bitstreams are not supported", s);
 
-	if (ov_time_total(sound->vorbisFile, -1) > 10.0) {
+	if (is_stream) {
+		alGenSources(1, &sound->static_source);
 		sound->type = SOUND_STREAMING;
 		sound->mutex = SDL_CreateMutex();
 		if (sound->mutex == NULL) luaL_error(L, "out of memory");
@@ -236,7 +238,8 @@ static int loadsoundLua(lua_State *L) {
 		sound->loaderThread = SDL_CreateThread(streamingLoader, sound);
 	}
 	else {
-		sound->loaderThread = SDL_CreateThread(staticLoader, sound);
+		sound->static_source = 0;
+		staticLoader(sound);
 	}
 
 	return 1;
@@ -249,14 +252,14 @@ const luaL_reg soundlib[] = {
 
 static int soundTostringLua(lua_State *L) {
 	Sound *s;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	s = (Sound*)auxiliar_checkclass(L, "sound{buffer}", 1);
 	lua_pushfstring(L, "sound \"%s\" : %s", s->path, (s->type == SOUND_STREAMING) ? "<stream>" : "<static>");
 	return 1;
 }
 
 static int soundCollectLua(lua_State *L) {
 	Sound *s;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	s = (Sound*)auxiliar_checkclass(L, "sound{buffer}", 1);
 
 	if (s->type == SOUND_STREAMING) {
 		s->loaderShouldExit = 1;
@@ -269,7 +272,6 @@ static int soundCollectLua(lua_State *L) {
 		if (s->loaderThread != NULL) SDL_WaitThread(s->loaderThread, NULL);
 	}
 
-	alDeleteSources(1, &s->source);
 	alDeleteBuffers(2, s->buffers);
 	if (s->path != NULL) free(s->path);
 	if (s->vorbisFile != NULL) {
@@ -279,71 +281,102 @@ static int soundCollectLua(lua_State *L) {
 	return 0;
 }
 
+static int sourceCollectLua(lua_State *L) {
+	SoundSource *s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
+
+	if (!s->is_static_source) alDeleteSources(1, &s->source);
+	luaL_unref(L, LUA_REGISTRYINDEX, s->sound_ref);
+
+	return 0;
+}
+
+static int soundNewSource(lua_State *L) {
+	Sound *s = (Sound*)auxiliar_checkclass(L, "sound{buffer}", 1);
+	int ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+	SoundSource *source = (SoundSource*)lua_newuserdata(L, sizeof(SoundSource));
+	auxiliar_setclass(L, "sound{source}", -1);
+
+	source->sound_ref = ref;
+	source->sound = s;
+	if (s->static_source)
+	{
+		source->source = s->static_source;
+		source->is_static_source = TRUE;
+	}
+	else
+	{
+		alGenSources(1, &source->source);
+//	printf("==source : %s\n",  alGetString(alGetError()));
+		source->is_static_source = FALSE;
+		alSourcei(source->source, AL_BUFFER, s->buffers[0]);
+//	printf("==source buffer assigned : %s\n",  alGetString(alGetError()));
+	}
+
+	return 1;
+}
+
 static int soundPlayLua(lua_State *L) {
-	Sound *s;
+	SoundSource *s;
 	ALint i;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
-	if (s->type == SOUND_STREAMING) {
+	s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
+	if (s->sound->type == SOUND_STREAMING) {
 		alGetSourcei(s->source, AL_SOURCE_STATE, &i);
-				printf("====>>play %d\n",i);
+//				printf("====>>play %d\n",i);
 		switch (i) {
 			case AL_PLAYING:
 				alSourceStop(s->source);
 			case AL_STOPPED:
-				ov_raw_seek(s->vorbisFile, 0);
+				ov_raw_seek(s->sound->vorbisFile, 0);
 				alSourcei(s->source, AL_BUFFER, AL_NONE); /*unqueue all buffers*/
 			case AL_INITIAL:
 			case AL_PAUSED:
-				SDL_LockMutex(s->mutex);
-				SDL_CondSignal(s->cond); /*wake up loader*/
-				SDL_CondWait(s->cond, s->mutex); /*wait until loader has queued initial buffers (if necessary), it will have gone to sleep when this returns because the source isn't playing yet*/
+				SDL_LockMutex(s->sound->mutex);
+				SDL_CondSignal(s->sound->cond); /*wake up loader*/
+				SDL_CondWait(s->sound->cond, s->sound->mutex); /*wait until loader has queued initial buffers (if necessary), it will have gone to sleep when this returns because the source isn't playing yet*/
 				alSourcePlay(s->source);
-				SDL_CondSignal(s->cond); /*wake up loader again (it will stay awake this time since the source is playing now)*/
-				SDL_UnlockMutex(s->mutex);
+				SDL_CondSignal(s->sound->cond); /*wake up loader again (it will stay awake this time since the source is playing now)*/
+				SDL_UnlockMutex(s->sound->mutex);
 				break;
 		}
 	}
 	else {
-		if (s->loaderThread != NULL) {
-			SDL_WaitThread(s->loaderThread, NULL);
-			s->loaderThread = NULL;
-		}
 		alSourcePlay(s->source);
 	}
 	return 0;
 }
 
 static int soundPauseLua(lua_State *L) {
-	Sound *s;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	SoundSource *s;
+	s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
 	alSourcePause(s->source);
 	return 0;
 }
 
 static int soundStopLua(lua_State *L) {
-	Sound *s;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	SoundSource *s;
+	s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
 	alSourceStop(s->source);
 	return 0;
 }
 
 static int soundLoopLua(lua_State *L) {
-	Sound *s;
+	SoundSource *s;
 	ALint old;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
 	alGetSourcei(s->source, AL_LOOPING, &old);
 	if (!lua_isnone(L, 2)) {
-		if (s->type == SOUND_STATIC) alSourcei(s->source, AL_LOOPING, lua_toboolean(L, 2));
-		else s->loop = lua_toboolean(L, 2);
+		if (s->sound->type == SOUND_STATIC) alSourcei(s->source, AL_LOOPING, lua_toboolean(L, 2));
+		else s->sound->loop = lua_toboolean(L, 2);
 	}
 	lua_pushboolean(L, old);
 	return 1;
 }
 
 static int soundVolumeLua(lua_State *L) {
-	Sound *s;
+	SoundSource *s;
 	ALfloat old, new;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
 	new = (ALfloat)luaL_optnumber(L, 2, -2893.0);
 	alGetSourcef(s->source, AL_GAIN, &old);
 	if (new != -2893.0) {
@@ -354,9 +387,9 @@ static int soundVolumeLua(lua_State *L) {
 }
 
 static int soundPitchLua(lua_State *L) {
-	Sound *s;
+	SoundSource *s;
 	ALfloat old, new;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
 	new = (ALfloat)luaL_optnumber(L, 2, -2893.0);
 	alGetSourcef(s->source, AL_PITCH, &old);
 	if (new != -2893.0) {
@@ -367,12 +400,12 @@ static int soundPitchLua(lua_State *L) {
 }
 
 static int soundLocationLua(lua_State *L) {
-	Sound *s;
+	SoundSource *s;
 	ALfloat x, y, z;
 	float oldaz, oldel, newaz = 0, newel = 0;
 	int choice;
 
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
 	if (lua_isnoneornil(L, 2)) {
 		choice = 0;
 	}
@@ -408,9 +441,9 @@ static int soundLocationLua(lua_State *L) {
 }
 
 static int soundPlayingLua(lua_State *L) {
-	Sound *s;
+	SoundSource *s;
 	ALint i;
-	s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1);
+	s = (SoundSource*)auxiliar_checkclass(L, "sound{source}", 1);
 	alGetSourcei(s->source, AL_SOURCE_STATE, &i);
 	lua_pushboolean(L, (i == AL_PLAYING));
 	return 1;
@@ -419,6 +452,12 @@ static int soundPlayingLua(lua_State *L) {
 const luaL_reg soundFuncs[] = {
 	{"__tostring", soundTostringLua},
 	{"__gc", soundCollectLua},
+	{"use", soundNewSource},
+	{NULL, NULL}
+};
+
+const luaL_reg sourceFuncs[] = {
+	{"__gc", sourceCollectLua},
 	{"play", soundPlayLua},
 	{"pause", soundPauseLua},
 	{"stop", soundStopLua},
@@ -432,7 +471,8 @@ const luaL_reg soundFuncs[] = {
 
 int luaopen_sound(lua_State *L)
 {
-	auxiliar_newclass(L, "sound{source}", soundFuncs);
+	auxiliar_newclass(L, "sound{buffer}", soundFuncs);
+	auxiliar_newclass(L, "sound{source}", sourceFuncs);
 	luaL_openlib(L, "core.sound", soundlib, 0);
 	lua_pop(L, 1);
 	return 1;
diff --git a/src/music.h b/src/music.h
index cb8710408ed03920e6167286850b94deded7b7b9..2c33b487623e518e390826e24c51955d39e61484 100644
--- a/src/music.h
+++ b/src/music.h
@@ -39,12 +39,13 @@
 #include "SDL_thread.h"
 #include "lua.h"
 #include "lauxlib.h"
+#include "types.h"
 
 
 typedef struct Sound {
 	enum { SOUND_STATIC, SOUND_STREAMING } type;
 	char *path;
-	ALuint source;
+	ALuint static_source;
 	ALuint buffers[2];
 	unsigned loop:1, loaderShouldExit:1;
 	SDL_Thread *loaderThread;
@@ -53,6 +54,13 @@ typedef struct Sound {
 	OggVorbis_File *vorbisFile;
 } Sound;
 
+typedef struct SoundSource {
+	int sound_ref;
+	Sound *sound;
+	ALuint source;
+	bool is_static_source;
+} SoundSource;
+
 int init_openal();
 void deinit_openal();