diff --git a/dat/outfit.xml b/dat/outfit.xml
index 29d0901..3dc6234 100644
--- a/dat/outfit.xml
+++ b/dat/outfit.xml
@@ -8,6 +8,7 @@
 		</general>
     <specific type="1">
       <gfx>lasergreen</gfx>
+			<sound>laser</sound>
       <delay>500</delay>
       <speed>550</speed>
       <range>300</range>
diff --git a/src/main.c b/src/main.c
index 3cc5ea3..8fcd20f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -111,7 +111,7 @@ int main(int argc, char** argv) {
 	// OpenAL sound.
 	if(sound_init()) WARN("Problem setting up sound!");
 	music_load("Machina");
-	music_play();
+	//music_play();
 
   // Input.
   if((indjoystick >= 0) || (namjoystick != NULL)) {
@@ -177,6 +177,8 @@ int main(int argc, char** argv) {
       input_handle(&event); // handles all the events the player keybinds.
     }
 
+		sound_update(); // Do the sound stuff.
+
     glClear(GL_COLOR_BUFFER_BIT);
     
     fps_control(); // Who doesn't love FPS control?
diff --git a/src/music.c b/src/music.c
index 55ae090..62f97c1 100644
--- a/src/music.c
+++ b/src/music.c
@@ -153,6 +153,8 @@ void music_exit(void) {
 	for(i = 0; i < nmusic_selection; i++)
 		free(music_selection[i]);
 	free(music_selection);
+
+	SDL_DestroyMutex(music_vorbis_lock);
 }
 
 // Internal music loading ruitines.
@@ -220,6 +222,10 @@ static void music_free(void) {
 	SDL_mutexV(music_vorbis_lock);
 }
 
+void music_volume(const double vol) {
+	alSourcef(music_source, AL_GAIN, (ALfloat)vol);
+}
+
 // Music control functions.
 void music_load(const char* name) {
 	int i;
diff --git a/src/music.h b/src/music.h
index 857e93c..96bb65f 100644
--- a/src/music.h
+++ b/src/music.h
@@ -9,6 +9,7 @@ int music_init(void);
 void music_exit(void);
 
 // Music control.
+void music_volume(const double vol);
 void music_load(const char* name);
 void music_play(void);
 void music_stop(void);
diff --git a/src/outfit.c b/src/outfit.c
index a9dce7c..0a8a49d 100644
--- a/src/outfit.c
+++ b/src/outfit.c
@@ -105,6 +105,8 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
       snprintf(str, strlen(xml_get(node))+sizeof(OUTFIT_GFX)+4, OUTFIT_GFX"%s.png", xml_get(node));
       tmp->gfx_space = gl_newSprite(str, 6, 6);
     }
+		else if(xml_isNode(node, "sound"))
+			tmp->sound = sound_get(xml_get(node));
     else if(xml_isNode(node, "damage")) {
       cur = node->children;
       do {
@@ -116,6 +118,7 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
 #define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
   if(tmp->gfx_space == NULL)
     WARN("Outfit '%s' missing 'gfx' element", tmp->name);
+	MELEMENT(tmp->sound,					"sound");
   MELEMENT(tmp->delay,          "delay");
   MELEMENT(tmp->speed,          "speed");
   MELEMENT(tmp->range,          "range");
@@ -159,6 +162,8 @@ static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent) {
             OUTFIT_GFX"%s.png", xml_get(node));
       tmp->gfx_space = gl_newSprite(str, 6, 6);
     }
+		else if(xml_isNode(node, "sound"))
+			tmp->sound = sound_get(xml_get(node));
     else if(xml_isNode(node, "damage")) {
       cur = node->children;
       do {
@@ -170,7 +175,8 @@ static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent) {
 #define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
   if(tmp->gfx_space == NULL)
     WARN("Outfit '%s' missing 'gfx' element", tmp->name);
-  MELEMENT(tmp->thrust,   "     thrust");
+	MELEMENT(tmp->sound,					"sound");
+  MELEMENT(tmp->thrust,   			"thrust");
   MELEMENT(tmp->turn,           "turn");
   MELEMENT(tmp->speed,          "speed");
   MELEMENT(tmp->range,          "duration");
diff --git a/src/outfit.h b/src/outfit.h
index 2eceb69..99921de 100644
--- a/src/outfit.h
+++ b/src/outfit.h
@@ -1,5 +1,6 @@
 #pragma once
 #include "opengl.h"
+#include "sound.h"
 
 #define outfit_isProp(o,p)  ((o)->properties & p)
 // Property flags.
@@ -46,6 +47,7 @@ typedef struct {
       double damage_armour, damage_shield; // Damage.
 
       glTexture* gfx_space;
+			ALuint sound; // Sound to play.
     };
     struct { // Launcher.
       //unsigned int delay; // Delay between shots.
diff --git a/src/pilot.c b/src/pilot.c
index 5ebe951..5d633e2 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -252,8 +252,12 @@ static void pilot_update(Pilot* pilot, const double dt) {
   if(!pilot_isFlag(pilot, PILOT_HYPERSPACE) && VMOD(pilot->solid->vel) > 
         pilot->ship->speed)
     // Should not go faster.
-    vect_pset(&pilot->solid->vel, VMOD(pilot->solid->vel) - 0.3*pilot->ship->thrust*dt,
+    vect_pset(&pilot->solid->vel, pilot->ship->speed,
           VANGLE(pilot->solid->vel));
+
+	// Update the source.
+	//alSource3f(pilot->source, AL_POSITION, pilot->solid->pos.x, pilot->solid->pos.y, 0.);
+	//alSource3f(pilot->source, AL_VELOCITY, pilot->solid->vel.x, pilot->solid->vel.y, 0.);
 }
 
 // Pilot is getting ready or is in, hyperspace.
@@ -356,7 +360,12 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi
     }
   }
 
+	// Sound source.
+	// Eh....
+
+	// Set flags and functions.
   if(flags & PILOT_PLAYER) {
+		//alSourcef(pilot->source, AL_GAIN, 0.);
     pilot->think = player_think; // Players don't need to thing! :P
     pilot->render = NULL; // Render will be called from player_think
     pilot_setFlag(pilot, PILOT_PLAYER); // It's a player!
diff --git a/src/pilot.h b/src/pilot.h
index 53b8bbd..8d1ff23 100644
--- a/src/pilot.h
+++ b/src/pilot.h
@@ -4,6 +4,7 @@
 #include "ai.h"
 #include "outfit.h"
 #include "faction.h"
+#include "sound.h"
 #include "ship.h"
 
 #define PLAYER_ID 1
@@ -66,7 +67,11 @@ typedef struct Pilot {
   PilotOutfit* secondary; // Secondary weapon.
   PilotOutfit* ammo;      // Secondary ammo (if needed).
 
-  unsigned int flags; // Used for AI etc.
+	// Sound source.
+	ALuint source;
+  
+	// Misc.
+	unsigned int flags; // Used for AI etc.
   unsigned int ptimer;  // Generic timer for internal pilot use.
 
   // AI.
diff --git a/src/player.c b/src/player.c
index 30852a1..7977c98 100644
--- a/src/player.c
+++ b/src/player.c
@@ -174,7 +174,7 @@ void player_new(void) {
   d = RNG(0, 359)/180.*M_PI;
 
   pilot_create(ship, "Player", faction_get("Player"), NULL, d, &v, NULL, PILOT_PLAYER);
-  gl_bindCamera(&player->solid->pos);
+  gl_bindCamera(&player->solid->pos); // Set opengl camers.
   space_init(system);
 
   // Welcome message.
@@ -796,6 +796,14 @@ void player_think(Pilot* player) {
     pilot_shoot(player, player_target, 1);
 
   vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
+
+	// Set the listener stuff.
+	ALfloat ori[] = { 0., 0., 0., 0., 0., 1. };
+	ori[0] = cos(player->solid->dir);
+	ori[1] = sin(player->solid->dir);
+	alListenerfv(AL_ORIENTATION, ori);
+	alListener3f(AL_POSITION, player->solid->pos.x, player->solid->pos.y, 0.);
+	alListener3f(AL_VELOCITY, player->solid->vel.x, player->solid->vel.y, 0.);
 }
 
 // Modify the radar resolution.
diff --git a/src/ship.c b/src/ship.c
index ec9a791..ef96c31 100644
--- a/src/ship.c
+++ b/src/ship.c
@@ -38,81 +38,83 @@ static Ship* ship_parse(xmlNodePtr parent) {
   ShipOutfit* otmp, *ocur;
 
   char str[PATH_MAX] = "\0";
-  xmlChar* xstr;
+	char* stmp;
 
-  tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name");
+  tmp->name = xml_nodeProp(parent, "name");
   if(tmp->name == NULL) WARN("Ship in "SHIP_DATA" has invalid or no name");
 
   node = parent->xmlChildrenNode;
 
   do {
     // Load all the data.
-    if(strcmp((char*)node->name, "GFX")==0) {
-      snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX)+sizeof(SHIP_EXT),
-            SHIP_GFX"%s"SHIP_EXT, (char*)node->children->content);
+    if(xml_isNode(node,"GFX")) {
+					snprintf(str, strlen(xml_get(node)) + sizeof(SHIP_GFX) + sizeof(SHIP_EXT),
+            SHIP_GFX"%s"SHIP_EXT, xml_get(node));
       tmp->gfx_space = gl_newSprite(str, 6, 6);
       // Target.
-      snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX)+sizeof(SHIP_TARGET)+sizeof(SHIP_EXT),
-            SHIP_GFX"%s"SHIP_TARGET SHIP_EXT, (char*)node->children->content);
+      snprintf(str, strlen(xml_get(node)) + sizeof(SHIP_GFX)+sizeof(SHIP_TARGET)+sizeof(SHIP_EXT),
+            SHIP_GFX"%s"SHIP_TARGET SHIP_EXT, xml_get(node));
       tmp->gfx_target = gl_newImage(str);
 
     }
-    else if(strcmp((char*)node->name, "GUI")==0)
-      tmp->gui = strdup((char*)node->children->content);
-    else if(strcmp((char*)node->name, "class")==0)
-      tmp->class = atoi((char*)node->children->content);
-    else if(strcmp((char*)node->name, "movement")==0) {
+    else if(xml_isNode(node, "GUI"))
+      tmp->gui = strdup(xml_get(node));
+		else if(xml_isNode(node, "sound"))
+			tmp->sound = sound_get(xml_get(node));
+    else if(xml_isNode(node, "class"))
+      tmp->class = atoi(xml_get(node));
+    else if(xml_isNode(node, "movement")) {
       cur = node->children;
       do {
-        if(strcmp((char*)cur->name, "thrust")==0)
-          tmp->thrust = atoi((char*)cur->children->content);
-        else if(strcmp((char*)cur->name, "turn")==0)
-          tmp->turn = atoi((char*)cur->children->content);
-        else if(strcmp((char*)cur->name, "speed")==0)
-          tmp->speed = atoi((char*)cur->children->content);
+        if(xml_isNode(cur, "thrust"))
+          tmp->thrust = xml_getInt(cur);
+        else if(xml_isNode(cur, "turn"))
+          tmp->turn = xml_getInt(cur);
+        else if(xml_isNode(cur, "speed"))
+          tmp->speed = xml_getInt(cur);
       } while((cur = cur->next));
     }
-    else if(strcmp((char*)node->name, "health")==0) {
+    else if(xml_isNode(node, "health")) {
       cur = node->children;
       do {
-        if(strcmp((char*)cur->name, "armour")==0)
-          tmp->armour = (double)atoi((char*)cur->children->content);
-        else if(strcmp((char*)cur->name, "shield")==0)
-          tmp->shield = (double)atoi((char*)cur->children->content);
-        else if(strcmp((char*)cur->name, "energy")==0)
-          tmp->energy = (double)atoi((char*)cur->children->content);
-        else if(strcmp((char*)cur->name, "armour_regen")==0)
-          tmp->armour_regen = (double)(atoi((char*)cur->children->content))/60.0;
-        else if(strcmp((char*)cur->name, "shield_regen")==0)
-          tmp->shield_regen = (double)(atoi((char*)cur->children->content))/60.0;
-        else if(strcmp((char*)cur->name, "energy_regen")==0)
-          tmp->energy_regen = (double)(atoi((char*)cur->children->content))/60.0;
+        if(xml_isNode(cur, "armour"))
+          tmp->armour = (double)xml_getInt(cur);
+        else if(xml_isNode(cur, "shield"))
+          tmp->shield = (double)xml_getInt(cur);
+        else if(xml_isNode(cur, "energy"))
+          tmp->energy = (double)xml_getInt(cur);
+        else if(xml_isNode(cur, "armour_regen"))
+          tmp->armour_regen = (double)(xml_getInt(cur))/60.0;
+        else if(xml_isNode(cur, "shield_regen"))
+          tmp->shield_regen = (double)(xml_getInt(cur))/60.0;
+        else if(xml_isNode(cur, "energy_regen"))
+          tmp->energy_regen = (double)(xml_getInt(cur))/60.0;
     } while((cur = cur->next));
   }
-  else if(strcmp((char*)node->name, "characteristics")==0) {
+  else if(xml_isNode(node, "characteristics")) {
     cur = node->children;
     do {
-      if(strcmp((char*)cur->name, "crew")==0)
-        tmp->crew = atoi((char*)cur->children->content);
-      else if(strcmp((char*)cur->name, "mass")==0)
-        tmp->mass = (double)atoi((char*)cur->children->content);
-      else if(strcmp((char*)cur->name, "cap_weapon")==0)
-        tmp->cap_weapon = atoi((char*)cur->children->content);
-      else if(strcmp((char*)cur->name, "cap_cargo")==0)
-        tmp->cap_cargo = atoi((char*)cur->children->content);
+      if(xml_isNode(cur, "crew"))
+        tmp->crew = xml_getInt(cur);
+      else if(xml_isNode(cur, "mass"))
+        tmp->mass = (double)xml_getInt(cur);
+      else if(xml_isNode(cur, "cap_weapon"))
+        tmp->cap_weapon = xml_getInt(cur);
+      else if(xml_isNode(cur, "cap_cargo"))
+        tmp->cap_cargo = xml_getInt(cur);
       } while((cur = cur->next));
     }
-    else if(strcmp((char*)node->name, "outfits")==0) {
+    else if(xml_isNode(node, "outfits")) {
       cur = node->children;
       do {
-        if(strcmp((char*)cur->name, "outfit")==0) {
+        if(xml_isNode(cur, "outfit")) {
           otmp = MALLOC_L(ShipOutfit);
-          otmp->data = outfit_get((char*)cur->children->content);
-          xstr = xmlGetProp(cur, (xmlChar*)"quantity");
-          if(!xstr)
+          otmp->data = outfit_get(xml_get(cur));
+          stmp = xml_nodeProp(cur, "quantity");
+          if(!stmp)
             WARN("Ship '%s' is missing tag 'quantity for outfit '%s'",  tmp->name, otmp->data->name);
-          otmp->quantity = atoi((char*)xstr);
-          free(xstr);
+          otmp->quantity = atoi(stmp);
+          free(stmp);
           otmp->next = NULL;
 
           if((ocur = tmp->outfit) == NULL) tmp->outfit = otmp;
@@ -130,17 +132,18 @@ static Ship* ship_parse(xmlNodePtr parent) {
 #define MELEMENT(o,s) if(o == 0) WARN("Ship '%s' missing '"s"' element", tmp->name)
   if(tmp->name == NULL) WARN("Ship '%s' missing 'name' tag", tmp->name);
   if(tmp->gfx_space == NULL) WARN("Ship '%s' missing 'GFX' element", tmp->name);
+	if(tmp->gui == NULL) WARN("Ship '%s' missing 'GUI' element", tmp->name);
   MELEMENT(tmp->thrust,       "thrust");
   MELEMENT(tmp->turn,         "turn");
   MELEMENT(tmp->speed,        "speed");
-  MELEMENT(tmp->crew,         "crew");
-  MELEMENT(tmp->mass,         "mass");
   MELEMENT(tmp->armour,       "armour");
   MELEMENT(tmp->armour_regen, "armour_regen");
   MELEMENT(tmp->shield,       "shield");
   MELEMENT(tmp->shield_regen, "shield_regen");
   MELEMENT(tmp->energy,       "energy");
   MELEMENT(tmp->energy_regen, "energt_regen");
+  MELEMENT(tmp->crew,         "crew");
+  MELEMENT(tmp->mass,         "mass");
   MELEMENT(tmp->cap_cargo,    "cap_cargo");
   MELEMENT(tmp->cap_weapon,   "cap_weapon");
 #undef MELEMENT
diff --git a/src/ship.h b/src/ship.h
index 0555900..fbfca35 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -36,6 +36,9 @@ typedef struct {
 
   // GUI interface.
   char* gui;
+
+	// Sound.
+	ALuint sound;
   
   // Characteristics.
   int crew;
diff --git a/src/sound.c b/src/sound.c
index 256f9a4..1b99d49 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -9,21 +9,43 @@
 #include "music.h"
 #include "sound.h"
 
-// This isn't always set?
-#ifndef AL_FORMAT_VORBIS_EXT
-#define AL_FORMAT_VORBIS_EXT 0x10003
-#endif
+#define SOUND_PREFIX		"snd/sounds/"
+#define SOUND_SUFFIX		".wav"
 
+// Give the buffers a name.
 typedef struct {
-	ALfloat x, y;
-} alVector;
+	char* name;			// Buffers name.
+	ALuint buffer;	// Associated OpenAL buffer.
+} alSound;
 
+#define VOICE_PLAYING		(1<<0)	// Voice is playing.
+#define VOICE_LOOPING		(1<<1)	// Voice is looping.
+#define voice_set(v,f)	((v)->flags |= f)
+#define voice_is(v,f)		((v)->flags & f)
+
+// Gobal device and context.
 static ALCcontext* al_context = NULL;
 static ALCdevice* al_device = NULL;
 
+// Music player thread to assure streaming is perfect.
 static SDL_Thread* music_player = NULL;
 
+// List of sounds available (All preloaded into a buffer).
+static alSound* sound_list = NULL;
+static int nsound_list = 0;
+
+// Current sources playing.
+static alVoice** voice_stack = NULL;
+static int nvoice_stack = 0;
+static int mvoice_stack = 0;
+
+static int sound_makeList(void);
+static int sound_load(ALuint* buffer, char* filename);
+static void sound_free(alSound* snd);
+
 int sound_init(void) {
+	const ALchar* device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
+	DEBUG("OpenAL using device '%s'", device);
 	// Open the default device.
 	al_device = alcOpenDevice(NULL);
 	if(al_device == NULL) {
@@ -38,11 +60,8 @@ int sound_init(void) {
 		return -2;
 	}
 
-	// We use the vorbis extension for AL to load it easily.
-	if(alIsExtensionPresent("AL_EXT_vorbis") == AL_FALSE) {
-		WARN("AL_EXT_vorbis not available in OpenAL context!");
-		return -3;
-	}
+	// Clear the errors.
+	alGetError();
 
 	// Set active context.
 	if(alcMakeContextCurrent(al_context)==AL_FALSE) {
@@ -50,6 +69,10 @@ int sound_init(void) {
 		return -4;
 	}
 
+	// Load up all the sounds.
+	sound_makeList();
+
+	// Start the music server.
 	music_init();
 	music_player = SDL_CreateThread(music_thread, NULL);
 
@@ -59,6 +82,16 @@ int sound_init(void) {
 
 // Clean up after the sound system.
 void sound_exit(void) {
+	int i;
+	// Free the sounds.
+	for(i = 0; i < &nsound_list; i++)
+		sound_free(&sound_list[i]);
+	free(sound_list);
+	sound_list = NULL;
+	nsound_list = 0;
+
+	// Must stop the music before killing it,
+	// then thread should commit suicide.
 	music_stop();
 	music_kill();
 	SDL_WaitThread(music_player, NULL);
@@ -71,19 +104,67 @@ void sound_exit(void) {
 	if(al_device) alcCloseDevice(al_device);
 }
 
-// Loads a vorbis file.
-ALuint sound_sndCreate(char* filename) {
-	void* ovdata;
+// Get the buffer to sound of [name].
+ALuint sound_get(char* name) {
+	int i;
+	for(i = 0; i < nsound_list; i++)
+		if(strcmp(name, sound_list[i].name)==0)
+			return sound_list[i].buffer;
+	WARN("Sound '%s' not found in sound list", name);
+	return 0;
+}
+
+// Make list of available sounds.
+static int sound_makeList(void) {
+	char** files;
+	uint32_t nfiles, i;
+	char tmp[64];
+	int len;
+
+	// Get the file list.
+	files = pack_listfiles(data, &nfiles);
+
+	// Load the profiles.
+	for(i = 0; i < nfiles; i++)
+		if((strncmp(files[i], SOUND_PREFIX, strlen(SOUND_PREFIX))==0) &&
+					(strncmp(files[i] + strlen(files[i]) - strlen(SOUND_SUFFIX),
+					SOUND_SUFFIX, strlen(SOUND_SUFFIX))==0)) {
+		
+			// Expand the selection size.
+			sound_list = realloc(sound_list, ++nsound_list * sizeof(alSound));
+
+			// Remove the prefix and suffix.
+			len = strlen(files[i]) - strlen(SOUND_SUFFIX SOUND_SUFFIX);
+			strncpy(tmp, files[i] + strlen(SOUND_PREFIX), len);
+			tmp[len] = '\0';
+
+			// give it the new name.
+			sound_list[nsound_list-1].name = strdup(tmp);
+			sound_load(&sound_list[nsound_list-1].buffer, files[i]);
+		}
+	
+	// Free the char* allocated by pack.
+	for(i = 0; i < nfiles; i++)
+		free(files[i]);
+	free(files);
+
+	DEBUG("Loaded %d sound%c", nsound_list, (nsound_list==1)?' ':'s');
+
+	return 0;
+}
+
+// Loads a sound into the sound_list.
+static int sound_load(ALuint* buffer, char* filename) {
+	void* wavdata;
 	unsigned int size;
 	ALenum err;
-	ALuint buf;
 
 	// Get the file data buffer from the packfile.
-	ovdata = pack_readfile(DATA, filename, &size);
+	wavdata = pack_readfile(DATA, filename, &size);
 
 	// Bind to OpenAL buffer.
-	alGenBuffers(1, &buf);
-	alBufferData(buf, AL_FORMAT_VORBIS_EXT, ovdata, size, 44800);
+	alGenBuffers(1, buffer);
+	alBufferData(*buffer, AL_FORMAT_MONO16, wavdata, size, 22050);
 
 	// Errors?
 	if((err = alGetError()) != AL_NO_ERROR) {
@@ -92,11 +173,112 @@ ALuint sound_sndCreate(char* filename) {
 	}
 
 	// Finish up.
-	free(ovdata);
-	return buf;
+	free(wavdata);
+	return 0;
 }
 
-void sound_sndFree(const ALuint snd) {
-	alDeleteBuffers(1, &snd);
+static void sound_free(alSound* snd) {
+	if(snd->name) free(snd->name);
+	alDeleteBuffers(1, &snd->buffer);
+}
+
+// Update the sounds and prioritize them.
+void sound_update(void) {
+	int i;
+	
+	// TODO: Prioritize the things.
+
+	for(i = 0; i < nvoice_stack; i++) {
+		if(voice_is(voice_stack[i], VOICE_PLAYING)) {
+			// Update position.
+			alSource3f(voice_stack[i]->source, AL_POSITION,
+						voice_stack[i]->px, voice_stack[i]->py, 0.);
+			alSource3f(voice_stack[i]->source, AL_VELOCITY,
+						voice_stack[i]->vx, voice_stack[i]->vy, 0.);
+
+		}
+	}
+}
+
+// Create a dynamic moving voice.
+alVoice* sound_addVoice(int priority, double px, double py, double vx, double vy,
+			const ALuint buffer, const int looping) {
+
+	alVoice* voc;
+	ALenum err;
+
+	nvoice_stack++;
+	if(nvoice_stack > mvoice_stack)
+		voice_stack = realloc(voice_stack, ++mvoice_stack*sizeof(alVoice*));
+	
+	voc = malloc(sizeof(alVoice));
+	voice_stack[nvoice_stack-1] = voc;
+
+	// Try and grab a source.
+	voc->source = 0;
+	alGenSources(1, &voc->source);
+	err = alGetError();
+	if(err != AL_NO_ERROR) voc->source = 0;
+
+	// Set the data.
+	voc->priority = priority;
+	voc->start = SDL_GetTicks();
+	voc->buffer = buffer;
+	if(looping) voice_set(voc, VOICE_LOOPING);
+	voc->px = px;
+	voc->py = py;
+	voc->vx = vx;
+	voc->vy = vy;
+
+	// Set the source.
+	if(voc->source) {
+		alSourcei(voc->source, AL_SOURCE_RELATIVE, AL_TRUE);
+		alSourcef(voc->source, AL_GAIN, 1.);
+		alSourcei(voc->source, AL_BUFFER, buffer);
+		alSource3f(voc->source, AL_POSITION, voc->px, voc->py, 0.);
+		alSource3f(voc->source, AL_VELOCITY,	voc->vx, voc->vy, 0.);
+		if(voice_is(voc, VOICE_LOOPING))
+			alSourcei(voc->source, AL_LOOPING, AL_TRUE);
+
+		// Try to play the source.
+		alSourcePlay(voc->source);
+		err = alGetError();
+		if(err == AL_NO_ERROR) voice_set(voc, VOICE_PLAYING);
+		else DEBUG("Source player failure");
+	}
+	return voc;
+}
+
+void sound_delVoice(alVoice* voice) {
+	ALint stat;
+	int i;
+
+	for(i = 0; i < nvoice_stack; i++)
+		if(voice == voice_stack[i])
+			break;
+
+	// No match found.
+	if(i >= nvoice_stack) {
+		WARN("Unable to find voice to free from stack");
+		return;
+	}
+
+	if(voice->source) {
+		alGetSourcei(voice->source, AL_SOURCE_STATE, &stat);
+		if(stat == AL_PLAYING) alSourceStop(voice->source);
+		alDeleteSources(1, &voice->source);
+		voice->source = 0;
+	}
+
+	nvoice_stack--;
+	for(; i < nvoice_stack; i++)
+		voice_stack[i] = voice_stack[i+1];
+}
+
+void voice_update(alVoice* voice, double px, double py, double vx, double vy) {
+	voice->px = px;
+	voice->py = py;
+	voice->vx = vx;
+	voice->vy = vy;
 }
 
diff --git a/src/sound.h b/src/sound.h
index 06157b8..b8e62b1 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -2,15 +2,35 @@
 #include <AL/al.h>
 #include "physics.h"
 
+#define SOUND_REFERENCE_DIST 	500.
+#define SOUND_MAX_DIST				1000.
+
+// Virtual voice.
+typedef struct {
+	ALuint source;	// Source itself, 0 if not set.
+	ALuint buffer;	// Buffer.
+
+	int priority; 	// Base priority.
+
+	double px, py;	// Position.
+	double vx, vy;	// Velocity.
+
+	unsigned int start; // Time started in ms.
+	unsigned int flags; // Flags to set properties.
+} alVoice;
+
 // Sound subsystem.
 int sound_init(void);
 void sound_exit(void);
+void sound_update(void);
 
 // Sound manupulation functions.
-ALuint sound_sndCreate(char* filename);
-void sound_sndFree(const ALuint snd);
+ALuint sound_get(char* name);
 
-// Source manipulation function.
-#define sound_initSource(s)		(alGenSources(1, &(s)))
-#define sound_delSource(s)		(alDeleteSources(1, &(s))
+// Voice manipulation function.
+alVoice* sound_addVoice(int priority, double px, double py, double vx, double vy,
+			const ALuint buffer, const int looping);
+
+void sound_delVoice(alVoice* voice);
+void voice_update(alVoice* voice, double px, double py, double vx, double vy);
 
diff --git a/src/weapon.c b/src/weapon.c
index b059eff..61956f5 100644
--- a/src/weapon.c
+++ b/src/weapon.c
@@ -14,6 +14,9 @@
 
 #define weapon_isSmart(w) (w->think)
 
+#define VOICE_PRIORITY_BOLD		10 	// Default.
+#define VOICE_PRIORITY_AMMP		8		// Higher.
+
 // Some stuff from pilot.
 extern Pilot** pilot_stack;
 extern int pilots;
@@ -29,7 +32,9 @@ typedef struct Weapon {
   const Outfit* outfit; // Related outfit that fired.
   unsigned int timer; // Mainly used to see when the weapon was fired.
 
-  // Update position and render.
+	//alVoice voice; // Virtual voise.
+	
+	// Update position and render.
   void(*update)(struct Weapon*, const double, WeaponLayer); // Position update and render.
   void(*think)(struct Weapon*); // Some missiles need to be inteligent.
 } Weapon;
@@ -43,7 +48,6 @@ static Weapon** wfrontLayer = NULL;  // Behind pilots.
 static int nwfrontLayer    = 0;    // Number of elements.
 static int mwfrontLayer    = 0;    // Allocated memory size.
 
-
 static Weapon* weapon_create(const Outfit* outfit, const double dir,
       const Vec2* pos, const Vec2* vel, const unsigned int parent, 
       const unsigned int target);
@@ -222,6 +226,11 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
   }
   if(weapon_isSmart(w)) (*w->think)(w);
   (*w->solid->update)(w->solid, dt);
+
+	// Update the sound.
+	/*if(w->voise)
+		voice_update(w->voice, w->solid->pos.x, w->solid->pos.y,
+					w->solid->vel.x, w->solid->vel.y);*/
 }
 
 // Good shot.