diff --git a/src/sound.c b/src/sound.c
index 453a0dd..b9e5fc5 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -188,22 +188,27 @@ int sound_get(char* name) {
  *
  * @brief Play the sound in the first available channel.
  *    @param sound Sound to play.
- *    @return 0 on success.
+ *    @return Voice identifier on success..
  */
 int sound_play(int sound) {
-  int channel;
+  alVoice* v;
 
   if(sound_disabled) return 0;
 
   if((sound < 0) || (sound > sound_nlist))
     return -1;
 
-  channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
+  v = voice_new();
 
-  if(channel < 0)
+  v->channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
+
+  if(v->channel < 0)
     WARN("Unable to play sound: %s", Mix_GetError());
 
-  return 0;
+  v->state = VOICE_PLAYING;
+  v->id = ++voice_genid;
+  voice_add(v);
+  return v->id;
 }
 
 /**
@@ -311,15 +316,23 @@ int sound_update(void) {
     if((v->state == VOICE_STOPPED) || (v->state == VOICE_DESTROY)) {
       /* Remove from active list. */
       tv = v->prev;
-      if(tv == NULL)
+      if(tv == NULL) {
         voice_active = v->next;
-      else
+        if(voice_active != NULL)
+          voice_active->prev = NULL;
+      } else {
         tv->next = v->next;
+        if(tv->next != NULL)
+          tv->next->prev = tv;
+      }
 
       /* Add to free pool. */
       v->next = voice_pool;
+      v->prev = NULL;
       voice_pool = v;
       v->channel = 0;
+      if(v->next != NULL)
+        v->next->prev = v;
 
       /* Avoid loop blockage. */
       v = (tv != NULL) ? tv->next : voice_active;
@@ -604,7 +617,7 @@ static alVoice* voice_new(void) {
   }
 
   /* First free voice. */
-  v = voice_pool;
+  v = voice_pool; /* We do not touch the next nor prev, it's still in the pool. */
   return v;
 }
 
@@ -618,10 +631,12 @@ static alVoice* voice_new(void) {
 static int voice_add(alVoice* v) {
   alVoice* tv;
 
-  /* Set previous to point to next. */
+  /* Remove from pool. */
   if(v->prev != NULL) {
     tv = v->prev;
     tv->next = v->next;
+    if(tv->next != NULL)
+      voice_pool->prev = NULL;
   } else {  /* Set pool to be the next. */
     voice_pool = v->next;
   }
@@ -630,6 +645,9 @@ static int voice_add(alVoice* v) {
   tv = voice_active;
   voice_active = v;
   v->next = tv;
+  v->prev = NULL;
+  if(tv != NULL)
+    tv->prev = v;
   return 0;
 }
 
diff --git a/src/weapon.c b/src/weapon.c
index b0bd66a..cfa45e6 100644
--- a/src/weapon.c
+++ b/src/weapon.c
@@ -46,6 +46,7 @@ typedef struct Weapon_ {
   unsigned int target;  /* Target to hit. Only used by seeking stuff. */
   const Outfit* outfit; /* Related outfit that fired. */
 
+  int voice;            /**< Weapons voice. */
   double lockon;        /* Some weapons have a lockon delay. */
   double timer;         /* Mainly used to see when the weapon was fired. */
 
@@ -312,9 +313,6 @@ static void weapons_updateLayer(const double dt, const WeaponLayer layer) {
     case OUTFIT_TYPE_TURRET_BEAM:
       wlayer[i]->timer -= dt;
       if(wlayer[i]->timer < 0.) {
-        sound_playPos(w->outfit->u.bem.sound_off,
-            w->solid->pos.x,
-            w->solid->pos.y);
         weapon_destroy(wlayer[i],layer);
         continue;
       }
@@ -494,7 +492,11 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
   /* Smart weapons also get to think their next move. */
   if(weapon_isSmart(w)) (*w->think)(w,dt);
 
+  /* Update the solid position. */
   (*w->solid->update)(w->solid, dt);
+
+  /* Update the sound. */
+  sound_updatePos(w->voice, w->solid->pos.x, w->solid->pos.y);
 }
 
 /**
@@ -627,7 +629,7 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
     vect_cadd(&v, outfit->u.blt.speed*cos(rdir), outfit->u.blt.speed*sin(rdir));
     w->timer += outfit->u.blt.range/outfit->u.blt.speed;
     w->solid = solid_create(mass, rdir, pos, &v);
-    sound_playPos(w->outfit->u.blt.sound,
+    w->voice = sound_playPos(w->outfit->u.blt.sound,
         w->solid->pos.x + w->solid->vel.x,
         w->solid->pos.y + w->solid->vel.y);
     break;
@@ -646,7 +648,7 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
       w->solid = solid_create(mass, rdir, pos, NULL);
       w->think = think_beam;
       w->timer = outfit->u.bem.duration;
-      sound_playPos(w->outfit->u.bem.sound,
+      w->voice = sound_playPos(w->outfit->u.bem.sound,
           w->solid->pos.x + vel->x,
           w->solid->pos.y + vel->y);
       break;
@@ -670,7 +672,7 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
       w->think = think_seeker;
     else if(outfit->type == OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO)
       w->think = think_smart;*/
-    sound_playPos(w->outfit->u.amm.sound,
+    w->voice = sound_playPos(w->outfit->u.amm.sound,
         w->solid->pos.x + w->solid->vel.x,
         w->solid->pos.y + w->solid->vel.y);
     break;
@@ -683,7 +685,7 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
     vect_pset(&w->solid->force, w->outfit->u.amm.thrust, dir);
     w->think = NULL; /* No AI. */
 
-    sound_playPos(w->outfit->u.amm.sound,
+    w->voice = sound_playPos(w->outfit->u.amm.sound,
         w->solid->pos.x + w->solid->vel.x,
         w->solid->pos.y + w->solid->vel.y);
     break;
@@ -870,6 +872,14 @@ static void weapon_destroy(Weapon* w, WeaponLayer layer) {
       pilot_target->lockons--;
   }
 
+  /* Stop playing sound if beam weapon. */
+  if(outfit_isBeam(w->outfit)) {
+    sound_stop(w->voice);
+    sound_playPos(w->outfit->u.bem.sound_off,
+        w->solid->pos.x,
+        w->solid->pos.y);
+  }
+
   switch(layer) {
   case WEAPON_LAYER_BG:
     wlayer = wbackLayer;