diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2022-12-12 14:27:21 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2022-12-12 14:27:21 -0800 |
commit | a84eb6daae60abe2546312d91bf9bb94dd75a4b7 (patch) | |
tree | fdace84c4eb0738cc187972c04fb98876434e652 /src | |
parent | 5ec2d49bdca3531f4baebc9a69b30ec4728b02a2 (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.c | 36 | ||||
-rw-r--r-- | src/sfx.c | 73 | ||||
-rw-r--r-- | src/sfx.h | 37 |
3 files changed, 91 insertions, 55 deletions
@@ -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; @@ -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); + } } @@ -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 |