diff --git a/src/lephisto.c b/src/lephisto.c
index 0cb909a..7d7bc0d 100644
--- a/src/lephisto.c
+++ b/src/lephisto.c
@@ -332,6 +332,8 @@ void main_loop(void) {
   glClear(GL_COLOR_BUFFER_BIT);
 
   fps_control(); /* Everyone loves fps control.. */
+
+  sound_update(); /* Update sounds. */
   if(toolkit) toolkit_update(); /* To simulate key repetition. */
   if(!menu_isOpen(MENU_MAIN)) {
     if(!paused) update_all(); /* Update game. */
diff --git a/src/sound.c b/src/sound.c
index 9830e68..453a0dd 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -26,19 +26,64 @@ int sound_disabled        = 0;  /**< Whether sound is disabled. */
 static int sound_reserved = 0;  /**< Amount of reserved channels. */
 static double sound_pos[3];     /**< Position of listener. */
 
-/* Give the buffers a name. */
+/**
+ * @struct alSound
+ * 
+ * @brief Contains a sound buffer.
+ */
 typedef struct alSound_ {
   char* name;         /**< Buffers name. */
   Mix_Chunk* buffer;  /**< Buffer data. */
 } alSound;
 
+/**
+ * @typedef voice_state_t
+ *
+ * @brief The state of a voice.
+ *
+ * @sa alVoice
+ */
+typedef enum voice_state_ {
+  VOICE_STOPPED,    /**< Voice is stopped. */
+  VOICE_PLAYING,    /**< Voice is playing. */
+  VOICE_DESTROY     /**< Voice should get destroyed asap. */
+} voice_state_t;
+
+/**
+ * @struct alVoice
+ *
+ * @brief Represents a voice in the game.
+ *
+ * A voice would be any object that is creating sound.
+ */
+typedef struct alVoice_ {
+  struct alVoice_* prev;    /**< Linked list previous member. */
+  struct alVoice_* next;    /**< Linked list next member. */
+
+  int id;                   /**< Identifier of the voice. */
+  double pos[2];            /**< Position of the voice. */
+  int channel;              /**< Channel currently in use. */
+  unsigned int state;       /**< Current state of the sound. */
+} alVoice;
+
 /* List of sounds available (All preloaded into a buffer). */
+static int voice_genid = 0;         /**< Voice identifier generator. */
 static alSound* sound_list  = NULL; /**< List of available sounds. */
 static int sound_nlist      = 0;    /**< Number of available sounds. */
 
+/* Voice linked list. */
+static alVoice* voice_active;       /**< Active voices. */
+static alVoice* voice_pool;         /**< Pool of free voices. */
+
+/* General prototypes. */
 static int  sound_makeList(void);
 static Mix_Chunk* sound_load(char* filename);
 static void sound_free(alSound* snd);
+/* Voices. */
+static void voice_markStopped(int channel);
+static alVoice* voice_new(void);
+static int voice_add(alVoice* v);
+static alVoice* voice_get(int id);
 
 /**
  * @fn int sound_init(void)
@@ -77,6 +122,9 @@ int sound_init(void) {
   sound_makeList();
   sound_volume(0.4);
 
+  /* Finish function. */
+  Mix_ChannelFinished(voice_markStopped);
+
   /* Init the music. */
   music_init();
 
@@ -90,6 +138,19 @@ int sound_init(void) {
  */
 void sound_exit(void) {
   int i;
+  alVoice* v;
+
+  /* Free the voices. */
+  while(voice_active != NULL) {
+    v = voice_active;
+    voice_active = v->next;
+    free(v);
+  }
+  while(voice_pool != NULL) {
+    v = voice_pool;
+    voice_pool = v->next;
+    free(v);
+  }
   
   /* Free the sounds. */
   for(i = 0; i < sound_nlist; i++)
@@ -155,7 +216,7 @@ int sound_play(int sound) {
  *    @return 0 on success.
  */
 int sound_playPos(int sound, double x, double y) {
-  int channel;
+  alVoice* v;
   double angle, dist;
   double px, py;
 
@@ -164,28 +225,128 @@ int sound_playPos(int sound, double x, double y) {
   if((sound < 0) || (sound > sound_nlist))
     return -1;
 
-  px = x - sound_pos[0];
-  py = y - sound_pos[1];
+  /* Get a new voice. */
+  v = voice_new();
+
+  v->pos[0] = x;
+  v->pos[1] = y;
+
+  px = v->pos[0] - sound_pos[0];
+  py = v->pos[1] - sound_pos[1];
 
   angle = sound_pos[2] - ANGLE(px, py)/M_PI*180.;
-
   dist = MOD(px, py);
 
-  channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
+  v->channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
 
-  if(channel < 0) {
+  if(v->channel < 0) {
     WARN("Unable to play sound: %s", Mix_GetError());
     return -1;
   }
 
-  if(Mix_SetPosition(channel, (int)angle, (int)dist/10) < 0) {
+  if(Mix_SetPosition(v->channel, (int)angle, (int)dist/10) < 0) {
     WARN("Unable to set sound position: %s", Mix_GetError());
     return -1;
   }
 
+  /* Actually add the voice to the list. */
+  v->state = VOICE_PLAYING;
+  v->id = ++voice_genid;
+  voice_add(v);
+
+  return v->id;
+}
+
+/**
+ * @fn int sound_updatePos(int voice, double x, double y)
+ *
+ * @brief Update the position of a voice.
+ *    @param voice Identifier of the voice to update.
+ *    @param x New x position to update to.
+ *    @param y New y position to update to.
+ */
+int sound_updatePos(int voice, double x, double y) {
+  alVoice* v;
+  double angle, dist;
+  double px, py;
+
+  if(sound_disabled) return 0;
+
+  v = voice_get(voice);
+
+  if(v != NULL) {
+    v->pos[0] = x;
+    v->pos[1] = y;
+
+    px = x - sound_pos[0];
+    py = y - sound_pos[1];
+
+    angle = sound_pos[2] - ANGLE(px, py)/M_PI*180.;
+    dist = MOD(px, py);
+
+    if(Mix_SetPosition(v->channel, (int)angle, (int)dist/10) < 0) {
+      WARN("Unable to set sound position: %s", Mix_GetError());
+      return -1;
+    }
+  }
   return 0;
 }
 
+/**
+ * @fn int sound_update(void)
+ *
+ * @brief Update the sounds removing obsolete ones and such.
+ *    @return 0 on success.
+ */
+int sound_update(void) {
+  alVoice* v, *tv;
+
+  if(sound_disabled) return 0;
+
+  if(voice_active == NULL) return 0;
+
+  /* The actualy control loop. */
+  for(v = voice_active; v != NULL; v = v->next) {
+    /* Destroy and toss into pool. */
+    if((v->state == VOICE_STOPPED) || (v->state == VOICE_DESTROY)) {
+      /* Remove from active list. */
+      tv = v->prev;
+      if(tv == NULL)
+        voice_active = v->next;
+      else
+        tv->next = v->next;
+
+      /* Add to free pool. */
+      v->next = voice_pool;
+      voice_pool = v;
+      v->channel = 0;
+
+      /* Avoid loop blockage. */
+      v = (tv != NULL) ? tv->next : voice_active;
+      if(v == NULL) break;
+    }
+  }
+  return 0;
+}
+
+/**
+ * @fn void sound_stop(int voice)
+ *
+ * @brief Stop a voice from playing.
+ *    @param voice Identifier of the voice to stop.
+ */
+void sound_stop(int voice) {
+  alVoice* v;
+  
+  if(sound_disabled) return;
+
+  v = voice_get(voice);
+  if(v != NULL) {
+    Mix_HaltChannel(v->channel);
+    v->state = VOICE_STOPPED;
+  }
+}
+
 /**
  * @fn int sound_updateListener(double dir, double x, double y)
  *
@@ -410,3 +571,83 @@ void sound_stopGroup(int group) {
   Mix_HaltGroup(group);
 }
 
+/**
+ * @fn static void voice_markStopped(int channel)
+ *
+ * @brief Mark the voice to which channel belongs to as stopped.
+ */
+static void voice_markStopped(int channel) {
+  alVoice* v;
+
+  for(v = voice_active; v != NULL; v = v->next)
+    if(v->channel == channel) {
+      v->state = VOICE_STOPPED;
+      return;
+    }
+}
+
+/**
+ * @fn static alVoice* voice_new(void)
+ *
+ * @brief Get a new voice ready to be used.
+ *    @return New voice ready to use.
+ */
+static alVoice* voice_new(void) {
+  alVoice* v;
+
+  /* No free voices, allocate a new one. */
+  if(voice_pool == NULL) {
+    v = malloc(sizeof(alVoice));
+    memset(v, 0, sizeof(alVoice));
+    voice_pool = v;
+    return v;
+  }
+
+  /* First free voice. */
+  v = voice_pool;
+  return v;
+}
+
+/**
+ * @fn static int voice_add(alVoice* v)
+ *
+ * @brief Add a voice to the active voice stack.
+ *    @param v Voice to add to the active voice stack.
+ *    @return 0 on success.
+ */
+static int voice_add(alVoice* v) {
+  alVoice* tv;
+
+  /* Set previous to point to next. */
+  if(v->prev != NULL) {
+    tv = v->prev;
+    tv->next = v->next;
+  } else {  /* Set pool to be the next. */
+    voice_pool = v->next;
+  }
+
+  /* Insert to the front of active voices. */
+  tv = voice_active;
+  voice_active = v;
+  v->next = tv;
+  return 0;
+}
+
+/**
+ * @fn static alVoice* voice_get(int id)
+ *
+ * @brief Get a voice by identifier.
+ *    @param id Identifier to look for.
+ *    @return Voice matching identifier or NULL if not found.
+ */
+static alVoice* voice_get(int id) {
+  alVoice* v;
+
+  if(voice_active == NULL) return NULL;
+
+  for(v = voice_active; v != NULL; v = v->next)
+    if(v->id == id)
+      return v;
+  return NULL;
+}
+
diff --git a/src/sound.h b/src/sound.h
index 4a04f76..daf4750 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -5,12 +5,15 @@ extern int sound_disabled;
 /* Sound subsystem. */
 int sound_init(void);
 void sound_exit(void);
+int sound_update(void);
 
 /* Sound manupulation functions. */
 int sound_get(char* name);
 int sound_volume(const double vol);
 int sound_play(int sound);
 int sound_playPos(int sound, double x, double y);
+void sound_stop(int voice);
+int sound_updatePos(int voice, double x, double y);
 int sound_updateListener(double dir, double x, double y);
 
 /* Group functions. */