Pulled over Sound-Shader code from TW. We'll use this soon over hard-coded

sounds.
This commit is contained in:
Marco Cawthorne 2020-04-02 22:43:37 +02:00
parent 47f8e41185
commit 4f44d96be9
23 changed files with 481 additions and 24 deletions

View file

@ -11,6 +11,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../valve/defs.h
../cstrike/defs.h
../valve/particles.h

View file

@ -84,12 +84,3 @@ void View_SetMuzzleflash(int);
void View_UpdateWeapon(entity, entity);
void View_PlayAnimation(int);
void Game_Input(void);
typedef struct
{
string m_strSnd;
float m_flPitch;
float len;
} sound_t;

View file

@ -12,6 +12,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../valve/defs.h
../valve/particles.h
../defs.h

View file

@ -12,6 +12,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../valve/defs.h
../valve/particles.h
../defs.h

View file

@ -12,6 +12,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../valve/defs.h
../valve/particles.h
../defs.h

View file

@ -12,6 +12,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../valve/defs.h
../valve/particles.h
../defs.h

View file

@ -11,6 +11,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../valve/defs.h
../valve/particles.h
../defs.h

View file

@ -65,7 +65,7 @@ void Sound_PlayVOX(string msg)
for (int i = 0; i < g_voxcount; i++) {
g_voxque[i].m_strSnd = sprintf("vox/%s.wav", argv(i));
g_voxque[i].len = soundlength(g_voxque[i].m_strSnd);
g_voxque[i].m_flLength = soundlength(g_voxque[i].m_strSnd);
}
g_voxtime = time;
}
@ -85,7 +85,7 @@ void Sound_ProcessWordQue(void)
g_voxcount = 0;
g_voxpos = 0;
} else {
g_voxtime = time + g_voxque[g_voxpos - 1].len;
g_voxtime = time + g_voxque[g_voxpos - 1].m_flLength;
}
}
}

View file

@ -11,6 +11,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../valve/defs.h
../valve/particles.h
../defs.h

View file

@ -11,6 +11,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../valve/defs.h
../valve/particles.h
../defs.h

View file

@ -149,7 +149,7 @@ CBaseEntity::ProcessWordQue(void)
m_iSentencePos = 0;
m_pSentenceQue = 0;
} else {
m_flSentenceTime = time + m_pSentenceQue[m_iSentenceCount - 1].len;
m_flSentenceTime = time + m_pSentenceQue[m_iSentenceCount - 1].m_flLength;
}
}
@ -174,7 +174,7 @@ CBaseEntity::Sentence(string msg)
for (int i = 0; i < m_iSentenceCount; i++) {
m_pSentenceQue[i].m_strSnd = sprintf("%s.wav", argv(i));
m_pSentenceQue[i].len = soundlength(m_pSentenceQue[i].m_strSnd);
m_pSentenceQue[i].m_flLength = soundlength(m_pSentenceQue[i].m_strSnd);
m_pSentenceQue[i].m_flPitch = 100;
}
m_flSentenceTime = time;

View file

@ -47,6 +47,9 @@ void games_init(void)
games = memalloc(sizeof(gameinfo_t) * gameinfo_count);
if (!games)
error(sprintf("Attempting to allocate mod data for %i entries failed\n", gameinfo_count));
for (id = 0; (gamedirname = getgamedirinfo(id, 0)); id++) {
gamedescription = getgamedirinfo(id, 2);

View file

@ -12,6 +12,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../../shared/valve/animations.h
../defs.h
../plugins.c

View file

@ -51,6 +51,17 @@ Gamerules_DecodeChangeParms(player pl)
pl.crossbow_mag = parm28;
pl.rpg_mag = parm29;
pl.satchel_chg = parm30;
/* near gearbox additions */
pl.ammo_556 = parm31;
pl.ammo_762 = parm32;
pl.ammo_spore = parm33;
pl.ammo_shock = parm34;
pl.ammo_penguin = parm35;
pl.eagle_mag = parm36;
pl.sniper_mag = parm37;
pl.m249_mag = parm38;
pl.sporelauncher_mag = parm39;
}
/* prepare the client-info for level-transition */
@ -87,6 +98,17 @@ Gamerules_SetChangeParms(player pl)
parm28 = pl.crossbow_mag;
parm29 = pl.rpg_mag;
parm30 = pl.satchel_chg;
/* near gearbox additions */
parm31 = pl.ammo_556;
parm32 = pl.ammo_762;
parm33 = pl.ammo_spore;
parm34 = pl.ammo_shock;
parm35 = pl.ammo_penguin;
parm36 = pl.eagle_mag;
parm37 = pl.sniper_mag;
parm38 = pl.m249_mag;
parm39 = pl.sporelauncher_mag;
}
/* yuck, whenever 'changelevel' does not happen. */
@ -97,7 +119,8 @@ Gamerules_SetNewParms(void)
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm29 = parm30 = parm31 = parm32 = parm33 = parm34 = parm35 =
parm36 = parm37 = parm39 = parm39 = 0;
}
/* called when the player first spawns/respawns */

View file

@ -13,6 +13,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../../shared/valve/animations.h
../defs.h
../plugins.c

View file

@ -13,6 +13,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../../shared/valve/animations.h
../defs.h
../plugins.c

View file

@ -13,6 +13,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../../shared/valve/animations.h
../defs.h
../plugins.c

View file

@ -12,6 +12,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../../shared/valve/animations.h
../defs.h
../plugins.c

View file

@ -13,6 +13,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../../shared/valve/animations.h
../defs.h

View file

@ -12,6 +12,7 @@
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../../shared/valve/animations.h
../defs.h
../plugins.c

View file

@ -12,6 +12,7 @@ defs.h
../../shared/materials.h
../../shared/events.h
../../shared/entities.h
../../shared/sound.c
../../shared/valve/animations.h
../defs.h
../plugins.c

View file

@ -133,16 +133,6 @@ void Util_Destroy(void)
remove(self);
}
int Sound_Precache(string s)
{
return -1;
}
void Sound_Update(entity a, int b, int c, float d)
{
}
__wrap void dprint(string m)
{
if (cvar("developer") == 1)

434
src/shared/sound.c Normal file
View file

@ -0,0 +1,434 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var hashtable g_hashsounds;
enumflags
{
SNDFL_LOOPING, /* forceloop */
SNDFL_NODUPS, /* don't random the samples */
SNDFL_GLOBAL, /* no attenuation */
SNDFL_NOREVERB, /* skip reverb */
SNDFL_OMNI, /* volume on all channels is equal */
SNDFL_PRIVATE, /* only play on target */
SNDFL_FOLLOW
};
typedef struct
{
float dist_min;
float dist_max;
float offset;
float pitch_min;
float pitch_max;
float shake;
float volume;
int flags;
int playc;
int sample_count;
string samples;
string name;
} snd_t;
typedef struct
{
string m_strSnd;
float m_flLength;
float m_flPitch;
} sound_t;
snd_t *g_sounds;
static int g_sounds_count;
void
Sound_ParseField(int i, int a)
{
switch (argv(0)) {
case "dist_min":
if (a == 2) {
dprint("\tMin distance set\n");
g_sounds[i].dist_min = stof(argv(1));
}
break;
case "dist_max":
if (a == 2) {
dprint("\tMax distance set\n");
g_sounds[i].dist_max = stof(argv(1));
}
break;
case "volume":
if (a == 2) {
dprint("\tVolume set\n");
g_sounds[i].volume = stof(argv(1));
}
break;
case "shakes":
if (a == 2) {
dprint("\tShake set\n");
g_sounds[i].shake = stof(argv(1));
}
break;
case "pitch":
if (a == 2) {
dprint("\tPitch set\n");
g_sounds[i].pitch_min = fabs(stof(argv(1))) * 100;
g_sounds[i].pitch_max = g_sounds[i].pitch_min;
}
break;
case "pitch_min":
if (a == 2) {
dprint("\tMinimum pitch set\n");
g_sounds[i].pitch_min = fabs(stof(argv(1))) * 100;
}
break;
case "pitch_max":
if (a == 2) {
dprint("\tMaximum pitch set\n");
g_sounds[i].pitch_max = fabs(stof(argv(1))) * 100;
}
break;
case "offset":
if (a == 2) {
dprint("\tOffset set\n");
g_sounds[i].offset = stof(argv(1));
}
break;
case "looping":
dprint("\tSound set to loop\n");
g_sounds[i].flags |= SNDFL_LOOPING;
break;
case "nodups":
dprint("\tSound set to not play duplicate samples\n");
g_sounds[i].flags |= SNDFL_NODUPS;
break;
case "global":
dprint("\tSound set to play everywhere\n");
g_sounds[i].flags |= SNDFL_GLOBAL;
break;
case "private":
dprint("\tSound set to play privately\n");
g_sounds[i].flags |= SNDFL_PRIVATE;
break;
case "no_reverb":
dprint("\tSound set to ignore reverb\n");
g_sounds[i].flags |= SNDFL_NOREVERB;
break;
case "omnidirectional":
dprint("\tSound set to be omnidirectional\n");
g_sounds[i].flags |= SNDFL_OMNI;
break;
case "follow":
dprint("\tSound set to follow\n");
g_sounds[i].flags |= SNDFL_FOLLOW;
break;
case "sample":
if (a == 2) {
dprint("\tAdded sample ");
dprint(argv(1));
dprint("\n");
precache_sound(argv(1));
g_sounds[i].samples = sprintf("%s%s\n", g_sounds[i].samples, argv(1));
g_sounds[i].sample_count++;
}
break;
}
}
int
Sound_Parse(int i, string line, string shader)
{
int c;
static string t_name;
static int braced;
c = tokenize_console(line);
switch(argv(0)) {
case "{":
/* skip broken syntax */
if (braced == TRUE || t_name == "") {
break;
}
dprint("{\n");
braced = TRUE;
break;
case "}":
/* skip broken syntax */
if (braced == FALSE) {
break;
}
dprint("}\n");
braced = FALSE;
t_name = "";
return TRUE;
break;
default:
if (braced == TRUE) {
Sound_ParseField(i, c);
} else {
/* name/identifer of our message */
t_name = strtolower(line);
if (t_name == shader) {
/* I guess it's what we want */
dprint("Found shader ");
dprint(shader);
dprint(":\n");
g_sounds[i].name = shader;
} else {
/* not what we're looking for */
t_name = "";
}
}
}
return FALSE;
}
int
Sound_Precache(string shader)
{
searchhandle sh;
filestream fh;
string line;
int index;
index = g_sounds_count;
shader = strtolower(shader);
dprint("[SOUND] Precaching sound shader ");
dprint(shader);
dprint("\n");
/* create the hash-table if it doesn't exist */
if (!g_hashsounds) {
g_hashsounds = hash_createtab(2, HASH_ADD);
}
/* check if it's already cached */
for (int i = 0; i < g_sounds_count; i++) {
if (shader == g_sounds[i].name) {
dprint("[SOUND] Shader already precached.\n");
return i;
}
}
g_sounds_count++;
g_sounds = memrealloc(g_sounds, sizeof(snd_t), index, g_sounds_count);
g_sounds[index].volume = 1.0f;
g_sounds[index].dist_max = 1;
g_sounds[index].pitch_min = g_sounds[index].pitch_max = 100;
sh = search_begin("sound/*.sndshd", TRUE, TRUE);
for (int i = 0; i < search_getsize(sh); i++) {
fh = fopen(search_getfilename(sh, i), FILE_READ);
if (fh < 0) {
continue;
}
while ((line = fgets(fh))) {
/* when we found it, quit */
if (Sound_Parse(index, line, shader) == TRUE) {
search_end(sh);
fclose(fh);
hash_add(g_hashsounds, shader, (int)index);
return index;
}
}
fclose(fh);
}
dprint("^1[SOUND] No shader found for ");
dprint(shader);
dprint("\n");
search_end(sh);
fclose(fh);
return -1;
}
void
Sound_Play(entity target, int chan, string shader)
{
int r;
float radius;
float pitch;
int flags;
int sample;
sample = (int)hash_get(g_hashsounds, shader);
if (sample < 0) {
return;
}
/* pick a sample */
r = floor(random(0, g_sounds[sample].sample_count));
tokenizebyseparator(g_sounds[sample].samples, "\n");
/* set pitch */
pitch = random(g_sounds[sample].pitch_min, g_sounds[sample].pitch_max);
radius = g_sounds[sample].dist_max;
/* flags */
if (g_sounds[sample].flags & SNDFL_NOREVERB) {
flags |= SOUNDFLAG_NOREVERB;
}
if (g_sounds[sample].flags & SNDFL_GLOBAL) {
radius = ATTN_NONE;
}
if (g_sounds[sample].flags & SNDFL_LOOPING) {
flags |= SOUNDFLAG_FORCELOOP;
}
if (g_sounds[sample].flags & SNDFL_NODUPS) {
if (g_sounds[sample].playc >= g_sounds[sample].sample_count) {
g_sounds[sample].playc = 0;
}
r = g_sounds[sample].playc++;
}
if (g_sounds[sample].flags & SOUNDFLAG_FOLLOW) {
flags |= SOUNDFLAG_FOLLOW;
}
#ifdef CSQC
if (g_sounds[sample].flags & SNDFL_OMNI) {
flags |= SOUNDFLAG_NOSPACIALISE;
}
#else
if (g_sounds[sample].flags & SNDFL_PRIVATE) {
flags |= SOUNDFLAG_UNICAST;
msg_entity = target;
}
#endif
#ifdef DEVELOPER
print(sprintf("Sound_Play: %s\n", argv(r)));
#endif
sound(
target,
chan,
argv(r),
g_sounds[sample].volume,
radius,
pitch,
flags,
g_sounds[sample].offset
);
}
void
Sound_PlayAt(vector pos, string shader)
{
int r;
float radius;
float pitch;
int flags;
int sample;
sample = (int)hash_get(g_hashsounds, shader);
if (sample < 0) {
return;
}
/* pick a sample */
r = floor(random(0, g_sounds[sample].sample_count));
tokenizebyseparator(g_sounds[sample].samples, "\n");
/* set pitch */
pitch = random(g_sounds[sample].pitch_min, g_sounds[sample].pitch_max);
/* flags */
if (g_sounds[sample].flags & SNDFL_NOREVERB) {
flags |= SOUNDFLAG_NOREVERB;
}
if (g_sounds[sample].flags & SNDFL_GLOBAL) {
radius = 0;
}
if (g_sounds[sample].flags & SNDFL_LOOPING) {
flags |= SOUNDFLAG_FORCELOOP;
}
if (g_sounds[sample].flags & SNDFL_NODUPS) {
if (g_sounds[sample].playc >= g_sounds[sample].sample_count) {
g_sounds[sample].playc = 0;
}
r = g_sounds[sample].playc++;
}
#ifdef CSQC
if (g_sounds[sample].flags & SNDFL_OMNI) {
flags |= SOUNDFLAG_NOSPACIALISE;
}
#endif
/* really? this doesn't do any more? */
pointsound(pos, argv(r), g_sounds[sample].volume, g_sounds[sample].dist_max);
}
#ifdef CSQC
void
Sound_Update(entity target, int channel, int sample, float volume)
{
int r;
float radius;
float pitch;
int flags;
if (sample < 0) {
return;
}
/* pick a sample */
r = floor(random(0, g_sounds[sample].sample_count));
tokenizebyseparator(g_sounds[sample].samples, "\n");
/* set pitch */
pitch = random(g_sounds[sample].pitch_min, g_sounds[sample].pitch_max);
radius = g_sounds[sample].dist_max;
/* flags */
if (g_sounds[sample].flags & SNDFL_NOREVERB) {
flags |= SOUNDFLAG_NOREVERB;
}
if (g_sounds[sample].flags & SNDFL_GLOBAL) {
radius = ATTN_NONE;
}
if (g_sounds[sample].flags & SNDFL_LOOPING) {
flags |= SOUNDFLAG_FORCELOOP;
}
if (g_sounds[sample].flags & SNDFL_NODUPS) {
if (g_sounds[sample].playc >= g_sounds[sample].sample_count) {
g_sounds[sample].playc = 0;
}
r = g_sounds[sample].playc++;
}
if (g_sounds[sample].flags & SNDFL_OMNI) {
flags |= SOUNDFLAG_NOSPACIALISE;
}
soundupdate(
target,
channel,
argv(0),
g_sounds[sample].volume * volume,
radius,
pitch,
flags,
g_sounds[sample].offset
);
}
#endif