ref: be176cb096df301fd3ca221c0b08a88cf812c8b9
parent: a13439378618f7b8b372ab6526ca5578b21e65cd
author: Konstantinn Bonnet <qu7uux@gmail.com>
date: Thu Mar 9 15:10:58 EST 2017
fix and simplify sound - don't buffer writes to /dev/audio, nuke all the stupid cargocult multiproc bullshit - write variable number of samples based on time from last write + a bit more to avoid underruns - move all sound code to snd.c, refactor sampling code, remove useless cvars and commands
--- a/bspfile.h
+++ b/bspfile.h
@@ -177,15 +177,6 @@
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
-
-
-#define AMBIENT_WATER 0
-#define AMBIENT_SKY 1
-#define AMBIENT_SLIME 2
-#define AMBIENT_LAVA 3
-
-#define NUM_AMBIENTS 4 // automatic ambient sounds
-
// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
// all other leafs need visibility info
typedef struct
@@ -199,7 +190,7 @@
unsigned short firstmarksurface;
unsigned short nummarksurfaces;
- byte ambient_level[NUM_AMBIENTS];
+ byte ambient_level[Namb];
} dleaf_t;
#pragma pack off
--- a/cd.c
+++ b/cd.c
@@ -52,7 +52,7 @@
{
int a, n, afd, fd;
char s[24];
- uchar buf[SNBUF];
+ uchar buf[8192];
short *p;
if((afd = open("/dev/audio", OWRITE)) < 0)
--- a/cl_main.c
+++ b/cl_main.c
@@ -82,7 +82,7 @@
void CL_Disconnect (void)
{
// stop sounds (especially looping!)
- S_StopAllSounds (true);
+ stopallsfx();
// bring the console down and fade the colors back to normal
// SCR_BringDownConsole ();
--- a/cl_parse.c
+++ b/cl_parse.c
@@ -96,12 +96,12 @@
if (field_mask & SND_VOLUME)
volume = MSG_ReadByte ();
else
- volume = DEFAULT_SOUND_PACKET_VOLUME;
+ volume = Spktvol;
if (field_mask & SND_ATTENUATION)
attenuation = MSG_ReadByte () / 64.0;
else
- attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
+ attenuation = Spktatt;
channel = MSG_ReadShort ();
sound_num = MSG_ReadByte ();
@@ -115,7 +115,7 @@
for (i=0 ; i<3 ; i++)
pos[i] = MSG_ReadCoord ();
- S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
+ startsfx (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
}
/*
@@ -261,7 +261,7 @@
return;
}
strcpy (sound_precache[numsounds], str);
- S_TouchSound (str);
+ touchsfx (str);
}
//
@@ -279,13 +279,11 @@
CL_KeepaliveMessage ();
}
- S_BeginPrecaching ();
for (i=1 ; i<numsounds ; i++)
{
- cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
+ cl.sound_precache[i] = precachesfx (sound_precache[i]);
CL_KeepaliveMessage ();
}
- S_EndPrecaching ();
// local state
@@ -667,7 +665,7 @@
vol = MSG_ReadByte ();
atten = MSG_ReadByte ();
- S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
+ staticsfx (cl.sound_precache[sound_num], org, vol, atten);
}
@@ -794,7 +792,7 @@
case svc_stopsound:
i = MSG_ReadShort();
- S_StopSound(i>>3, i&7);
+ stopsfx(i>>3, i&7);
break;
case svc_updatename:
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -8,13 +8,13 @@
entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
beam_t cl_beams[MAX_BEAMS];
-sfx_t *cl_sfx_wizhit;
-sfx_t *cl_sfx_knighthit;
-sfx_t *cl_sfx_tink1;
-sfx_t *cl_sfx_ric1;
-sfx_t *cl_sfx_ric2;
-sfx_t *cl_sfx_ric3;
-sfx_t *cl_sfx_r_exp3;
+Sfx *cl_sfx_wizhit;
+Sfx *cl_sfx_knighthit;
+Sfx *cl_Sfxink1;
+Sfx *cl_sfx_ric1;
+Sfx *cl_sfx_ric2;
+Sfx *cl_sfx_ric3;
+Sfx *cl_sfx_r_exp3;
/*
=================
@@ -23,13 +23,13 @@
*/
void CL_InitTEnts (void)
{
- cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
- cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
- cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
- cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
- cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
- cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
- cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
+ cl_sfx_wizhit = precachesfx ("wizard/hit.wav");
+ cl_sfx_knighthit = precachesfx ("hknight/hit.wav");
+ cl_Sfxink1 = precachesfx ("weapons/tink1.wav");
+ cl_sfx_ric1 = precachesfx ("weapons/ric1.wav");
+ cl_sfx_ric2 = precachesfx ("weapons/ric2.wav");
+ cl_sfx_ric3 = precachesfx ("weapons/ric3.wav");
+ cl_sfx_r_exp3 = precachesfx ("weapons/r_exp3.wav");
}
/*
@@ -103,7 +103,7 @@
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_RunParticleEffect (pos, vec3_origin, 20, 30);
- S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_wizhit, pos, 1, 1);
break;
case TE_KNIGHTSPIKE: // spike hitting wall
@@ -111,7 +111,7 @@
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_RunParticleEffect (pos, vec3_origin, 226, 20);
- S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_knighthit, pos, 1, 1);
break;
case TE_SPIKE: // spike hitting wall
@@ -120,16 +120,16 @@
pos[2] = MSG_ReadCoord ();
R_RunParticleEffect (pos, vec3_origin, 0, 10);
if ( rand() % 5 )
- S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
+ startsfx (-1, 0, cl_Sfxink1, pos, 1, 1);
else
{
rnd = rand() & 3;
if (rnd == 1)
- S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_ric1, pos, 1, 1);
else if (rnd == 2)
- S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_ric2, pos, 1, 1);
else
- S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_ric3, pos, 1, 1);
}
break;
case TE_SUPERSPIKE: // super spike hitting wall
@@ -139,16 +139,16 @@
R_RunParticleEffect (pos, vec3_origin, 0, 20);
if ( rand() % 5 )
- S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
+ startsfx (-1, 0, cl_Sfxink1, pos, 1, 1);
else
{
rnd = rand() & 3;
if (rnd == 1)
- S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_ric1, pos, 1, 1);
else if (rnd == 2)
- S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_ric2, pos, 1, 1);
else
- S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_ric3, pos, 1, 1);
}
break;
@@ -169,7 +169,7 @@
dl->radius = 350;
dl->die = cl.time + 0.5;
dl->decay = 300;
- S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
case TE_TAREXPLOSION: // tarbaby explosion
@@ -178,7 +178,7 @@
pos[2] = MSG_ReadCoord ();
R_BlobExplosion (pos);
- S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
case TE_LIGHTNING1: // lightning bolts
@@ -225,7 +225,7 @@
dl->radius = 350;
dl->die = cl.time + 0.5;
dl->decay = 300;
- S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
+ startsfx (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
default:
--- a/client.h
+++ b/client.h
@@ -179,7 +179,7 @@
// information that is static for the entire time connected to a server
//
struct model_s *model_precache[MAX_MODELS];
- struct sfx_s *sound_precache[MAX_SOUNDS];
+ Sfx *sound_precache[MAX_SOUNDS];
char levelname[40]; // for display on solo scoreboard
int viewentity; // cl_entitites[cl.viewentity] = player
--- a/console.c
+++ b/console.c
@@ -223,7 +223,7 @@
if (txt[0] == 1)
{
mask = 128; // go to colored text
- S_LocalSound ("misc/talk.wav");
+ localsfx ("misc/talk.wav");
// play talk wav
txt++;
}
--- a/dat.h
+++ b/dat.h
@@ -1,3 +1,5 @@
+typedef struct Sfx Sfx;
+
enum{
Npath = 64,
Nfspath = 128,
@@ -5,7 +7,9 @@
Nsav = 12,
Nsavcm = 40,
Nsavver = 5,
- Nparms = 16
+ Nparms = 16,
+
+ Te9 = 1000000000
};
extern char fsdir[];
@@ -13,3 +17,21 @@
extern char savs[][Nsavcm];
extern int savcanld[];
+
+enum{
+ Fpsmin = 10,
+ Fpsmax = 72
+};
+
+enum{
+ Ambwater = 0,
+ Ambsky,
+ Ambslime,
+ Amblava,
+ Namb
+};
+
+enum{
+ Spktvol = 255
+};
+#define Spktatt 1.0
--- a/draw.c
+++ b/draw.c
@@ -809,10 +809,6 @@
int x,y;
byte *pbuf;
- VID_UnlockBuffer ();
- S_ExtraUpdate ();
- VID_LockBuffer ();
-
for (y=0 ; y<vid.height ; y++)
{
int t;
@@ -826,10 +822,6 @@
pbuf[x] = 0;
}
}
-
- VID_UnlockBuffer ();
- S_ExtraUpdate ();
- VID_LockBuffer ();
}
//=============================================================================
--- a/fns.h
+++ b/fns.h
@@ -1,3 +1,13 @@
+void stepsnd(vec3_t, vec3_t, vec3_t, vec3_t);
+void stopallsfx(void);
+void stopsfx(int, int);
+void startsfx(int, int, Sfx *, vec3_t, float, float);
+void localsfx(char *);
+void staticsfx(Sfx *, vec3_t, float, float);
+void touchsfx(char *);
+Sfx* precachesfx(char *);
+void shutsnd(void);
+int initsnd(void);
void setcvar(char*, char*);
void setcvarv(char*, float);
void abortdemo(void);
--- a/fs.c
+++ b/fs.c
@@ -344,10 +344,10 @@
switch(mth){
case Fhunk: buf = Hunk_AllocName(m + 1, r); break;
case Fcache: buf = Cache_Alloc(loadcache, m + 1, r); break;
- case Fstack: buf = m+1 <= loadsize ? loadbuf : Hunk_TempAlloc(m+1);
+ case Fstack: buf = m + 1 <= loadsize ? loadbuf : Hunk_TempAlloc(m + 1); break;
}
if(buf == nil)
- fatal("loadlmp %s %d: memory allocation failed: %r", f, m+1);
+ fatal("loadlmp %s %d: memory allocation failed: %r", f, m + 1);
buf[m] = 0;
Draw_BeginDisc();
eread(bf, buf, m);
@@ -684,7 +684,7 @@
goto exit;
n = strtol(s, nil, 10);
if(n != Nsavver){
- werrstr("invalid version %d\n", n);
+ werrstr("invalid version %d", n);
goto exit;
}
Brdline(bf, '\n');
--- a/host.c
+++ b/host.c
@@ -57,7 +57,6 @@
cvar_t temp1 = {"temp1","0"};
-
/*
================
Host_EndGame
@@ -426,43 +425,8 @@
memset(&cl, 0, sizeof cl);
}
-
-//============================================================================
-
-
/*
===================
-Host_FilterTime
-
-Returns false if the time is too short to run a frame
-===================
-*/
-qboolean Host_FilterTime (float time)
-{
- realtime += time;
-
- if (!cls.timedemo && realtime - oldrealtime < 1.0/72.0)
- return false; // framerate is too high
-
- host_frametime = realtime - oldrealtime;
- oldrealtime = realtime;
-
- if (host_framerate.value > 0)
- host_frametime = host_framerate.value;
- else
- { // don't allow really long or short frames
- if (host_frametime > 0.1)
- host_frametime = 0.1;
- if (host_frametime < 0.001)
- host_frametime = 0.001;
- }
-
- return true;
-}
-
-
-/*
-===================
Host_GetConsoleCommands
Add them exactly as if they had been typed at the console
@@ -511,15 +475,21 @@
SV_SendClientMessages ();
}
+static int
+boundfps(float t)
+{
+ realtime += t;
+ if(!cls.timedemo && realtime - oldrealtime < 1.0 / Fpsmax)
+ return -1;
+ host_frametime = realtime - oldrealtime;
+ oldrealtime = realtime;
+ if(host_framerate.value > 0)
+ host_frametime = host_framerate.value;
+ else if(host_frametime > 1.0 / Fpsmin)
+ host_frametime = 1.0 / Fpsmin;
+ return 0;
+}
-
-/*
-==================
-Host_Frame
-
-Runs all active servers
-==================
-*/
void _Host_Frame (float time)
{
static double time1 = 0;
@@ -532,10 +502,9 @@
// keep the random time dependent
rand ();
-
-// decide the simulation time
- if (!Host_FilterTime (time))
- return; // don't run too fast, or packets will flood out
+
+ if(boundfps(time) < 0)
+ return;
// get new key events
Sys_SendKeyEvents ();
@@ -595,11 +564,11 @@
// update audio
if (cls.signon == SIGNONS)
{
- S_Update (r_origin, vpn, vright, vup);
+ stepsnd (r_origin, vpn, vright, vup);
CL_DecayLights ();
}
else
- S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
+ stepsnd (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
CDAudio_Update();
@@ -711,7 +680,8 @@
Draw_Init ();
SCR_Init ();
R_Init ();
- S_Init ();
+ if(initsnd() < 0)
+ fprint(2, "initsnd: %r\n");
CDAudio_Init ();
Sbar_Init ();
CL_Init ();
@@ -753,7 +723,7 @@
CDAudio_Shutdown ();
NET_Shutdown ();
- S_Shutdown();
+ shutsnd();
IN_Shutdown ();
if (cls.state != ca_dedicated)
--- a/menu.c
+++ b/menu.c
@@ -296,13 +296,13 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (++m_main_cursor >= MAIN_ITEMS)
m_main_cursor = 0;
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (--m_main_cursor < 0)
m_main_cursor = MAIN_ITEMS - 1;
break;
@@ -375,13 +375,13 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (++m_singleplayer_cursor >= SINGLEPLAYER_ITEMS)
m_singleplayer_cursor = 0;
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (--m_singleplayer_cursor < 0)
m_singleplayer_cursor = SINGLEPLAYER_ITEMS - 1;
break;
@@ -483,7 +483,7 @@
break;
case K_ENTER:
- S_LocalSound ("misc/menu2.wav");
+ localsfx ("misc/menu2.wav");
if (!savcanld[load_cursor])
return;
m_state = m_none;
@@ -499,7 +499,7 @@
case K_UPARROW:
case K_LEFTARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
load_cursor--;
if (load_cursor < 0)
load_cursor = Nsav-1;
@@ -507,7 +507,7 @@
case K_DOWNARROW:
case K_RIGHTARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
load_cursor++;
if (load_cursor >= Nsav)
load_cursor = 0;
@@ -532,7 +532,7 @@
case K_UPARROW:
case K_LEFTARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
load_cursor--;
if (load_cursor < 0)
load_cursor = Nsav-1;
@@ -540,7 +540,7 @@
case K_DOWNARROW:
case K_RIGHTARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
load_cursor++;
if (load_cursor >= Nsav)
load_cursor = 0;
@@ -592,13 +592,13 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (++m_multiplayer_cursor >= MULTIPLAYER_ITEMS)
m_multiplayer_cursor = 0;
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (--m_multiplayer_cursor < 0)
m_multiplayer_cursor = MULTIPLAYER_ITEMS - 1;
break;
@@ -700,7 +700,7 @@
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
setup_cursor--;
if (setup_cursor < 0)
setup_cursor = NUM_SETUP_CMDS-1;
@@ -707,7 +707,7 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
setup_cursor++;
if (setup_cursor >= NUM_SETUP_CMDS)
setup_cursor = 0;
@@ -716,7 +716,7 @@
case K_LEFTARROW:
if (setup_cursor < 2)
return;
- S_LocalSound ("misc/menu3.wav");
+ localsfx ("misc/menu3.wav");
if (setup_cursor == 2)
setup_top = setup_top - 1;
if (setup_cursor == 3)
@@ -726,7 +726,7 @@
if (setup_cursor < 2)
return;
forward:
- S_LocalSound ("misc/menu3.wav");
+ localsfx ("misc/menu3.wav");
if (setup_cursor == 2)
setup_top = setup_top + 1;
if (setup_cursor == 3)
@@ -916,13 +916,13 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (++m_net_cursor >= m_net_items)
m_net_cursor = 0;
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (--m_net_cursor < 0)
m_net_cursor = m_net_items - 1;
break;
@@ -983,7 +983,7 @@
void M_AdjustSliders (int dir)
{
- S_LocalSound ("misc/menu3.wav");
+ localsfx ("misc/menu3.wav");
switch (options_cursor)
{
@@ -1170,7 +1170,7 @@
return;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
options_cursor--;
if (options_cursor < 0)
options_cursor = OPTIONS_ITEMS-1;
@@ -1177,7 +1177,7 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
options_cursor++;
if (options_cursor >= OPTIONS_ITEMS)
options_cursor = 0;
@@ -1340,7 +1340,7 @@
if (bind_grab)
{ // defining a key
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
if (k != '`')
{
sprint (cmd, "bind \"%s\" \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);
@@ -1359,7 +1359,7 @@
case K_LEFTARROW:
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
keys_cursor--;
if (keys_cursor < 0)
keys_cursor = NUMCOMMANDS-1;
@@ -1367,7 +1367,7 @@
case K_DOWNARROW:
case K_RIGHTARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
keys_cursor++;
if (keys_cursor >= NUMCOMMANDS)
keys_cursor = 0;
@@ -1375,7 +1375,7 @@
case K_ENTER: // go into bind mode
M_FindKeysForCommand (bindnames[keys_cursor][0], keys);
- S_LocalSound ("misc/menu2.wav");
+ localsfx ("misc/menu2.wav");
if (keys[1] != -1)
M_UnbindCommand (bindnames[keys_cursor][0]);
bind_grab = true;
@@ -1383,7 +1383,7 @@
case K_BACKSPACE: // delete bindings
case K_DEL: // delete bindings
- S_LocalSound ("misc/menu2.wav");
+ localsfx ("misc/menu2.wav");
M_UnbindCommand (bindnames[keys_cursor][0]);
break;
}
@@ -1707,7 +1707,7 @@
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
serialConfig_cursor--;
if (serialConfig_cursor < 0)
serialConfig_cursor = NUM_SERIALCONFIG_CMDS-1;
@@ -1714,7 +1714,7 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
serialConfig_cursor++;
if (serialConfig_cursor >= NUM_SERIALCONFIG_CMDS)
serialConfig_cursor = 0;
@@ -1723,7 +1723,7 @@
case K_LEFTARROW:
if (serialConfig_cursor > 2)
break;
- S_LocalSound ("misc/menu3.wav");
+ localsfx ("misc/menu3.wav");
if (serialConfig_cursor == 0)
{
@@ -1755,7 +1755,7 @@
if (serialConfig_cursor > 2)
break;
forward:
- S_LocalSound ("misc/menu3.wav");
+ localsfx ("misc/menu3.wav");
if (serialConfig_cursor == 0)
{
@@ -1933,7 +1933,7 @@
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
modemConfig_cursor--;
if (modemConfig_cursor < 0)
modemConfig_cursor = NUM_MODEMCONFIG_CMDS-1;
@@ -1940,7 +1940,7 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
modemConfig_cursor++;
if (modemConfig_cursor >= NUM_MODEMCONFIG_CMDS)
modemConfig_cursor = 0;
@@ -1954,7 +1954,7 @@
modemConfig_dialing = 'T';
else
modemConfig_dialing = 'P';
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
}
break;
@@ -2135,7 +2135,7 @@
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
lanConfig_cursor--;
if (lanConfig_cursor < 0)
lanConfig_cursor = NUM_LANCONFIG_CMDS-1;
@@ -2142,7 +2142,7 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
lanConfig_cursor++;
if (lanConfig_cursor >= NUM_LANCONFIG_CMDS)
lanConfig_cursor = 0;
@@ -2637,7 +2637,7 @@
break;
case K_UPARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
gameoptions_cursor--;
if (gameoptions_cursor < 0)
gameoptions_cursor = NUM_GAMEOPTIONS-1;
@@ -2644,7 +2644,7 @@
break;
case K_DOWNARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
gameoptions_cursor++;
if (gameoptions_cursor >= NUM_GAMEOPTIONS)
gameoptions_cursor = 0;
@@ -2653,7 +2653,7 @@
case K_LEFTARROW:
if (gameoptions_cursor == 0)
break;
- S_LocalSound ("misc/menu3.wav");
+ localsfx ("misc/menu3.wav");
M_NetStart_Change (-1);
break;
@@ -2660,12 +2660,12 @@
case K_RIGHTARROW:
if (gameoptions_cursor == 0)
break;
- S_LocalSound ("misc/menu3.wav");
+ localsfx ("misc/menu3.wav");
M_NetStart_Change (1);
break;
case K_ENTER:
- S_LocalSound ("misc/menu2.wav");
+ localsfx ("misc/menu2.wav");
if (gameoptions_cursor == 0)
{
if (sv.active)
@@ -2821,7 +2821,7 @@
case K_UPARROW:
case K_LEFTARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
slist_cursor--;
if (slist_cursor < 0)
slist_cursor = hostCacheCount - 1;
@@ -2829,7 +2829,7 @@
case K_DOWNARROW:
case K_RIGHTARROW:
- S_LocalSound ("misc/menu1.wav");
+ localsfx ("misc/menu1.wav");
slist_cursor++;
if (slist_cursor >= hostCacheCount)
slist_cursor = 0;
@@ -2836,7 +2836,7 @@
break;
case K_ENTER:
- S_LocalSound ("misc/menu2.wav");
+ localsfx ("misc/menu2.wav");
m_return_state = m_state;
m_return_onerror = true;
slist_sorted = false;
@@ -2883,12 +2883,7 @@
scr_copyeverything = 1;
if (scr_con_current)
- {
Draw_ConsoleBackground (vid.height);
- VID_UnlockBuffer ();
- S_ExtraUpdate ();
- VID_LockBuffer ();
- }
else
Draw_FadeScreen ();
@@ -2979,13 +2974,9 @@
if (m_entersound)
{
- S_LocalSound ("misc/menu2.wav");
+ localsfx ("misc/menu2.wav");
m_entersound = false;
}
-
- VID_UnlockBuffer ();
- S_ExtraUpdate ();
- VID_LockBuffer ();
}
void
--- a/mkfile
+++ b/mkfile
@@ -4,6 +4,7 @@
TARG=quake
OFILES=\
+ cd.$O\
cl_demo.$O\
cl_input.$O\
cl_main.$O\
@@ -30,14 +31,16 @@
fs.$O\
host.$O\
host_cmd.$O\
+ in.$O\
keys.$O\
- menu.$O\
mathlib.$O\
+ menu.$O\
model.$O\
+ net_bsd.$O\
+ net_dgrm.$O\
net_loop.$O\
net_main.$O\
- net_dgrm.$O\
- net_bsd.$O\
+ net_udp.$O\
pr_cmds.$O\
pr_edict.$O\
pr_exec.$O\
@@ -45,36 +48,30 @@
r_aclip.$O\
r_alias.$O\
r_bsp.$O\
- r_light.$O\
r_draw.$O\
r_efrag.$O\
r_edge.$O\
- r_misc.$O\
+ r_light.$O\
r_main.$O\
+ r_misc.$O\
+ r_part.$O\
r_sky.$O\
r_sprite.$O\
r_surf.$O\
- r_part.$O\
r_vars.$O\
screen.$O\
sbar.$O\
+ snd.$O\
sv_main.$O\
- sv_phys.$O\
sv_move.$O\
+ sv_phys.$O\
sv_user.$O\
- zone.$O\
+ sys.$O\
+ vid.$O\
view.$O\
wad.$O\
world.$O\
- snd_dma.$O\
- snd_mem.$O\
- snd_mix.$O\
- in.$O\
- sys.$O\
- vid.$O\
- snd.$O\
- cd.$O\
- net_udp.$O\
+ zone.$O\
HFILES=\
dat.h\
@@ -109,7 +106,6 @@
sbar.h\
screen.h\
server.h\
- sound.h\
spritegn.h\
sys.h\
vid.h\
--- a/model.h
+++ b/model.h
@@ -141,7 +141,7 @@
msurface_t **firstmarksurface;
int nummarksurfaces;
int key; // BSP sequence number for leaf's contents
- byte ambient_sound_level[NUM_AMBIENTS];
+ byte ambient_sound_level[Namb];
} mleaf_t;
// !!! if this is changed, it must be changed in asm_i386.h too !!!
--- a/quakedef.h
+++ b/quakedef.h
@@ -167,7 +167,15 @@
#include "protocol.h"
#include "cmd.h"
#include "sbar.h"
-#include "sound.h"
+
+struct Sfx{
+ char s[Npath];
+ cache_user_t cu;
+};
+
+extern cvar_t bgmvolume;
+extern cvar_t volume;
+
#include "render.h"
#include "client.h"
#include "progs.h"
--- a/r_edge.c
+++ b/r_edge.c
@@ -689,10 +689,6 @@
// the next scan
if (span_p >= max_span_p)
{
- VID_UnlockBuffer ();
- S_ExtraUpdate (); // don't let sound get messed up if going slow
- VID_LockBuffer ();
-
if (r_drawculledpolys)
{
R_DrawCulledPolys ();
--- a/r_main.c
+++ b/r_main.c
@@ -881,13 +881,6 @@
db_time2 = Sys_FloatTime ();
se_time1 = db_time2;
}
-
- if (!r_dspeeds.value)
- {
- VID_UnlockBuffer ();
- S_ExtraUpdate (); // don't let sound get messed up if going slow
- VID_LockBuffer ();
- }
if (!(r_drawpolys | r_drawculledpolys))
R_ScanEdges ();
@@ -927,22 +920,8 @@
if (!cl_entities[0].model || !cl.worldmodel)
fatal ("R_RenderView: NULL worldmodel");
-
- if (!r_dspeeds.value)
- {
- VID_UnlockBuffer ();
- S_ExtraUpdate (); // don't let sound get messed up if going slow
- VID_LockBuffer ();
- }
R_EdgeDrawing ();
-
- if (!r_dspeeds.value)
- {
- VID_UnlockBuffer ();
- S_ExtraUpdate (); // don't let sound get messed up if going slow
- VID_LockBuffer ();
- }
if (r_dspeeds.value)
{
--- a/screen.c
+++ b/screen.c
@@ -609,7 +609,7 @@
*/
void SCR_BeginLoadingPlaque (void)
{
- S_StopAllSounds (true);
+ stopallsfx();
if (cls.state != ca_connected)
return;
@@ -702,9 +702,6 @@
scr_drawdialog = true;
SCR_UpdateScreen ();
scr_drawdialog = false;
-
- S_ClearBuffer (); // so dma doesn't loop current sound
-
do
{
key_count = -1; // wait for a key down and up
--- a/snd.c
+++ b/snd.c
@@ -1,94 +1,832 @@
#include <u.h>
#include <libc.h>
-#include <thread.h>
#include "dat.h"
#include "quakedef.h"
#include "fns.h"
+cvar_t bgmvolume = {"bgmvolume", "1", 1};
+cvar_t volume = {"volume", "0.7", 1};
+
+typedef struct Chan Chan;
+
enum{
- Nbuf = 8
+ Srate = 44100,
+ Ssize = 2,
+ Sch = 2,
+ Sblk = Ssize * Sch,
+ Ssamp = Srate / Fpsmin,
+ Snbuf = Ssamp * Sblk,
+
+ Nchan = 128,
+ Ndyn = 8,
+ Sstat = Ndyn + Namb
};
-static int afd;
-static int stid = -1;
-static uint wpos;
-static Channel *schan;
-static QLock sndlock;
+static float Clipdist = 1000.0;
+struct Chan{
+ Sfx *sfx;
+ int chvol;
+ int lvol;
+ int rvol;
+ vec_t attf;
+ vec3_t zp;
+ int entn;
+ int entch;
+ int p;
+ int n;
+};
+static Chan chans[Nchan], *che;
+static int afd = -1;
+static uchar mixbuf[Snbuf];
+static vlong sndt, sampt;
+static int nsamp;
+static int sampbuf[Ssamp*Sch*sizeof(int)];
+static int scalt[32][256];
+
+static Sfx *ambsfx[Namb];
+
+typedef struct
+{
+ int length;
+ int speed;
+ int width;
+ int stereo;
+ int loop;
+ byte data[1]; // variable sized
+} sfxcache_t;
+
+typedef struct
+{
+ int rate;
+ int width;
+ int channels;
+ int loopofs;
+ int samples;
+ int dataofs;
+} wavinfo_t;
+
+static vec3_t listener_origin;
+static vec3_t listener_forward;
+static vec3_t listener_right;
+static vec3_t listener_up;
+#define MAX_SFX 512
+static Sfx *known_sfx; // hunk allocated [MAX_SFX]
+static int num_sfx;
+
+static cvar_t precache = {"precache", "1"};
+static cvar_t loadas8bit = {"loadas8bit", "0"};
+static cvar_t ambient_level = {"ambient_level", "0.3"};
+static cvar_t ambient_fade = {"ambient_fade", "100"};
+
+static byte *data_p;
+static byte *iff_end;
+static byte *last_chunk;
+static byte *iff_data;
+
+/* TODO: refuctor wav loading */
static void
-sproc(void *)
+resample(sfxcache_t *sc, byte *data, float stepscale)
{
- int n;
+ int inwidth;
+ int outcount;
+ int srcsample;
+ int i;
+ int sample, samplefrac, fracstep;
- for(;;){
- if(recv(schan, nil) < 0)
- break;
- if((n = write(afd, shm->buffer, SNBUF)) != SNBUF)
- break;
- qlock(&sndlock);
- wpos += n;
- qunlock(&sndlock);
+ inwidth = sc->width;
+ outcount = sc->length / stepscale;
+ sc->length = outcount;
+ sc->speed = Srate;
+ if (loadas8bit.value)
+ sc->width = 1;
+ else
+ sc->width = inwidth;
+ sc->stereo = 0;
+
+ if (stepscale == 1 && inwidth == 1 && sc->width == 1)
+ {
+// fast special case
+ for (i=0 ; i<outcount ; i++)
+ ((signed char *)sc->data)[i]
+ = (int)( (unsigned char)(data[i]) - 128);
}
+ else
+ {
+// general case
+ samplefrac = 0;
+ fracstep = stepscale*256;
+ for (i=0 ; i<outcount ; i++)
+ {
+ srcsample = samplefrac >> 8;
+ samplefrac += fracstep;
+ if (inwidth == 2)
+ sample = LittleShort ( ((short *)data)[srcsample] );
+ else
+ sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
+ if (sc->width == 2)
+ ((short *)sc->data)[i] = sample;
+ else
+ ((signed char *)sc->data)[i] = sample >> 8;
+ }
+ }
}
-qboolean
-SNDDMA_Init(void)
+static short
+GetLittleShort(void)
{
- if((afd = open("/dev/audio", OWRITE)) < 0){
- fprint(2, "open: %r\n");
- return 0;
+ short val;
+
+ val = *data_p;
+ val = val + (*(data_p+1)<<8);
+ data_p += 2;
+ return val;
+}
+
+static int
+GetLittleLong(void)
+{
+ int val;
+
+ val = *data_p;
+ val = val + (*(data_p+1)<<8);
+ val = val + (*(data_p+2)<<16);
+ val = val + (*(data_p+3)<<24);
+ data_p += 4;
+ return val;
+}
+
+static void
+FindNextChunk(char *name)
+{
+ int iff_chunk_len;
+
+ while (1)
+ {
+ data_p=last_chunk;
+
+ if (data_p >= iff_end)
+ { // didn't find the chunk
+ data_p = nil;
+ return;
+ }
+
+ data_p += 4;
+ iff_chunk_len = GetLittleLong();
+ if (iff_chunk_len < 0)
+ {
+ data_p = nil;
+ return;
+ }
+// if (iff_chunk_len > 1024*1024)
+// fatal ("FindNextChunk: %d length is past the 1 meg sanity limit", iff_chunk_len);
+ data_p -= 8;
+ last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
+ if(strncmp((char *)data_p, name, 4) == 0)
+ return;
}
+}
- shm = &sn;
- shm->splitbuffer = 0;
- shm->submission_chunk = 1;
- shm->samplebits = SAMPLESZ;
- shm->speed = RATE;
- shm->channels = 2;
- shm->samples = NSAMPLE;
- shm->samplepos = 0;
- if((shm->buffer = mallocz(SNBUF, 1)) == nil)
- sysfatal("mallocz: %r\n");
+static void
+FindChunk(char *name)
+{
+ last_chunk = iff_data;
+ FindNextChunk (name);
+}
- wpos = 0;
- if((schan = chancreate(sizeof(int), Nbuf)) == nil)
- sysfatal("SNDDMA_Init:chancreate: %r");
- if((stid = proccreate(sproc, nil, 8192)) < 0)
- sysfatal("SNDDMA_Init:proccreate: %r");
- return 1;
+static wavinfo_t
+GetWavinfo(char *name, byte *wav, vlong wavlength)
+{
+ wavinfo_t info;
+ int i;
+ int format;
+ int samples;
+
+ memset(&info, 0, sizeof info);
+
+ if (!wav)
+ return info;
+
+ iff_data = wav;
+ iff_end = wav + wavlength;
+
+// find "RIFF" chunk
+ FindChunk("RIFF");
+ if(!(data_p && strncmp((char *)data_p+8, "WAVE", 4) == 0))
+ {
+ Con_Printf("Missing RIFF/WAVE chunks\n");
+ return info;
+ }
+
+// get "fmt " chunk
+ iff_data = data_p + 12;
+
+ FindChunk("fmt ");
+ if (!data_p)
+ {
+ Con_Printf("Missing fmt chunk\n");
+ return info;
+ }
+ data_p += 8;
+ format = GetLittleShort();
+ if (format != 1)
+ {
+ Con_Printf("Microsoft PCM format only\n");
+ return info;
+ }
+
+ info.channels = GetLittleShort();
+ info.rate = GetLittleLong();
+ data_p += 4+2;
+ info.width = GetLittleShort() / 8;
+
+// get cue chunk
+ FindChunk("cue ");
+ if (data_p)
+ {
+ data_p += 32;
+ info.loopofs = GetLittleLong();
+
+ // if the next chunk is a LIST chunk, look for a cue length marker
+ FindNextChunk ("LIST");
+ if (data_p)
+ {
+ if(strncmp((char *)data_p+28, "mark", 4) == 0)
+ { // this is not a proper parse, but it works with cooledit...
+ data_p += 24;
+ i = GetLittleLong (); // samples in loop
+ info.samples = info.loopofs + i;
+// Con_Printf("looped length: %d\n", i);
+ }
+ }
+ }
+ else
+ info.loopofs = -1;
+
+// find data chunk
+ FindChunk("data");
+ if (!data_p)
+ {
+ Con_Printf("Missing data chunk\n");
+ return info;
+ }
+
+ data_p += 4;
+ samples = GetLittleLong () / info.width;
+
+ if (info.samples)
+ {
+ if (samples < info.samples)
+ fatal ("Sound %s has a bad loop length", name);
+ }
+ else
+ info.samples = samples;
+
+ info.dataofs = data_p - wav;
+
+ return info;
}
-uint
-SNDDMA_GetDMAPos(void)
+static sfxcache_t *
+loadsfx(Sfx *sfx)
{
- if(stid < 0)
- return 0;
- qlock(&sndlock);
- shm->samplepos = wpos / SAMPLEB;
- qunlock(&sndlock);
- return shm->samplepos;
+ wavinfo_t info;
+ int len;
+ float stepscale;
+ sfxcache_t *sc;
+ uchar *u, buf[1024]; /* avoid dirtying the cache heap */
+
+ if(sc = Cache_Check(&sfx->cu), sc != nil)
+ return sc;
+ u = loadstklmp(va("sound/%s", sfx->s), buf, sizeof buf, &len);
+ if(u == nil){
+ fprint(2, "loadsfx: %r\n");
+ return nil;
+ }
+ info = GetWavinfo(sfx->s, u, len);
+ if(info.channels != 1){
+ fprint(2, "loadsfx: non mono wave %s\n", sfx->s);
+ return nil;
+ }
+ stepscale = (float)info.rate / Srate;
+ len = info.samples / stepscale;
+ len *= info.width * info.channels;
+ if(sc = Cache_Alloc(&sfx->cu, len + sizeof *sc, sfx->s), sc == nil)
+ return nil;
+ sc->length = info.samples;
+ sc->loop = info.loopofs;
+ if(info.loopofs >= 0)
+ sc->loop /= stepscale;
+ sc->speed = info.rate;
+ sc->width = info.width;
+ sc->stereo = info.channels;
+ resample(sc, u + info.dataofs, stepscale);
+ return sc;
}
+static void
+sndout(void)
+{
+ int v, vol, *pb, *pe;
+ uchar *p;
+
+ vol = volume.value * 256;
+ p = mixbuf;
+ pb = sampbuf;
+ pe = sampbuf + nsamp * 2;
+ while(pb < pe){
+ v = *pb++ * vol >> 8;
+ if(v > 0x7fff)
+ v = 0x7fff;
+ else if(v < -0x8000)
+ v = -0x8000;
+ p[0] = v;
+ p[1] = v >> 8;
+ p += 2;
+ }
+}
+
+static void
+sample8(Chan *c, void *d, int n)
+{
+ int v, *pb, *pe, *ls, *rs;
+ uchar *p;
+
+ if(c->lvol > 255)
+ c->lvol = 255;
+ if(c->rvol > 255)
+ c->rvol = 255;
+ ls = scalt[c->lvol >> 3];
+ rs = scalt[c->rvol >> 3];
+ p = (uchar *)d + c->p;
+ pb = sampbuf;
+ pe = sampbuf + n * 2;
+ while(pb < pe){
+ v = *p++;
+ *pb++ += ls[v];
+ *pb++ += rs[v];
+ }
+}
+
+static void
+sample16(Chan *c, void *d, int n)
+{
+ int v, *pb, *pe, lv, rv;
+ short *p;
+
+ lv = c->lvol;
+ rv = c->rvol;
+ p = (short *)d + c->p;
+ pb = sampbuf;
+ pe = sampbuf + n * 2;
+ while(pb < pe){
+ v = *p++;
+ *pb++ += v * lv >> 8;
+ *pb++ += v * rv >> 8;
+ }
+}
+
+static void
+samplesfx(void)
+{
+ int n, m;
+ Chan *c;
+ sfxcache_t *sc;
+ void (*sf)(Chan *, void *, int);
+
+ memset(sampbuf, 0, sizeof sampbuf);
+ for(c=chans; c<che; c++){
+ if(c->sfx == nil)
+ continue;
+ if(c->lvol == 0 && c->rvol == 0)
+ continue;
+ if(sc = loadsfx(c->sfx), sc == nil)
+ continue;
+ sf = sc->width == 1 ? sample8 : sample16;
+ n = nsamp;
+ while(n > 0){
+ m = n < c->n ? n : c->n;
+ if(m > 0)
+ sf(c, sc->data, m);
+ c->p += m;
+ c->n -= m;
+ n -= m;
+ if(c->n <= 0){
+ if(sc->loop >= 0){
+ c->p = sc->loop;
+ c->n = sc->length - c->p;
+ }else{
+ c->sfx = nil;
+ break;
+ }
+ }
+ }
+ }
+ sndout();
+}
+
+static void
+spatialize(Chan *c)
+{
+ vec_t Δr, m;
+ vec3_t src;
+
+ if(c->entn == cl.viewentity){
+ c->lvol = c->chvol;
+ c->rvol = c->chvol;
+ return;
+ }
+ VectorSubtract(c->zp, listener_origin, src);
+ Δr = 1.0 - VectorNormalize(src) * c->attf;
+ m = DotProduct(listener_right, src);
+ c->rvol = Δr * (1.0 + m) * c->chvol;
+ if(c->rvol < 0)
+ c->rvol = 0;
+ c->lvol = Δr * (1.0 - m) * c->chvol;
+ if(c->lvol < 0)
+ c->lvol = 0;
+}
+
+static void
+ambs(void)
+{
+ uchar *av;
+ float vol;
+ Chan *c, *e;
+ mleaf_t *l;
+ Sfx **sfx;
+
+ if(cl.worldmodel == nil)
+ return;
+ c = chans;
+ e = chans + Namb;
+ l = Mod_PointInLeaf(listener_origin, cl.worldmodel);
+ if(l == nil || !ambient_level.value){
+ while(c < e)
+ c++->sfx = nil;
+ return;
+ }
+ sfx = ambsfx;
+ av = l->ambient_sound_level;
+ while(c < e){
+ c->sfx = *sfx++;
+ vol = ambient_level.value * *av++;
+ if(vol < 8)
+ vol = 0;
+ if(c->chvol < vol){
+ c->chvol += host_frametime * ambient_fade.value;
+ if(c->chvol > vol)
+ c->chvol = vol;
+ }else if(c->chvol > vol){
+ c->chvol -= host_frametime * ambient_fade.value;
+ if(c->chvol < vol)
+ c->chvol = vol;
+ }
+ c->lvol = c->chvol;
+ c->rvol = c->chvol;
+ c++;
+ }
+}
+
void
-SNDDMA_Shutdown(void)
+stepsnd(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
{
- if(stid < 0)
+ Chan *c, *sum;
+
+ if(afd < 0)
return;
+ VectorCopy(origin, listener_origin);
+ VectorCopy(forward, listener_forward);
+ VectorCopy(right, listener_right);
+ VectorCopy(up, listener_up);
+ ambs();
+ sum = nil;
+ for(c=chans+Namb; c<che; c++){
+ if(c->sfx == nil)
+ continue;
+ spatialize(c);
+ if(c->lvol == 0 && c->rvol == 0)
+ continue;
+ /* sum static sounds to avoid useless remixing */
+ if(c >= chans + Sstat){
+ if(sum != nil && sum->sfx == c->sfx){
+ sum->lvol += c->lvol;
+ sum->rvol += c->rvol;
+ c->lvol = c->rvol = 0;
+ continue;
+ }
+ for(sum=chans + Sstat; sum<c; sum++)
+ if(sum->sfx == c->sfx)
+ break;
+ if(sum == che)
+ sum = nil;
+ else if(sum != c){
+ sum->lvol += c->lvol;
+ sum->rvol += c->rvol;
+ c->lvol = c->rvol = 0;
+ }
+ }
+ }
+ if(sndt == 0)
+ sndt = nsec() - Te9 / Fpsmax;
+ nsamp = (nsec() - sndt) / (Te9 / Srate);
+ if(!cls.timedemo)
+ nsamp = nsamp + 15 & ~15;
+ if(nsamp > Ssamp)
+ nsamp = Ssamp;
+ samplesfx();
+ sampt += nsamp;
+ nsamp *= Sblk;
+ if(write(afd, mixbuf, nsamp) != nsamp){
+ fprint(2, "sndwrite: %r\n");
+ shutsnd();
+ }
+ sndt = nsec();
+}
- threadint(stid);
- stid = -1;
- close(afd);
- free(shm->buffer);
- if(schan != nil)
- chanfree(schan);
- schan = nil;
+void
+stopallsfx(void)
+{
+ if(afd < 0)
+ return;
+ memset(chans, 0, sizeof chans);
+ che = chans + Sstat;
}
void
-SNDDMA_Submit(void)
+stopsfx(int n, int ch)
{
- if(nbsend(schan, nil) < 0){
- fprint(2, "SNDDMA_Submit:nbsend: %r\n");
- SNDDMA_Shutdown();
+ Chan *c, *e;
+
+ if(afd < 0)
+ return;
+ c = chans;
+ e = chans + Ndyn;
+ while(c < e){
+ if(c->entn == n && c->entch == ch){
+ c->sfx = nil;
+ return;
+ }
+ c++;
}
+}
+
+static Chan *
+pickchan(int entn, int entch)
+{
+ int Δt;
+ Chan *c, *p, *e;
+
+ p = nil;
+ Δt = 0x7fffffff;
+ for(c=chans+Namb, e=c+Ndyn; c<e; c++){
+ if(entch != 0 && c->entn == entn
+ && (c->entch == entch || entch == -1)){
+ p = c;
+ break;
+ }
+ if(c->entn == cl.viewentity && entn != cl.viewentity && c->sfx != nil)
+ continue;
+ if(c->n < Δt){
+ Δt = c->n;
+ p = c;
+ }
+ }
+ if(p != nil)
+ p->sfx = nil;
+ return p;
+}
+
+void
+startsfx(int entn, int entch, Sfx *sfx, vec3_t zp, float vol, float att)
+{
+ int skip;
+ Chan *c, *c2, *e;
+ sfxcache_t *sc;
+
+ if(afd < 0 || sfx == nil)
+ return;
+ if(c = pickchan(entn, entch), c == nil)
+ return;
+ memset(c, 0, sizeof *c);
+ VectorCopy(zp, c->zp);
+ c->attf = att / Clipdist;
+ c->chvol = vol * 255;
+ c->entn = entn;
+ c->entch = entch;
+ spatialize(c);
+ if(c->lvol == 0 && c->rvol == 0)
+ return;
+ if(sc = loadsfx(sfx), sc == nil)
+ return;
+ c->sfx = sfx;
+ c->p = 0;
+ c->n = sc->length;
+ /* don't sum identical sfx started on the same frame */
+ for(c2=chans+Namb, e=chans+Sstat; c2<e; c2++){
+ if(c2 == c || c2->sfx != sfx || c2->p != 0)
+ continue;
+ skip = nrand(Srate / Fpsmin);
+ if(skip >= c->n)
+ skip = c->n - 1;
+ c->p += skip;
+ c->n -= skip;
+ break;
+ }
+}
+
+void
+localsfx(char *s)
+{
+ Sfx *sfx;
+
+ if(afd < 0)
+ return;
+ sfx = precachesfx(s);
+ startsfx(cl.viewentity, -1, sfx, vec3_origin, 1, 1);
+}
+
+void
+staticsfx(Sfx *sfx, vec3_t zp, float vol, float att)
+{
+ Chan *c;
+ sfxcache_t *sc;
+
+ if(sfx == nil)
+ return;
+ if(che >= chans + nelem(chans)){
+ fprint(2, "staticsfx: channel overflow\n");
+ return;
+ }
+ c = che++;
+ if(sc = loadsfx(sfx), sc == nil)
+ return;
+ if(sc->loop < 0){
+ fprint(2, "staticsfx %s: nonlooped static sound\n", sfx->s);
+ return;
+ }
+ c->sfx = sfx;
+ VectorCopy(zp, c->zp);
+ c->chvol = vol;
+ c->attf = (att / 64) / Clipdist;
+ c->n = sc->length;
+ spatialize(c);
+}
+
+static Sfx *
+findsfx(char *s)
+{
+ Sfx *sfx, *e;
+
+ if(s == nil)
+ fatal("findsfx: nil pointer\n");
+ if(strlen(s) >= Npath)
+ fatal("findsfx: path too long %s", s);
+ sfx = known_sfx;
+ e = known_sfx + num_sfx;
+ while(sfx < e){
+ if(strcmp(sfx->s, s) == 0)
+ return sfx;
+ sfx++;
+ }
+ if(num_sfx == MAX_SFX)
+ fatal("findsfx: sfx list overflow");
+ strcpy(sfx->s, s);
+ num_sfx++;
+ return sfx;
+}
+
+void
+touchsfx(char *s)
+{
+ Sfx *sfx;
+
+ if(afd < 0)
+ return;
+ sfx = findsfx(s);
+ Cache_Check(&sfx->cu);
+}
+
+Sfx *
+precachesfx(char *s)
+{
+ Sfx *sfx;
+
+ if(afd < 0)
+ return nil;
+ sfx = findsfx(s);
+ if(precache.value)
+ loadsfx(sfx);
+ return sfx;
+}
+
+static void
+playsfx(void)
+{
+ static int hash = 345;
+ int i;
+ char *s;
+ Sfx *sfx;
+
+ if(Cmd_Argc() < 2){
+ Con_Printf("play wav [wav..]: play a wav lump\n");
+ return;
+ }
+ i = 1;
+ while(i < Cmd_Argc()){
+ if(strrchr(Cmd_Argv(i), '.') == nil)
+ s = va("%s.wav", Cmd_Argv(i));
+ else
+ s = Cmd_Argv(i);
+ sfx = precachesfx(s);
+ startsfx(hash++, 0, sfx, listener_origin, 1.0, 1.0);
+ i++;
+ }
+}
+
+static void
+playvolsfx(void)
+{
+ static int hash = 543;
+ int i;
+ float vol;
+ char *s;
+ Sfx *sfx;
+
+ if(Cmd_Argc() < 3){
+ Con_Printf("play wav vol [wav vol]..: play an amplified wav lump\n");
+ return;
+ }
+ i = 1;
+ while(i < Cmd_Argc()){
+ if(strrchr(Cmd_Argv(i), '.') == nil)
+ s = va("%s.wav", Cmd_Argv(i));
+ else
+ s = Cmd_Argv(i);
+ sfx = precachesfx(s);
+ vol = atof(Cmd_Argv(++i));
+ startsfx(hash++, 0, sfx, listener_origin, vol, 1.0);
+ i++;
+ }
+}
+
+static void
+sfxlist(void)
+{
+ char c;
+ int sz, sum;
+ Sfx *sfx, *e;
+ sfxcache_t *sc;
+
+ sum = 0;
+ for(sfx=known_sfx, e=known_sfx+num_sfx; sfx<e; sfx++){
+ if(sc = Cache_Check(&sfx->cu), sc == nil)
+ continue;
+ sz = sc->length * sc->width * (sc->stereo + 1);
+ sum += sz;
+ c = sc->loop >= 0 ? 'L' : ' ';
+ Con_Printf("%c(%2db) %6d : %s\n", c, sc->width * 8, sz, sfx->s);
+ }
+ Con_Printf("Total resident: %d\n", sum);
+}
+
+void
+shutsnd(void)
+{
+ if(afd < 0)
+ return;
+ close(afd);
+}
+
+int
+initsnd(void)
+{
+ int i, j, *p;
+
+ if(afd = open("/dev/audio", OWRITE), afd < 0)
+ return -1;
+ for(p=scalt[1], i=8; i<8*nelem(scalt); i+=8)
+ for(j=0; j<256; j++)
+ *p++ = (char)j * i;
+ Cmd_AddCommand("play", playsfx);
+ Cmd_AddCommand("playvol", playvolsfx);
+ Cmd_AddCommand("stopsound", stopallsfx);
+ Cmd_AddCommand("soundlist", sfxlist);
+ Cvar_RegisterVariable(&volume);
+ Cvar_RegisterVariable(&precache);
+ Cvar_RegisterVariable(&loadas8bit);
+ Cvar_RegisterVariable(&bgmvolume);
+ Cvar_RegisterVariable(&ambient_level);
+ Cvar_RegisterVariable(&ambient_fade);
+
+ if(host_parms.memsize < 0x800000){
+ setcvar("loadas8bit", "1");
+ fprint(2, "initsnd: forcing 8bit width\n");
+ }
+ known_sfx = Hunk_AllocName(MAX_SFX * sizeof *known_sfx, "Sfx");
+ num_sfx = 0;
+ ambsfx[Ambwater] = precachesfx("ambience/water1.wav");
+ ambsfx[Ambsky] = precachesfx("ambience/wind2.wav");
+ stopallsfx();
+ return 0;
}
--- a/snd_dma.c
+++ /dev/null
@@ -1,916 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "dat.h"
-#include "quakedef.h"
-#include "fns.h"
-
-void S_Play(void);
-void S_PlayVol(void);
-void S_SoundList(void);
-void S_Update_(void);
-void S_StopAllSounds(qboolean clear);
-void S_StopAllSoundsC(void);
-
-// =======================================================================
-// Internal sound data & structures
-// =======================================================================
-
-channel_t channels[MAX_CHANNELS];
-int total_channels;
-
-int snd_blocked = 0;
-static qboolean snd_ambient = 1;
-static qboolean snd_initialized;
-
-// pointer should go away
-volatile dma_t *shm;
-volatile dma_t sn;
-
-vec3_t listener_origin;
-vec3_t listener_forward;
-vec3_t listener_right;
-vec3_t listener_up;
-vec_t sound_nominal_clip_dist=1000.0;
-
-int soundtime; // sample PAIRS
-int paintedtime; // sample PAIRS
-
-
-#define MAX_SFX 512
-sfx_t *known_sfx; // hunk allocated [MAX_SFX]
-int num_sfx;
-
-sfx_t *ambient_sfx[NUM_AMBIENTS];
-
-int desired_speed = 11025;
-int desired_bits = 16;
-
-int sound_started=0;
-
-cvar_t bgmvolume = {"bgmvolume", "1", true};
-cvar_t volume = {"volume", "0.7", true};
-
-cvar_t nosound = {"nosound", "0"};
-cvar_t precache = {"precache", "1"};
-cvar_t loadas8bit = {"loadas8bit", "0"};
-cvar_t bgmbuffer = {"bgmbuffer", "4096"};
-cvar_t ambient_level = {"ambient_level", "0.3"};
-cvar_t ambient_fade = {"ambient_fade", "100"};
-cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"};
-cvar_t snd_show = {"snd_show", "0"};
-cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true};
-
-
-// ====================================================================
-// User-setable variables
-// ====================================================================
-
-
-//
-// Fake dma is a synchronous faking of the DMA progress used for
-// isolating performance in the renderer. The fakedma_updates is
-// number of times S_Update() is called per second.
-//
-
-qboolean fakedma = false;
-int fakedma_updates = 15;
-
-
-void S_AmbientOff (void)
-{
- snd_ambient = false;
-}
-
-
-void S_AmbientOn (void)
-{
- snd_ambient = true;
-}
-
-
-void S_SoundInfo_f(void)
-{
- if (!sound_started || !shm)
- {
- Con_Printf ("sound system not started\n");
- return;
- }
-
- Con_Printf("%5d stereo\n", shm->channels - 1);
- Con_Printf("%5d samples\n", shm->samples);
- Con_Printf("%5d samplepos\n", shm->samplepos);
- Con_Printf("%5d samplebits\n", shm->samplebits);
- Con_Printf("%5d submission_chunk\n", shm->submission_chunk);
- Con_Printf("%5d speed\n", shm->speed);
- Con_Printf("%#p dma buffer\n", shm->buffer);
- Con_Printf("%5d total_channels\n", total_channels);
-}
-
-
-/*
-================
-S_Startup
-================
-*/
-
-void S_Startup (void)
-{
- int rc;
-
- if (!snd_initialized)
- return;
-
- if (!fakedma)
- {
- rc = SNDDMA_Init();
-
- if (!rc)
- {
- Con_Printf("S_Startup: SNDDMA_Init failed.\n");
- sound_started = 0;
- return;
- }
- }
-
- sound_started = 1;
-}
-
-
-/*
-================
-S_Init
-================
-*/
-void S_Init (void)
-{
-
- Con_Printf("\nSound Initialization\n");
-
- if (COM_CheckParm("-nosound"))
- return;
-
- if (COM_CheckParm("-simsound"))
- fakedma = true;
-
- Cmd_AddCommand("play", S_Play);
- Cmd_AddCommand("playvol", S_PlayVol);
- Cmd_AddCommand("stopsound", S_StopAllSoundsC);
- Cmd_AddCommand("soundlist", S_SoundList);
- Cmd_AddCommand("soundinfo", S_SoundInfo_f);
-
- Cvar_RegisterVariable(&nosound);
- Cvar_RegisterVariable(&volume);
- Cvar_RegisterVariable(&precache);
- Cvar_RegisterVariable(&loadas8bit);
- Cvar_RegisterVariable(&bgmvolume);
- Cvar_RegisterVariable(&bgmbuffer);
- Cvar_RegisterVariable(&ambient_level);
- Cvar_RegisterVariable(&ambient_fade);
- Cvar_RegisterVariable(&snd_noextraupdate);
- Cvar_RegisterVariable(&snd_show);
- Cvar_RegisterVariable(&_snd_mixahead);
-
- if (host_parms.memsize < 0x800000)
- {
- setcvar("loadas8bit", "1");
- Con_Printf ("loading all sounds as 8bit\n");
- }
-
- snd_initialized = true;
-
- S_Startup ();
-
- SND_InitScaletable ();
-
- known_sfx = Hunk_AllocName(MAX_SFX * sizeof *known_sfx, "sfx_t");
- num_sfx = 0;
-
-// create a piece of DMA memory
-
- if (fakedma)
- {
- shm = Hunk_AllocName(sizeof *shm, "shm");
- shm->splitbuffer = 0;
- shm->samplebits = 16;
- shm->speed = 22050;
- shm->channels = 2;
- shm->samples = 32768;
- shm->samplepos = 0;
- shm->soundalive = true;
- shm->gamealive = true;
- shm->submission_chunk = 1;
- shm->buffer = Hunk_AllocName(1<<16, "shmbuf");
- }
-
- if(shm != nil)
- Con_Printf ("Sound sampling rate: %d\n", shm->speed);
-
- // provides a tick sound until washed clean
-
-// if (shm->buffer)
-// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging
-
- ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
- ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
-
- S_StopAllSounds (true);
-}
-
-
-// =======================================================================
-// Shutdown sound engine
-// =======================================================================
-
-void S_Shutdown(void)
-{
- if(!sound_started)
- return;
- if(shm != nil)
- shm->gamealive = 0;
- if(!fakedma)
- SNDDMA_Shutdown();
- shm = nil;
- sound_started = 0;
-}
-
-
-// =======================================================================
-// Load a sound
-// =======================================================================
-
-/*
-==================
-S_FindName
-
-==================
-*/
-sfx_t *S_FindName (char *name)
-{
- int i;
- sfx_t *sfx;
-
- if (name == nil)
- fatal ("S_FindName: NULL\n");
-
- if(strlen(name) >= Npath)
- fatal ("Sound name too long: %s", name);
-
-// see if already loaded
- for (i=0 ; i < num_sfx ; i++)
- if(strcmp(known_sfx[i].name, name) == 0)
- return &known_sfx[i];
-
- if (num_sfx == MAX_SFX)
- fatal ("S_FindName: out of sfx_t");
-
- sfx = &known_sfx[i];
- strcpy (sfx->name, name);
-
- num_sfx++;
-
- return sfx;
-}
-
-
-/*
-==================
-S_TouchSound
-
-==================
-*/
-void S_TouchSound (char *name)
-{
- sfx_t *sfx;
-
- if (!sound_started)
- return;
-
- sfx = S_FindName (name);
- Cache_Check (&sfx->cache);
-}
-
-/*
-==================
-S_PrecacheSound
-
-==================
-*/
-sfx_t *S_PrecacheSound (char *name)
-{
- sfx_t *sfx;
-
- if (!sound_started || nosound.value)
- return nil;
-
- sfx = S_FindName (name);
-
-// cache it in
- if (precache.value)
- S_LoadSound (sfx);
-
- return sfx;
-}
-
-
-//=============================================================================
-
-/*
-=================
-SND_PickChannel
-=================
-*/
-channel_t *SND_PickChannel(int entnum, int entchannel)
-{
- int ch_idx;
- int first_to_die;
- int life_left;
-
-// Check for replacement sound, or find the best one to replace
- first_to_die = -1;
- life_left = 0x7fffffff;
- for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
- {
- if (entchannel != 0 // channel 0 never overrides
- && channels[ch_idx].entnum == entnum
- && (channels[ch_idx].entchannel == entchannel || entchannel == -1) )
- { // allways override sound from same entity
- first_to_die = ch_idx;
- break;
- }
-
- // don't let monster sounds override player sounds
- if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx)
- continue;
-
- if (channels[ch_idx].end - paintedtime < life_left)
- {
- life_left = channels[ch_idx].end - paintedtime;
- first_to_die = ch_idx;
- }
- }
-
- if (first_to_die == -1)
- return nil;
-
- if (channels[first_to_die].sfx)
- channels[first_to_die].sfx = nil;
-
- return &channels[first_to_die];
-}
-
-/*
-=================
-SND_Spatialize
-=================
-*/
-void SND_Spatialize(channel_t *ch)
-{
- vec_t dot;
- vec_t dist;
- vec_t lscale, rscale, scale;
- vec3_t source_vec;
-
-// anything coming from the view entity will allways be full volume
- if (ch->entnum == cl.viewentity)
- {
- ch->leftvol = ch->master_vol;
- ch->rightvol = ch->master_vol;
- return;
- }
-
-// calculate stereo seperation and distance attenuation
-
- VectorSubtract(ch->origin, listener_origin, source_vec);
-
- dist = VectorNormalize(source_vec) * ch->dist_mult;
-
- dot = DotProduct(listener_right, source_vec);
-
- if (shm->channels == 1)
- {
- rscale = 1.0;
- lscale = 1.0;
- }
- else
- {
- rscale = 1.0 + dot;
- lscale = 1.0 - dot;
- }
-
-// add in distance effect
- scale = (1.0 - dist) * rscale;
- ch->rightvol = (int) (ch->master_vol * scale);
- if (ch->rightvol < 0)
- ch->rightvol = 0;
-
- scale = (1.0 - dist) * lscale;
- ch->leftvol = (int) (ch->master_vol * scale);
- if (ch->leftvol < 0)
- ch->leftvol = 0;
-}
-
-
-// =======================================================================
-// Start a sound effect
-// =======================================================================
-
-void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
-{
- channel_t *target_chan, *check;
- sfxcache_t *sc;
- int vol;
- int ch_idx;
- int skip;
-
- if (!sound_started)
- return;
-
- if (!sfx)
- return;
-
- if (nosound.value)
- return;
-
- vol = fvol*255;
-
-// pick a channel to play on
- target_chan = SND_PickChannel(entnum, entchannel);
- if (!target_chan)
- return;
-
-// spatialize
- memset(target_chan, 0, sizeof *target_chan);
- VectorCopy(origin, target_chan->origin);
- target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
- target_chan->master_vol = vol;
- target_chan->entnum = entnum;
- target_chan->entchannel = entchannel;
- SND_Spatialize(target_chan);
-
- if (!target_chan->leftvol && !target_chan->rightvol)
- return; // not audible at all
-
-// new channel
- sc = S_LoadSound (sfx);
- if (!sc)
- {
- target_chan->sfx = nil;
- return; // couldn't load the sound's data
- }
-
- target_chan->sfx = sfx;
- target_chan->pos = 0.0;
- target_chan->end = paintedtime + sc->length;
-
-// if an identical sound has also been started this frame, offset the pos
-// a bit to keep it from just making the first one louder
- check = &channels[NUM_AMBIENTS];
- for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++)
- {
- if (check == target_chan)
- continue;
- if (check->sfx == sfx && !check->pos)
- {
- skip = rand () % (int)(0.1*shm->speed);
- if (skip >= target_chan->end)
- skip = target_chan->end - 1;
- target_chan->pos += skip;
- target_chan->end -= skip;
- break;
- }
-
- }
-}
-
-void S_StopSound(int entnum, int entchannel)
-{
- int i;
-
- for (i=0 ; i<MAX_DYNAMIC_CHANNELS ; i++)
- {
- if (channels[i].entnum == entnum
- && channels[i].entchannel == entchannel)
- {
- channels[i].end = 0;
- channels[i].sfx = nil;
- return;
- }
- }
-}
-
-void S_StopAllSounds(qboolean clear)
-{
- int i;
-
- if (!sound_started)
- return;
-
- total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics
-
- for (i=0 ; i<MAX_CHANNELS ; i++)
- if (channels[i].sfx)
- channels[i].sfx = nil;
-
- memset(channels, 0, sizeof channels);
-
- if (clear)
- S_ClearBuffer ();
-}
-
-void S_StopAllSoundsC (void)
-{
- S_StopAllSounds (true);
-}
-
-void S_ClearBuffer (void)
-{
- int clear;
-
- if (!sound_started || shm == nil || shm->buffer == nil)
- return;
-
- if (shm->samplebits == 8)
- clear = 0x80;
- else
- clear = 0;
-
- memset(shm->buffer, clear, shm->samples * shm->samplebits/8);
-}
-
-
-/*
-=================
-S_StaticSound
-=================
-*/
-void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
-{
- channel_t *ss;
- sfxcache_t *sc;
-
- if (!sfx)
- return;
-
- if (total_channels == MAX_CHANNELS)
- {
- Con_Printf ("total_channels == MAX_CHANNELS\n");
- return;
- }
-
- ss = &channels[total_channels];
- total_channels++;
-
- sc = S_LoadSound (sfx);
- if (!sc)
- return;
-
- if (sc->loopstart == -1)
- {
- Con_Printf ("Sound %s not looped\n", sfx->name);
- return;
- }
-
- ss->sfx = sfx;
- VectorCopy (origin, ss->origin);
- ss->master_vol = vol;
- ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
- ss->end = paintedtime + sc->length;
-
- SND_Spatialize (ss);
-}
-
-
-//=============================================================================
-
-/*
-===================
-S_UpdateAmbientSounds
-===================
-*/
-void S_UpdateAmbientSounds (void)
-{
- mleaf_t *l;
- float vol;
- int ambient_channel;
- channel_t *chan;
-
- if (!snd_ambient)
- return;
-
-// calc ambient sound levels
- if (!cl.worldmodel)
- return;
-
- l = Mod_PointInLeaf (listener_origin, cl.worldmodel);
- if (!l || !ambient_level.value)
- {
- for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
- channels[ambient_channel].sfx = nil;
- return;
- }
-
- for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
- {
- chan = &channels[ambient_channel];
- chan->sfx = ambient_sfx[ambient_channel];
-
- vol = ambient_level.value * l->ambient_sound_level[ambient_channel];
- if (vol < 8)
- vol = 0;
-
- // don't adjust volume too fast
- if (chan->master_vol < vol)
- {
- chan->master_vol += host_frametime * ambient_fade.value;
- if (chan->master_vol > vol)
- chan->master_vol = vol;
- }
- else if (chan->master_vol > vol)
- {
- chan->master_vol -= host_frametime * ambient_fade.value;
- if (chan->master_vol < vol)
- chan->master_vol = vol;
- }
-
- chan->leftvol = chan->rightvol = chan->master_vol;
- }
-}
-
-
-/*
-============
-S_Update
-
-Called once each time through the main loop
-============
-*/
-void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
-{
- int i, j;
- int total;
- channel_t *ch;
- channel_t *combine;
-
- if (!sound_started || (snd_blocked > 0))
- return;
-
- VectorCopy(origin, listener_origin);
- VectorCopy(forward, listener_forward);
- VectorCopy(right, listener_right);
- VectorCopy(up, listener_up);
-
-// update general area ambient sound sources
- S_UpdateAmbientSounds ();
-
- combine = nil;
-
-// update spatialization for static and dynamic sounds
- ch = channels+NUM_AMBIENTS;
- for (i=NUM_AMBIENTS ; i<total_channels; i++, ch++)
- {
- if (!ch->sfx)
- continue;
- SND_Spatialize(ch); // respatialize channel
- if (!ch->leftvol && !ch->rightvol)
- continue;
-
- // try to combine static sounds with a previous channel of the same
- // sound effect so we don't mix five torches every frame
-
- if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS)
- {
- // see if it can just use the last one
- if (combine && combine->sfx == ch->sfx)
- {
- combine->leftvol += ch->leftvol;
- combine->rightvol += ch->rightvol;
- ch->leftvol = ch->rightvol = 0;
- continue;
- }
- // search for one
- combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;
- for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; j<i; j++, combine++)
- if (combine->sfx == ch->sfx)
- break;
-
- if (j == total_channels)
- {
- combine = nil;
- }
- else
- {
- if (combine != ch)
- {
- combine->leftvol += ch->leftvol;
- combine->rightvol += ch->rightvol;
- ch->leftvol = ch->rightvol = 0;
- }
- continue;
- }
- }
-
-
- }
-
-//
-// debugging output
-//
- if (snd_show.value)
- {
- total = 0;
- ch = channels;
- for (i=0 ; i<total_channels; i++, ch++)
- if (ch->sfx && (ch->leftvol || ch->rightvol) )
- {
- //Con_Printf ("%3d %3d %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
- total++;
- }
-
- Con_Printf ("----(%d)----\n", total);
- }
-
-// mix some sound
- S_Update_();
-}
-
-void GetSoundtime(void)
-{
- uint samplepos;
- static int buffers;
- static uint oldsamplepos;
- int fullsamples;
-
- fullsamples = shm->samples / shm->channels;
-
-// it is possible to miscount buffers if it has wrapped twice between
-// calls to S_Update. Oh well.
- samplepos = SNDDMA_GetDMAPos();
-
-
- if (samplepos < oldsamplepos)
- {
- buffers++; // buffer wrapped
-
- if (paintedtime > 0x40000000)
- { // time to chop things off to avoid 32 bit limits
- buffers = 0;
- paintedtime = fullsamples;
- S_StopAllSounds (true);
- }
- }
- oldsamplepos = samplepos;
-
- soundtime = buffers*fullsamples + samplepos/shm->channels;
-}
-
-void S_ExtraUpdate (void)
-{
-
- if (snd_noextraupdate.value)
- return; // don't pollute timings
- S_Update_();
-}
-
-void S_Update_(void)
-{
- unsigned endtime;
- int samps;
-
- if (!sound_started || (snd_blocked > 0))
- return;
-
-// Updates DMA time
- GetSoundtime();
-
-// check to make sure that we haven't overshot
- if (paintedtime < soundtime)
- {
- //Con_Printf ("S_Update_ : overflow\n");
- paintedtime = soundtime;
- }
-
-// mix ahead of current position
- endtime = soundtime + _snd_mixahead.value * shm->speed;
- samps = shm->samples >> (shm->channels-1);
- if (endtime - soundtime > samps)
- endtime = soundtime + samps;
-
- S_PaintChannels (endtime);
-
- SNDDMA_Submit ();
-}
-
-/*
-===============================================================================
-
-console functions
-
-===============================================================================
-*/
-
-void S_Play(void)
-{
- static int hash=345;
- int i;
- char name[256];
- sfx_t *sfx;
-
- i = 1;
- while (i<Cmd_Argc())
- {
- if(strrchr(Cmd_Argv(i), '.') == nil)
- {
- strcpy(name, Cmd_Argv(i));
- strcat(name, ".wav");
- }
- else
- strcpy(name, Cmd_Argv(i));
- sfx = S_PrecacheSound(name);
- S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0);
- i++;
- }
-}
-
-void S_PlayVol(void)
-{
- static int hash=543;
- int i;
- float vol;
- char name[256];
- sfx_t *sfx;
-
- i = 1;
- while (i<Cmd_Argc())
- {
- if(strrchr(Cmd_Argv(i), '.') == nil)
- {
- strcpy(name, Cmd_Argv(i));
- strcat(name, ".wav");
- }
- else
- strcpy(name, Cmd_Argv(i));
- sfx = S_PrecacheSound(name);
- vol = atof(Cmd_Argv(i+1));
- S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0);
- i+=2;
- }
-}
-
-void S_SoundList(void)
-{
- int i;
- sfx_t *sfx;
- sfxcache_t *sc;
- int size, total;
-
- total = 0;
- for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
- {
- sc = Cache_Check (&sfx->cache);
- if (!sc)
- continue;
- size = sc->length*sc->width*(sc->stereo+1);
- total += size;
- if (sc->loopstart >= 0)
- Con_Printf ("L");
- else
- Con_Printf (" ");
- Con_Printf("(%2db) %6d : %s\n",sc->width*8, size, sfx->name);
- }
- Con_Printf ("Total resident: %d\n", total);
-}
-
-
-void S_LocalSound (char *sound)
-{
- sfx_t *sfx;
-
- if (nosound.value)
- return;
- if (!sound_started)
- return;
-
- sfx = S_PrecacheSound (sound);
- if (!sfx)
- {
- Con_Printf ("S_LocalSound: can't cache %s\n", sound);
- return;
- }
- S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1);
-}
-
-
-void S_ClearPrecache (void)
-{
-}
-
-
-void S_BeginPrecaching (void)
-{
-}
-
-
-void S_EndPrecaching (void)
-{
-}
-
--- a/snd_mem.c
+++ /dev/null
@@ -1,324 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "dat.h"
-#include "quakedef.h"
-#include "fns.h"
-
-int cache_full_cycle;
-
-byte *S_Alloc (int size);
-
-/*
-================
-ResampleSfx
-================
-*/
-void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data)
-{
- int outcount;
- int srcsample;
- float stepscale;
- int i;
- int sample, samplefrac, fracstep;
- sfxcache_t *sc;
-
- sc = Cache_Check (&sfx->cache);
- if (!sc)
- return;
-
- stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2
-
- outcount = sc->length / stepscale;
- sc->length = outcount;
- if (sc->loopstart != -1)
- sc->loopstart = sc->loopstart / stepscale;
-
- sc->speed = shm->speed;
- if (loadas8bit.value)
- sc->width = 1;
- else
- sc->width = inwidth;
- sc->stereo = 0;
-
-// resample / decimate to the current source rate
-
- if (stepscale == 1 && inwidth == 1 && sc->width == 1)
- {
-// fast special case
- for (i=0 ; i<outcount ; i++)
- ((signed char *)sc->data)[i]
- = (int)( (unsigned char)(data[i]) - 128);
- }
- else
- {
-// general case
- samplefrac = 0;
- fracstep = stepscale*256;
- for (i=0 ; i<outcount ; i++)
- {
- srcsample = samplefrac >> 8;
- samplefrac += fracstep;
- if (inwidth == 2)
- sample = LittleShort ( ((short *)data)[srcsample] );
- else
- sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
- if (sc->width == 2)
- ((short *)sc->data)[i] = sample;
- else
- ((signed char *)sc->data)[i] = sample >> 8;
- }
- }
-}
-
-//=============================================================================
-
-/*
-==============
-S_LoadSound
-==============
-*/
-sfxcache_t *S_LoadSound (sfx_t *s)
-{
- char namebuffer[256];
- byte *data;
- wavinfo_t info;
- int len;
- float stepscale;
- sfxcache_t *sc;
- byte stackbuf[1*1024]; // avoid dirtying the cache heap
-
-// see if still in memory
- sc = Cache_Check (&s->cache);
- if (sc)
- return sc;
-
-//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf);
-// load it in
- strcpy(namebuffer, "sound/");
- strcat(namebuffer, s->name);
-
-// Con_Printf ("loading %s\n",namebuffer);
-
- data = loadstklmp(namebuffer, stackbuf, sizeof stackbuf, &len);
- if(data == nil){
- Con_Printf("Couldn't load %s: %r\n", namebuffer);
- return nil;
- }
-
- info = GetWavinfo (s->name, data, len);
- if (info.channels != 1)
- {
- Con_Printf ("%s is a stereo sample\n",s->name);
- return nil;
- }
-
- stepscale = (float)info.rate / shm->speed;
- len = info.samples / stepscale;
-
- len = len * info.width * info.channels;
-
- sc = Cache_Alloc(&s->cache, len + sizeof *sc, s->name);
- if (!sc)
- return nil;
-
- sc->length = info.samples;
- sc->loopstart = info.loopstart;
- sc->speed = info.rate;
- sc->width = info.width;
- sc->stereo = info.channels;
-
- ResampleSfx (s, sc->speed, sc->width, data + info.dataofs);
-
- return sc;
-}
-
-
-
-/*
-===============================================================================
-
-WAV loading
-
-===============================================================================
-*/
-
-
-byte *data_p;
-byte *iff_end;
-byte *last_chunk;
-byte *iff_data;
-int iff_chunk_len;
-
-
-short GetLittleShort(void)
-{
- short val;
-
- val = *data_p;
- val = val + (*(data_p+1)<<8);
- data_p += 2;
- return val;
-}
-
-int GetLittleLong(void)
-{
- int val;
-
- val = *data_p;
- val = val + (*(data_p+1)<<8);
- val = val + (*(data_p+2)<<16);
- val = val + (*(data_p+3)<<24);
- data_p += 4;
- return val;
-}
-
-void FindNextChunk(char *name)
-{
- while (1)
- {
- data_p=last_chunk;
-
- if (data_p >= iff_end)
- { // didn't find the chunk
- data_p = nil;
- return;
- }
-
- data_p += 4;
- iff_chunk_len = GetLittleLong();
- if (iff_chunk_len < 0)
- {
- data_p = nil;
- return;
- }
-// if (iff_chunk_len > 1024*1024)
-// fatal ("FindNextChunk: %d length is past the 1 meg sanity limit", iff_chunk_len);
- data_p -= 8;
- last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
- if(strncmp((char *)data_p, name, 4) == 0)
- return;
- }
-}
-
-void FindChunk(char *name)
-{
- last_chunk = iff_data;
- FindNextChunk (name);
-}
-
-
-void DumpChunks(void)
-{
- char str[5];
-
- str[4] = 0;
- data_p=iff_data;
- do
- {
- memcpy (str, data_p, 4);
- data_p += 4;
- iff_chunk_len = GetLittleLong();
- Con_Printf ("0x%zud : %s (%d)\n", (uintptr)(data_p - 4), str, iff_chunk_len);
- data_p += (iff_chunk_len + 1) & ~1;
- } while (data_p < iff_end);
-}
-
-/*
-============
-GetWavinfo
-============
-*/
-wavinfo_t GetWavinfo (char *name, byte *wav, vlong wavlength)
-{
- wavinfo_t info;
- int i;
- int format;
- int samples;
-
- memset(&info, 0, sizeof info);
-
- if (!wav)
- return info;
-
- iff_data = wav;
- iff_end = wav + wavlength;
-
-// find "RIFF" chunk
- FindChunk("RIFF");
- if(!(data_p && strncmp((char *)data_p+8, "WAVE", 4) == 0))
- {
- Con_Printf("Missing RIFF/WAVE chunks\n");
- return info;
- }
-
-// get "fmt " chunk
- iff_data = data_p + 12;
-// DumpChunks ();
-
- FindChunk("fmt ");
- if (!data_p)
- {
- Con_Printf("Missing fmt chunk\n");
- return info;
- }
- data_p += 8;
- format = GetLittleShort();
- if (format != 1)
- {
- Con_Printf("Microsoft PCM format only\n");
- return info;
- }
-
- info.channels = GetLittleShort();
- info.rate = GetLittleLong();
- data_p += 4+2;
- info.width = GetLittleShort() / 8;
-
-// get cue chunk
- FindChunk("cue ");
- if (data_p)
- {
- data_p += 32;
- info.loopstart = GetLittleLong();
-// Con_Printf("loopstart=%d\n", sfx->loopstart);
-
- // if the next chunk is a LIST chunk, look for a cue length marker
- FindNextChunk ("LIST");
- if (data_p)
- {
- if(strncmp((char *)data_p+28, "mark", 4) == 0)
- { // this is not a proper parse, but it works with cooledit...
- data_p += 24;
- i = GetLittleLong (); // samples in loop
- info.samples = info.loopstart + i;
-// Con_Printf("looped length: %d\n", i);
- }
- }
- }
- else
- info.loopstart = -1;
-
-// find data chunk
- FindChunk("data");
- if (!data_p)
- {
- Con_Printf("Missing data chunk\n");
- return info;
- }
-
- data_p += 4;
- samples = GetLittleLong () / info.width;
-
- if (info.samples)
- {
- if (samples < info.samples)
- fatal ("Sound %s has a bad loop length", name);
- }
- else
- info.samples = samples;
-
- info.dataofs = data_p - wav;
-
- return info;
-}
-
--- a/snd_mix.c
+++ /dev/null
@@ -1,278 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "dat.h"
-#include "quakedef.h"
-#include "fns.h"
-
-#define DWORD u32int
-
-#define PAINTBUFFER_SIZE 512
-portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
-int snd_scaletable[32][256];
-int *snd_p, snd_linear_count, snd_vol;
-short *snd_out;
-
-
-void Snd_WriteLinearBlastStereo16 (void)
-{
- int i;
- int val;
-
- for (i=0 ; i<snd_linear_count ; i+=2)
- {
- val = (snd_p[i]*snd_vol)>>8;
- if (val > 0x7fff)
- snd_out[i] = 0x7fff;
- else if (val < (short)0x8000)
- snd_out[i] = (short)0x8000;
- else
- snd_out[i] = val;
-
- val = (snd_p[i+1]*snd_vol)>>8;
- if (val > 0x7fff)
- snd_out[i+1] = 0x7fff;
- else if (val < (short)0x8000)
- snd_out[i+1] = (short)0x8000;
- else
- snd_out[i+1] = val;
- }
-}
-
-void S_TransferStereo16 (int endtime)
-{
- int lpos;
- int lpaintedtime;
- DWORD *pbuf;
-
- snd_vol = volume.value*256;
-
- snd_p = (int *) paintbuffer;
- lpaintedtime = paintedtime;
-
- pbuf = (DWORD *)shm->buffer;
-
- while (lpaintedtime < endtime)
- {
- // handle recirculating buffer issues
- lpos = lpaintedtime & ((shm->samples>>1)-1);
-
- snd_out = (short *) pbuf + (lpos<<1);
-
- snd_linear_count = (shm->samples>>1) - lpos;
- if (lpaintedtime + snd_linear_count > endtime)
- snd_linear_count = endtime - lpaintedtime;
-
- snd_linear_count <<= 1;
-
- // write a linear blast of samples
- Snd_WriteLinearBlastStereo16 ();
-
- snd_p += snd_linear_count;
- lpaintedtime += (snd_linear_count>>1);
- }
-}
-
-void S_TransferPaintBuffer(int endtime)
-{
- int out_idx;
- int count;
- int out_mask;
- int *p;
- int step;
- int val;
- int snd_vol;
- DWORD *pbuf;
-
- if (shm->samplebits == 16 && shm->channels == 2)
- {
- S_TransferStereo16 (endtime);
- return;
- }
-
- p = (int *) paintbuffer;
- count = (endtime - paintedtime) * shm->channels;
- out_mask = shm->samples - 1;
- out_idx = paintedtime * shm->channels & out_mask;
- step = 3 - shm->channels;
- snd_vol = volume.value*256;
-
- pbuf = (DWORD *)shm->buffer;
-
- if (shm->samplebits == 16)
- {
- short *out = (short *) pbuf;
- while (count--)
- {
- val = (*p * snd_vol) >> 8;
- p+= step;
- if (val > 0x7fff)
- val = 0x7fff;
- else if (val < (short)0x8000)
- val = (short)0x8000;
- out[out_idx] = val;
- out_idx = (out_idx + 1) & out_mask;
- }
- }
- else if (shm->samplebits == 8)
- {
- unsigned char *out = (unsigned char *) pbuf;
- while (count--)
- {
- val = (*p * snd_vol) >> 8;
- p+= step;
- if (val > 0x7fff)
- val = 0x7fff;
- else if (val < (short)0x8000)
- val = (short)0x8000;
- out[out_idx] = (val>>8) + 128;
- out_idx = (out_idx + 1) & out_mask;
- }
- }
-}
-
-
-/*
-===============================================================================
-
-CHANNEL MIXING
-
-===============================================================================
-*/
-
-void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime);
-void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime);
-
-void S_PaintChannels(int endtime)
-{
- int i;
- int end;
- channel_t *ch;
- sfxcache_t *sc;
- int ltime, count;
-
- while (paintedtime < endtime)
- {
- // if paintbuffer is smaller than DMA buffer
- end = endtime;
- if (endtime - paintedtime > PAINTBUFFER_SIZE)
- end = paintedtime + PAINTBUFFER_SIZE;
-
- // clear the paint buffer
- memset(paintbuffer, 0, (end - paintedtime) * sizeof *paintbuffer);
-
- // paint in the channels.
- ch = channels;
- for (i=0; i<total_channels ; i++, ch++)
- {
- if (!ch->sfx)
- continue;
- if (!ch->leftvol && !ch->rightvol)
- continue;
- sc = S_LoadSound (ch->sfx);
- if (!sc)
- continue;
-
- ltime = paintedtime;
-
- while (ltime < end)
- { // paint up to end
- if (ch->end < end)
- count = ch->end - ltime;
- else
- count = end - ltime;
-
- if (count > 0)
- {
- if (sc->width == 1)
- SND_PaintChannelFrom8(ch, sc, count);
- else
- SND_PaintChannelFrom16(ch, sc, count);
-
- ltime += count;
- }
-
- // if at end of loop, restart
- if (ltime >= ch->end)
- {
- if (sc->loopstart >= 0)
- {
- ch->pos = sc->loopstart;
- ch->end = ltime + sc->length - ch->pos;
- }
- else
- { // channel just stopped
- ch->sfx = nil;
- break;
- }
- }
- }
-
- }
-
- // transfer out according to DMA format
- S_TransferPaintBuffer(end);
- paintedtime = end;
- }
-}
-
-void SND_InitScaletable (void)
-{
- int i, j;
-
- for (i=0 ; i<32 ; i++)
- for (j=0 ; j<256 ; j++)
- snd_scaletable[i][j] = ((signed char)j) * i * 8;
-}
-
-
-void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
-{
- int data;
- int *lscale, *rscale;
- uchar *sfx;
- int i;
-
- if (ch->leftvol > 255)
- ch->leftvol = 255;
- if (ch->rightvol > 255)
- ch->rightvol = 255;
-
- lscale = snd_scaletable[ch->leftvol >> 3];
- rscale = snd_scaletable[ch->rightvol >> 3];
- sfx = (uchar *)((uintptr)sc->data + (uintptr)ch->pos);
-
- for (i=0 ; i<count ; i++)
- {
- data = sfx[i];
- paintbuffer[i].left += lscale[data];
- paintbuffer[i].right += rscale[data];
- }
-
- ch->pos += count;
-}
-
-
-void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
-{
- int data;
- int left, right;
- int leftvol, rightvol;
- signed short *sfx;
- int i;
-
- leftvol = ch->leftvol;
- rightvol = ch->rightvol;
- sfx = (signed short *)sc->data + ch->pos;
-
- for (i=0 ; i<count ; i++)
- {
- data = sfx[i];
- left = (data * leftvol) >> 8;
- right = (data * rightvol) >> 8;
- paintbuffer[i].left += left;
- paintbuffer[i].right += right;
- }
-
- ch->pos += count;
-}
-
--- a/sound.h
+++ /dev/null
@@ -1,159 +1,0 @@
-// sound.h -- client sound i/o functions
-
-enum{
- NSAMPLE = 4096,
- SAMPLESZ = 16,
- SAMPLEB = SAMPLESZ / 8,
- RATE = 44100,
- SNBUF = SAMPLEB * NSAMPLE
-};
-
-#define DEFAULT_SOUND_PACKET_VOLUME 255
-#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
-
-// !!! if this is changed, it much be changed in asm_i386.h too !!!
-typedef struct
-{
- int left;
- int right;
-} portable_samplepair_t;
-
-typedef struct sfx_s
-{
- char name[Npath];
- cache_user_t cache;
-} sfx_t;
-
-// !!! if this is changed, it much be changed in asm_i386.h too !!!
-typedef struct
-{
- int length;
- int loopstart;
- int speed;
- int width;
- int stereo;
- byte data[1]; // variable sized
-} sfxcache_t;
-
-typedef struct
-{
- qboolean gamealive;
- qboolean soundalive;
- qboolean splitbuffer;
- int channels;
- int samples; // mono samples in buffer
- int submission_chunk; // don't mix less than this #
- uint samplepos; // in mono samples
- int samplebits;
- int speed;
- unsigned char *buffer;
-} dma_t;
-
-// !!! if this is changed, it much be changed in asm_i386.h too !!!
-typedef struct
-{
- sfx_t *sfx; // sfx number
- int leftvol; // 0-255 volume
- int rightvol; // 0-255 volume
- int end; // end time in global paintsamples
- int pos; // sample position in sfx
- int looping; // where to loop, -1 = no looping
- int entnum; // to allow overriding a specific sound
- int entchannel; //
- vec3_t origin; // origin of sound effect
- vec_t dist_mult; // distance multiplier (attenuation/clipK)
- int master_vol; // 0-255 master volume
-} channel_t;
-
-typedef struct
-{
- int rate;
- int width;
- int channels;
- int loopstart;
- int samples;
- int dataofs; // chunk starts this many bytes from file start
-} wavinfo_t;
-
-void S_Init (void);
-void S_Startup (void);
-void S_Shutdown (void);
-void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation);
-void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
-void S_StopSound (int entnum, int entchannel);
-void S_StopAllSounds(qboolean clear);
-void S_ClearBuffer (void);
-void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
-void S_ExtraUpdate (void);
-
-sfx_t *S_PrecacheSound (char *sample);
-void S_TouchSound (char *sample);
-void S_ClearPrecache (void);
-void S_BeginPrecaching (void);
-void S_EndPrecaching (void);
-void S_PaintChannels(int endtime);
-void S_InitPaintChannels (void);
-
-// picks a channel based on priorities, empty slots, number of channels
-channel_t *SND_PickChannel(int entnum, int entchannel);
-
-// spatializes a channel
-void SND_Spatialize(channel_t *ch);
-
-// initializes cycling through a DMA buffer and returns information on it
-qboolean SNDDMA_Init(void);
-
-// gets the current DMA position
-uint SNDDMA_GetDMAPos(void);
-
-// shutdown the DMA xfer.
-void SNDDMA_Shutdown(void);
-
-// ====================================================================
-// User-setable variables
-// ====================================================================
-
-#define MAX_CHANNELS 128
-#define MAX_DYNAMIC_CHANNELS 8
-
-
-extern channel_t channels[MAX_CHANNELS];
-// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds
-// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc
-// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds
-
-extern int total_channels;
-
-//
-// Fake dma is a synchronous faking of the DMA progress used for
-// isolating performance in the renderer. The fakedma_updates is
-// number of times S_Update() is called per second.
-//
-
-extern qboolean fakedma;
-extern int fakedma_updates;
-extern int paintedtime;
-extern vec3_t listener_origin;
-extern vec3_t listener_forward;
-extern vec3_t listener_right;
-extern vec3_t listener_up;
-extern volatile dma_t *shm;
-extern volatile dma_t sn;
-extern vec_t sound_nominal_clip_dist;
-
-extern cvar_t loadas8bit;
-extern cvar_t bgmvolume;
-extern cvar_t volume;
-
-extern int snd_blocked;
-
-void S_LocalSound (char *s);
-sfxcache_t *S_LoadSound (sfx_t *s);
-
-wavinfo_t GetWavinfo (char *name, byte *wav, vlong wavlength);
-
-void SND_InitScaletable (void);
-void SNDDMA_Submit(void);
-
-void S_AmbientOff (void);
-void S_AmbientOn (void);
--- a/sv_main.c
+++ b/sv_main.c
@@ -135,9 +135,9 @@
channel = (ent<<3) | channel;
field_mask = 0;
- if (volume != DEFAULT_SOUND_PACKET_VOLUME)
+ if (volume != Spktvol)
field_mask |= SND_VOLUME;
- if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
+ if (attenuation != Spktatt)
field_mask |= SND_ATTENUATION;
// directed messages go only to the entity the are targeted on
--- a/sys.c
+++ b/sys.c
@@ -61,10 +61,8 @@
static void
croak(void *, char *note)
{
- if(strncmp(note, "sys:", 4) == 0){
+ if(strncmp(note, "sys:", 4) == 0)
IN_Shutdown();
- SNDDMA_Shutdown();
- }
noted(NDFLT);
}
@@ -102,7 +100,7 @@
Host_Init(&parms);
- oldtime = Sys_FloatTime() - 0.1;
+ oldtime = Sys_FloatTime() - 1.0 / Fpsmax;
for(;;){
// find time spent rendering last frame
newtime = Sys_FloatTime();