summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2022-12-12 14:27:21 -0800
committerVito Caputo <vcaputo@pengaru.com>2022-12-12 14:27:21 -0800
commita84eb6daae60abe2546312d91bf9bb94dd75a4b7 (patch)
treefdace84c4eb0738cc187972c04fb98876434e652 /src
parent5ec2d49bdca3531f4baebc9a69b30ec4728b02a2 (diff)
sfx: introduce concept of voices and concurrency limits
This is a first stab at reeling in the cacophony of noise that develops in the late stages of sars.
Diffstat (limited to 'src')
-rw-r--r--src/game.c36
-rw-r--r--src/sfx.c73
-rw-r--r--src/sfx.h37
3 files changed, 91 insertions, 55 deletions
diff --git a/src/game.c b/src/game.c
index adc8932..9c9943a 100644
--- a/src/game.c
+++ b/src/game.c
@@ -403,7 +403,7 @@ static void infect_entity(game_t *game, entity_t *entity, const char *name)
{
/* convert entity into inanimate virus (off the viruses array) */
(void) virus_node_new(&(stage_conf_t){ .stage = entity->any.node, .replace = 1, .name = name, .active = 1, .alpha = 1.f }, &game->sars->projection_x, &entity->any.model_x);
- sfx_play(sfx.baby_infected);
+ sfx_play(&sfx.baby_infected);
entity->any.type = ENTITY_TYPE_VIRUS;
entity->virus.corpse = 1;
@@ -416,7 +416,7 @@ static void infect_entity(game_t *game, entity_t *entity, const char *name)
static void hat_baby(game_t *game, baby_t *baby, mask_t *mask)
{
(void) baby_hatted_node_new(&(stage_conf_t){ .stage = baby->entity.node, .replace = 1, .name = "baby-hatted", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &baby->entity.model_x);
- sfx_play(sfx.baby_hatted);
+ sfx_play(&sfx.baby_hatted);
stage_set_active(mask->entity.node, 0);
}
@@ -428,7 +428,7 @@ static void maga_adult(game_t *game, adult_t *adult, maga_t *maga)
adult->maga = 1;
adult->masked = 0;
- sfx_play(sfx.adult_maga);
+ sfx_play(&sfx.adult_maga);
stage_set_active(maga->entity.node, 0);
}
@@ -438,13 +438,13 @@ static void mask_adult(game_t *game, adult_t *adult, mask_t *mask)
if (adult->maga) { /* MAGA discards masks */
stage_set_active(mask->entity.node, 0);
- return sfx_play(sfx.adult_maga);
+ return sfx_play(&sfx.adult_maga);
}
(void) adult_masked_node_new(&(stage_conf_t){ .stage = adult->entity.node, .replace = 1, .name = "adult-masked", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &adult->entity.model_x);
adult->masked += GAME_MASK_PROTECTION;
- sfx_play(sfx.adult_mine);
+ sfx_play(&sfx.adult_mine);
stage_set_active(mask->entity.node, 0);
}
@@ -472,7 +472,7 @@ static void more_teepee(game_t *game, teepee_t *teepee)
if (game->adult->holding) {
/* disallow picking up teepee if holding something, flash what's held and the teepee we missed */
if (flash_entity(game, &teepee->entity, 5))
- sfx_play(sfx.adult_armsfull);
+ sfx_play(&sfx.adult_armsfull);
(void) flash_entity(game, &game->adult->holding->any, 5);
return;
@@ -507,7 +507,7 @@ static void more_teepee(game_t *game, teepee_t *teepee)
}
(*teepee->bonus_release) = BONUS_NODE_RELEASE_MS;
(*teepee->bonus_release_position) = teepee->entity.position;
- sfx_play(sfx.adult_mine);
+ sfx_play(&sfx.adult_mine);
stage_set_active(teepee->entity.node, 0);
}
@@ -734,9 +734,9 @@ static ix2_search_status_t virus_search(void *cb_context, ix2_object_t *ix2_obje
if (!--entity->adult.masked) {
(void) adult_node_new(&(stage_conf_t){ .stage = search->game->adult->entity.node, .replace = 1, .name = "adult-unmasked", .active = 1, .alpha = 1.f }, &search->game->sars->projection_x, &search->game->adult->entity.model_x);
- sfx_play(sfx.adult_unmasked);
+ sfx_play(&sfx.adult_unmasked);
} else
- sfx_play(sfx.adult_maskhit);
+ sfx_play(&sfx.adult_maskhit);
(void) flash_entity(search->game, &entity->any, 4);
@@ -744,7 +744,7 @@ static ix2_search_status_t virus_search(void *cb_context, ix2_object_t *ix2_obje
}
(void) virus_node_new(&(stage_conf_t){ .stage = entity->any.node, .replace = 1, .name = "adult-virus", .active = 1, .alpha = 1.f }, &search->game->sars->projection_x, &entity->any.model_x);
- sfx_play(sfx.adult_infected);
+ sfx_play(&sfx.adult_infected);
search->game->state = GAME_STATE_OVER;
return IX2_SEARCH_STOP_HIT;
@@ -934,7 +934,7 @@ static ix2_search_status_t adult_search(void *cb_context, ix2_object_t *ix2_obje
switch (entity->any.type) {
case ENTITY_TYPE_BABY:
if (!game->adult->holding) {
- sfx_play(sfx.baby_held);
+ sfx_play(&sfx.baby_held);
game->adult->holding = entity;
}
@@ -954,9 +954,9 @@ static ix2_search_status_t adult_search(void *cb_context, ix2_object_t *ix2_obje
if (game->adult->masked) {
if (!--game->adult->masked) {
(void) adult_node_new(&(stage_conf_t){ .stage = game->adult->entity.node, .replace = 1, .name = "adult-unmasked", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &game->adult->entity.model_x);
- sfx_play(sfx.adult_unmasked);
+ sfx_play(&sfx.adult_unmasked);
} else
- sfx_play(sfx.adult_maskhit);
+ sfx_play(&sfx.adult_maskhit);
(void) flash_entity(game, &game->adult->entity, 4);
reset_virus(&entity->virus);
@@ -965,11 +965,11 @@ static ix2_search_status_t adult_search(void *cb_context, ix2_object_t *ix2_obje
/* convert adult into inanimate virus (off the viruses array) */
(void) virus_node_new(&(stage_conf_t){ .stage = game->adult->entity.node, .replace = 1, .name = "adult-virus", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &game->adult->entity.model_x);
- sfx_play(sfx.adult_infected);
+ sfx_play(&sfx.adult_infected);
if (game->adult->holding) {
(void) virus_node_new(&(stage_conf_t){ .stage = game->adult->holding->any.node, .replace = 1, .name = "baby-virus", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &game->adult->holding->any.model_x);
- sfx_play(sfx.baby_infected);
+ sfx_play(&sfx.baby_infected);
}
game->state = GAME_STATE_OVER;
return IX2_SEARCH_STOP_HIT;
@@ -979,12 +979,12 @@ static ix2_search_status_t adult_search(void *cb_context, ix2_object_t *ix2_obje
return IX2_SEARCH_MORE_MISS;
game->adult->captivated = 1;
- sfx_play(sfx.adult_captivated);
+ sfx_play(&sfx.adult_captivated);
/* shifted because rand() tends to have more activity in the upper bits,
* but this could be more careful about avoiding repetition by randomizing
* a 0-9 list every time it stepped through said list. TODO
*/
- sfx_play(sfx.tv_talk[(rand() >> 8) % NELEMS(sfx.tv_talk)]);
+ sfx_play(&sfx.tv_talk[(rand() >> 8) % NELEMS(sfx.tv_talk)]);
return IX2_SEARCH_STOP_HIT;
@@ -1051,7 +1051,7 @@ static void game_move_adult(game_t *game, v2f_t *dir)
game->adult->entity.position.y < -1.05f) {
/* rescued baby */
- sfx_play(sfx.baby_rescued);
+ sfx_play(&sfx.baby_rescued);
/* make the rescued baby available for respawn reuse */
game->adult->holding->any.flashes_remaining = 0;
diff --git a/src/sfx.c b/src/sfx.c
index c542d74..04b0fbc 100644
--- a/src/sfx.c
+++ b/src/sfx.c
@@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <assert.h>
#include <SDL_mixer.h>
#include "sfx.h"
@@ -21,34 +22,58 @@
sfx_t sfx;
+static void sfx_load(sfx_voice_t voice, const char *path, sfx_sound_t *res_sound)
+{
+ assert(path);
+ assert(res_sound);
+
+ (*res_sound).voice = voice;
+ (*res_sound).chunk = Mix_LoadWAV(path);
+}
+
+
void sfx_init(void)
{
- sfx.baby_infected = Mix_LoadWAV("assets/baby-infected.wav");
- sfx.baby_hatted = Mix_LoadWAV("assets/baby-hatted.wav");
- sfx.baby_held = Mix_LoadWAV("assets/baby-held.wav");
- sfx.baby_rescued = Mix_LoadWAV("assets/baby-rescued.wav");
- sfx.adult_armsfull = Mix_LoadWAV("assets/adult-armsfull.wav");
- sfx.adult_infected = Mix_LoadWAV("assets/adult-infected.wav");
- sfx.adult_captivated = Mix_LoadWAV("assets/adult-captivated.wav");
- sfx.adult_maga = Mix_LoadWAV("assets/adult-maga.wav");
- sfx.adult_maskhit = Mix_LoadWAV("assets/adult-maskhit.wav");
- sfx.adult_mine = Mix_LoadWAV("assets/adult-mine.wav");
- sfx.adult_unmasked = Mix_LoadWAV("assets/adult-unmasked.wav");
- sfx.tv_talk[0] = Mix_LoadWAV("assets/talk/0.wav");
- sfx.tv_talk[1] = Mix_LoadWAV("assets/talk/1.wav");
- sfx.tv_talk[2] = Mix_LoadWAV("assets/talk/2.wav");
- sfx.tv_talk[3] = Mix_LoadWAV("assets/talk/3.wav");
- sfx.tv_talk[4] = Mix_LoadWAV("assets/talk/4.wav");
- sfx.tv_talk[5] = Mix_LoadWAV("assets/talk/5.wav");
- sfx.tv_talk[6] = Mix_LoadWAV("assets/talk/6.wav");
- sfx.tv_talk[7] = Mix_LoadWAV("assets/talk/7.wav");
- sfx.tv_talk[8] = Mix_LoadWAV("assets/talk/8.wav");
- sfx.tv_talk[9] = Mix_LoadWAV("assets/talk/9.wav");
+ sfx_load(SFX_VOICE_BABY, "assets/baby-infected.wav", &sfx.baby_infected);
+ sfx_load(SFX_VOICE_BABY, "assets/baby-hatted.wav", &sfx.baby_hatted);
+ sfx_load(SFX_VOICE_BABY, "assets/baby-held.wav", &sfx.baby_held);
+ sfx_load(SFX_VOICE_BABY, "assets/baby-rescued.wav", &sfx.baby_rescued);
+ Mix_GroupChannels(0, 4, SFX_VOICE_BABY);
+
+ sfx_load(SFX_VOICE_ADULT, "assets/adult-armsfull.wav", &sfx.adult_armsfull);
+ sfx_load(SFX_VOICE_ADULT, "assets/adult-infected.wav", &sfx.adult_infected);
+ sfx_load(SFX_VOICE_ADULT, "assets/adult-captivated.wav", &sfx.adult_captivated);
+ sfx_load(SFX_VOICE_ADULT, "assets/adult-maga.wav", &sfx.adult_maga);
+ sfx_load(SFX_VOICE_ADULT, "assets/adult-maskhit.wav", &sfx.adult_maskhit);
+ sfx_load(SFX_VOICE_ADULT, "assets/adult-mine.wav", &sfx.adult_mine);
+ sfx_load(SFX_VOICE_ADULT, "assets/adult-unmasked.wav", &sfx.adult_unmasked);
+ Mix_GroupChannel(4, SFX_VOICE_ADULT);
+
+ sfx_load(SFX_VOICE_TV, "assets/talk/0.wav", &sfx.tv_talk[0]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/1.wav", &sfx.tv_talk[1]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/2.wav", &sfx.tv_talk[2]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/3.wav", &sfx.tv_talk[3]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/4.wav", &sfx.tv_talk[4]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/5.wav", &sfx.tv_talk[5]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/6.wav", &sfx.tv_talk[6]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/7.wav", &sfx.tv_talk[7]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/8.wav", &sfx.tv_talk[8]);
+ sfx_load(SFX_VOICE_TV, "assets/talk/9.wav", &sfx.tv_talk[9]);
+ Mix_GroupChannel(5, SFX_VOICE_TV);
}
-void sfx_play(Mix_Chunk *chunk)
+void sfx_play(sfx_sound_t *sound)
{
- if (chunk)
- Mix_PlayChannel(-1, chunk, 0);
+ assert(sound);
+
+ if (sound->chunk) {
+ int channel;
+
+ channel = Mix_GroupAvailable(sound->voice);
+ if (channel < 0)
+ channel = Mix_GroupOldest(sound->voice);
+
+ Mix_PlayChannel(channel, sound->chunk, 0);
+ }
}
diff --git a/src/sfx.h b/src/sfx.h
index 3b02621..a37b22c 100644
--- a/src/sfx.h
+++ b/src/sfx.h
@@ -19,24 +19,35 @@
#include <SDL_mixer.h>
+typedef enum sfx_voice_t {
+ SFX_VOICE_ADULT,
+ SFX_VOICE_TV,
+ SFX_VOICE_BABY,
+} sfx_voice_t;
+
+typedef struct sfx_sound_t {
+ sfx_voice_t voice;
+ Mix_Chunk *chunk;
+} sfx_sound_t;
+
typedef struct sfx_t {
- Mix_Chunk *baby_infected;
- Mix_Chunk *baby_hatted;
- Mix_Chunk *baby_held;
- Mix_Chunk *baby_rescued;
- Mix_Chunk *adult_armsfull;
- Mix_Chunk *adult_infected;
- Mix_Chunk *adult_captivated;
- Mix_Chunk *adult_maga;
- Mix_Chunk *adult_maskhit;
- Mix_Chunk *adult_mine;
- Mix_Chunk *adult_unmasked;
- Mix_Chunk *tv_talk[10];
+ sfx_sound_t baby_infected;
+ sfx_sound_t baby_hatted;
+ sfx_sound_t baby_held;
+ sfx_sound_t baby_rescued;
+ sfx_sound_t adult_armsfull;
+ sfx_sound_t adult_infected;
+ sfx_sound_t adult_captivated;
+ sfx_sound_t adult_maga;
+ sfx_sound_t adult_maskhit;
+ sfx_sound_t adult_mine;
+ sfx_sound_t adult_unmasked;
+ sfx_sound_t tv_talk[10];
} sfx_t;
extern sfx_t sfx;
void sfx_init(void);
-void sfx_play(Mix_Chunk *chunk);
+void sfx_play(sfx_sound_t *sound);
#endif
© All Rights Reserved