From 9bb4b6e90e981020f980fa0968bb778fb9ea5e4d Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Fri, 23 Aug 2013 20:45:49 +0100
Subject: [PATCH] [Add] Primitive positional sound.

---
 src/player.c |  4 ++++
 src/sound.c  | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
 src/sound.h  |  2 ++
 src/weapon.c |  8 ++++++--
 4 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/src/player.c b/src/player.c
index 216ece6..13b46e6 100644
--- a/src/player.c
+++ b/src/player.c
@@ -1239,6 +1239,10 @@ void player_think(Pilot* pplayer) {
     vect_pset(&pplayer->solid->force, pplayer->thrust * player_acc,
               pplayer->solid->dir);
 
+  /* Update sound position. */
+  sound_updateListener(pplayer->solid->dir,
+      pplayer->solid->pos.x, pplayer->solid->pos.y);
+
 }
 
 /* Modify the radar resolution. */
diff --git a/src/sound.c b/src/sound.c
index c8efb90..1d7256c 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -8,6 +8,7 @@
 #include "log.h"
 #include "pack.h"
 #include "music.h"
+#include "physics.h"
 #include "sound.h"
 
 #define SOUND_CHANNEL_MAX 256 /* Overkill. */
@@ -15,8 +16,10 @@
 #define SOUND_PREFIX      "../snd/sounds/"
 #define SOUND_SUFFIX      ".wav"
 
-int sound_disabled        = 0; /* Whether sound is disabled. */
-static int sound_reserved = 0; /* Amount of reserved channels. */
+/* Global sound properties. */
+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. */
 typedef struct alSound_ {
@@ -91,8 +94,9 @@ int sound_get(char* name) {
   if(sound_disabled) return 0;
 
   for(i = 0; i < sound_nlist; i++)
-    if(strcmp(name, sound_list[i].name)==0)
+    if(strcmp(name, sound_list[i].name)==0) {
       return i;
+    }
 
   WARN("Sound '%s' not found in sound list", name);
   return -1;
@@ -110,11 +114,50 @@ int sound_play(int sound) {
   channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
 
   if(channel < 0)
-    DEBUG("SDL_Mixer: %s", Mix_GetError());
+    WARN("Unable to play sound: %s", Mix_GetError());
 
   return 0;
 }
 
+int sound_playPos(int sound, double x, double y) {
+  int channel;
+  double angle, dist;
+  double px, py;
+
+  if(sound_disabled) return 0;
+
+  if((sound < 0) || (sound > sound_nlist))
+    return -1;
+
+  px = x - sound_pos[0];
+  py = y - 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);
+
+  if(channel < 0) {
+    WARN("Unable to play sound: %s", Mix_GetError());
+    return -1;
+  }
+
+  if(Mix_SetPosition(channel, (int)angle, (int)dist/10) < 0) {
+    WARN("Unable to set sound position: %s", Mix_GetError());
+    return -1;
+  }
+
+  return 0;
+}
+
+int sound_updateListener(double dir, double x, double y) {
+  sound_pos[0] = x;
+  sound_pos[1] = y;
+  sound_pos[2] = dir/M_PI*180.;
+  return 0;
+}
+
 /* Make list of available sounds. */
 static int sound_makeList(void) {
   char** files;
diff --git a/src/sound.h b/src/sound.h
index 57aab91..4a04f76 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -10,6 +10,8 @@ void sound_exit(void);
 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);
+int sound_updateListener(double dir, double x, double y);
 
 /* Group functions. */
 int sound_reserve(int num);
diff --git a/src/weapon.c b/src/weapon.c
index 7e701d3..57cbdd0 100644
--- a/src/weapon.c
+++ b/src/weapon.c
@@ -428,7 +428,9 @@ 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_play(w->outfit->u.blt.sound);
+    sound_playPos(w->outfit->u.blt.sound,
+        w->solid->pos.x + w->solid->vel.x,
+        w->solid->pos.y + w->solid->vel.y);
     break;
   
   /* Treat seekers togther. */
@@ -450,7 +452,9 @@ 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_play(w->outfit->u.amm.sound);
+    sound_playPos(w->outfit->u.amm.sound,
+        w->solid->pos.x + w->solid->vel.x,
+        w->solid->pos.y + w->solid->vel.y);
     break;
  
   /* Just dump it where the player is. */