From e1274e6481a8763fee203f92f6297a70765d2a24 Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Mon, 14 Nov 2022 20:21:55 +0100 Subject: [PATCH] implement SDL-native sound looping for moving walls (#803) * implement SDL-native sound looping for moving walls * add an extra check that new and oldlooping sound are same * stop looping sounds during menus and pause * stop looping sounds on level exit * stop looping sounds if P_Ticker() didn't run through * do not iterate through sound channels more than necessary * correctly count looping sounds --- src/g_game.c | 4 ++++ src/i_sound.c | 4 ++-- src/i_sound.h | 2 +- src/p_ceilng.c | 4 ++-- src/p_floor.c | 4 ++-- src/p_plats.c | 6 +++--- src/s_sound.c | 53 +++++++++++++++++++++++++++++++++++++++++++++----- src/s_sound.h | 2 ++ 8 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index abb99a24..2f655221 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2356,6 +2356,10 @@ void G_Ticker(void) gamestate == GS_INTERMISSION ? WI_Ticker() : gamestate == GS_FINALE ? F_Ticker() : gamestate == GS_DEMOSCREEN ? D_PageTicker() : (void) 0; + + // [FG] stop looping sounds if P_Ticker() didn't run through + if (leveltime == oldleveltime) + S_StopLoopSounds(); } // diff --git a/src/i_sound.c b/src/i_sound.c index 144d66b4..240928f4 100644 --- a/src/i_sound.c +++ b/src/i_sound.c @@ -519,7 +519,7 @@ int I_GetSfxLumpNum(sfxinfo_t *sfx) // active sounds, which is maintained as a given number // of internal channels. Returns a handle. // -int I_StartSound(sfxinfo_t *sound, int cnum, int vol, int sep, int pitch, int pri) +int I_StartSound(sfxinfo_t *sound, int cnum, int vol, int sep, int pitch, int pri, boolean loop) { static unsigned int id = 0; int handle; @@ -549,7 +549,7 @@ int I_StartSound(sfxinfo_t *sound, int cnum, int vol, int sep, int pitch, int pr if(addsfx(sound, handle, pitch)) { channelinfo[handle].idnum = id++; // give the sound a unique id - Mix_PlayChannelTimed(handle, &channelinfo[handle].chunk, 0, -1); + Mix_PlayChannelTimed(handle, &channelinfo[handle].chunk, loop ? -1 : 0, -1); updateSoundParams(handle, vol, sep, pitch); } else diff --git a/src/i_sound.h b/src/i_sound.h index 59216c0f..5c5e5bc6 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -75,7 +75,7 @@ int I_GetSfxLumpNum(sfxinfo_t *sfxinfo); // Starts a sound in a particular sound channel. int I_StartSound(sfxinfo_t *sound, int cnum, int vol, int sep, int pitch, - int pri); + int pri, boolean loop); // Stops a sound channel. void I_StopSound(int handle); diff --git a/src/p_ceilng.c b/src/p_ceilng.c index b8a975b1..59f433f5 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -84,7 +84,7 @@ void T_MoveCeiling (ceiling_t* ceiling) case genSilentCrusher: break; default: - S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov); + S_LoopSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov); break; } } @@ -148,7 +148,7 @@ void T_MoveCeiling (ceiling_t* ceiling) case genSilentCrusher: break; default: - S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov); + S_LoopSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov); } } diff --git a/src/p_floor.c b/src/p_floor.c index 0f59dfa1..28650b1b 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -254,7 +254,7 @@ void T_MoveFloor(floormove_t* floor) ); if (!(leveltime&7)) // make the floormove sound - S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_stnmov); + S_LoopSound((mobj_t *)&floor->sector->soundorg, sfx_stnmov); if (res == pastdest) // if destination height is reached { @@ -401,7 +401,7 @@ void T_MoveElevator(elevator_t* elevator) // make floor move sound if (!(leveltime&7)) - S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_stnmov); + S_LoopSound((mobj_t *)&elevator->sector->soundorg, sfx_stnmov); if (res == pastdest) // if destination height acheived { diff --git a/src/p_plats.c b/src/p_plats.c index 72a39c65..23bba963 100644 --- a/src/p_plats.c +++ b/src/p_plats.c @@ -62,7 +62,7 @@ void T_PlatRaise(plat_t* plat) || plat->type == raiseToNearestAndChange) { if (!(leveltime&7)) - S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_stnmov); + S_LoopSound((mobj_t *)&plat->sector->soundorg, sfx_stnmov); } // if encountered an obstacle, and not a crush type, reverse direction @@ -240,7 +240,7 @@ int EV_DoPlat //jff 3/14/98 clear old field as well sec->oldspecial = 0; - S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov); + S_LoopSound((mobj_t *)&sec->soundorg,sfx_stnmov); break; case raiseAndChange: @@ -250,7 +250,7 @@ int EV_DoPlat plat->wait = 0; plat->status = up; - S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov); + S_LoopSound((mobj_t *)&sec->soundorg,sfx_stnmov); break; case downWaitUpStay: diff --git a/src/s_sound.c b/src/s_sound.c index 2a8a2cb8..43dd52b2 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -67,6 +67,7 @@ typedef struct channel_s int priority; // current priority value int singularity; // haleyjd 09/27/06: stored singularity value int idnum; // haleyjd 09/30/06: unique id num for sound event + boolean loop; } channel_t; // the set of channels available @@ -74,6 +75,8 @@ static channel_t channels[MAX_CHANNELS]; // [FG] removed map objects may finish their sounds static degenmobj_t sobjs[MAX_CHANNELS]; +static int looping_sounds; + // These are not used, but should be (menu). // Maximum volume of a sound effect. // Internal default is max out of 0-15. @@ -117,12 +120,34 @@ static void S_StopChannel(int cnum) { if(I_SoundIsPlaying(channels[cnum].handle)) I_StopSound(channels[cnum].handle); // stop the sound playing - + + if (channels[cnum].loop) + looping_sounds--; + // haleyjd 09/27/06: clear the entire channel memset(&channels[cnum], 0, sizeof(channel_t)); } } +void S_StopLoopSounds (void) +{ + int cnum; + + if (looping_sounds == 0) + return; + + if (!nosfxparm) + { + for (cnum = 0; cnum < numChannels; ++cnum) + { + if (channels[cnum].sfxinfo && channels[cnum].loop) + S_StopChannel(cnum); + } + } + + looping_sounds = 0; +} + // // S_AdjustSoundParams // @@ -211,7 +236,7 @@ static int S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, // Note that a higher priority number means lower priority! // static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo, - int priority, int singularity) + int priority, int singularity, boolean loop) { // channel number to use int cnum; @@ -231,6 +256,10 @@ static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo, channels[cnum].singularity == singularity && channels[cnum].origin == origin) { + // [FG] looping sounds don't interrupt each other + if (channels[cnum].sfxinfo == sfxinfo && channels[cnum].loop && loop) + return -1; + S_StopChannel(cnum); break; } @@ -298,7 +327,7 @@ static boolean BlockSFX(sfxinfo_t *sfx) return sfx->parallel_count > parallel_sfx_limit; } -void S_StartSound(const mobj_t *origin, int sfx_id) +static void S_StartSoundEx(const mobj_t *origin, int sfx_id, boolean loop) { int sep, pitch, o_priority, priority, singularity, cnum, handle; int volumeScale = 127; @@ -383,7 +412,7 @@ void S_StartSound(const mobj_t *origin, int sfx_id) } // try to find a channel - if((cnum = S_getChannel(origin, sfx, priority, singularity)) < 0) + if((cnum = S_getChannel(origin, sfx, priority, singularity, loop)) < 0) return; #ifdef RANGECHECK @@ -398,7 +427,7 @@ void S_StartSound(const mobj_t *origin, int sfx_id) sfx = sfx->link; // sf: skip thru link(s) // Assigns the handle to one of the channels in the mix/output buffer. - handle = I_StartSound(sfx, cnum, volume, sep, pitch, priority); + handle = I_StartSound(sfx, cnum, volume, sep, pitch, priority, loop); // haleyjd: check to see if the sound was started if(handle >= 0) @@ -414,12 +443,25 @@ void S_StartSound(const mobj_t *origin, int sfx_id) channels[cnum].priority = priority; // scaled priority channels[cnum].singularity = singularity; channels[cnum].idnum = I_SoundID(handle); // unique instance id + channels[cnum].loop = loop; + if (loop) + looping_sounds++; } else // haleyjd: the sound didn't start, so clear the channel info memset(&channels[cnum], 0, sizeof(channel_t)); } +void S_StartSound(const mobj_t *origin, int sfx_id) +{ + S_StartSoundEx(origin, sfx_id, false); +} + +void S_LoopSound(const mobj_t *origin, int sfx_id) +{ + S_StartSoundEx(origin, sfx_id, true); +} + // // S_StopSound // @@ -760,6 +802,7 @@ void S_Start(void) if(channels[cnum].sfxinfo) S_StopChannel(cnum); } + looping_sounds = 0; } // start new music for the level diff --git a/src/s_sound.h b/src/s_sound.h index 9634d940..c5ec226c 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -50,9 +50,11 @@ void S_Start(void); // using from sounds.h // void S_StartSound(const mobj_t *origin, int sound_id); +void S_LoopSound(const mobj_t *origin, int sound_id); // Stop sound for thing at void S_StopSound(const mobj_t *origin); +void S_StopLoopSounds(void); // [FG] play sounds in full length extern boolean full_sounds;