about summary refs log tree commit diff
path: root/src/engine
diff options
context:
space:
mode:
authorJoel de Vahl <joel@stalverk80.se>2007-10-02 16:19:25 +0000
committerJoel de Vahl <joel@stalverk80.se>2007-10-02 16:19:25 +0000
commit21df126c88230f11749bc9241ed51a26d31f0810 (patch)
treecb1975ea5c41e44f1361c96c4105c702cf865ae1 /src/engine
parent4bf60da04b668d10c53d5d3784ba3543c7a4d314 (diff)
downloadzcatch-21df126c88230f11749bc9241ed51a26d31f0810.tar.gz
zcatch-21df126c88230f11749bc9241ed51a26d31f0810.zip
sound fixes and initial lock implementation
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/client/snd.c41
-rw-r--r--src/engine/interface.h3
-rw-r--r--src/engine/system.c57
-rw-r--r--src/engine/system.h6
4 files changed, 98 insertions, 9 deletions
diff --git a/src/engine/client/snd.c b/src/engine/client/snd.c
index da18a3be..e11ace52 100644
--- a/src/engine/client/snd.c
+++ b/src/engine/client/snd.c
@@ -20,6 +20,8 @@ enum
 	MAX_FRAMES = 1024
 };
 
+static LOCK sound_lock = 0;
+
 static struct sound
 {
 	short *data;
@@ -128,6 +130,7 @@ static inline void fill_stereo(int *out, unsigned frames, struct voice *v, float
 static void mix(short *out, unsigned frames)
 {
 	static int main_buffer[MAX_FRAMES*2];
+	unsigned locked = 0;
 
 	dbg_assert(frames <= MAX_FRAMES, "too many frames to fill");
 
@@ -148,7 +151,9 @@ static void mix(short *out, unsigned frames)
 		while(v)
 		{
 			unsigned filled = 0;
-			while(v->sound && filled < frames)
+			unsigned step = 1;
+
+			while(v && v->sound && filled < frames)
 			{
 				// calculate maximum frames to fill
 				unsigned frames_left = (v->sound->num_samples - v->tick) >> (v->sound->channels-1);
@@ -214,6 +219,14 @@ static void mix(short *out, unsigned frames)
 					v->stop -=  to_fill;
 				if(v->tick >= v->sound->num_samples || v->stop == 0)
 				{
+					struct voice *vn = v->next;
+					if(!locked)
+					{
+						lock_wait(sound_lock);
+						locked = 1;
+					}
+
+
 					if(v->next)
 						v->next->prev = v->prev;
 
@@ -225,15 +238,21 @@ static void mix(short *out, unsigned frames)
 					dbg_msg("snd", "sound stopped");
 
 					reset_voice(v);
+					step = 0;
+					v = vn;
 				}
 
 				filled += to_fill;
 			}
 
-			v = (struct voice*)v->next;
+			if(step)
+				v = (struct voice*)v->next;
 		}
 	}
 
+	if(locked)
+		lock_release(sound_lock);
+
 	// clamp accumulated values
 	for(i = 0; i < frames; i++)
 	{
@@ -266,6 +285,8 @@ int snd_init()
 	params.suggestedLatency = Pa_GetDeviceInfo(params.device)->defaultLowOutputLatency;
 	params.hostApiSpecificStreamInfo = 0x0;
 
+	sound_lock = lock_create();
+
 	err = Pa_OpenStream(
 			&stream,        /* passes back stream pointer */
 			0,              /* no input channels */
@@ -285,6 +306,8 @@ int snd_shutdown()
 	Pa_StopStream(stream);
 	Pa_Terminate();
 
+	lock_destroy(sound_lock);
+
 	return 0;
 }
 
@@ -547,9 +570,10 @@ int snd_load_wav(const char *filename)
 	return sid;
 }
 
-int snd_play(int cid, int sid, int loop, int x, int y)
+int snd_play(int cid, int sid, int loop, float x, float y)
 {
 	int vid;
+	dbg_msg("snd", "try adding sound");
 	for(vid = 0; vid < NUM_VOICES; vid++)
 	{
 		if(voices[vid].sound == 0x0)
@@ -563,15 +587,18 @@ int snd_play(int cid, int sid, int loop, int x, int y)
 			else
 				voices[vid].loop = -1;
 
-			// add voice to channel last, to avoid threding errors
+			lock_wait(sound_lock);
+			dbg_msg("snd", "sound added");
 			voices[vid].next = channels[cid].first_voice;
 			if(channels[cid].first_voice)
 				channels[cid].first_voice->prev = &voices[vid];
 			channels[cid].first_voice = &voices[vid];
+			lock_release(sound_lock);
 			return vid;
 		}
 	}
 
+	dbg_msg("snd", "failed");
 	return -1;
 }
 
@@ -585,3 +612,9 @@ void snd_stop(int vid)
 	//TODO: lerp volume to 0
 	voices[vid].stop = 0;
 }
+
+void snd_set_listener_pos(float x, float y)
+{
+	center_x = x;
+	center_y = y;
+}
diff --git a/src/engine/interface.h b/src/engine/interface.h
index 18a434dd..c1a0b282 100644
--- a/src/engine/interface.h
+++ b/src/engine/interface.h
@@ -356,9 +356,10 @@ float snd_get_master_volume();
 void snd_set_master_volume(float val);
 int snd_load_wav(const char *filename);
 int snd_load_wv(const char *filename);
-int snd_play(int cid, int sid, int loop, int x, int y);
+int snd_play(int cid, int sid, int loop, float x, float y);
 void snd_stop(int id);
 void snd_set_vol(int id, float vol);
+void snd_set_listener_pos(float x, float y);
 int snd_shutdown();
 
 /*
diff --git a/src/engine/system.c b/src/engine/system.c
index 8717d58a..381b7ca3 100644
--- a/src/engine/system.c
+++ b/src/engine/system.c
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <time.h>
 
+#include "detect.h"
 #include "system.h"
 
 #if defined(CONF_FAMILY_UNIX)
@@ -18,6 +19,7 @@
 	#include <netdb.h>      
 	#include <netinet/in.h>
 	#include <fcntl.h>
+	#include <pthread.h>
 
 	#include <dirent.h>
 	#include <unistd.h>
@@ -250,6 +252,61 @@ void thread_sleep(int milliseconds)
 #endif
 }
 
+#if defined(CONF_FAMILY_UNIX)
+typedef pthread_mutex_t LOCKINTERNAL;
+#else
+	#error not implemented on this platform
+#endif
+
+LOCK lock_create()
+{
+	LOCKINTERNAL *l = (LOCKINTERNAL*)mem_alloc(sizeof(LOCKINTERNAL), 4);
+
+#if defined(CONF_FAMILY_UNIX)
+	pthread_mutex_init(l, 0x0);
+#else
+	#error not implemented on this platform
+#endif
+	return l;
+}
+
+void lock_destroy(LOCK lock)
+{
+#if defined(CONF_FAMILY_UNIX)
+	pthread_mutex_destroy(lock);
+#else
+	#error not implemented on this platform
+#endif
+	mem_free(lock);
+}
+
+int lock_try(LOCK lock)
+{
+#if defined(CONF_FAMILY_UNIX)
+	return pthread_mutex_trylock(lock);
+#else
+	#error not implemented on this platform
+#endif
+}
+
+void lock_wait(LOCK lock)
+{
+#if defined(CONF_FAMILY_UNIX)
+	pthread_mutex_lock(lock);
+#else
+	#error not implemented on this platform
+#endif
+}
+
+void lock_release(LOCK lock)
+{
+#if defined(CONF_FAMILY_UNIX)
+	pthread_mutex_unlock(lock);
+#else
+	#error not implemented on this platform
+#endif
+}
+
 /* -----  time ----- */
 int64 time_get()
 {
diff --git a/src/engine/system.h b/src/engine/system.h
index 692aae06..fe866cdc 100644
--- a/src/engine/system.h
+++ b/src/engine/system.h
@@ -297,10 +297,8 @@ typedef struct LOCKINTERNAL *LOCK;
 LOCK lock_create();
 void lock_destroy(LOCK lock);
 
-void lock_shared(LOCK lock);
-void lock_exclusive(LOCK lock);
-int lock_try_shared(LOCK lock);
-int lock_try_exclusive(LOCK lock);
+int lock_try(LOCK lock);
+void lock_wait(LOCK lock);
 void lock_release(LOCK lock);
 
 /**** Group: Timer ****/