From 21df126c88230f11749bc9241ed51a26d31f0810 Mon Sep 17 00:00:00 2001 From: Joel de Vahl Date: Tue, 2 Oct 2007 16:19:25 +0000 Subject: sound fixes and initial lock implementation --- src/engine/client/snd.c | 41 ++++++++++++++++++++++++++--- src/engine/interface.h | 3 ++- src/engine/system.c | 57 +++++++++++++++++++++++++++++++++++++++++ src/engine/system.h | 6 ++--- src/game/client/game_client.cpp | 1 + 5 files changed, 99 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 #include +#include "detect.h" #include "system.h" #if defined(CONF_FAMILY_UNIX) @@ -18,6 +19,7 @@ #include #include #include + #include #include #include @@ -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 ****/ diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp index 644d781f..705db9f1 100644 --- a/src/game/client/game_client.cpp +++ b/src/game/client/game_client.cpp @@ -454,6 +454,7 @@ extern "C" void modc_init() // TODO: should be removed music_menu = snd_load_wav("data/audio/music_menu.wav"); + snd_set_listener_pos(0.0f, 0.0f); float total = data->num_sounds+data->num_images; float current = 0; -- cgit 1.4.1