Don't play silenced muzzle flash sounds

This commit is contained in:
Boris I. Bendovsky 2020-04-22 17:53:41 +03:00
parent 563ef16ee3
commit 4646859535
No known key found for this signature in database
GPG key ID: 48CD539C0518594B
2 changed files with 141 additions and 0 deletions

View file

@ -66,6 +66,7 @@ typedef struct sfx_s
int registration_sequence; int registration_sequence;
sfxcache_t *cache; sfxcache_t *cache;
char *truename; char *truename;
qboolean is_silenced_muzzle_flash;
} sfx_t; } sfx_t;
/* A playsound_t will be generated by each call /* A playsound_t will be generated by each call

View file

@ -40,6 +40,19 @@
#define MAX_SFX (MAX_SOUNDS * 2) #define MAX_SFX (MAX_SOUNDS * 2)
#define MAX_PLAYSOUNDS 128 #define MAX_PLAYSOUNDS 128
/* Maximum length (seconds) of audio data to test for silence. */
#define S_MAX_LEN_TO_TEST_FOR_SILENCE_S (2)
/* Minimum length (milliseconds) of audio data to treat as silence. */
#define S_MIN_LEN_TO_TREAT_AS_SILENCE_MS (3)
/* Minimum amplitude absolute value of unsigned 8-bit audio data to treat as silence. */
#define S_MIN_ABS_AMP_8_TO_TREAT_AS_SILENCE (1)
/* Minimum amplitude absolute value of signed 16-bit audio data to treat as silence. */
#define S_MIN_ABS_AMP_16_TO_TREAT_AS_SILENCE (2)
vec3_t listener_origin; vec3_t listener_origin;
vec3_t listener_forward; vec3_t listener_forward;
vec3_t listener_right; vec3_t listener_right;
@ -77,6 +90,121 @@ qboolean snd_is_underwater;
qboolean snd_is_underwater_enabled; qboolean snd_is_underwater_enabled;
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
static qboolean
S_IsShortSilence(const wavinfo_t* info, const void* raw_data)
{
/* Test only mono-audio data. */
if (info->channels != 1)
{
return false;
}
/* Treat it as silence if sample count too small. */
if (((info->samples * 1000) / info->rate) <= S_MIN_LEN_TO_TREAT_AS_SILENCE_MS)
{
return true;
}
/* Test only several second's of audio data. */
if (info->samples > (info->rate * S_MAX_LEN_TO_TEST_FOR_SILENCE_S))
{
return false;
}
if (info->width == 1)
{
/* Unsigned 8-bit audio data. */
const unsigned char* samples = (const unsigned char*)raw_data;
const int sample_count = info->samples * info->width;
int i;
for (i = 0; i < sample_count; ++i)
{
const int sample = samples[i] - 0x80;
if (abs(sample) > S_MIN_ABS_AMP_8_TO_TREAT_AS_SILENCE)
{
return false;
}
}
}
else if (info->width == 2)
{
/* Signed 16-bit audio data. */
const short* samples = (const short*)raw_data;
const int sample_count = info->samples * info->width;
int i;
for (i = 0; i < sample_count; ++i)
{
const int sample = LittleShort(samples[i]);
if (abs(sample) > S_MIN_ABS_AMP_16_TO_TREAT_AS_SILENCE)
{
return false;
}
}
}
else
{
/* Unsupported bit depth. */
return false;
}
return true;
}
static qboolean
S_IsSilencedMuzzleFlash(const wavinfo_t* info, const void* raw_data, const char* name)
{
/* Skip the prefix. */
static const size_t base_sound_string_length = strlen("sound/");
const char* base_name = name + base_sound_string_length;
/* Match to well-known muzzle flash sound names. */
const qboolean is_name_matched =
strcmp(base_name, "weapons/bfg__f1y.wav") == 0 ||
strcmp(base_name, "weapons/blastf1a.wav") == 0 ||
strcmp(base_name, "weapons/disint2.wav") == 0 ||
strcmp(base_name, "weapons/grenlf1a.wav") == 0 ||
strcmp(base_name, "weapons/grenlr1b.wav") == 0 ||
strcmp(base_name, "weapons/hyprbf1a.wav") == 0 ||
strcmp(base_name, "weapons/machgf1b.wav") == 0 ||
strcmp(base_name, "weapons/machgf2b.wav") == 0 ||
strcmp(base_name, "weapons/machgf3b.wav") == 0 ||
strcmp(base_name, "weapons/machgf4b.wav") == 0 ||
strcmp(base_name, "weapons/machgf5b.wav") == 0 ||
strcmp(base_name, "weapons/nail1.wav") == 0 ||
strcmp(base_name, "weapons/plasshot.wav") == 0 ||
strcmp(base_name, "weapons/railgf1a.wav") == 0 ||
strcmp(base_name, "weapons/rippfire.wav") == 0 ||
strcmp(base_name, "weapons/rocklf1a.wav") == 0 ||
strcmp(base_name, "weapons/rocklr1b.wav") == 0 ||
strcmp(base_name, "weapons/shotg2.wav") == 0 ||
strcmp(base_name, "weapons/shotgf1b.wav") == 0 ||
strcmp(base_name, "weapons/shotgr1b.wav") == 0 ||
strcmp(base_name, "weapons/sshotf1b.wav") == 0 ||
false
;
if (!is_name_matched)
{
return false;
}
/* Now check for silence. */
if (!S_IsShortSilence(info, raw_data))
{
return false;
}
return true;
}
/* /*
* Loads one sample into memory * Loads one sample into memory
*/ */
@ -141,6 +269,11 @@ S_LoadSound(sfx_t *s)
return NULL; return NULL;
} }
if (S_IsSilencedMuzzleFlash(&info, data, namebuffer))
{
s->is_silenced_muzzle_flash = true;
}
#if USE_OPENAL #if USE_OPENAL
if (sound_started == SS_OAL) if (sound_started == SS_OAL)
{ {
@ -225,6 +358,7 @@ S_FindName(char *name, qboolean create)
sfx->truename = NULL; sfx->truename = NULL;
strcpy(sfx->name, name); strcpy(sfx->name, name);
sfx->registration_sequence = s_registration_sequence; sfx->registration_sequence = s_registration_sequence;
sfx->is_silenced_muzzle_flash = false;
return sfx; return sfx;
} }
@ -551,6 +685,12 @@ S_IssuePlaysound(playsound_t *ps)
Com_Printf("Issue %i\n", ps->begin); Com_Printf("Issue %i\n", ps->begin);
} }
if (ps->sfx->is_silenced_muzzle_flash)
{
S_FreePlaysound(ps);
return;
}
/* pick a channel to play on */ /* pick a channel to play on */
ch = S_PickChannel(ps->entnum, ps->entchannel); ch = S_PickChannel(ps->entnum, ps->entchannel);