From 5bf8a0b6897054af6a3fe0aef1c5ffade60499c8 Mon Sep 17 00:00:00 2001 From: Allanis Date: Wed, 2 Oct 2013 01:17:01 +0100 Subject: [PATCH] [Add] Sound should be fully positional now. --- src/sound.c | 36 +++++++++++++++++++++++++++--------- src/weapon.c | 24 +++++++++++++++++------- 2 files changed, 44 insertions(+), 16 deletions(-) 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;