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
This commit is contained in:
Fabian Greffrath 2022-11-14 20:21:55 +01:00 committed by GitHub
parent 49f2ec0ac4
commit e1274e6481
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 64 additions and 15 deletions

View File

@ -2356,6 +2356,10 @@ void G_Ticker(void)
gamestate == GS_INTERMISSION ? WI_Ticker() : gamestate == GS_INTERMISSION ? WI_Ticker() :
gamestate == GS_FINALE ? F_Ticker() : gamestate == GS_FINALE ? F_Ticker() :
gamestate == GS_DEMOSCREEN ? D_PageTicker() : (void) 0; gamestate == GS_DEMOSCREEN ? D_PageTicker() : (void) 0;
// [FG] stop looping sounds if P_Ticker() didn't run through
if (leveltime == oldleveltime)
S_StopLoopSounds();
} }
// //

View File

@ -519,7 +519,7 @@ int I_GetSfxLumpNum(sfxinfo_t *sfx)
// active sounds, which is maintained as a given number // active sounds, which is maintained as a given number
// of internal channels. Returns a handle. // 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; static unsigned int id = 0;
int handle; 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)) if(addsfx(sound, handle, pitch))
{ {
channelinfo[handle].idnum = id++; // give the sound a unique id 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); updateSoundParams(handle, vol, sep, pitch);
} }
else else

View File

@ -75,7 +75,7 @@ int I_GetSfxLumpNum(sfxinfo_t *sfxinfo);
// Starts a sound in a particular sound channel. // Starts a sound in a particular sound channel.
int I_StartSound(sfxinfo_t *sound, int cnum, int vol, int sep, int pitch, int I_StartSound(sfxinfo_t *sound, int cnum, int vol, int sep, int pitch,
int pri); int pri, boolean loop);
// Stops a sound channel. // Stops a sound channel.
void I_StopSound(int handle); void I_StopSound(int handle);

View File

@ -84,7 +84,7 @@ void T_MoveCeiling (ceiling_t* ceiling)
case genSilentCrusher: case genSilentCrusher:
break; break;
default: default:
S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov); S_LoopSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
break; break;
} }
} }
@ -148,7 +148,7 @@ void T_MoveCeiling (ceiling_t* ceiling)
case genSilentCrusher: case genSilentCrusher:
break; break;
default: default:
S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov); S_LoopSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
} }
} }

View File

@ -254,7 +254,7 @@ void T_MoveFloor(floormove_t* floor)
); );
if (!(leveltime&7)) // make the floormove sound 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 if (res == pastdest) // if destination height is reached
{ {
@ -401,7 +401,7 @@ void T_MoveElevator(elevator_t* elevator)
// make floor move sound // make floor move sound
if (!(leveltime&7)) 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 if (res == pastdest) // if destination height acheived
{ {

View File

@ -62,7 +62,7 @@ void T_PlatRaise(plat_t* plat)
|| plat->type == raiseToNearestAndChange) || plat->type == raiseToNearestAndChange)
{ {
if (!(leveltime&7)) 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 // 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 //jff 3/14/98 clear old field as well
sec->oldspecial = 0; sec->oldspecial = 0;
S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov); S_LoopSound((mobj_t *)&sec->soundorg,sfx_stnmov);
break; break;
case raiseAndChange: case raiseAndChange:
@ -250,7 +250,7 @@ int EV_DoPlat
plat->wait = 0; plat->wait = 0;
plat->status = up; plat->status = up;
S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov); S_LoopSound((mobj_t *)&sec->soundorg,sfx_stnmov);
break; break;
case downWaitUpStay: case downWaitUpStay:

View File

@ -67,6 +67,7 @@ typedef struct channel_s
int priority; // current priority value int priority; // current priority value
int singularity; // haleyjd 09/27/06: stored singularity value int singularity; // haleyjd 09/27/06: stored singularity value
int idnum; // haleyjd 09/30/06: unique id num for sound event int idnum; // haleyjd 09/30/06: unique id num for sound event
boolean loop;
} channel_t; } channel_t;
// the set of channels available // the set of channels available
@ -74,6 +75,8 @@ static channel_t channels[MAX_CHANNELS];
// [FG] removed map objects may finish their sounds // [FG] removed map objects may finish their sounds
static degenmobj_t sobjs[MAX_CHANNELS]; static degenmobj_t sobjs[MAX_CHANNELS];
static int looping_sounds;
// These are not used, but should be (menu). // These are not used, but should be (menu).
// Maximum volume of a sound effect. // Maximum volume of a sound effect.
// Internal default is max out of 0-15. // Internal default is max out of 0-15.
@ -117,12 +120,34 @@ static void S_StopChannel(int cnum)
{ {
if(I_SoundIsPlaying(channels[cnum].handle)) if(I_SoundIsPlaying(channels[cnum].handle))
I_StopSound(channels[cnum].handle); // stop the sound playing I_StopSound(channels[cnum].handle); // stop the sound playing
if (channels[cnum].loop)
looping_sounds--;
// haleyjd 09/27/06: clear the entire channel // haleyjd 09/27/06: clear the entire channel
memset(&channels[cnum], 0, sizeof(channel_t)); 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 // 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! // Note that a higher priority number means lower priority!
// //
static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo, 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 // channel number to use
int cnum; int cnum;
@ -231,6 +256,10 @@ static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo,
channels[cnum].singularity == singularity && channels[cnum].singularity == singularity &&
channels[cnum].origin == origin) 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); S_StopChannel(cnum);
break; break;
} }
@ -298,7 +327,7 @@ static boolean BlockSFX(sfxinfo_t *sfx)
return sfx->parallel_count > parallel_sfx_limit; 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 sep, pitch, o_priority, priority, singularity, cnum, handle;
int volumeScale = 127; int volumeScale = 127;
@ -383,7 +412,7 @@ void S_StartSound(const mobj_t *origin, int sfx_id)
} }
// try to find a channel // 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; return;
#ifdef RANGECHECK #ifdef RANGECHECK
@ -398,7 +427,7 @@ void S_StartSound(const mobj_t *origin, int sfx_id)
sfx = sfx->link; // sf: skip thru link(s) sfx = sfx->link; // sf: skip thru link(s)
// Assigns the handle to one of the channels in the mix/output buffer. // 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 // haleyjd: check to see if the sound was started
if(handle >= 0) 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].priority = priority; // scaled priority
channels[cnum].singularity = singularity; channels[cnum].singularity = singularity;
channels[cnum].idnum = I_SoundID(handle); // unique instance id 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 else // haleyjd: the sound didn't start, so clear the channel info
memset(&channels[cnum], 0, sizeof(channel_t)); 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 // S_StopSound
// //
@ -760,6 +802,7 @@ void S_Start(void)
if(channels[cnum].sfxinfo) if(channels[cnum].sfxinfo)
S_StopChannel(cnum); S_StopChannel(cnum);
} }
looping_sounds = 0;
} }
// start new music for the level // start new music for the level

View File

@ -50,9 +50,11 @@ void S_Start(void);
// using <sound_id> from sounds.h // using <sound_id> from sounds.h
// //
void S_StartSound(const mobj_t *origin, int sound_id); 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 <origin> // Stop sound for thing at <origin>
void S_StopSound(const mobj_t *origin); void S_StopSound(const mobj_t *origin);
void S_StopLoopSounds(void);
// [FG] play sounds in full length // [FG] play sounds in full length
extern boolean full_sounds; extern boolean full_sounds;