mirror of
https://github.com/fabiangreffrath/woof.git
synced 2025-09-22 11:22:18 -04:00
limit the number of identical sounds playing at once, based on priority ordering (#807)
* Revert "add parallel same-sound limit from DSDA-Doom (#796)" This reverts commit d7849c8fa7ba4b2c92a1784b92127df267f4e8db. * first shot at sorting sounds by priority * fix build * our S_AdjustSoundParams() already mangles volume into priority * add/fix comments * newer same-priority sounds are supposed to stop older ones * use qsort() instead of undocumented (whoops\!) SDL_qsort() * back to newer same-priority sounds let older ones finish * keep the singularity concept alive * get rid of the lowestpriority concept, we already ordered channels by priority * keep the "snd_channels = 16" default * Revert "keep the "snd_channels = 16" default" This reverts commit 79fc9b3332304aa7cd9f7ac687c46089f1d40918. * Update s_sound.c * maintain a stable sort (newer sounds have precedence) * fix typo/thinko * fix sort order * fix comparison function return value * Update s_sound.c * last nit-pick (hopefully!)
This commit is contained in:
parent
9bcf2be8a0
commit
f73f189abb
@ -3710,6 +3710,7 @@ enum {
|
||||
// [FG] uncapped rendering frame rate
|
||||
general_uncapped,
|
||||
general_vsync,
|
||||
general_stub1,
|
||||
general_trans,
|
||||
general_transpct,
|
||||
general_gamma,
|
||||
@ -3717,7 +3718,6 @@ enum {
|
||||
|
||||
general_title2,
|
||||
general_sndchan,
|
||||
general_parallelsfx,
|
||||
general_pitch,
|
||||
// [FG] play sounds in full length
|
||||
general_fullsnd,
|
||||
@ -3789,6 +3789,8 @@ setup_menu_t gen_settings1[] = { // General Settings screen1
|
||||
{"Vertical Sync", S_YESNO, m_null, M_X,
|
||||
M_Y+ general_vsync*M_SPC, {"use_vsync"}, 0, I_ResetScreen},
|
||||
|
||||
{"", S_SKIP, m_null, M_X, M_Y + general_stub1*M_SPC},
|
||||
|
||||
{"Enable predefined translucency", S_YESNO, m_null, M_X,
|
||||
M_Y+ general_trans*M_SPC, {"translucency"}, 0, M_Trans},
|
||||
|
||||
@ -3806,10 +3808,6 @@ setup_menu_t gen_settings1[] = { // General Settings screen1
|
||||
{"Number of Sound Channels", S_NUM|S_PRGWARN, m_null, M_X,
|
||||
M_Y + general_sndchan*M_SPC, {"snd_channels"}},
|
||||
|
||||
// [FG] parallel same-sound limit from DSDA-Doom
|
||||
{"Parallel Same-Sound Limit", S_YESNO, m_null, M_X,
|
||||
M_Y + general_parallelsfx*M_SPC, {"parallel_sfx"}},
|
||||
|
||||
{"Enable v1.1 Pitch Effects", S_YESNO, m_null, M_X,
|
||||
M_Y + general_pitch*M_SPC, {"pitched_sounds"}},
|
||||
|
||||
|
24
src/m_misc.c
24
src/m_misc.c
@ -1493,7 +1493,7 @@ default_t defaults[] = {
|
||||
{ // killough
|
||||
"snd_channels",
|
||||
(config_t *) &default_numChannels, NULL,
|
||||
{16}, {1, MAX_CHANNELS}, 0, ss_gen, wad_no,
|
||||
{MAX_CHANNELS}, {1, MAX_CHANNELS}, 0, ss_gen, wad_no,
|
||||
"number of sound effects handled simultaneously"
|
||||
},
|
||||
|
||||
@ -2253,28 +2253,6 @@ default_t defaults[] = {
|
||||
"1 to play sounds in full length"
|
||||
},
|
||||
|
||||
// [FG] parallel same-sound limit
|
||||
{
|
||||
"parallel_sfx",
|
||||
(config_t *) ¶llel_sfx, NULL,
|
||||
{0}, {0, 1}, number, ss_gen, wad_no,
|
||||
"1 to enable parallel same-sound limit"
|
||||
},
|
||||
|
||||
{
|
||||
"parallel_sfx_limit",
|
||||
(config_t *) ¶llel_sfx_limit, NULL,
|
||||
{2}, {0, 32}, number, ss_none, wad_no,
|
||||
"parallel same-sound limit"
|
||||
},
|
||||
|
||||
{
|
||||
"parallel_sfx_window",
|
||||
(config_t *) ¶llel_sfx_window, NULL,
|
||||
{4}, {1, 32}, number, ss_none, wad_no,
|
||||
"parallel same-sound limit window"
|
||||
},
|
||||
|
||||
// [FG] music backend
|
||||
{
|
||||
"midi_player",
|
||||
|
141
src/s_sound.c
141
src/s_sound.c
@ -29,6 +29,8 @@
|
||||
// killough 3/7/98: modified to allow arbitrary listeners in spy mode
|
||||
// killough 5/2/98: reindented, removed useless code, beautified
|
||||
|
||||
#include <stdlib.h> // [FG] qsort()
|
||||
|
||||
#include "doomstat.h"
|
||||
#include "s_sound.h"
|
||||
#include "s_musinfo.h" // [crispy] struct musinfo
|
||||
@ -228,6 +230,28 @@ static int S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source,
|
||||
return *vol > 0;
|
||||
}
|
||||
|
||||
//
|
||||
// S_CompareChannels
|
||||
//
|
||||
// A comparison function that determines which sound channel should
|
||||
// take priority. Can be used with std::sort.
|
||||
//
|
||||
// Returns true if the first channel should precede the second.
|
||||
//
|
||||
static int S_CompareChannels(const void *arg_a, const void *arg_b)
|
||||
{
|
||||
const channel_t *a = (const channel_t *) arg_a;
|
||||
const channel_t *b = (const channel_t *) arg_b;
|
||||
|
||||
// Note that a higher priority number means lower priority!
|
||||
const int ret = a->priority - b->priority;
|
||||
|
||||
return ret ? ret : (b->idnum - a->idnum);
|
||||
}
|
||||
|
||||
// How many instances of the same sfx can be playing concurrently
|
||||
static const unsigned int max_instances = 3;
|
||||
|
||||
//
|
||||
// S_getChannel :
|
||||
//
|
||||
@ -240,8 +264,10 @@ static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo,
|
||||
{
|
||||
// channel number to use
|
||||
int cnum;
|
||||
int lowestpriority = -1; // haleyjd
|
||||
int lpcnum = -1;
|
||||
int instances = 0;
|
||||
|
||||
// Sort the sound channels by descending priority levels
|
||||
qsort(channels, numChannels, sizeof(channel_t), S_CompareChannels);
|
||||
|
||||
// haleyjd 09/28/06: moved this here. If we kill a sound already
|
||||
// being played, we can use that channel. There is no need to
|
||||
@ -250,82 +276,65 @@ static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo,
|
||||
// kill old sound
|
||||
// killough 12/98: replace is_pickup hack with singularity flag
|
||||
// haleyjd 06/12/08: only if subchannel matches
|
||||
for(cnum = 0; cnum < numChannels; ++cnum)
|
||||
for (cnum = 0; cnum < numChannels; ++cnum)
|
||||
{
|
||||
if(channels[cnum].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;
|
||||
if (!channels[cnum].sfxinfo)
|
||||
continue;
|
||||
|
||||
S_StopChannel(cnum);
|
||||
break;
|
||||
}
|
||||
// [FG] looping sounds don't interrupt each other
|
||||
if (channels[cnum].sfxinfo == sfxinfo &&
|
||||
channels[cnum].origin == origin &&
|
||||
channels[cnum].loop && loop)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (channels[cnum].singularity == singularity &&
|
||||
channels[cnum].origin == origin)
|
||||
{
|
||||
S_StopChannel(cnum);
|
||||
return cnum;
|
||||
}
|
||||
|
||||
// Limit the number of identical sounds playing at once
|
||||
if (channels[cnum].sfxinfo == sfxinfo)
|
||||
{
|
||||
if (++instances >= max_instances)
|
||||
{
|
||||
if (priority < channels[cnum].priority)
|
||||
{
|
||||
S_StopChannel(cnum);
|
||||
return cnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find an open channel
|
||||
if(cnum == numChannels)
|
||||
for (cnum = 0; cnum < numChannels; ++cnum)
|
||||
{
|
||||
// haleyjd 09/28/06: it isn't necessary to look for playing sounds in
|
||||
// the same singularity class again, as we just did that above. Here
|
||||
// we are looking for an open channel. We will also keep track of the
|
||||
// channel found with the lowest sound priority while doing this.
|
||||
for(cnum = 0; cnum < numChannels && channels[cnum].sfxinfo; ++cnum)
|
||||
{
|
||||
if(channels[cnum].priority > lowestpriority)
|
||||
{
|
||||
lowestpriority = channels[cnum].priority;
|
||||
lpcnum = cnum;
|
||||
}
|
||||
}
|
||||
if (!channels[cnum].sfxinfo)
|
||||
return cnum;
|
||||
}
|
||||
|
||||
// None available?
|
||||
if(cnum == numChannels)
|
||||
for (cnum = numChannels - 1; cnum >= 0; --cnum)
|
||||
{
|
||||
// Look for lower priority
|
||||
// haleyjd: we have stored the channel found with the lowest priority
|
||||
// in the loop above
|
||||
if(priority > lowestpriority)
|
||||
return -1; // No lower priority. Sorry, Charlie.
|
||||
else
|
||||
{
|
||||
S_StopChannel(lpcnum); // Otherwise, kick out lowest priority.
|
||||
cnum = lpcnum;
|
||||
}
|
||||
// Look for lower priority
|
||||
if (priority < channels[cnum].priority)
|
||||
{
|
||||
S_StopChannel(cnum);
|
||||
return cnum;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if(cnum >= numChannels)
|
||||
I_Error("S_getChannel: handle %d out of range\n", cnum);
|
||||
#endif
|
||||
|
||||
return cnum;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// [FG] parallel same-sound limit from DSDA-Doom
|
||||
|
||||
boolean parallel_sfx;
|
||||
int parallel_sfx_limit;
|
||||
int parallel_sfx_window;
|
||||
|
||||
static boolean BlockSFX(sfxinfo_t *sfx)
|
||||
{
|
||||
if (!parallel_sfx)
|
||||
return false;
|
||||
|
||||
if (gametic - sfx->parallel_tic >= parallel_sfx_window)
|
||||
{
|
||||
sfx->parallel_tic = gametic;
|
||||
sfx->parallel_count = 0;
|
||||
}
|
||||
|
||||
++sfx->parallel_count;
|
||||
|
||||
return sfx->parallel_count > parallel_sfx_limit;
|
||||
}
|
||||
|
||||
static void S_StartSoundEx(const mobj_t *origin, int sfx_id, boolean loop)
|
||||
{
|
||||
@ -392,10 +401,6 @@ static void S_StartSoundEx(const mobj_t *origin, int sfx_id, boolean loop)
|
||||
sep = NORM_SEP;
|
||||
}
|
||||
|
||||
// [FG] parallel same-sound limit from DSDA-Doom
|
||||
if (BlockSFX(sfx))
|
||||
return;
|
||||
|
||||
if(pitched_sounds)
|
||||
{
|
||||
// hacks to vary the sfx pitches
|
||||
|
@ -78,16 +78,8 @@ typedef struct sfxinfo_struct {
|
||||
|
||||
// haleyjd 04/23/08: additional caching data
|
||||
unsigned int alen; // length of converted sound pointed to by data
|
||||
|
||||
// [FG] parallel same-sound limit from DSDA-Doom
|
||||
int parallel_tic;
|
||||
int parallel_count;
|
||||
} sfxinfo_t;
|
||||
|
||||
extern boolean parallel_sfx;
|
||||
extern int parallel_sfx_limit;
|
||||
extern int parallel_sfx_window;
|
||||
|
||||
//
|
||||
// MusicInfo struct.
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user