13 Jun 2008

This commit is contained in:
g-cont 2008-06-13 00:00:00 +04:00 committed by Alibek Omarov
parent ec93bac8e6
commit 89f509dccd
47 changed files with 3759 additions and 177 deletions

View File

@ -19,6 +19,7 @@ render\
imglib\
ripper\
vprogs\
vsound\
common\
common\bsplib
common\roqlib

View File

@ -35,6 +35,9 @@ if errorlevel 1 set BUILD_ERROR=1
%MSDEV% vprogs/vprogs.dsp %CONFIG%"vprogs - Win32 Debug" %build_target%
if errorlevel 1 set BUILD_ERROR=1
%MSDEV% vsound/vsound.dsp %CONFIG%"vsound - Win32 Debug" %build_target%
if errorlevel 1 set BUILD_ERROR=1
if "%BUILD_ERROR%"=="" goto build_ok
echo *********************
@ -63,9 +66,10 @@ if exist physic\physic.plg del /f /q physic\physic.plg
if exist render\render.plg del /f /q render\render.plg
if exist viewer\viewer.plg del /f /q viewer\viewer.plg
if exist vprogs\vprogs.plg del /f /q vprogs\vprogs.plg
if exist vsound\vsound.plg del /f /q vsound\vsound.plg
echo Build succeeded!
echo Please wait. Xash is now loading
cd D:\Xash3D\
quake.exe -log -game tmpQuArK -debug -dev 3 +map qctest
quake.exe -log -game tmpQuArK -debug -dev 3 +map start
:done

View File

@ -19,9 +19,6 @@
#define ROQ_PACKET 0x1030
#define ZA_SOUND_MONO 0x1020
#define ZA_SOUND_STEREO 0x1021
extern int s_paintedtime;
extern int s_soundtime; // sample PAIRS
extern int s_rawend;
static void RoQ_init( void );
static long ROQ_YY_tab[256];
@ -983,7 +980,7 @@ redump:
if (!cinTable.silent)
{
ssize = RllDecodeMonoToStereo( framedata, sbuf, cinTable.RoQFrameSize, 0, (word)cinTable.roq_flags);
S_RawSamples( ssize, 22050, 2, 1, (byte *)sbuf, s_volume->value );
S_RawSamples( ssize, 22050, 2, 1, (byte *)sbuf );
}
break;
case ZA_SOUND_STEREO:
@ -991,11 +988,10 @@ redump:
{
if (cinTable.numQuads == -1)
{
S_Update();
s_rawend = s_soundtime;
//S_Update();
}
ssize = RllDecodeStereoToStereo( framedata, sbuf, cinTable.RoQFrameSize, 0, (word)cinTable.roq_flags);
S_RawSamples( ssize, 22050, 2, 2, (byte *)sbuf, s_volume->value );
S_RawSamples( ssize, 22050, 2, 2, (byte *)sbuf );
}
break;
case ROQ_QUAD_INFO:
@ -1230,8 +1226,6 @@ bool CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemB
M_ForceMenuOff();
Con_Close();
s_rawend = s_soundtime;
return true;
}
@ -1347,6 +1341,7 @@ bool SCR_PlayCinematic( char *name, int bits )
SCR_StopCinematic();
S_StopAllSounds();
S_StartStreaming();
if (CIN_PlayCinematic( name, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, bits ))
{

View File

@ -918,3 +918,82 @@ void CL_GetEntitySoundOrigin (int ent, vec3_t org)
// FIXME: bmodel issues...
}
//
// sound engine implementation
//
void CL_GetEntitySoundSpatialization( int ent, vec3_t origin, vec3_t velocity )
{
centity_t *cent;
cmodel_t *cmodel;
vec3_t midPoint;
if( ent < 0 || ent >= MAX_EDICTS )
{
MsgDev( D_ERROR, "CL_GetEntitySoundSpatialization: invalid entnum", ent );
VectorCopy( vec3_origin, origin );
VectorCopy( vec3_origin, velocity );
return;
}
cent = &cl_entities[ent];
if( cent->current.renderfx & (RF_FRAMELERP|RF_BEAM))
{
// calculate origin
origin[0] = cent->current.old_origin[0] + (cent->current.origin[0] - cent->current.old_origin[0]) * cl.lerpfrac;
origin[1] = cent->current.old_origin[1] + (cent->current.origin[1] - cent->current.old_origin[1]) * cl.lerpfrac;
origin[2] = cent->current.old_origin[2] + (cent->current.origin[2] - cent->current.old_origin[2]) * cl.lerpfrac;
// calculate velocity
VectorSubtract( cent->current.origin, cent->current.old_origin, velocity );
VectorScale(velocity, 10, velocity);
}
else
{
// calculate origin
origin[0] = cent->prev.origin[0] + (cent->current.origin[0] - cent->prev.origin[0]) * cl.lerpfrac;
origin[1] = cent->prev.origin[1] + (cent->current.origin[1] - cent->prev.origin[1]) * cl.lerpfrac;
origin[2] = cent->prev.origin[2] + (cent->current.origin[2] - cent->prev.origin[2]) * cl.lerpfrac;
// calculate velocity
VectorSubtract(cent->current.origin, cent->prev.origin, velocity);
VectorScale(velocity, 10, velocity);
}
// if a brush model, offset the origin
if( cent->current.solid == SOLID_BMODEL )
{
cmodel = cl.model_clip[cent->current.modelindex];
if(!cmodel) return;
VectorAverage(cmodel->mins, cmodel->maxs, midPoint);
VectorAdd(origin, midPoint, origin);
}
}
/*
=================
S_AddLoopingSounds
Entities with a sound field will generate looping sounds that are
automatically started and stopped as the entities are sent to the
client
=================
*/
void CL_AddLoopingSounds( void )
{
entity_state_t *ent;
int num, i;
if( cl_paused->value ) return;
if( cls.state != ca_active ) return;
//if( !cl.sound_prepped ) return;
for( i = 0; i < cl.frame.num_entities; i++ )
{
num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
ent = &cl_parse_entities[num];
se->AddLoopingSound( ent->number, cl.sound_precache[ent->soundindex], 1.0f, ATTN_IDLE );
}
}

View File

@ -198,6 +198,10 @@ void CL_Drop (void)
CL_Disconnect();
}
float CL_GetTime( void )
{
return cl.time;
}
/*
=======================
@ -832,21 +836,6 @@ void CL_Userinfo_f (void)
Info_Print (Cvar_Userinfo());
}
/*
=================
CL_Snd_Restart_f
Restart the sound subsystem so it can pick up
new parameters and flush all sounds
=================
*/
void CL_Snd_Restart_f (void)
{
S_Shutdown();
S_Init();
CL_RegisterSounds();
}
int precache_check; // for autodownload of precache items
int precache_spawncount;
int precache_tex;
@ -1086,6 +1075,8 @@ void CL_RequestNextDownload (void)
//ZOID
CL_RegisterSounds();
CL_PrepRefresh();
if( cls.demoplayback ) return; // not really connected
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_WriteString( &cls.netchan.message, va("begin %i\n", precache_spawncount));
}
@ -1193,8 +1184,6 @@ void CL_InitLocal (void)
Cmd_AddCommand ("pingservers", CL_PingServers_f, "send a broadcast packet" );
Cmd_AddCommand ("userinfo", CL_Userinfo_f, "print current client userinfo" );
Cmd_AddCommand ("snd_restart", CL_Snd_Restart_f, "restart sound system" );
Cmd_AddCommand ("changing", CL_Changing_f, "sent by server to tell client to wait for level change" );
Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server" );
Cmd_AddCommand ("record", CL_Record_f, "record a demo" );
@ -1421,8 +1410,7 @@ void CL_Frame( float time )
SCR_UpdateScreen();
// update audio
S_Update();
S_Respatialize( cl.playernum + 1, cl.refdef.vieworg, cl.v_forward, cl.v_left, cl.v_up );
S_Update( cl.playernum + 1, cl.refdef.vieworg, vec3_origin, cl.v_forward, cl.v_up );
// advance local effects for next frame
CL_RunDLights ();
@ -1442,7 +1430,7 @@ void CL_Frame( float time )
CL_Init
====================
*/
void CL_Init (void)
void CL_Init( void )
{
if (dedicated->value) return; // nothing running on the client
@ -1462,7 +1450,6 @@ void CL_Init (void)
SCR_Init();
CL_InitLocal();
S_ClearLoopingSounds( true );
}

View File

@ -591,7 +591,7 @@ void CL_ParseAmbientSound( sizebuf_t *msg )
loopSoundHandle = S_RegisterSound( cl.configstrings[CS_SOUNDS + soundNum] );
// add ambient looping sound
S_AddRealLoopingSound( entityNum, ambient_org, vec3_origin, loopSoundHandle );
// S_AddRealLoopingSound( entityNum, ambient_org, vec3_origin, loopSoundHandle );
}
void SHOWNET( sizebuf_t *msg, char *s )

View File

@ -512,11 +512,17 @@ void CL_ParseTEnt( sizebuf_t *msg )
// impact sound
cnt = rand()&15;
if (cnt == 1)
{
S_StartSound (pos, 0, 0, cl_sfx_ric1);
}
else if (cnt == 2)
{
S_StartSound (pos, 0, 0, cl_sfx_ric2);
}
else if (cnt == 3)
{
S_StartSound (pos, 0, 0, cl_sfx_ric3);
}
}
break;
@ -623,9 +629,13 @@ void CL_ParseTEnt( sizebuf_t *msg )
ex->ent.angles[1] = rand() % 360;
CL_ExplosionParticles (pos);
if (type == TE_GRENADE_EXPLOSION_WATER)
{
S_StartSound (pos, 0, 0, cl_sfx_watrexp);
}
else
{
S_StartSound (pos, 0, 0, cl_sfx_grenexp);
}
break;
// RAFAEL
@ -668,9 +678,13 @@ void CL_ParseTEnt( sizebuf_t *msg )
ex->frames = 8;
CL_ExplosionParticles (pos); // PMM
if (type == TE_ROCKET_EXPLOSION_WATER)
{
S_StartSound (pos, 0, 0, cl_sfx_watrexp);
}
else
{
S_StartSound (pos, 0, 0, cl_sfx_rockexp);
}
break;
case TE_BFG_EXPLOSION:

View File

@ -129,6 +129,7 @@ typedef struct
int timeoutcount;
bool refresh_prepped; // false if on new level or new ref dll
bool sound_prepped; // false if on new level or new snd dll
bool force_refdef; // vid has changed, so we can't use a paused refdef
int parse_entities; // index (not anded off) into cl_parse_entities[]
@ -551,48 +552,29 @@ void CL_FreeClientProgs( void );
//
// cl_sound.c
//
void S_Init( void );
void S_Shutdown( void );
#define S_Shutdown se->Shutdown
// if origin is NULL, the sound will be dynamically sourced from the entity
void S_StartSound( vec3_t origin, int entnum, int entchannel, sound_t sfx );
int S_StartLocalSound( const char *name );
void S_StartBackgroundTrack( const char *intro, const char *loop );
void S_StopBackgroundTrack( void );
// cinematics and voice-over-network will send raw samples
// 1.0 volume will be direct output of source samples
void S_RawSamples (int samples, int rate, int width, int channels, const byte *data, float volume);
// stop all sounds and the background track
void S_StopAllSounds( void );
// all continuous looping sounds must be added before calling S_Update
void S_ClearLoopingSounds( bool killall );
void S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sound_t sfx );
void S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sound_t sfx );
void S_StopLoopingSound(int entityNum );
#define S_StartStreaming se->StartStreaming
#define S_RegisterSound se->RegisterSound
#define S_StartSound( a, b, c, d ) se->StartSound( a, b, c, d, 1.0f, ATTN_NORM );
#define S_StartLocalSound se->StartLocalSound
#define S_StartBackgroundTrack se->StartBackgroundTrack
#define S_StopBackgroundTrack se->StopBackgroundTrack
#define S_RawSamples se->StreamRawSamples
#define S_StopAllSounds se->StopAllSounds
// recompute the reletive volumes for all running sounds
// reletive to the given entityNum / orientation
void S_Respatialize( int entityNum, const vec3_t origin, vec3_t v_forward, vec3_t v_left, vec3_t v_up );
// let the sound system know where an entity currently is
void S_UpdateEntityPosition( int entityNum, const vec3_t origin );
void S_Update( void );
void S_DisableSounds( void );
void S_EnableSounds( void );
void S_BeginRegistration( void );
void S_EndRegistration( void );
#define S_Update se->Frame
#define S_BeginRegistration se->BeginRegistration
#define S_EndRegistration se->EndRegistration
// RegisterSound will allways return a valid sample, even if it
// has to create a placeholder. This prevents continuous filesystem
// checks for missing files
sound_t S_RegisterSound( const char *sample );
void S_DisplayFreeMemory(void);
void S_ClearSoundBuffer( void );
void SNDDMA_Activate( void );
void S_UpdateBackgroundTrack( void );
extern cvar_t *s_volume;
extern cvar_t *s_nosound;
@ -647,6 +629,12 @@ void CL_InitPrediction (void);
void CL_PredictMove (void);
void CL_CheckPredictionError (void);
//
// cl_ents.c
//
void CL_GetEntitySoundSpatialization( int ent, vec3_t origin, vec3_t velocity );
void CL_AddLoopingSounds( void );
//
// cl_fx.c
//

View File

@ -22,6 +22,7 @@
extern stdlib_api_t com;
extern physic_exp_t *pe;
extern vprogs_exp_t *vm;
extern vsound_exp_t *se;
/*
==============================================================
@ -137,7 +138,7 @@ HOST INTERFACE
*/
typedef enum
{
HOST_INIT, // initalize operations
HOST_INIT = 0, // initalize operations
HOST_FRAME, // host running
HOST_SHUTDOWN, // shutdown operations
HOST_ERROR, // host stopped by error
@ -179,7 +180,7 @@ typedef struct host_parm_s
} host_parm_t;
extern host_parm_t host;
long _stdcall Host_WndProc( HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam);
long Host_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam );
void Host_Init ( uint funcname, int argc, char **argv );
void Host_Main ( void );
void Host_Free ( void );
@ -193,6 +194,7 @@ void Host_Error( const char *error, ... );
// host dlls managment
void Host_FreeRender( void );
void Host_SndRestart_f( void );
// host cmds
void Host_Error_f( void );
@ -365,7 +367,12 @@ enum e_clprint
extern byte *zonepool;
#define Z_Malloc(size) Mem_Alloc( zonepool, size )
void CL_GetEntitySoundSpatialization( int ent, vec3_t origin, vec3_t velocity );
void SV_Transform( sv_edict_t *ed, matrix4x3 transform );
int CL_PMpointcontents( vec3_t point );
void CL_AddLoopingSounds( void );
void CL_RegisterSounds( void );
float CL_GetTime( void );
void CL_Drop( void );
char *Info_ValueForKey( char *s, char *key );
void Info_RemoveKey( char *s, char *key );

View File

@ -54,7 +54,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /opt:nowin98
# ADD LINK32 winmm.lib user32.lib msvcrt.lib ole32.lib /nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /opt:nowin98
# ADD LINK32 winmm.lib user32.lib msvcrt.lib /nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /opt:nowin98
# SUBTRACT LINK32 /debug /nodefaultlib
# Begin Custom Build
TargetDir=\Xash3D\src_main\temp\engine\!release
@ -91,7 +91,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
# ADD LINK32 winmm.lib user32.lib msvcrt.lib ole32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"msvcrtd.lib" /pdbtype:sept
# ADD LINK32 winmm.lib user32.lib msvcrt.lib /nologo /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"msvcrtd.lib" /pdbtype:sept
# SUBTRACT LINK32 /incremental:no /map /nodefaultlib
# Begin Custom Build
TargetDir=\Xash3D\src_main\temp\engine\!debug
@ -174,10 +174,6 @@ SOURCE=.\client\cl_scrn.c
# End Source File
# Begin Source File
SOURCE=.\client\cl_sound.c
# End Source File
# Begin Source File
SOURCE=.\client\cl_tent.c
# End Source File
# Begin Source File
@ -306,10 +302,6 @@ SOURCE=.\net_msg.h
# End Source File
# Begin Source File
SOURCE=.\progdefs.h
# End Source File
# Begin Source File
SOURCE=.\uimenu\qmenu.h
# End Source File
# Begin Source File
@ -322,14 +314,6 @@ SOURCE=.\server\server.h
# End Source File
# Begin Source File
SOURCE=.\client\snd_loc.h
# End Source File
# Begin Source File
SOURCE=.\client\sound.h
# End Source File
# Begin Source File
SOURCE=.\uimenu\uimenu.h
# End Source File
# Begin Source File

View File

@ -12,6 +12,7 @@
physic_exp_t *pe;
render_exp_t *re;
vprogs_exp_t *vm;
vsound_exp_t *se;
host_parm_t host; // host parms
stdlib_api_t com, newcom;
@ -21,6 +22,7 @@ char *buildstring = __TIME__ " " __DATE__;
dll_info_t physic_dll = { "physic.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(physic_exp_t) };
dll_info_t render_dll = { "render.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(render_exp_t) };
dll_info_t vprogs_dll = { "vprogs.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(vprogs_exp_t) };
dll_info_t vsound_dll = { "vsound.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(vsound_exp_t) };
cvar_t *timescale;
cvar_t *fixedtime;
@ -148,16 +150,15 @@ void Host_InitRender( void )
// studio callbacks
ri.StudioEvent = CL_StudioEvent;
ri.ShowCollision = pe->DrawCollision;
ri.WndProc = Host_WndProc;
Sys_LoadLibrary( &render_dll );
CreateRender = (void *)render_dll.main;
re = CreateRender( &newcom, &ri );
if(!re->Init(GetModuleHandle(NULL), Host_WndProc ))
if(!re->Init(GetModuleHandle(NULL)))
Sys_Error("VID_InitRender: can't init render.dll\nUpdate your opengl drivers\n");
CL_Snd_Restart_f();
}
void Host_FreeRender( void )
@ -172,7 +173,7 @@ void Host_FreeRender( void )
void Host_InitVprogs( int argc, char **argv )
{
launch_t CreateVprogs;
launch_t CreateVprogs;
Sys_LoadLibrary( &vprogs_dll );
@ -192,6 +193,36 @@ void Host_FreeVprogs( void )
Sys_FreeLibrary( &vprogs_dll );
}
void Host_InitSound( void )
{
static vsound_imp_t si;
launch_t CreateSound;
// phys callback
si.api_size = sizeof(vsound_imp_t);
si.GetSoundSpatialization = CL_GetEntitySoundSpatialization;
si.PointContents = CL_PMpointcontents;
si.AddLoopingSounds = CL_AddLoopingSounds;
si.GetClientTime = CL_GetTime;
Sys_LoadLibrary( &vsound_dll );
CreateSound = (void *)vsound_dll.main;
se = CreateSound( &newcom, &si );
se->Init( host.hWnd );
}
void Host_FreeSound( void )
{
if(vsound_dll.link)
{
se->Shutdown();
memset( &se, 0, sizeof(se));
}
Sys_FreeLibrary( &vsound_dll );
}
/*
================
Host_AbortCurrentFrame
@ -241,6 +272,21 @@ void Host_VidRestart_f( void )
Host_InitRender(); // load it again
}
/*
=================
Host_SndRestart_f
Restart the audio subsystem
=================
*/
void Host_SndRestart_f( void )
{
Host_FreeSound(); // release vsound.dll
Host_InitSound(); // load it again
CL_RegisterSounds();
}
/*
============
VID_Init
@ -251,9 +297,12 @@ void VID_Init( void )
scr_width = Cvar_Get("width", "640", 0 );
scr_height = Cvar_Get("height", "480", 0 );
vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE );
Cmd_AddCommand ("vid_restart", Host_VidRestart_f, "restarts video system" );
Cmd_AddCommand ("snd_restart", Host_SndRestart_f, "restarts audio system" );
Host_InitRender();
Host_InitSound();
}
/*
@ -297,7 +346,7 @@ Host_WndProc
main window procedure
====================
*/
long _stdcall Host_WndProc( HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
long Host_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
{
int temp = 0;
@ -332,8 +381,8 @@ long _stdcall Host_WndProc( HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
else if(LOWORD(wParam) == WA_INACTIVE) host.state = HOST_NOFOCUS;
else host.state = HOST_FRAME;
if( se ) se->Activate( (host.state == HOST_FRAME) ? true : false );
Key_ClearStates(); // FIXME!!!
SNDDMA_Activate();
if( host.state == HOST_FRAME )
{

View File

@ -239,18 +239,6 @@ typedef enum
#define SND_ENT (1<<3) // a short 0-2: channel, 3-12: entity
#define SND_OFFSET (1<<4) // a byte, msec offset from frame start
// sound channels
// channel 0 never willingly overrides
// other channels (1-7) allways override a playing sound on that channel
#define CHAN_AUTO 0
#define CHAN_WEAPON 1
#define CHAN_VOICE 2
#define CHAN_ITEM 3
#define CHAN_BODY 4
#define CHAN_ANNOUNCER 5 // announcer
#define CHAN_NO_PHS_ADD 8 // send to all clients, not just ones in PHS (ATTN 0 will also do this)
#define CHAN_RELIABLE 16 // send by reliable message, not datagram
// 0-compressed fields
#define DEFAULT_SOUND_PACKET_VOL 1.0
#define DEFAULT_SOUND_PACKET_ATTN 1.0

View File

@ -126,6 +126,7 @@ struct sv_entvars_s
vec3_t post_angles;
vec3_t origin_offset;
float ltime;
string_t loopsound;
float bouncetype;
float movetype;
float solid;

View File

@ -50,7 +50,7 @@ void SV_UpdateEntityState( edict_t *ent)
ent->priv.sv->s.renderfx = (int)ent->progs.sv->renderfx; // renderer flags
ent->priv.sv->s.alpha = ent->progs.sv->alpha; // alpha value
ent->priv.sv->s.animtime = ent->progs.sv->animtime; // auto-animating time
ent->priv.sv->s.soundindex = (int)ent->progs.sv->sounds;
ent->priv.sv->s.soundindex = ent->progs.sv->loopsound;
}
/*
@ -404,7 +404,7 @@ void SV_BuildClientFrame (client_state_t *client)
ent = PRVM_EDICT_NUM(e);
// ignore ents without visible models unless they have an effect
if (!ent->progs.sv->modelindex && !ent->progs.sv->effects && !ent->progs.sv->noise3 && !ent->priv.sv->event)
if (!ent->progs.sv->modelindex && !ent->progs.sv->effects && !ent->progs.sv->loopsound && !ent->priv.sv->event)
continue;
// ignore if not touching a PV leaf
@ -430,7 +430,7 @@ void SV_BuildClientFrame (client_state_t *client)
{
// FIXME: if an ent has a model and a sound, but isn't
// in the PVS, only the PHS, clear the model
if (ent->progs.sv->noise3) bitvector = clientphs;
if (ent->progs.sv->loopsound ) bitvector = clientphs;
else bitvector = clientpvs;
// check individual leafs

View File

@ -101,7 +101,7 @@ void SV_CreateBaseline (void)
{
svent = PRVM_EDICT_NUM(entnum);
if (svent->priv.sv->free) continue;
if (!svent->progs.sv->modelindex && !svent->progs.sv->noise3 && !svent->progs.sv->effects)
if (!svent->progs.sv->modelindex && !svent->progs.sv->loopsound && !svent->progs.sv->effects)
continue;
svent->priv.sv->serialnumber = entnum;

View File

@ -1116,6 +1116,7 @@ void PF_inpvs( void )
if(!VM_ValidateArgs( "EntitiesInPVS", 2 )) return;
pvsent = PRVM_G_EDICT(OFS_PARM0);
playeronly = (bool)PRVM_G_FLOAT(OFS_PARM1);
chain = (edict_t *)prog->edicts;
if( playeronly )
{
@ -1162,6 +1163,7 @@ void PF_inphs( void )
if(!VM_ValidateArgs( "EntitiesInPHS", 2 )) return;
pvsent = PRVM_G_EDICT(OFS_PARM0);
playeronly = (bool)PRVM_G_FLOAT(OFS_PARM1);
chain = (edict_t *)prog->edicts;
if( playeronly )
{
@ -1458,7 +1460,9 @@ void PF_ambientsound( void )
soundent = PRVM_G_EDICT(OFS_PARM0);
samp = PRVM_G_STRING(OFS_PARM1);
if( soundent ) SV_AmbientSound( soundent, SV_SoundIndex( samp ), 0.0f, 0.0f ); // unused parms
// check to see if samp was properly precached
if( soundent ) soundent->progs.sv->loopsound = SV_SoundIndex( samp );
//SV_AmbientSound( soundent, SV_SoundIndex( samp ), 0.0f, 0.0f ); // unused parms
}
/*

View File

@ -1091,7 +1091,7 @@ static void UpdateSoundQualityFunc( void *unused )
// the text box won't show up unless we do a buffer swap
re->EndFrame();
CL_Snd_Restart_f();
Host_SndRestart_f();
}
void Options_MenuInit( void )

View File

@ -16,7 +16,7 @@ void ImageLib_Init ( uint funcname )
zonepool = Mem_AllocPool( "ImageLib Pool" );
app_name = funcname;
img_resample_lerp = Cvar_Get( "img_lerping", "1", CVAR_ARCHIVE );
img_resample_lerp = Cvar_Get( "img_lerping", "1", CVAR_SYSTEMINFO );
}
void ImageLib_Free ( void )

View File

@ -1,6 +1,6 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// launcher.c - main engine launcher
// export.c - main engine launcher
//=======================================================================
#include "launch.h"

View File

@ -54,15 +54,14 @@ typedef struct mempool_s
uint sentinel2; // should always be MEMHEADER_SENTINEL1
} mempool_t;
typedef struct memarray_s
typedef struct memcluster_s
{
byte *data;
byte *allocflags;
size_t numflaggedrecords;
} memcluster_t;
typedef struct memarraypool_s
typedef struct memarray_s
{
byte *mempool;
size_t recordsize;

View File

@ -944,4 +944,22 @@ bool SC_FilterToken(char *filter, char *name, int casecmp)
}
}
return true;
}
/*
=================
SC_HashKey
returns hash key for string
=================
*/
uint SC_HashKey( const char *string, uint hashSize )
{
uint hashKey = 0;
int i;
for( i = 0; string[i]; i++ )
hashKey = (hashKey + i) * 37 + com_tolower(string[i]);
return (hashKey % hashSize);
}

View File

@ -100,6 +100,7 @@ void Sys_GetStdAPI( void )
com.Com_ParseWord = SC_ParseWord; // parse word from char buffer
com.Com_Search = FS_Search; // returned list of founded files
com.Com_Filter = SC_FilterToken; // compare keyword by mask with filter
com.Com_HashKey = SC_HashKey; // returns hash key for a string (generic fucntion)
com.com_token = token; // contains current token
// console variables

View File

@ -136,7 +136,7 @@ SOURCE=.\common\filesystem.c
# End Source File
# Begin Source File
SOURCE=.\common\launcher.c
SOURCE=.\common\export.c
# End Source File
# Begin Source File

View File

@ -362,6 +362,7 @@ uint Com_BlockChecksumKey(void *buffer, int length, int key);
bool SC_LoadScript( const char *filename, char *buf, int size );
bool SC_AddScript( const char *filename, char *buf, int size );
bool SC_FilterToken(char *filter, char *name, int casecmp);
uint SC_HashKey( const char *string, uint hashSize );
bool SC_ParseToken_Simple(const char **data_p);
char *SC_ParseToken(const char **data_p );
char *SC_ParseWord( const char **data_p );

View File

@ -71,6 +71,23 @@
#define PM_MAXTOUCH 32
// sound channels
#define CHAN_AUTO 0
#define CHAN_WEAPON 1
#define CHAN_VOICE 2
#define CHAN_ITEM 3
#define CHAN_BODY 4
#define CHAN_ANNOUNCER 5 // announcer
// flags
#define CHAN_NO_PHS_ADD 8 // Send to all clients, not just ones in PHS (ATTN 0 will also do this)
#define CHAN_RELIABLE 16 // Send by reliable message, not datagram
// Sound attenuation values
#define ATTN_NONE 0 // Full volume the entire level
#define ATTN_NORM 1
#define ATTN_IDLE 2
#define ATTN_STATIC 3 // Diminish very rapidly with distance
// player_state->stats[] indexes
enum player_stats
{
@ -355,7 +372,7 @@ typedef struct render_exp_s
size_t api_size; // must matched with sizeof(render_exp_t)
// initialize
bool (*Init)( void *hInstance, void *WndProc ); // init all render systems
bool (*Init)( void *hInst ); // init all render systems
void (*Shutdown)( void ); // shutdown all render systems
void (*BeginRegistration) (char *map);
@ -387,7 +404,7 @@ typedef struct render_imp_s
// client fundamental callbacks
void (*StudioEvent)( mstudioevent_t *event, entity_t *ent );
void (*ShowCollision)( cmdraw_t callback ); // debug
long (*WndProc)( void *hWnd, uint uMsg, uint wParam, long lParam );
} render_imp_t;
/*
@ -471,7 +488,7 @@ typedef struct physic_imp_s
/*
==============================================================================
IMGLIB.DLL INTERFACE
VPROGS.DLL INTERFACE
==============================================================================
*/
typedef struct vprogs_exp_s
@ -525,10 +542,58 @@ typedef struct vprogs_exp_s
void (*ExecuteProgram)( func_t fnum, const char *errormessage );
void (*Crash)( void ); // crash virtual machine
prvm_prog_t *prog; // virtual machine state
prvm_prog_t *prog; // virtual machine current state
} vprogs_exp_t;
/*
==============================================================================
VSOUND.DLL INTERFACE
==============================================================================
*/
typedef struct vsound_exp_s
{
// interface validator
size_t api_size; // must matched with sizeof(vprogs_api_t)
void (*Init)( void *hInst ); // init host
void (*Shutdown)( void ); // close host
// sound manager
void (*BeginRegistration)( void );
sound_t (*RegisterSound)( const char *name );
void (*EndRegistration)( void );
void (*StartSound)( const vec3_t pos, int entnum, int channel, sound_t sfx, float vol, float attn );
void (*StreamRawSamples)( int samples, int rate, int width, int channels, const byte *data );
bool (*AddLoopingSound)( int entnum, sound_t handle, float volume, float attn );
bool (*StartLocalSound)( const char *name );
void (*StartBackgroundTrack)( const char *introTrack, const char *loopTrack );
void (*StopBackgroundTrack)( void );
void (*StartStreaming)( void );
void (*StopStreaming)( void );
void (*Frame)( int entnum, const vec3_t pos, const vec3_t vel, const vec3_t at, const vec3_t up );
void (*StopAllSounds)( void );
void (*FreeSounds)( void );
void (*Activate)( bool active );
} vsound_exp_t;
typedef struct vsound_imp_s
{
// interface validator
size_t api_size; // must matched with sizeof(vsound_imp_t)
void (*GetSoundSpatialization)( int entnum, vec3_t origin, vec3_t velocity );
int (*PointContents)( vec3_t point );
void (*AddLoopingSounds)( void );
float (*GetClientTime)( void );
} vsound_imp_t;
// this is the only function actually exported at the linker level
typedef void *(*launch_t)( stdlib_api_t*, void* );

View File

@ -56,6 +56,7 @@
#define VectorLength2(a) (DotProduct(a, a))
#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
#define VectorDistance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))
#define VectorAverage(a,b,o) ((o)[0]=((a)[0]+(b)[0])*0.5,(o)[1]=((a)[1]+(b)[1])*0.5,(o)[2]=((a)[2]+(b)[2])*0.5)
#define VectorSet(v, x, y, z) {v[0] = x; v[1] = y; v[2] = z;}
#define Vector4Set(v, x, y, z, w) {v[0] = x, v[1] = y, v[2] = z, v[3] = w;}
#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}

View File

@ -93,6 +93,7 @@ typedef struct stdilib_api_s
char *(*Com_ParseWord)( const char **data ); // parse word from char buffer
search_t *(*Com_Search)(const char *pattern, int casecmp ); // returned list of found files
bool (*Com_Filter)(char *filter, char *name, int casecmp ); // compare keyword by mask with filter
uint (*Com_HashKey)( const char *string, uint hashSize ); // returns hash key for a string
char *com_token; // contains current token
// console variables
@ -227,6 +228,7 @@ typedef struct stdilib_api_s
#define Com_ParseWord com.Com_ParseWord
#define Com_SimpleGetToken com.Com_ParseToken_Simple
#define Com_Filter com.Com_Filter
#define Com_HashKey com.Com_HashKey
#define Com_LoadScript com.Com_LoadScript
#define Com_IncludeScript com.Com_AddScript
#define Com_ResetScript com.Com_ResetScript

View File

@ -35,6 +35,9 @@ if errorlevel 1 set BUILD_ERROR=1
%MSDEV% vprogs/vprogs.dsp %CONFIG%"vprogs - Win32 Release" %build_target%
if errorlevel 1 set BUILD_ERROR=1
%MSDEV% vsound/vsound.dsp %CONFIG%"vsound - Win32 Release" %build_target%
if errorlevel 1 set BUILD_ERROR=1
if "%BUILD_ERROR%"=="" goto build_ok
echo *********************
@ -63,6 +66,7 @@ if exist physic\physic.plg del /f /q physic\physic.plg
if exist render\render.plg del /f /q render\render.plg
if exist viewer\viewer.plg del /f /q viewer\viewer.plg
if exist vprogs\vprogs.plg del /f /q vprogs\vprogs.plg
if exist vsound\vsound.plg del /f /q vsound\vsound.plg
echo Build succeeded!
echo Please wait. Xash is now loading

View File

@ -310,8 +310,8 @@ extern int registration_sequence;
void V_AddBlend (float r, float g, float b, float a, float *v_blend);
int R_Init( void *hinstance, void *hWnd );
void R_Shutdown( void );
int R_Init( void *hinstance );
void R_Shutdown( void );
void R_RenderView (refdef_t *fd);
void R_DrawStudioModel( int passnum );
@ -505,7 +505,7 @@ IMPLEMENTATION SPECIFIC FUNCTIONS
void GLimp_BeginFrame( void );
void GLimp_EndFrame( void );
int GLimp_Init( void *hinstance, void *hWnd );
int GLimp_Init( void *hinstance );
void GLimp_Shutdown( void );
int GLimp_SetMode( int vid_mode, bool fullscreen );
void GLimp_AppActivate( bool active );

View File

@ -1114,7 +1114,7 @@ bool R_SetMode (void)
R_Init
===============
*/
int R_Init( void *hinstance, void *hWnd )
int R_Init( void *hinstance )
{
int j, err;
extern float r_turbsin[256];
@ -1137,7 +1137,7 @@ int R_Init( void *hinstance, void *hWnd )
}
// initialize OS-specific parts of OpenGL
if ( !GLimp_Init( hinstance, hWnd ) )
if ( !GLimp_Init( hinstance ))
{
QGL_Shutdown();
return false;

View File

@ -345,7 +345,7 @@ void GLimp_Shutdown( void )
** of OpenGL. Under Win32 this means dealing with the pixelformats and
** doing the wgl interface stuff.
*/
bool GLimp_Init( void *hinstance, void *wndproc )
bool GLimp_Init( void *hinstance )
{
#define OSR2_BUILD_NUMBER 1111
@ -383,7 +383,7 @@ bool GLimp_Init( void *hinstance, void *wndproc )
}
glw_state.hInstance = ( HINSTANCE ) hinstance;
glw_state.wndproc = wndproc;
glw_state.wndproc = ri.WndProc;
return true;
}

View File

@ -20,8 +20,10 @@ fopen
7. избавиться от sv.moved_edicts
Звуковой движок:
1. Сделать OpenAL совместимый движок
2. Поддержка OGG Vorbis
1. Сделать OpenAL совместимый движок OK
2. Поддержка OGG Vorbis OK
3. Сделать поддержку loop звуков OK
4.
Физика игрока:
1. Убрать отскоки от стен

View File

@ -23,7 +23,7 @@ extern int prvm_developer;
#define Host_Error com.error
#define PROG_CRC_SERVER 406
#define PROG_CRC_SERVER 14510
#define PROG_CRC_CLIENT 7430
#define PROG_CRC_UIMENU 36416

BIN
vsound/libogg.lib Normal file

Binary file not shown.

51
vsound/s_export.c Normal file
View File

@ -0,0 +1,51 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// s_export.c - sound library main
//=======================================================================
#include "sound.h"
vsound_imp_t si;
stdlib_api_t com;
byte *sndpool;
vsound_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, vsound_imp_t *engfuncs )
{
static vsound_exp_t snd;
com = *input;
// Sys_LoadLibrary can create fake instance, to check
// api version and api size, but second argument will be 0
// and always make exception, run simply check for avoid it
if(engfuncs) si = *engfuncs;
// generic functions
snd.api_size = sizeof(vsound_exp_t);
snd.Init = S_Init;
snd.Shutdown = S_Shutdown;
// sound manager
snd.BeginRegistration = S_BeginRegistration;
snd.RegisterSound = S_RegisterSound;
snd.EndRegistration = S_EndRegistration;
snd.StartSound = S_StartSound;
snd.StreamRawSamples = S_StreamRawSamples;
snd.AddLoopingSound = S_AddLoopingSound;
snd.StartLocalSound = S_StartLocalSound;
snd.StartBackgroundTrack = S_StartBackgroundTrack;
snd.StopBackgroundTrack = S_StopBackgroundTrack;
snd.StartStreaming = S_StartStreaming;
snd.StopStreaming = S_StopStreaming;
snd.Frame = S_Update;
snd.StopAllSounds = S_StopAllSounds;
snd.FreeSounds = S_FreeSounds;
snd.Activate = S_Activate;
return &snd;
}

490
vsound/s_load.c Normal file
View File

@ -0,0 +1,490 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// s_load.c - sound managment
//=======================================================================
#include "sound.h"
#define MAX_SFX 4096
static sfx_t s_knownSfx[MAX_SFX];
static int s_numSfx = 0;
#define SFX_HASHSIZE 128
static sfx_t *sfxHash[SFX_HASHSIZE];
/*
=================
S_SoundList_f
=================
*/
void S_SoundList_f( void )
{
sfx_t *sfx;
int i, samples = 0;
Msg("\n");
Msg(" -samples -hz-- -format- -name--------\n");
for( i = 0; i < s_numSfx; i++ )
{
sfx = &s_knownSfx[i];
Msg("%4i: ", i);
if( sfx->loaded )
{
samples += sfx->samples;
Msg("%8i ", sfx->samples);
Msg("%5i ", sfx->rate);
switch( sfx->format )
{
case AL_FORMAT_STEREO16: Msg("STEREO16 "); break;
case AL_FORMAT_STEREO8: Msg("STEREO8 "); break;
case AL_FORMAT_MONO16: Msg("MONO16 "); break;
case AL_FORMAT_MONO8: Msg("MONO8 "); break;
default: Msg("???????? "); break;
}
if( sfx->name[0] == '#' ) Msg("%s", &sfx->name[1]);
else Msg("sound/%s", sfx->name);
if( sfx->default_snd ) Msg(" (DEFAULTED)\n");
else Msg("\n");
}
else
{
if( sfx->name[0] == '*' ) Msg(" placeholder %s\n", sfx->name);
else Msg(" not loaded %s\n", sfx->name);
}
}
Msg("-------------------------------------------\n");
Msg("%i total samples\n", samples);
Msg("%i total sounds\n", s_numSfx);
Msg("\n");
}
/*
=======================================================================
WAV LOADING
=======================================================================
*/
static byte *iff_data;
static byte *iff_dataPtr;
static byte *iff_end;
static byte *iff_lastChunk;
static int iff_chunkLen;
/*
=================
S_GetLittleShort
=================
*/
static short S_GetLittleShort( void )
{
short val = 0;
val += (*(iff_dataPtr+0) << 0);
val += (*(iff_dataPtr+1) << 8);
iff_dataPtr += 2;
return val;
}
/*
=================
S_GetLittleLong
=================
*/
static int S_GetLittleLong( void )
{
int val = 0;
val += (*(iff_dataPtr+0) << 0);
val += (*(iff_dataPtr+1) << 8);
val += (*(iff_dataPtr+2) << 16);
val += (*(iff_dataPtr+3) << 24);
iff_dataPtr += 4;
return val;
}
/*
=================
S_FindNextChunk
=================
*/
static void S_FindNextChunk( const char *name )
{
while( 1 )
{
iff_dataPtr = iff_lastChunk;
if( iff_dataPtr >= iff_end )
{
// didn't find the chunk
iff_dataPtr = NULL;
return;
}
iff_dataPtr += 4;
iff_chunkLen = S_GetLittleLong();
if (iff_chunkLen < 0)
{
iff_dataPtr = NULL;
return;
}
iff_dataPtr -= 8;
iff_lastChunk = iff_dataPtr + 8 + ((iff_chunkLen + 1) & ~1);
if(!com.strncmp( iff_dataPtr, name, 4 ))
return;
}
}
/*
=================
S_FindChunk
=================
*/
static void S_FindChunk( const char *name )
{
iff_lastChunk = iff_data;
S_FindNextChunk( name );
}
/*
=================
S_LoadWAV
=================
*/
static bool S_LoadWAV( const char *name, byte **wav, wavinfo_t *info )
{
byte *buffer, *out;
int length;
buffer = FS_LoadFile( name, &length );
if( !buffer ) return false;
iff_data = buffer;
iff_end = buffer + length;
// dind "RIFF" chunk
S_FindChunk( "RIFF" );
if(!(iff_dataPtr && !com.strncmp(iff_dataPtr+8, "WAVE", 4)))
{
MsgDev( D_WARN, "S_LoadWAV: missing 'RIFF/WAVE' chunks (%s)\n", name );
Mem_Free( buffer );
return false;
}
// get "fmt " chunk
iff_data = iff_dataPtr + 12;
S_FindChunk("fmt ");
if( !iff_dataPtr )
{
MsgDev( D_WARN, "S_LoadWAV: missing 'fmt ' chunk (%s)\n", name );
Mem_Free( buffer );
return false;
}
iff_dataPtr += 8;
if( S_GetLittleShort() != 1 )
{
MsgDev( D_WARN, "S_LoadWAV: microsoft PCM format only (%s)\n", name );
Mem_Free( buffer );
return false;
}
info->channels = S_GetLittleShort();
if( info->channels != 1 )
{
MsgDev( D_WARN, "S_LoadWAV: only mono WAV files supported (%s)\n", name );
Mem_Free( buffer );
return false;
}
info->rate = S_GetLittleLong();
iff_dataPtr += 4+2;
info->width = S_GetLittleShort() / 8;
if( info->width != 1 && info->width != 2 )
{
MsgDev( D_WARN, "S_LoadWAV: only 8 and 16 bit WAV files supported (%s)\n", name );
Mem_Free( buffer );
return false;
}
// Find data chunk
S_FindChunk("data");
if( !iff_dataPtr )
{
MsgDev( D_WARN, "S_LoadWAV: missing 'data' chunk (%s)\n", name );
Mem_Free( buffer );
return false;
}
iff_dataPtr += 4;
info->samples = S_GetLittleLong() / info->width;
if( info->samples <= 0 )
{
MsgDev( D_WARN, "S_LoadWAV: file with 0 samples (%s)\n", name);
Mem_Free( buffer );
return false;
}
// Load the data
*wav = out = Z_Malloc( info->samples * info->width );
Mem_Copy( out, buffer + (iff_dataPtr - buffer), info->samples * info->width );
Mem_Free( buffer );
return true;
}
/*
=================
S_UploadSound
=================
*/
static void S_UploadSound( byte *data, int width, int channels, sfx_t *sfx )
{
int size;
// calculate buffer size
size = sfx->samples * width * channels;
// Set buffer format
if( width == 2 )
{
if( channels == 2 ) sfx->format = AL_FORMAT_STEREO16;
else sfx->format = AL_FORMAT_MONO16;
}
else
{
if( channels == 2 ) sfx->format = AL_FORMAT_STEREO8;
else sfx->format = AL_FORMAT_MONO8;
}
// upload the sound
palGenBuffers(1, &sfx->bufferNum);
palBufferData( sfx->bufferNum, sfx->format, data, size, sfx->rate );
}
/*
=================
S_CreateDefaultSound
=================
*/
static void S_CreateDefaultSound( byte **wav, wavinfo_t *info )
{
byte *out;
int i;
info->rate = 22050;
info->width = 2;
info->channels = 1;
info->samples = 11025;
*wav = out = Z_Malloc( info->samples * info->width );
for( i = 0; i < info->samples; i++ )
((short *)out)[i] = sin(i * 0.1f) * 20000;
}
/*
=================
S_LoadSound
=================
*/
bool S_LoadSound( sfx_t *sfx )
{
string name;
byte *data;
wavinfo_t info;
if( !sfx ) return false;
if( sfx->name[0] == '*' ) return false;
if( sfx->loaded ) return true; // see if still in memory
// load it from disk
if( sfx->name[0] == '#' )
com.snprintf( name, sizeof(name), "%s", &sfx->name[1]);
else com.snprintf( name, sizeof(name), "sound/%s", sfx->name );
if(!S_LoadWAV(name, &data, &info))
{
sfx->default_snd = true;
MsgWarn( "couldn't find sound '%s', using default...\n", name );
S_CreateDefaultSound( &data, &info );
}
// load it in
sfx->loaded = true;
sfx->samples = info.samples;
sfx->rate = info.rate;
S_UploadSound( data, info.width, info.channels, sfx );
Mem_Free(data);
return true;
}
// =======================================================================
// Load a sound
// =======================================================================
/*
================
return a hash value for the sfx name
================
*/
static long S_HashSFXName( const char *name )
{
int i = 0;
long hash = 0;
char letter;
while( name[i] != '\0' )
{
letter = com.tolower(name[i]);
if (letter =='.') break; // don't include extension
if (letter =='\\') letter = '/'; // damn path names
hash += (long)(letter)*(i+119);
i++;
}
hash &= (SFX_HASHSIZE-1);
return hash;
}
/*
=================
S_FindSound
=================
*/
sfx_t *S_FindSound( const char *name )
{
int i, hash;
sfx_t *sfx;
if( !name || !name[0] )
{
MsgWarn("S_FindSound: empty name\n");
return NULL;
}
if( com.strlen(name) >= MAX_STRING )
{
MsgWarn("S_FindSound: sound name too long: %s", name);
return NULL;
}
hash = S_HashSFXName(name);
sfx = sfxHash[hash];
// see if already loaded
while( sfx )
{
if (!stricmp(sfx->name, name))
return sfx;
sfx = sfx->nextHash;
}
// find a free sfx slot
for (i = 0; i < s_numSfx; i++)
{
if(!s_knownSfx[i].name[0])
break;
}
if (i == s_numSfx)
{
if (s_numSfx == MAX_SFX)
{
MsgWarn("S_FindName: MAX_SFX limit exceeded\n");
return NULL;
}
s_numSfx++;
}
sfx = &s_knownSfx[i];
memset (sfx, 0, sizeof(*sfx));
strcpy (sfx->name, name);
sfx->nextHash = sfxHash[hash];
sfxHash[hash] = sfx;
return sfx;
}
/*
=====================
S_BeginRegistration
=====================
*/
void S_BeginRegistration( void )
{
}
/*
=====================
S_EndRegistration
=====================
*/
void S_EndRegistration( void )
{
}
/*
=================
S_RegisterSound
=================
*/
sound_t S_RegisterSound( const char *name )
{
sfx_t *sfx;
if(!al_state.initialized)
return 0;
sfx = S_FindSound( name );
S_LoadSound( sfx );
if( !sfx ) return 0;
return sfx - s_knownSfx;
}
sfx_t *S_GetSfxByHandle( sound_t handle )
{
if( handle < 0 || handle >= s_numSfx )
{
MsgWarn("S_GetSfxByHandle: handle %i out of range (%i)\n", handle, s_numSfx );
return NULL;
}
return &s_knownSfx[handle];
}
/*
=================
S_FreeSounds
=================
*/
void S_FreeSounds( void )
{
sfx_t *sfx;
int i;
// Stop all sounds
S_StopAllSounds();
// Free all sounds
for (i = 0; i < s_numSfx; i++)
{
sfx = &s_knownSfx[i];
palDeleteBuffers(1, &sfx->bufferNum);
}
memset( sfxHash, 0, sizeof(sfx_t *)*SFX_HASHSIZE);
memset( s_knownSfx, 0, sizeof(s_knownSfx));
s_numSfx = 0;
}

454
vsound/s_load.c.old Normal file
View File

@ -0,0 +1,454 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// s_load.c - sound managment
//=======================================================================
#include "sound.h"
#define SFX_HASHSIZE 256
#define MAX_SFX 1024
static sfx_t *s_sfxHash[SFX_HASHSIZE];
static sfx_t *s_sfx[MAX_SFX];
static int s_numSfx;
/*
=================
S_SoundList_f
=================
*/
void S_SoundList_f( void )
{
sfx_t *sfx;
int i, samples = 0;
Msg("\n");
Msg(" -samples -hz-- -format- -name--------\n");
for( i = 0; i < s_numSfx; i++ )
{
sfx = s_sfx[i];
Msg("%4i: ", i);
if( sfx->loaded )
{
samples += sfx->samples;
Msg("%8i ", sfx->samples);
Msg("%5i ", sfx->rate);
switch( sfx->format )
{
case AL_FORMAT_STEREO16: Msg("STEREO16 "); break;
case AL_FORMAT_STEREO8: Msg("STEREO8 "); break;
case AL_FORMAT_MONO16: Msg("MONO16 "); break;
case AL_FORMAT_MONO8: Msg("MONO8 "); break;
default: Msg("???????? "); break;
}
if( sfx->name[0] == '#' ) Msg("%s", &sfx->name[1]);
else Msg("sound/%s", sfx->name);
if( sfx->default_snd ) Msg(" (DEFAULTED)\n");
else Msg("\n");
}
else
{
if( sfx->name[0] == '*' ) Msg(" placeholder %s\n", sfx->name);
else Msg(" not loaded %s\n", sfx->name);
}
}
Msg("-------------------------------------------\n");
Msg("%i total samples\n", samples);
Msg("%i total sounds\n", s_numSfx);
Msg("\n");
}
/*
=======================================================================
WAV LOADING
=======================================================================
*/
static byte *iff_data;
static byte *iff_dataPtr;
static byte *iff_end;
static byte *iff_lastChunk;
static int iff_chunkLen;
/*
=================
S_GetLittleShort
=================
*/
static short S_GetLittleShort( void )
{
short val = 0;
val += (*(iff_dataPtr+0) << 0);
val += (*(iff_dataPtr+1) << 8);
iff_dataPtr += 2;
return val;
}
/*
=================
S_GetLittleLong
=================
*/
static int S_GetLittleLong( void )
{
int val = 0;
val += (*(iff_dataPtr+0) << 0);
val += (*(iff_dataPtr+1) << 8);
val += (*(iff_dataPtr+2) << 16);
val += (*(iff_dataPtr+3) << 24);
iff_dataPtr += 4;
return val;
}
/*
=================
S_FindNextChunk
=================
*/
static void S_FindNextChunk( const char *name )
{
while( 1 )
{
iff_dataPtr = iff_lastChunk;
if( iff_dataPtr >= iff_end )
{
// didn't find the chunk
iff_dataPtr = NULL;
return;
}
iff_dataPtr += 4;
iff_chunkLen = S_GetLittleLong();
if (iff_chunkLen < 0)
{
iff_dataPtr = NULL;
return;
}
iff_dataPtr -= 8;
iff_lastChunk = iff_dataPtr + 8 + ((iff_chunkLen + 1) & ~1);
if(!com.strncmp( iff_dataPtr, name, 4 ))
return;
}
}
/*
=================
S_FindChunk
=================
*/
static void S_FindChunk( const char *name )
{
iff_lastChunk = iff_data;
S_FindNextChunk( name );
}
/*
=================
S_LoadWAV
=================
*/
static bool S_LoadWAV( const char *name, byte **wav, wavinfo_t *info )
{
byte *buffer, *out;
int length;
buffer = FS_LoadFile( name, &length );
if( !buffer ) return false;
iff_data = buffer;
iff_end = buffer + length;
// dind "RIFF" chunk
S_FindChunk( "RIFF" );
if(!(iff_dataPtr && !com.strncmp(iff_dataPtr+8, "WAVE", 4)))
{
MsgDev( D_WARN, "S_LoadWAV: missing 'RIFF/WAVE' chunks (%s)\n", name );
Mem_Free( buffer );
return false;
}
// get "fmt " chunk
iff_data = iff_dataPtr + 12;
S_FindChunk("fmt ");
if( !iff_dataPtr )
{
MsgDev( D_WARN, "S_LoadWAV: missing 'fmt ' chunk (%s)\n", name );
Mem_Free( buffer );
return false;
}
iff_dataPtr += 8;
if( S_GetLittleShort() != 1 )
{
MsgDev( D_WARN, "S_LoadWAV: microsoft PCM format only (%s)\n", name );
Mem_Free( buffer );
return false;
}
info->channels = S_GetLittleShort();
if( info->channels != 1 )
{
MsgDev( D_WARN, "S_LoadWAV: only mono WAV files supported (%s)\n", name );
Mem_Free( buffer );
return false;
}
info->rate = S_GetLittleLong();
iff_dataPtr += 4+2;
info->width = S_GetLittleShort() / 8;
if( info->width != 1 && info->width != 2 )
{
MsgDev( D_WARN, "S_LoadWAV: only 8 and 16 bit WAV files supported (%s)\n", name );
Mem_Free( buffer );
return false;
}
// Find data chunk
S_FindChunk("data");
if( !iff_dataPtr )
{
MsgDev( D_WARN, "S_LoadWAV: missing 'data' chunk (%s)\n", name );
Mem_Free( buffer );
return false;
}
iff_dataPtr += 4;
info->samples = S_GetLittleLong() / info->width;
if( info->samples <= 0 )
{
MsgDev( D_WARN, "S_LoadWAV: file with 0 samples (%s)\n", name);
Mem_Free( buffer );
return false;
}
// Load the data
*wav = out = Z_Malloc( info->samples * info->width );
Mem_Copy( out, buffer + (iff_dataPtr - buffer), info->samples * info->width );
Mem_Free( buffer );
return true;
}
/*
=================
S_UploadSound
=================
*/
static void S_UploadSound( byte *data, int width, int channels, sfx_t *sfx )
{
int size;
// calculate buffer size
size = sfx->samples * width * channels;
// Set buffer format
if( width == 2 )
{
if( channels == 2 ) sfx->format = AL_FORMAT_STEREO16;
else sfx->format = AL_FORMAT_MONO16;
}
else
{
if( channels == 2 ) sfx->format = AL_FORMAT_STEREO8;
else sfx->format = AL_FORMAT_MONO8;
}
// upload the sound
palGenBuffers(1, &sfx->bufferNum);
palBufferData(sfx->bufferNum, sfx->format, data, size, sfx->rate);
}
/*
=================
S_CreateDefaultSound
=================
*/
static void S_CreateDefaultSound( byte **wav, wavinfo_t *info )
{
byte *out;
int i;
info->rate = 22050;
info->width = 2;
info->channels = 1;
info->samples = 11025;
*wav = out = Z_Malloc( info->samples * info->width );
for( i = 0; i < info->samples; i++ )
((short *)out)[i] = sin(i * 0.1f) * 20000;
}
/*
=================
S_LoadSound
=================
*/
bool S_LoadSound( sfx_t *sfx )
{
string name;
byte *data;
wavinfo_t info;
if( !sfx ) return false;
if( sfx->name[0] == '*' ) return false;
if( sfx->loaded ) return true; // see if still in memory
// load it from disk
if( sfx->name[0] == '#' )
com.snprintf( name, sizeof(name), "%s", &sfx->name[1]);
else com.snprintf( name, sizeof(name), "sound/%s", sfx->name );
if(!S_LoadWAV(name, &data, &info))
{
sfx->default_snd = true;
MsgWarn( "couldn't find sound '%s', using default...\n", name );
S_CreateDefaultSound( &data, &info );
}
// load it in
sfx->loaded = true;
sfx->samples = info.samples;
sfx->rate = info.rate;
S_UploadSound( data, info.width, info.channels, sfx );
Mem_Free(data);
return true;
}
/*
=================
S_FindSound
=================
*/
sfx_t *S_FindSound( const char *name )
{
sfx_t *sfx;
uint hashKey;
if( !name || !name[0] )
{
MsgWarn("S_FindSound: empty name\n");
return NULL;
}
if( com.strlen(name) >= MAX_STRING )
{
MsgWarn("S_FindSound: sound name too long: %s", name);
return NULL;
}
hashKey = Com_HashKey(name, SFX_HASHSIZE);
for( sfx = s_sfxHash[hashKey]; sfx; sfx = sfx->nextHash )
{
if (!com.stricmp( sfx->name, name ))
return sfx;
}
// Create a new sfx_t
if( s_numSfx == MAX_SFX )
{
MsgWarn("S_FindSound: MAX_SFX limit exceeded\n");
return NULL;
}
s_sfx[s_numSfx++] = sfx = Z_Malloc(sizeof(sfx_t));
// fill it in
com.strncpy( sfx->name, name, sizeof(sfx->name));
// add to hash table
sfx->nextHash = s_sfxHash[hashKey];
s_sfxHash[hashKey] = sfx;
return sfx;
}
/*
=====================
S_BeginRegistration
=====================
*/
void S_BeginRegistration( void )
{
}
/*
=====================
S_EndRegistration
=====================
*/
void S_EndRegistration( void )
{
}
/*
=================
S_RegisterSound
=================
*/
sound_t S_RegisterSound( const char *name )
{
sfx_t *sfx;
if(!al_state.initialized)
return 0;
sfx = S_FindSound( name );
S_LoadSound( sfx );
if( !sfx ) return 0;
return sfx - *s_sfx;
}
sfx_t *S_GetSfxByHandle( sound_t handle )
{
if( handle < 0 || handle >= s_numSfx )
{
MsgWarn("S_GetSfxByHandle: handle %i out of range (%i)\n", handle, s_numSfx );
return NULL;
}
return s_sfx[handle];
}
/*
=================
S_FreeSounds
=================
*/
void S_FreeSounds( void )
{
sfx_t *sfx;
int i;
// Stop all sounds
S_StopAllSounds();
// Free all sounds
for (i = 0; i < s_numSfx; i++){
sfx = s_sfx[i];
palDeleteBuffers(1, &sfx->bufferNum);
Mem_Free(sfx);
}
memset( s_sfxHash, 0, sizeof(s_sfxHash));
memset( s_sfx, 0, sizeof(s_sfx));
s_numSfx = 0;
}

809
vsound/s_main.c Normal file
View File

@ -0,0 +1,809 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// s_main.c - sound engine
//=======================================================================
#include "sound.h"
cvar_t *s_initSound;
cvar_t *s_show;
cvar_t *s_alDevice;
cvar_t *s_allowExtensions;
cvar_t *s_soundfx;
cvar_t *s_ignoreALErrors;
cvar_t *s_masterVolume;
cvar_t *s_sfxVolume;
cvar_t *s_musicVolume;
cvar_t *s_minDistance;
cvar_t *s_maxDistance;
cvar_t *s_rolloffFactor;
cvar_t *s_dopplerFactor;
cvar_t *s_dopplerVelocity;
#define MAX_PLAYSOUNDS 128
#define MAX_CHANNELS 64
static playSound_t s_playSounds[MAX_PLAYSOUNDS];
static playSound_t s_freePlaySounds;
static playSound_t s_pendingPlaySounds;
static channel_t s_channels[MAX_CHANNELS];
static int s_numChannels;
static listener_t s_listener;
static int s_frameCount;
const guid_t DSPROPSETID_EAX20_ListenerProperties = {0x306a6a8, 0xb224, 0x11d2, {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};
const guid_t DSPROPSETID_EAX20_BufferProperties = {0x306a6a7, 0xb224, 0x11d2, {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};
cvar_t *s_initSound;
cvar_t *s_show;
cvar_t *s_alDriver;
cvar_t *s_alDevice;
cvar_t *s_allowExtensions;
cvar_t *s_ext_eax;
cvar_t *s_ignoreALErrors;
cvar_t *s_masterVolume;
cvar_t *s_sfxVolume;
cvar_t *s_musicVolume;
cvar_t *s_minDistance;
cvar_t *s_maxDistance;
cvar_t *s_rolloffFactor;
cvar_t *s_dopplerFactor;
cvar_t *s_dopplerVelocity;
/*
=================
S_CheckForErrors
=================
*/
static void S_CheckForErrors( void )
{
int err;
char *str;
if((err = palGetError()) == AL_NO_ERROR)
return;
switch( err )
{
case AL_INVALID_NAME:
str = "AL_INVALID_NAME";
break;
case AL_INVALID_ENUM:
str = "AL_INVALID_ENUM";
break;
case AL_INVALID_VALUE:
str = "AL_INVALID_VALUE";
break;
case AL_INVALID_OPERATION:
str = "AL_INVALID_OPERATION";
break;
case AL_OUT_OF_MEMORY:
str = "AL_OUT_OF_MEMORY";
break;
default:
str = "UNKNOWN ERROR";
break;
}
Host_Error( "S_CheckForErrors: %s", str );
}
/*
=================
S_AllocChannels
=================
*/
static void S_AllocChannels( void )
{
channel_t *ch;
int i;
for( i = 0, ch = s_channels; i < MAX_CHANNELS; i++, ch++)
{
palGenSources(1, &ch->sourceNum);
if(palGetError() != AL_NO_ERROR)
break;
al_state.num_channels++;
}
}
/*
=================
S_FreeChannels
=================
*/
static void S_FreeChannels( void )
{
channel_t *ch;
int i;
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
{
palDeleteSources(1, &ch->sourceNum);
memset(ch, 0, sizeof(*ch));
}
al_state.num_channels = 0;
}
/*
=================
S_ChannelState
=================
*/
static int S_ChannelState( channel_t *ch )
{
int state;
palGetSourcei( ch->sourceNum, AL_SOURCE_STATE, &state );
return state;
}
/*
=================
S_PlayChannel
=================
*/
static void S_PlayChannel( channel_t *ch, sfx_t *sfx )
{
ch->sfx = sfx;
palSourcei(ch->sourceNum, AL_BUFFER, sfx->bufferNum);
palSourcei(ch->sourceNum, AL_LOOPING, ch->loopsound);
palSourcei(ch->sourceNum, AL_SOURCE_RELATIVE, false);
palSourcePlay(ch->sourceNum);
}
/*
=================
S_StopChannel
=================
*/
static void S_StopChannel( channel_t *ch )
{
ch->sfx = NULL;
palSourceStop(ch->sourceNum);
palSourcei(ch->sourceNum, AL_BUFFER, 0);
}
/*
=================
S_SpatializeChannel
=================
*/
static void S_SpatializeChannel( channel_t *ch )
{
vec3_t position, velocity;
// update position and velocity
if( ch->entnum == al_state.clientnum || !ch->distanceMult )
{
palSourcefv(ch->sourceNum, AL_POSITION, s_listener.position);
palSourcefv(ch->sourceNum, AL_VELOCITY, s_listener.velocity);
}
else
{
if( ch->fixedPosition )
{
palSource3f(ch->sourceNum, AL_POSITION, ch->position[1], ch->position[2], -ch->position[0]);
palSource3f(ch->sourceNum, AL_VELOCITY, 0, 0, 0);
}
else
{
if( ch->loopsound ) si.GetSoundSpatialization(ch->loopnum, position, velocity);
else si.GetSoundSpatialization( ch->entnum, position, velocity);
palSource3f(ch->sourceNum, AL_POSITION, position[1], position[2], -position[0]);
palSource3f(ch->sourceNum, AL_VELOCITY, velocity[1], velocity[2], -velocity[0]);
}
}
// Update min/max distance
if( ch->distanceMult )
palSourcef(ch->sourceNum, AL_REFERENCE_DISTANCE, s_minDistance->value * ch->distanceMult );
else palSourcef(ch->sourceNum, AL_REFERENCE_DISTANCE, s_maxDistance->value );
palSourcef( ch->sourceNum, AL_MAX_DISTANCE, s_maxDistance->value );
// update volume and rolloff factor
palSourcef( ch->sourceNum, AL_GAIN, s_sfxVolume->value * ch->volume );
palSourcef( ch->sourceNum, AL_ROLLOFF_FACTOR, s_rolloffFactor->value );
}
/*
=================
S_PickChannel
Tries to find a free channel, or tries to replace an active channel
=================
*/
channel_t *S_PickChannel( int entnum, int entChannel )
{
channel_t *ch;
int i;
int firstToDie = -1;
int oldestTime = si.GetClientTime();
if( entnum < 0 || entChannel < 0 )
Host_Error( "S_PickChannel: entnum or entChannel less than 0" );
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
{
// don't let game sounds override streaming sounds
if( ch->streaming )continue;
// check if this channel is active
if( !ch->sfx )
{
// free channel
firstToDie = i;
break;
}
// channel 0 never overrides
if( entChannel != 0 && (ch->entnum == entnum && ch->entchannel == entChannel))
{
// always override sound from same entity
firstToDie = i;
break;
}
// don't let monster sounds override player sounds
if( entnum != al_state.clientnum && ch->entnum == al_state.clientnum )
continue;
// replace the oldest sound
if( ch->startTime < oldestTime )
{
oldestTime = ch->startTime;
firstToDie = i;
}
}
if( firstToDie == -1 ) return NULL;
ch = &s_channels[firstToDie];
ch->entnum = entnum;
ch->entchannel = entChannel;
ch->startTime = si.GetClientTime();
// Make sure this channel is stopped
palSourceStop(ch->sourceNum);
palSourcei(ch->sourceNum, AL_BUFFER, 0);
return ch;
}
/*
=================
S_AddLoopingSounds
Entities with a sound field will generate looping sounds that are
automatically started and stopped as the entities are sent to the
client
=================
*/
bool S_AddLoopingSound( int entnum, sound_t handle, float volume, float attn )
{
channel_t *ch;
sfx_t *sfx = NULL;
int i;
if(!al_state.initialized )
return false;
sfx = S_GetSfxByHandle( handle );
// default looped sound it's terrible :)
if( !sfx || !sfx->loaded || sfx->default_snd )
return false;
// if this entity is already playing the same sound effect on an
// active channel, then simply update it
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
{
if( ch->sfx != sfx ) continue;
if( !ch->loopsound ) continue;
if( ch->loopnum != entnum ) continue;
if( ch->loopframe + 1 != al_state.framecount )
continue;
ch->loopframe = al_state.framecount;
break;
}
if( i != al_state.num_channels )
return false;
// otherwise pick a channel and start the sound effect
ch = S_PickChannel( 0, 0 );
if( !ch )
{
if( sfx->name[0] == '#' ) MsgDev(D_ERROR, "dropped sound %s\n", &sfx->name[1] );
else MsgDev( D_ERROR, "dropped sound \"sound/%s\"\n", sfx->name );
return false;
}
ch->loopsound = true;
ch->loopnum = entnum;
ch->loopframe = al_state.framecount;
ch->fixedPosition = false;
ch->volume = 1.0;
ch->distanceMult = 1.0 / ATTN_STATIC;
S_SpatializeChannel( ch );
S_PlayChannel( ch, sfx );
return true;
}
/*
=================
S_AllocPlaySound
=================
*/
static playSound_t *S_AllocPlaySound( void )
{
playSound_t *ps;
ps = s_freePlaySounds.next;
if( ps == &s_freePlaySounds )
return NULL; // No free playSounds
ps->prev->next = ps->next;
ps->next->prev = ps->prev;
return ps;
}
/*
=================
S_FreePlaySound
=================
*/
static void S_FreePlaySound( playSound_t *ps )
{
ps->prev->next = ps->next;
ps->next->prev = ps->prev;
// add to free list
ps->next = s_freePlaySounds.next;
s_freePlaySounds.next->prev = ps;
ps->prev = &s_freePlaySounds;
s_freePlaySounds.next = ps;
}
/*
=================
S_IssuePlaySounds
Take all the pending playSounds and begin playing them.
This is never called directly by S_Start*, but only by the update loop.
=================
*/
static void S_IssuePlaySounds( void )
{
playSound_t *ps;
channel_t *ch;
while( 1 )
{
ps = s_pendingPlaySounds.next;
if(ps == &s_pendingPlaySounds)
break; // no more pending playSounds
if( ps->beginTime > si.GetClientTime())
break; // No more pending playSounds this frame
// pick a channel and start the sound effect
ch = S_PickChannel( ps->entnum, ps->entchannel );
if(!ch)
{
if( ps->sfx->name[0] == '#' ) MsgDev(D_ERROR, "dropped sound %s\n", &ps->sfx->name[1] );
else MsgDev( D_ERROR, "dropped sound \"sound/%s\"\n", ps->sfx->name );
S_FreePlaySound( ps );
continue;
}
ch->loopsound = false;
ch->fixedPosition = ps->fixedPosition;
VectorCopy( ps->position, ch->position );
ch->volume = ps->volume;
if( ps->attenuation != ATTN_NONE ) ch->distanceMult = 1.0 / ps->attenuation;
else ch->distanceMult = 0.0;
S_SpatializeChannel( ch );
S_PlayChannel( ch, ps->sfx );
// free the playSound
S_FreePlaySound( ps );
}
}
/*
=================
S_StartSound
Validates the parms and queues the sound up.
if origin is NULL, the sound will be dynamically sourced from the entity.
entchannel 0 will never override a playing sound.
=================
*/
void S_StartSound( const vec3_t position, int entnum, int entChannel, sound_t handle, float volume, float attenuation )
{
playSound_t *ps, *sort;
sfx_t *sfx = NULL;
if(!al_state.initialized )
return;
sfx = S_GetSfxByHandle( handle );
if( !sfx ) return;
// Make sure the sound is loaded
if(!S_LoadSound(sfx)) return;
// Allocate a playSound
ps = S_AllocPlaySound();
if(!ps)
{
if( sfx->name[0] == '#' ) MsgDev(D_ERROR, "dropped sound %s\n", &sfx->name[1] );
else MsgDev( D_ERROR, "dropped sound \"sound/%s\"\n", sfx->name );
return;
}
ps->sfx = sfx;
ps->entnum = entnum;
ps->entchannel = entChannel;
if( position )
{
ps->fixedPosition = true;
VectorCopy( position, ps->position );
}
else ps->fixedPosition = false;
ps->volume = volume;
ps->attenuation = attenuation;
ps->beginTime = si.GetClientTime();
// Sort into the pending playSounds list
for( sort = s_pendingPlaySounds.next; sort != &s_pendingPlaySounds&& sort->beginTime < ps->beginTime; sort = sort->next );
ps->next = sort;
ps->prev = sort->prev;
ps->next->prev = ps;
ps->prev->next = ps;
}
/*
=================
S_StartLocalSound
menu sound
=================
*/
bool S_StartLocalSound( const char *name )
{
sound_t sfxHandle;
if(!al_state.initialized)
return false;
sfxHandle = S_RegisterSound( name );
S_StartSound( NULL, al_state.clientnum, 0, sfxHandle, 1.0f, ATTN_NONE );
return true;
}
/*
=================
S_StopAllSounds
=================
*/
void S_StopAllSounds( void )
{
channel_t *ch;
int i;
if(!al_state.initialized)
return;
// Clear all the playSounds
memset( s_playSounds, 0, sizeof(s_playSounds));
s_freePlaySounds.next = s_freePlaySounds.prev = &s_freePlaySounds;
s_pendingPlaySounds.next = s_pendingPlaySounds.prev = &s_pendingPlaySounds;
for( i = 0; i < MAX_PLAYSOUNDS; i++ )
{
s_playSounds[i].prev = &s_freePlaySounds;
s_playSounds[i].next = s_freePlaySounds.next;
s_playSounds[i].prev->next = &s_playSounds[i];
s_playSounds[i].next->prev = &s_playSounds[i];
}
// Stop all the channels
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
{
if( !ch->sfx ) continue;
S_StopChannel( ch );
}
S_StopStreaming(); // stop streaming channel
S_StopBackgroundTrack(); // stop background track
al_state.framecount = 0; // reset frame count
}
/*
=================
S_AddEnvironmentEffects
process all effects here
=================
*/
void S_AddEnvironmentEffects( const vec3_t position )
{
uint eaxEnv;
if( !al_config.allow_3DMode ) return;
// if eax is enabled, apply listener environmental effects
if( si.PointContents((float *)position ) & MASK_WATER )
eaxEnv = EAX_ENVIRONMENT_UNDERWATER;
else eaxEnv = EAX_ENVIRONMENT_GENERIC;
al_config.Set3DMode(&DSPROPSETID_EAX20_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT|DSPROPERTY_EAXLISTENER_DEFERRED, 0, &eaxEnv, sizeof(eaxEnv));
}
/*
=================
S_Update
Called once each time through the main loop
=================
*/
void S_Update( int clientnum, const vec3_t position, const vec3_t velocity, const vec3_t at, const vec3_t up )
{
channel_t *ch;
int i;
if(!al_state.initialized ) return;
// Bump frame count
al_state.framecount++;
al_state.clientnum = clientnum;
// Set up listener
VectorSet( s_listener.position, position[1], position[2], -position[0]);
VectorSet( s_listener.velocity, velocity[1], velocity[2], -velocity[0]);
// set listener orientation matrix
s_listener.orientation[0] = at[1];
s_listener.orientation[1] = -at[2];
s_listener.orientation[2] = -at[0];
s_listener.orientation[3] = up[1];
s_listener.orientation[4] = -up[2];
s_listener.orientation[5] = -up[0];
palListenerfv(AL_POSITION, s_listener.position);
palListenerfv(AL_VELOCITY, s_listener.velocity);
palListenerfv(AL_ORIENTATION, s_listener.orientation);
palListenerf(AL_GAIN, (al_state.active) ? s_masterVolume->value : 0.0f );
// Set state
palDistanceModel( AL_INVERSE_DISTANCE_CLAMPED );
palDopplerFactor(s_dopplerFactor->value);
palDopplerVelocity(s_dopplerVelocity->value);
S_AddEnvironmentEffects( position );
// Stream background track
S_StreamBackgroundTrack();
// Add looping sounds
si.AddLoopingSounds();
// Issue playSounds
S_IssuePlaySounds();
// update spatialization for all sounds
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
{
if(!ch->sfx) continue; // not active
// check for stop
if( ch->loopsound )
{
if(ch->loopframe != al_state.framecount)
{
S_StopChannel( ch );
continue;
}
}
else
{
if( S_ChannelState( ch ) == AL_STOPPED )
{
S_StopChannel( ch );
continue;
}
}
// respatialize channel
S_SpatializeChannel( ch );
}
// check for errors
if(!s_ignoreALErrors->integer)
S_CheckForErrors();
}
/*
=================
S_Activate
Called when the main window gains or loses focus.
The window may have been destroyed and recreated between a deactivate
and an activate.
=================
*/
void S_Activate( bool active )
{
if(!al_state.initialized )
return;
al_state.active = active;
if( active ) palListenerf( AL_GAIN, s_masterVolume->value );
else palListenerf( AL_GAIN, 0.0 );
}
/*
=================
S_Play_f
=================
*/
void S_Play_f( void )
{
int i = 1;
string name;
if( Cmd_Argc() == 1 )
{
Msg("Usage: play <soundfile> [...]\n");
return;
}
while ( i < Cmd_Argc())
{
if ( !com.strrchr(Cmd_Argv(i), '.')) com.sprintf( name, "%s.wav", Cmd_Argv(1) );
else com.strncpy( name, Cmd_Argv(i), sizeof(name) );
S_StartLocalSound( name );
i++;
}
}
/*
=================
S_Music_f
=================
*/
void S_Music_f( void )
{
int c = Cmd_Argc();
if( c == 2 ) S_StartBackgroundTrack( Cmd_Argv(1), Cmd_Argv(1) );
else if( c == 3 ) S_StartBackgroundTrack( Cmd_Argv(1), Cmd_Argv(2) );
else Msg("Usage: music <musicfile> [loopfile]\n");
}
/*
=================
S_StopSound_f
=================
*/
void S_StopSound_f( void )
{
S_StopAllSounds();
}
/*
=================
S_SoundInfo_f
=================
*/
void S_SoundInfo_f( void )
{
if(!al_state.initialized )
{
Msg("Sound system not started\n");
return;
}
Msg("\n");
Msg("AL_VENDOR: %s\n", al_config.vendor_string);
Msg("AL_RENDERER: %s\n", al_config.renderer_string);
Msg("AL_VERSION: %s\n", al_config.version_string);
Msg("AL_EXTENSIONS: %s\n", al_config.extensions_string);
Msg("\n");
Msg("DEVICE: %s\n", s_alDevice->string );
Msg("CHANNELS: %i\n", al_state.num_channels);
Msg("3D sound: %s\n", (al_config.allow_3DMode) ? "enabled" : "disabled" );
Msg("\n");
}
/*
=================
S_Init
=================
*/
void S_Init( void *hInst )
{
s_initSound = Cvar_Get("s_initsound", "1", CVAR_SYSTEMINFO );
s_alDevice = Cvar_Get("s_device", "Generic Software", CVAR_LATCH|CVAR_ARCHIVE );
s_allowExtensions = Cvar_Get("s_allowextensions", "1", CVAR_LATCH|CVAR_ARCHIVE );
s_soundfx = Cvar_Get("s_soundfx", "1", CVAR_LATCH|CVAR_ARCHIVE );
s_ignoreALErrors = Cvar_Get("s_ignoreALErrors", "1", CVAR_ARCHIVE );
s_masterVolume = Cvar_Get("s_volume", "1.0", CVAR_ARCHIVE );
s_sfxVolume = Cvar_Get("s_soundvolume", "1.0", CVAR_ARCHIVE );
s_musicVolume = Cvar_Get("s_musicvolume", "1.0", CVAR_ARCHIVE );
s_minDistance = Cvar_Get("s_mindistance", "240.0", CVAR_ARCHIVE );
s_maxDistance = Cvar_Get("s_maxdistance", "8192.0", CVAR_ARCHIVE );
s_rolloffFactor = Cvar_Get("s_rollofffactor", "1.0", CVAR_ARCHIVE );
s_dopplerFactor = Cvar_Get("s_dopplerfactor", "1.0", CVAR_ARCHIVE );
s_dopplerVelocity = Cvar_Get("s_dopplervelocity", "10976.0", CVAR_ARCHIVE );
Cmd_AddCommand("play", S_Play_f, "playing a specified sound file" );
Cmd_AddCommand("music", S_Music_f, "starting a background track" );
Cmd_AddCommand("s_stop", S_StopSound_f, "stop all sounds" );
Cmd_AddCommand("s_info", S_SoundInfo_f, "print sound system information" );
Cmd_AddCommand("soundlist", S_SoundList_f, "display loaded sounds" );
if(!s_initSound->integer)
{
MsgDev(D_INFO, "S_Init: sound system disabled\n" );
return;
}
if(!S_Init_OpenAL())
{
MsgDev( D_INFO, "S_Init: sound system can't initialized\n");
return;
}
sndpool = Mem_AllocPool("Sound Zone");
al_state.initialized = true;
S_AllocChannels();
S_StopAllSounds();
if(!s_ignoreALErrors->integer)
S_CheckForErrors();
al_state.active = true; // enabled
}
/*
=================
S_Shutdown
=================
*/
void S_Shutdown( void )
{
Cmd_RemoveCommand( "play" );
Cmd_RemoveCommand( "music" );
Cmd_RemoveCommand( "s_stop" );
Cmd_RemoveCommand( "s_info" );
Cmd_RemoveCommand( "soundlist" );
if( !al_state.initialized )
return;
S_FreeSounds();
S_FreeChannels();
Mem_FreePool( &sndpool );
S_Free_OpenAL();
al_state.initialized = false;
}

399
vsound/s_openal.c Normal file
View File

@ -0,0 +1,399 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// s_main.c - sound engine
//=======================================================================
#include "sound.h"
static dllfunc_t openal_funcs[] =
{
{"alcOpenDevice", (void **) &palcOpenDevice },
{"alcCloseDevice", (void **) &palcCloseDevice },
{"alcCreateContext", (void **) &palcCreateContext },
{"alcDestroyContext", (void **) &palcDestroyContext },
{"alcMakeContextCurrent", (void **) &palcMakeContextCurrent },
{"alcProcessContext", (void **) &palcProcessContext },
{"alcSuspendContext", (void **) &palcSuspendContext },
{"alcGetCurrentContext", (void **) &palcGetCurrentContext },
{"alcGetContextsDevice", (void **) &palcGetContextsDevice },
{"alcGetString", (void **) &palcGetString },
{"alcGetIntegerv", (void **) &palcGetIntegerv },
{"alcGetError", (void **) &palcGetError },
{"alcIsExtensionPresent", (void **) &palcIsExtensionPresent },
{"alcGetProcAddress", (void **) &palcGetProcAddress },
{"alcGetEnumValue", (void **) &palcGetEnumValue },
{"alBufferData", (void **) &palBufferData },
{"alDeleteBuffers", (void **) &palDeleteBuffers },
{"alDeleteSources", (void **) &palDeleteSources },
{"alDisable", (void **) &palDisable },
{"alDistanceModel", (void **) &palDistanceModel },
{"alDopplerFactor", (void **) &palDopplerFactor },
{"alDopplerVelocity", (void **) &palDopplerVelocity },
{"alEnable", (void **) &palEnable },
{"alGenBuffers", (void **) &palGenBuffers },
{"alGenSources", (void **) &palGenSources },
{"alGetBoolean", (void **) &palGetBoolean },
{"alGetBooleanv", (void **) &palGetBooleanv },
{"alGetBufferf", (void **) &palGetBufferf },
{"alGetBufferi", (void **) &palGetBufferi },
{"alGetDouble", (void **) &palGetDouble },
{"alGetDoublev", (void **) &palGetDoublev },
{"alGetEnumValue", (void **) &palGetEnumValue },
{"alGetError", (void **) &palGetError },
{"alGetFloat", (void **) &palGetFloat },
{"alGetFloatv", (void **) &palGetFloatv },
{"alGetInteger", (void **) &palGetInteger },
{"alGetIntegerv", (void **) &palGetIntegerv },
{"alGetListener3f", (void **) &palGetListener3f },
{"alGetListenerf", (void **) &palGetListenerf },
{"alGetListenerfv", (void **) &palGetListenerfv },
{"alGetListeneri", (void **) &palGetListeneri },
{"alGetProcAddress", (void **) &palGetProcAddress },
{"alGetSource3f", (void **) &palGetSource3f },
{"alGetSourcef", (void **) &palGetSourcef },
{"alGetSourcefv", (void **) &palGetSourcefv },
{"alGetSourcei", (void **) &palGetSourcei },
{"alGetString", (void **) &palGetString },
{"alIsBuffer", (void **) &palIsBuffer },
{"alIsEnabled", (void **) &palIsEnabled },
{"alIsExtensionPresent", (void **) &palIsExtensionPresent },
{"alIsSource", (void **) &palIsSource },
{"alListener3f", (void **) &palListener3f },
{"alListenerf", (void **) &palListenerf },
{"alListenerfv", (void **) &palListenerfv },
{"alListeneri", (void **) &palListeneri },
{"alSource3f", (void **) &palSource3f },
{"alSourcef", (void **) &palSourcef },
{"alSourcefv", (void **) &palSourcefv },
{"alSourcei", (void **) &palSourcei },
{"alSourcePause", (void **) &palSourcePause },
{"alSourcePausev", (void **) &palSourcePausev },
{"alSourcePlay", (void **) &palSourcePlay },
{"alSourcePlayv", (void **) &palSourcePlayv },
{"alSourceQueueBuffers", (void **) &palSourceQueueBuffers },
{"alSourceRewind", (void **) &palSourceRewind },
{"alSourceRewindv", (void **) &palSourceRewindv },
{"alSourceStop", (void **) &palSourceStop },
{"alSourceStopv", (void **) &palSourceStopv },
{"alSourceUnqueueBuffers", (void **) &palSourceUnqueueBuffers },
{ NULL, NULL }
};
static dllfunc_t openal_effects[] =
{
{"alGenEffects", (void **) &alGenEffects },
{"alDeleteEffects", (void **) &alDeleteEffects },
{"alIsEffect", (void **) &alIsEffect },
{"alEffecti", (void **) &alEffecti },
{"alEffectiv", (void **) &alEffectiv },
{"alEffectf", (void **) &alEffectf },
{"alEffectfv", (void **) &alEffectfv },
{"alGetEffecti", (void **) &alGetEffecti },
{"alGetEffectiv", (void **) &alGetEffectiv },
{"alGetEffectf", (void **) &alGetEffectf },
{"alGetEffectfv", (void **) &alGetEffectfv },
{"alGenFilters", (void **) &alGenFilters },
{"alDeleteFilters", (void **) &alDeleteFilters },
{"alIsFilter", (void **) &alIsFilter },
{"alFilteri", (void **) &alFilteri },
{"alFilteriv", (void **) &alFilteriv },
{"alFilterf", (void **) &alFilterf },
{"alFilterfv", (void **) &alFilterfv },
{"alGetFilteri", (void **) &alGetFilteri },
{"alGetFilteriv", (void **) &alGetFilteriv },
{"alGetFilterf", (void **) &alGetFilterf },
{"alGetFilterfv", (void **) &alGetFilterfv },
{"alGenAuxiliaryEffectSlots", (void **) &alGenAuxiliaryEffectSlots },
{"alDeleteAuxiliaryEffectSlots", (void **) &alDeleteAuxiliaryEffectSlots },
{"alIsAuxiliaryEffectSlot", (void **) &alIsAuxiliaryEffectSlot },
{"alAuxiliaryEffectSloti", (void **) &alAuxiliaryEffectSloti },
{"alAuxiliaryEffectSlotiv", (void **) &alAuxiliaryEffectSlotiv },
{"alAuxiliaryEffectSlotf", (void **) &alAuxiliaryEffectSlotf },
{"alAuxiliaryEffectSlotfv", (void **) &alAuxiliaryEffectSlotfv },
{"alGetAuxiliaryEffectSloti", (void **) &alGetAuxiliaryEffectSloti },
{"alGetAuxiliaryEffectSlotiv", (void **) &alGetAuxiliaryEffectSlotiv },
{"alGetAuxiliaryEffectSlotf", (void **) &alGetAuxiliaryEffectSlotf },
{"alGetAuxiliaryEffectSlotfv", (void **) &alGetAuxiliaryEffectSlotfv },
{ NULL, NULL }
};
dll_info_t openal_dll = { "openal32.dll", openal_funcs, NULL, NULL, NULL, false, 0 };
alconfig_t al_config;
alstate_t al_state;
cvar_t *s_eax;
/*
=================
S_InitDriver
=================
*/
static bool S_InitDriver( void )
{
int attrlist[3] = { ALC_FREQUENCY, 44100, 0 };
int *al_contxt = attrlist;
if((al_state.hDevice = palcOpenDevice( s_alDevice->string )) == NULL)
{
Msg("alOpenDevice - failed\n" );
return false;
}
if((al_state.hALC = palcCreateContext( al_state.hDevice, al_contxt )) == NULL)
goto failed;
if(!palcMakeContextCurrent(al_state.hALC))
goto failed;
return true;
failed:
if(al_state.hALC)
{
palcDestroyContext( al_state.hALC );
al_state.hALC = NULL;
}
if(al_state.hDevice)
{
palcCloseDevice( al_state.hDevice );
al_state.hDevice = NULL;
}
// release openal at all
Sys_FreeLibrary( &openal_dll );
memset(&al_config, 0, sizeof(alconfig_t));
memset(&al_state, 0, sizeof(alstate_t));
return false;
}
static bool S_SetupEFX( void )
{
const dllfunc_t *func;
// get the function pointers
for(func = openal_effects; func && func->name != NULL; func++)
{
if (!(*func->func = palGetProcAddress( func->name )))
{
MsgDev(D_ERROR, "S_InitEffects: %s missing or invalid function\n", func->name );
return false;
}
}
return true;
}
static void S_InitEffects( void )
{
uint uiEffects[1] = { 0 };
alGenEffects(1, &uiEffects[0]);
if( palGetError() == AL_NO_ERROR )
{
MsgDev( D_NOTE, "S_InitEffects:" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_REVERB);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_revrb" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_eaxrevrb" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_CHORUS);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_chorus" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_DISTORTION);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_distortion" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_ECHO);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_echo" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_FLANGER);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_flanger" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_FREQUENCY_SHIFTER);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_frequency_shifter" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_VOCAL_MORPHER);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_vocal_morpher" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_pitch_shifter" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_ring_modulator" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_AUTOWAH);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_autowah" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_compressor" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_equalizer" );
MsgDev( D_NOTE, "\n" );
}
alDeleteEffects(1, &uiEffects[0]);
}
static void S_InitFilters( void )
{
uint uiFilters[1] = { 0 };
alGenFilters(1, &uiFilters[0]);
if( palGetError() == AL_NO_ERROR )
{
MsgDev( D_NOTE, "S_InitFilters:" );
alFilteri(uiFilters[0], AL_FILTER_TYPE, AL_FILTER_LOWPASS);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_lowpass" );
alFilteri(uiFilters[0], AL_FILTER_TYPE, AL_FILTER_HIGHPASS);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_highpass" );
alFilteri(uiFilters[0], AL_FILTER_TYPE, AL_FILTER_BANDPASS);
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_bandpass" );
MsgDev( D_NOTE, "\n" );
}
alDeleteFilters(1, &uiFilters[0]);
}
/*
=================
S_InitExtensions
grab extensions
=================
*/
static void S_InitExtensions( void )
{
// set initial state
al_config.Get3DMode = NULL;
al_config.Set3DMode = NULL;
al_config.allow_3DMode = false;
if( !s_soundfx->integer ) return;
// check I3DL2 extension for NVidia's Sound Storm chips. I3DL2 is hidden and can be missed in extension list.
if( !com.strcmp( NVIDIA_DEVICE_NAME, al_config.deviceList[0] ))
{
I3DL2Get = (void *)palGetProcAddress("I3DL2Get");
I3DL2Set = (void *)palGetProcAddress("I3DL2Set");
if( I3DL2Get && I3DL2Set )
{
al_config.allow_3DMode = true;
al_config.Get3DMode = I3DL2Get;
al_config.Set3DMode = I3DL2Set;
MsgDev( D_NOTE, "S_InitExtensions: enable I3DL2\n" );
}
}
if( palIsExtensionPresent("EAX3.0") && !al_config.allow_3DMode )
{
alEAXSet = (void *)palGetProcAddress( "EAXSet" );
alEAXGet = (void *)palGetProcAddress( "EAXGet" );
if( alEAXSet && alEAXGet )
{
al_config.allow_3DMode = true;
al_config.Get3DMode = alEAXGet;
al_config.Set3DMode = alEAXSet;
MsgDev( D_NOTE, "S_InitExtensions: enable EAX 3.0\n" );
}
}
if( palIsExtensionPresent("EAX2.0") && !al_config.allow_3DMode )
{
alEAXSet = (void *)palGetProcAddress( "EAXSet" );
alEAXGet = (void *)palGetProcAddress( "EAXGet" );
if( alEAXSet && alEAXGet )
{
al_config.allow_3DMode = true;
al_config.Get3DMode = alEAXGet;
al_config.Set3DMode = alEAXSet;
MsgDev( D_NOTE, "S_InitExtensions: enable EAX 2.0\n" );
}
}
if( palIsExtensionPresent("EAX") && !al_config.allow_3DMode )
{
alEAXSet = (void *)palGetProcAddress( "EAXSet" );
alEAXGet = (void *)palGetProcAddress( "EAXGet" );
if( alEAXSet && alEAXGet )
{
al_config.allow_3DMode = true;
al_config.Get3DMode = alEAXGet;
al_config.Set3DMode = alEAXSet;
MsgDev( D_NOTE, "S_InitExtensions: enable EAX 1.0\n" );
}
}
if(palcIsExtensionPresent( al_state.hDevice, "ALC_EXT_EFX"))
{
uint uiEffectSlots[MAX_EFFECTS] = { 0 };
if(!S_SetupEFX()) return;
// testing effect slots
for( al_config.num_slots = 0; al_config.num_slots < MAX_EFFECTS; al_config.num_slots++ )
{
alGenAuxiliaryEffectSlots( 1, &uiEffectSlots[al_config.num_slots] );
if( palGetError() != AL_NO_ERROR) break;
}
palcGetIntegerv( al_state.hDevice, ALC_MAX_AUXILIARY_SENDS, 1, &al_config.num_sends );
S_InitEffects();
S_InitFilters();
alDeleteAuxiliaryEffectSlots( al_config.num_slots, uiEffectSlots );
}
}
bool S_Init_OpenAL( void )
{
Sys_LoadLibrary( &openal_dll );
if( !openal_dll.link )
{
MsgDev( D_ERROR, "OpenAL driver not installed\n");
return false;
}
// Get device list
if( palcIsExtensionPresent( NULL, "ALC_ENUMERATION_EXT"))
{
// get list of devices
const char *device_enum = palcGetString( NULL, ALC_DEVICE_SPECIFIER );
al_config.defDevice = palcGetString( NULL, ALC_DEFAULT_DEVICE_SPECIFIER );
while( *device_enum )
{
// enumerate devices
com.strncpy( al_config.deviceList[al_config.device_count++], device_enum, MAX_STRING );
while(*device_enum) device_enum++;
device_enum++;
}
}
else
{
MsgDev( D_ERROR, "can't enumerate OpenAL devices\n" );
return false;
}
// initialize the device, context, etc...
if(!S_InitDriver()) return false;
// get some openal strings
al_config.vendor_string = palGetString(AL_VENDOR);
al_config.renderer_string = palGetString(AL_RENDERER); // stupid name :)
al_config.version_string = palGetString(AL_VERSION);
al_config.extensions_string = palGetString(AL_EXTENSIONS);
MsgDev(D_INFO, "Audio: %s\n", al_config.renderer_string );
// Initialize extensions
S_InitExtensions();
return true;
}
void S_Free_OpenAL( void )
{
if( al_state.hALC )
{
if( palcMakeContextCurrent )
palcMakeContextCurrent( NULL );
if( palcDestroyContext )
palcDestroyContext( al_state.hALC );
al_state.hALC = NULL;
}
if( al_state.hDevice )
{
if( palcCloseDevice )
palcCloseDevice( al_state.hDevice );
al_state.hDevice = NULL;
}
Sys_FreeLibrary( &openal_dll );
memset(&al_config, 0, sizeof(alconfig_t));
memset(&al_state, 0, sizeof(alstate_t));
}

287
vsound/s_openal.h Normal file
View File

@ -0,0 +1,287 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// s_openal.h - openal definition
//=======================================================================
#ifndef S_OPENAL_H
#define S_OPENAL_H
typedef struct aldevice_s aldevice;
typedef struct alcontext_s alcontext;
#define NVIDIA_DEVICE_NAME "NVIDIA(R) nForce(TM) Audio"
#define MAX_EFFECTS 128
#define AL_VENDOR 0xB001
#define AL_VERSION 0xB002
#define AL_RENDERER 0xB003
#define AL_EXTENSIONS 0xB004
#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
#define ALC_DEVICE_SPECIFIER 0x1005
#define ALC_EXTENSIONS 0x1006
#define ALC_MAJOR_VERSION 0x1000
#define ALC_MINOR_VERSION 0x1001
#define ALC_ATTRIBUTES_SIZE 0x1002
#define ALC_ALL_ATTRIBUTES 0x1003
#define ALC_FREQUENCY 0x1007
#define ALC_MAX_AUXILIARY_SENDS 0x20003
#define AL_SOURCE_RELATIVE 0x202
#define AL_CONE_INNER_ANGLE 0x1001
#define AL_CONE_OUTER_ANGLE 0x1002
#define AL_PITCH 0x1003
#define AL_POSITION 0x1004
#define AL_DIRECTION 0x1005
#define AL_VELOCITY 0x1006
#define AL_LOOPING 0x1007
#define AL_BUFFER 0x1009
#define AL_GAIN 0x100A
#define AL_MIN_GAIN 0x100D
#define AL_MAX_GAIN 0x100E
#define AL_ORIENTATION 0x100F
#define AL_SOURCE_STATE 0x1010
#define AL_INITIAL 0x1011
#define AL_PLAYING 0x1012
#define AL_PAUSED 0x1013
#define AL_STOPPED 0x1014
#define AL_REFERENCE_DISTANCE 0x1020
#define AL_ROLLOFF_FACTOR 0x1021
#define AL_CONE_OUTER_GAIN 0x1022
#define AL_MAX_DISTANCE 0x1023
#define AL_DISTANCE_MODEL 0xD000
#define AL_INVERSE_DISTANCE 0xD001
#define AL_INVERSE_DISTANCE_CLAMPED 0xD002
#define AL_LINEAR_DISTANCE 0xD003
#define AL_LINEAR_DISTANCE_CLAMPED 0xD004
#define AL_EXPONENT_DISTANCE 0xD005
#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006
// sound format
#define AL_FORMAT_MONO8 0x1100
#define AL_FORMAT_MONO16 0x1101
#define AL_FORMAT_STEREO8 0x1102
#define AL_FORMAT_STEREO16 0x1103
// buffer queues
#define AL_BUFFERS_QUEUED 0x1015
#define AL_BUFFERS_PROCESSED 0x1016
// openal errors
#define AL_NO_ERROR 0
#define AL_INVALID_NAME 0xA001
#define AL_INVALID_ENUM 0xA002
#define AL_INVALID_VALUE 0xA003
#define AL_INVALID_OPERATION 0xA004
#define AL_OUT_OF_MEMORY 0xA005
// openal effects
#define AL_EFFECT_TYPE 0x8001
#define AL_EFFECT_NULL 0x0000
#define AL_EFFECT_REVERB 0x0001
#define AL_EFFECT_CHORUS 0x0002
#define AL_EFFECT_DISTORTION 0x0003
#define AL_EFFECT_ECHO 0x0004
#define AL_EFFECT_FLANGER 0x0005
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
#define AL_EFFECT_VOCAL_MORPHER 0x0007
#define AL_EFFECT_PITCH_SHIFTER 0x0008
#define AL_EFFECT_RING_MODULATOR 0x0009
#define AL_EFFECT_AUTOWAH 0x000A
#define AL_EFFECT_COMPRESSOR 0x000B
#define AL_EFFECT_EQUALIZER 0x000C
#define AL_EFFECT_EAXREVERB 0x8000
// openal filters
#define AL_FILTER_TYPE 0x8001
#define AL_FILTER_NULL 0x0000
#define AL_FILTER_LOWPASS 0x0001
#define AL_FILTER_HIGHPASS 0x0002
#define AL_FILTER_BANDPASS 0x0003
enum
{
EAX_ENVIRONMENT_GENERIC,
EAX_ENVIRONMENT_PADDEDCELL,
EAX_ENVIRONMENT_ROOM,
EAX_ENVIRONMENT_BATHROOM,
EAX_ENVIRONMENT_LIVINGROOM,
EAX_ENVIRONMENT_STONEROOM,
EAX_ENVIRONMENT_AUDITORIUM,
EAX_ENVIRONMENT_CONCERTHALL,
EAX_ENVIRONMENT_CAVE,
EAX_ENVIRONMENT_ARENA,
EAX_ENVIRONMENT_HANGAR,
EAX_ENVIRONMENT_CARPETEDHALLWAY,
EAX_ENVIRONMENT_HALLWAY,
EAX_ENVIRONMENT_STONECORRIDOR,
EAX_ENVIRONMENT_ALLEY,
EAX_ENVIRONMENT_FOREST,
EAX_ENVIRONMENT_CITY,
EAX_ENVIRONMENT_MOUNTAINS,
EAX_ENVIRONMENT_QUARRY,
EAX_ENVIRONMENT_PLAIN,
EAX_ENVIRONMENT_PARKINGLOT,
EAX_ENVIRONMENT_SEWERPIPE,
EAX_ENVIRONMENT_UNDERWATER,
EAX_ENVIRONMENT_DRUGGED,
EAX_ENVIRONMENT_DIZZY,
EAX_ENVIRONMENT_PSYCHOTIC,
EAX_ENVIRONMENT_COUNT
};
typedef enum
{
DSPROPERTY_EAXLISTENER_NONE,
DSPROPERTY_EAXLISTENER_ALLPARAMETERS,
DSPROPERTY_EAXLISTENER_ROOM,
DSPROPERTY_EAXLISTENER_ROOMHF,
DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR,
DSPROPERTY_EAXLISTENER_DECAYTIME,
DSPROPERTY_EAXLISTENER_DECAYHFRATIO,
DSPROPERTY_EAXLISTENER_REFLECTIONS,
DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY,
DSPROPERTY_EAXLISTENER_REVERB,
DSPROPERTY_EAXLISTENER_REVERBDELAY,
DSPROPERTY_EAXLISTENER_ENVIRONMENT,
DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE,
DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION,
DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF,
DSPROPERTY_EAXLISTENER_FLAGS
} DSPROPERTY_EAX_LISTENERPROPERTY;
// or these flags with property id
#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately
#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later
// openal32.dll exports
aldevice *(_cdecl *palcOpenDevice)( const char *devicename );
char (_cdecl *palcCloseDevice)( aldevice *device );
alcontext *(_cdecl *palcCreateContext)( aldevice *device, const int *attrlist );
void (_cdecl *palcDestroyContext)( alcontext *context );
char (_cdecl *palcMakeContextCurrent)( alcontext *context );
void (_cdecl *palcProcessContext)( alcontext *context );
void (_cdecl *palcSuspendContext)( alcontext *context );
alcontext *(_cdecl *palcGetCurrentContext)( void );
aldevice *(_cdecl *palcGetContextsDevice)( alcontext *context );
const char *(_cdecl *palcGetString )( aldevice *device, int param );
void (_cdecl *palcGetIntegerv)( aldevice *device, int param, int size, int *dest );
int (_cdecl *palcGetError)( aldevice *device );
char (_cdecl *palcIsExtensionPresent)( aldevice *device, const char *extname );
void *(_cdecl *palcGetProcAddress)( aldevice *device, const char *funcname );
int (_cdecl *palcGetEnumValue)( aldevice *device, const char *enumname );
void (_cdecl *palBufferData)( uint bid, int format, const void* data, int size, int freq );
void (_cdecl *palDeleteBuffers)( int n, const uint* buffers );
void (_cdecl *palDeleteSources)( int n, const uint* sources );
void (_cdecl *palDisable)( int capability );
void (_cdecl *palDistanceModel)( int distanceModel );
void (_cdecl *palDopplerFactor)( float value );
void (_cdecl *palDopplerVelocity)( float value );
void (_cdecl *palEnable)( int capability );
void (_cdecl *palGenBuffers)( int n, uint* buffers );
void (_cdecl *palGenSources)( int n, uint* sources );
char (_cdecl *palGetBoolean)( int param );
void (_cdecl *palGetBooleanv)( int param, char* data );
void (_cdecl *palGetBufferf)( uint bid, int param, float* value );
void (_cdecl *palGetBufferi)( uint bid, int param, int* value );
double (_cdecl *palGetDouble)( int param );
void (_cdecl *palGetDoublev)( int param, double* data );
int (_cdecl *palGetEnumValue)( const char* ename );
int (_cdecl *palGetError)( void );
float (_cdecl *palGetFloat)( int param );
void (_cdecl *palGetFloatv)( int param, float* data );
int (_cdecl *palGetInteger)( int param );
void (_cdecl *palGetIntegerv)( int param, int* data );
void (_cdecl *palGetListener3f)( int param, float *value1, float *value2, float *value3 );
void (_cdecl *palGetListenerf)( int param, float* value );
void (_cdecl *palGetListenerfv)( int param, float* values );
void (_cdecl *palGetListeneri)( int param, int* value );
void *(_cdecl *palGetProcAddress)( const char* fname );
void (_cdecl *palGetSource3f)( uint sid, int param, float* value1, float* value2, float* value3 );
void (_cdecl *palGetSourcef)( uint sid, int param, float* value );
void (_cdecl *palGetSourcefv)( uint sid, int param, float* values );
void (_cdecl *palGetSourcei)( uint sid, int param, int* value );
const char *(_cdecl *palGetString)( int param );
char (_cdecl *palIsBuffer)( uint bid );
char (_cdecl *palIsEnabled)( int capability );
char (_cdecl *palIsExtensionPresent)(const char* extname );
char (_cdecl *palIsSource)( uint sid );
void (_cdecl *palListener3f)( int param, float value1, float value2, float value3 );
void (_cdecl *palListenerf)( int param, float value );
void (_cdecl *palListenerfv)( int param, const float* values );
void (_cdecl *palListeneri)( int param, int value );
void (_cdecl *palSource3f)( uint sid, int param, float value1, float value2, float value3 );
void (_cdecl *palSourcef)( uint sid, int param, float value );
void (_cdecl *palSourcefv)( uint sid, int param, const float* values );
void (_cdecl *palSourcei)( uint sid, int param, int value);
void (_cdecl *palSourcePause)( uint sid );
void (_cdecl *palSourcePausev)( int ns, const uint *sids );
void (_cdecl *palSourcePlay)( uint sid );
void (_cdecl *palSourcePlayv)( int ns, const uint *sids );
void (_cdecl *palSourceQueueBuffers)(uint sid, int numEntries, const uint *bids );
void (_cdecl *palSourceRewind)( uint sid );
void (_cdecl *palSourceRewindv)( int ns, const uint *sids );
void (_cdecl *palSourceStop)( uint sid );
void (_cdecl *palSourceStopv)( int ns, const uint *sids );
void (_cdecl *palSourceUnqueueBuffers)(uint sid, int numEntries, uint *bids );
// openal32.dll internal exports which can be get with by algetProcAddress
void (*alGenEffects)( int n, uint* effects );
void (*alDeleteEffects)( int n, uint* effects );
char (*alIsEffect)( uint eid );
void (*alEffecti)( uint eid, int param, int value);
void (*alEffectiv)( uint eid, int param, int* values );
void (*alEffectf)( uint eid, int param, float value);
void (*alEffectfv)( uint eid, int param, float* values );
void (*alGetEffecti)( uint eid, int pname, int* value );
void (*alGetEffectiv)( uint eid, int pname, int* values );
void (*alGetEffectf)( uint eid, int pname, float* value );
void (*alGetEffectfv)( uint eid, int pname, float* values );
void (*alGenFilters)( int n, uint* filters );
void (*alDeleteFilters)( int n, uint* filters );
char (*alIsFilter)( uint fid );
void (*alFilteri)( uint fid, int param, int value );
void (*alFilteriv)( uint fid, int param, int* values );
void (*alFilterf)( uint fid, int param, float value);
void (*alFilterfv)( uint fid, int param, float* values );
void (*alGetFilteri)( uint fid, int pname, int* value );
void (*alGetFilteriv)( uint fid, int pname, int* values );
void (*alGetFilterf)( uint fid, int pname, float* value );
void (*alGetFilterfv)( uint fid, int pname, float* values );
void (*alGenAuxiliaryEffectSlots)( int n, uint* slots );
void (*alDeleteAuxiliaryEffectSlots)( int n, uint* slots );
char (*alIsAuxiliaryEffectSlot)( uint slot );
void (*alAuxiliaryEffectSloti)( uint asid, int param, int value );
void (*alAuxiliaryEffectSlotiv)( uint asid, int param, int* values );
void (*alAuxiliaryEffectSlotf)( uint asid, int param, float value );
void (*alAuxiliaryEffectSlotfv)( uint asid, int param, float* values );
void (*alGetAuxiliaryEffectSloti)( uint asid, int pname, int* value );
void (*alGetAuxiliaryEffectSlotiv)( uint asid, int pname, int* values );
void (*alGetAuxiliaryEffectSlotf)( uint asid, int pname, float* value );
void (*alGetAuxiliaryEffectSlotfv)( uint asid, int pname, float* values );
typedef struct guid_s
{
dword Data1;
word Data2;
word Data3;
byte Data4[8];
} guid_t;
// EAX 2.0 extension
int (*alEAXSet)( const guid_t*, uint, uint, void*, uint );
int (*alEAXGet)( const guid_t*, uint, uint, void*, uint );
// I3DL2 OpenAL Extension
int (*I3DL2Get)( const guid_t*, uint, uint, void*, uint );
int (*I3DL2Set)( const guid_t*, uint, uint, void*, uint );
bool S_Init_OpenAL( void );
void S_Free_OpenAL( void );
#endif//S_OPENAL_H

367
vsound/s_stream.c Normal file
View File

@ -0,0 +1,367 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// s_stream.c - sound streaming
//=======================================================================
#include "sound.h"
#include "s_stream.h"
#define BUFFER_SIZE 16384
static bg_track_t s_bgTrack;
static channel_t *s_streamingChannel;
/*
=======================================================================
OGG VORBIS STREAMING
=======================================================================
*/
static size_t ovc_read( void *ptr, size_t size, size_t nmemb, void *datasource )
{
bg_track_t *track = (bg_track_t *)datasource;
if (!size || !nmemb)
return 0;
return FS_Read( track->file, ptr, size * nmemb ) / size;
}
static int ovc_seek ( void *datasource, ogg_int64_t offset, int whence )
{
bg_track_t *track = (bg_track_t *)datasource;
switch( whence )
{
case SEEK_SET:
FS_Seek(track->file, (int)offset, SEEK_SET);
break;
case SEEK_CUR:
FS_Seek(track->file, (int)offset, SEEK_CUR);
break;
case SEEK_END:
FS_Seek(track->file, (int)offset, SEEK_END);
break;
default:
return -1;
}
return 0;
}
static int ovc_close( void *datasource )
{
bg_track_t *track = (bg_track_t *)datasource;
//FIXME: FS_Close( track->file );
return 0;
}
static long ovc_tell (void *datasource)
{
bg_track_t *track = (bg_track_t *)datasource;
return FS_Tell( track->file );
}
/*
=================
S_OpenBackgroundTrack
=================
*/
static bool S_OpenBackgroundTrack (const char *name, bg_track_t *track)
{
vorbisfile_t *vorbisFile;
vorbis_info_t *vorbisInfo;
ov_callbacks_t vorbisCallbacks = { ovc_read, ovc_seek, ovc_close, ovc_tell };
track->file = FS_Open( name, "rb" );
if( !track->file )
{
MsgWarn( "S_OpenBackgroundTrack: couldn't find %s\n", name );
return false;
}
track->vorbisFile = vorbisFile = Z_Malloc(sizeof(vorbisfile_t));
if( ov_open_callbacks(track, vorbisFile, NULL, 0, vorbisCallbacks) < 0 )
{
MsgWarn( "S_OpenBackgroundTrack: couldn't open ogg stream %s\n", name );
return false;
}
vorbisInfo = ov_info( vorbisFile, -1 );
if( vorbisInfo->channels != 1 && vorbisInfo->channels != 2)
{
MsgWarn( "S_OpenBackgroundTrack: only mono and stereo ogg files supported %s\n", name );
return false;
}
track->start = ov_raw_tell( vorbisFile );
track->rate = vorbisInfo->rate;
track->format = (vorbisInfo->channels == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
return true;
}
/*
=================
S_CloseBackgroundTrack
=================
*/
static void S_CloseBackgroundTrack( bg_track_t *track )
{
if( track->vorbisFile )
{
ov_clear( track->vorbisFile );
Mem_Free( track->vorbisFile );
track->vorbisFile = NULL;
}
if( track->file )
{
FS_Close( track->file );
track->file = 0;
}
}
/*
=================
S_StreamBackgroundTrack
=================
*/
void S_StreamBackgroundTrack( void )
{
byte data[BUFFER_SIZE];
int processed, queued, state;
int size, read, dummy;
uint buffer;
if( !s_bgTrack.file || !s_musicVolume->value )
return;
if(!s_streamingChannel) return;
// unqueue and delete any processed buffers
palGetSourcei( s_streamingChannel->sourceNum, AL_BUFFERS_PROCESSED, &processed );
if( processed > 0 )
{
while( processed-- )
{
palSourceUnqueueBuffers(s_streamingChannel->sourceNum, 1, &buffer);
palDeleteBuffers(1, &buffer);
}
}
// make sure we always have at least 4 buffers in the queue
palGetSourcei( s_streamingChannel->sourceNum, AL_BUFFERS_QUEUED, &queued );
while( queued < 4 )
{
size = 0;
// stream from disk
while( size < BUFFER_SIZE )
{
read = ov_read( s_bgTrack.vorbisFile, data + size, BUFFER_SIZE - size, 0, 2, 1, &dummy );
if( read == 0 )
{
// end of file
if(!s_bgTrack.looping)
{
// close the intro track
S_CloseBackgroundTrack( &s_bgTrack );
// open the loop track
if(!S_OpenBackgroundTrack(s_bgTrack.loopName, &s_bgTrack))
{
S_StopBackgroundTrack();
return;
}
s_bgTrack.looping = true;
}
// restart the track, skipping over the header
ov_raw_seek(s_bgTrack.vorbisFile, (ogg_int64_t)s_bgTrack.start );
// try streaming again
read = ov_read( s_bgTrack.vorbisFile, data + size, BUFFER_SIZE - size, 0, 2, 1, &dummy );
}
if( read <= 0 )
{
// an error occurred
S_StopBackgroundTrack();
return;
}
size += read;
}
// upload and queue the new buffer
palGenBuffers( 1, &buffer );
palBufferData( buffer, s_bgTrack.format, data, size, s_bgTrack.rate );
palSourceQueueBuffers( s_streamingChannel->sourceNum, 1, &buffer );
queued++;
}
// update volume
palSourcef( s_streamingChannel->sourceNum, AL_GAIN, s_musicVolume->value );
// if not playing, then do so
palGetSourcei( s_streamingChannel->sourceNum, AL_SOURCE_STATE, &state );
if( state != AL_PLAYING ) palSourcePlay(s_streamingChannel->sourceNum);
}
/*
=================
S_StartBackgroundTrack
=================
*/
void S_StartBackgroundTrack( const char *introTrack, const char *loopTrack )
{
if( !al_state.initialized ) return;
// stop any playing tracks
S_StopBackgroundTrack();
// Start it up
com.snprintf( s_bgTrack.introName, sizeof(s_bgTrack.introName), "music/%s.ogg", introTrack);
com.snprintf( s_bgTrack.loopName, sizeof(s_bgTrack.loopName), "music/%s.ogg", loopTrack );
S_StartStreaming();
// open the intro track
if(!S_OpenBackgroundTrack( s_bgTrack.introName, &s_bgTrack))
{
S_StopBackgroundTrack();
return;
}
S_StreamBackgroundTrack();
}
/*
=================
S_StopBackgroundTrack
=================
*/
void S_StopBackgroundTrack( void )
{
if( !al_state.initialized ) return;
S_StopStreaming();
S_CloseBackgroundTrack(&s_bgTrack);
memset(&s_bgTrack, 0, sizeof(bg_track_t));
}
/*
=================
S_StartStreaming
=================
*/
void S_StartStreaming( void )
{
if( !al_state.initialized ) return;
if( s_streamingChannel ) return; // already started
s_streamingChannel = S_PickChannel( 0, 0 );
if( !s_streamingChannel ) return;
s_streamingChannel->streaming = true;
// FIXME: OpenAL bug?
//palDeleteSources(1, &s_streamingChannel->sourceNum);
//palGenSources(1, &s_streamingChannel->sourceNum);
// set up the source
palSourcei(s_streamingChannel->sourceNum, AL_BUFFER, 0 );
palSourcei(s_streamingChannel->sourceNum, AL_LOOPING, 0 );
palSourcei(s_streamingChannel->sourceNum, AL_SOURCE_RELATIVE, 1 );
palSourcefv(s_streamingChannel->sourceNum, AL_POSITION, vec3_origin);
palSourcefv(s_streamingChannel->sourceNum, AL_VELOCITY, vec3_origin);
palSourcef(s_streamingChannel->sourceNum, AL_REFERENCE_DISTANCE, 1.0);
palSourcef(s_streamingChannel->sourceNum, AL_MAX_DISTANCE, 1.0);
palSourcef(s_streamingChannel->sourceNum, AL_ROLLOFF_FACTOR, 0.0);
}
/*
=================
S_StopStreaming
=================
*/
void S_StopStreaming( void )
{
int processed;
uint buffer;
if( !al_state.initialized ) return;
if( !s_streamingChannel ) return; // already stopped
s_streamingChannel->streaming = false;
// clean up the source
palSourceStop(s_streamingChannel->sourceNum);
palGetSourcei(s_streamingChannel->sourceNum, AL_BUFFERS_PROCESSED, &processed);
if( processed > 0 )
{
while( processed-- )
{
palSourceUnqueueBuffers(s_streamingChannel->sourceNum, 1, &buffer);
palDeleteBuffers(1, &buffer);
}
}
palSourcei(s_streamingChannel->sourceNum, AL_BUFFER, 0);
// FIXME: OpenAL bug?
//palDeleteSources(1, &s_streamingChannel->sourceNum);
//palGenSources(1, &s_streamingChannel->sourceNum);
s_streamingChannel = NULL;
}
/*
=================
S_StreamRawSamples
Cinematic streaming
=================
*/
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data )
{
int processed, state, size;
uint format, buffer;
if( !al_state.initialized ) return;
if( !s_streamingChannel ) return;
// unqueue and delete any processed buffers
palGetSourcei( s_streamingChannel->sourceNum, AL_BUFFERS_PROCESSED, &processed );
if( processed > 0 )
{
while( processed-- )
{
palSourceUnqueueBuffers(s_streamingChannel->sourceNum, 1, &buffer);
palDeleteBuffers(1, &buffer);
}
}
// calculate buffer size
size = samples * width * channels;
// set buffer format
if( width == 2 )
{
if( channels == 2 ) format = AL_FORMAT_STEREO16;
else format = AL_FORMAT_MONO16;
}
else
{
if( channels == 2 ) format = AL_FORMAT_STEREO8;
else format = AL_FORMAT_MONO8;
}
// upload and queue the new buffer
palGenBuffers( 1, &buffer );
palBufferData( buffer, format, (byte *)data, size, rate );
palSourceQueueBuffers( s_streamingChannel->sourceNum, 1, &buffer );
// update volume
palSourcef( s_streamingChannel->sourceNum, AL_GAIN, s_sfxVolume->value );
// if not playing, then do so
palGetSourcei(s_streamingChannel->sourceNum, AL_SOURCE_STATE, &state);
if( state != AL_PLAYING ) palSourcePlay( s_streamingChannel->sourceNum );
}

185
vsound/s_stream.h Normal file
View File

@ -0,0 +1,185 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// s_openal.h - openal definition
//=======================================================================
#ifndef S_STREAM_H
#define S_STREAM_H
typedef __int64 ogg_int64_t;
typedef __int32 ogg_int32_t;
typedef unsigned __int32 ogg_uint32_t;
typedef __int16 ogg_int16_t;
typedef unsigned __int16 ogg_uint16_t;
/*
=======================================================================
OGG PACK DEFINITION
=======================================================================
*/
struct ogg_chain_s
{
void *ptr;
struct alloc_chain *next;
};
typedef struct oggpack_buffer_s
{
long endbyte;
int endbit;
byte *buffer;
byte *ptr;
long storage;
} oggpack_buffer_t;
typedef struct ogg_sync_state_s
{
byte *data;
int storage;
int fill;
int returned;
int unsynced;
int headerbytes;
int bodybytes;
} ogg_sync_state_t;
typedef struct ogg_stream_state_s
{
byte *body_data;
long body_storage;
long body_fill;
long body_returned;
int *lacing_vals;
ogg_int64_t *granule_vals;
long lacing_storage;
long lacing_fill;
long lacing_packet;
long lacing_returned;
byte header[282];
int header_fill;
int e_o_s;
int b_o_s;
long serialno;
long pageno;
ogg_int64_t packetno;
ogg_int64_t granulepos;
} ogg_stream_state_t;
/*
=======================================================================
VORBIS FILE DEFINITION
=======================================================================
*/
typedef struct vorbis_info_s
{
int version;
int channels;
long rate;
long bitrate_upper;
long bitrate_nominal;
long bitrate_lower;
long bitrate_window;
void *codec_setup;
} vorbis_info_t;
typedef struct vorbis_comment_s
{
char **user_comments;
int *comment_lengths;
int comments;
char *vendor;
} vorbis_comment_t;
typedef struct vorbis_dsp_state_s
{
int analysisp;
vorbis_info_t *vi;
float **pcm;
float **pcmret;
int pcm_storage;
int pcm_current;
int pcm_returned;
int preextrapolate;
int eofflag;
long lW;
long W;
long nW;
long centerW;
ogg_int64_t granulepos;
ogg_int64_t sequence;
ogg_int64_t glue_bits;
ogg_int64_t time_bits;
ogg_int64_t floor_bits;
ogg_int64_t res_bits;
void *backend_state;
} vorbis_dsp_state_t;
typedef struct vorbis_block_s
{
float **pcm;
oggpack_buffer_t opb;
long lW;
long W;
long nW;
int pcmend;
int mode;
int eofflag;
ogg_int64_t granulepos;
ogg_int64_t sequence;
vorbis_dsp_state_t *vd;
void *localstore;
long localtop;
long localalloc;
long totaluse;
struct ogg_chain_s *reap;
long glue_bits;
long time_bits;
long floor_bits;
long res_bits;
void *internal;
} vorbis_block_t;
typedef struct ov_callbacks_s
{
size_t (*read_func)( void *ptr, size_t size, size_t nmemb, void *datasource );
int (*seek_func)( void *datasource, ogg_int64_t offset, int whence );
int (*close_func)( void *datasource );
long (*tell_func)( void *datasource );
} ov_callbacks_t;
typedef struct vorbisfile_s
{
void *datasource;
int seekable;
ogg_int64_t offset;
ogg_int64_t end;
ogg_sync_state_t oy;
int links;
ogg_int64_t *offsets;
ogg_int64_t *dataoffsets;
long *serialnos;
ogg_int64_t *pcmlengths;
vorbis_info_t *vi;
vorbis_comment_t *vc;
ogg_int64_t pcm_offset;
int ready_state;
long current_serialno;
int current_link;
double bittrack;
double samptrack;
ogg_stream_state_t os;
vorbis_dsp_state_t vd;
vorbis_block_t vb;
ov_callbacks_t callbacks;
} vorbisfile_t;
// libvorbis exports
int ov_open_callbacks( void *datasource, vorbisfile_t *vf, char *initial, long ibytes, ov_callbacks_t callbacks );
long ov_read( vorbisfile_t *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream );
vorbis_info_t *ov_info( vorbisfile_t *vf, int link );
int ov_raw_seek( vorbisfile_t *vf, ogg_int64_t pos );
ogg_int64_t ov_raw_tell( vorbisfile_t *vf );
int ov_clear( vorbisfile_t *vf);
#endif//S_STREAM_H

View File

@ -1,11 +1,9 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// cl_sound.c - sound engine
// snd_main.c - sound engine
//=======================================================================
#include "common.h"
#include "client.h"
#include <dsound.h>
#include "sound.h"
#define PAINTBUFFER_SIZE 4096 // this is in samples
@ -145,6 +143,9 @@ void SND_free(sndBuffer *v);
sndBuffer* SND_malloc();
void SND_setup();
HWND hWnd;
uint framecount = 0;
void S_PaintChannels(int endtime);
void S_memoryLoad(sfx_t *sfx);
@ -231,7 +232,7 @@ void SNDDMA_Shutdown( void )
if ( pDS )
{
MsgDev(D_INFO, "...setting NORMAL coop level\n" );
pDS->lpVtbl->SetCooperativeLevel( pDS, host.hWnd, DSSCL_PRIORITY );
pDS->lpVtbl->SetCooperativeLevel( pDS, hWnd, DSSCL_PRIORITY );
}
if ( pDSBuf )
@ -289,7 +290,7 @@ int SNDDMA_InitDS( void )
MsgDev(D_INFO, "ok\n" );
MsgDev(D_INFO, "...setting DSSCL_PRIORITY coop level: " );
if(DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, host.hWnd, DSSCL_PRIORITY ))
if(DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, hWnd, DSSCL_PRIORITY ))
{
MsgDev(D_INFO, "failed\n");
SNDDMA_Shutdown ();
@ -489,7 +490,7 @@ void SNDDMA_Activate( void )
{
if( !pDS ) return;
if( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, host.hWnd, DSSCL_PRIORITY ))
if( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, hWnd, DSSCL_PRIORITY ))
{
MsgDev(D_INFO, "sound SetCooperativeLevel failed\n");
SNDDMA_Shutdown();
@ -586,10 +587,12 @@ void S_SoundInfo_f( void )
S_Init
================
*/
void S_Init( void )
void S_Init( void *hInst )
{
cvar_t *cv;
S_Init_OpenAL();
s_volume = Cvar_Get ("s_volume", "0.8", CVAR_ARCHIVE);
s_musicVolume = Cvar_Get ("s_musicvolume", "0.25", CVAR_ARCHIVE);
s_separation = Cvar_Get ("s_separation", "0.5", CVAR_ARCHIVE);
@ -609,6 +612,10 @@ void S_Init( void )
Cmd_AddCommand("snd_info", S_SoundInfo_f, "print sound system information" );
Cmd_AddCommand("snd_stop", S_StopAllSounds, "stop all sounds" );
hWnd = hInst;
sndpool = Mem_AllocPool("Sound Zone");
if (SNDDMA_Init())
{
s_soundStarted = 1;
@ -663,8 +670,9 @@ void S_Shutdown( void )
{
if ( !s_soundStarted ) return;
SNDDMA_Shutdown();
s_soundStarted = 0;
Mem_FreePool( &sndpool );
s_soundStarted = 0;
Cmd_RemoveCommand("play");
Cmd_RemoveCommand("music");
Cmd_RemoveCommand("stopsound");
@ -940,7 +948,7 @@ if pos is NULL, the sound will be dynamically sourced from the entity
Entchannel 0 will never override a playing sound
====================
*/
void S_StartSound(vec3_t origin, int entityNum, int entchannel, sound_t sfxHandle )
void S_StartSound( const vec3_t origin, int entityNum, int entchannel, sound_t sfxHandle, float vol, float attn )
{
channel_t *ch;
sfx_t *sfx;
@ -1075,7 +1083,7 @@ int S_StartLocalSound( const char *name )
return false;
}
S_StartSound (NULL, listener_number, CHAN_AUTO, sfxHandle );
S_StartSound (NULL, listener_number, CHAN_AUTO, sfxHandle, ATTN_NORM, 1.0f );
return true;
}
@ -1205,14 +1213,14 @@ void S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocit
lena = VectorDistance2(loopSounds[listener_number].origin, loopSounds[entityNum].origin);
VectorAdd(loopSounds[entityNum].origin, loopSounds[entityNum].velocity, out);
lenb = VectorDistance2(loopSounds[listener_number].origin, out);
if ((loopSounds[entityNum].framenum + 1) != cls.framecount)
if ((loopSounds[entityNum].framenum + 1) != framecount)
loopSounds[entityNum].oldDopplerScale = 1.0;
else loopSounds[entityNum].oldDopplerScale = loopSounds[entityNum].dopplerScale;
loopSounds[entityNum].dopplerScale = lenb/(lena * 100);
if (loopSounds[entityNum].dopplerScale<=1.0)
loopSounds[entityNum].doppler = false; // don't bother doing the math
}
loopSounds[entityNum].framenum = cls.framecount;
loopSounds[entityNum].framenum = framecount;
}
/*
@ -1464,7 +1472,7 @@ S_Respatialize
Change the volumes of all the playing sounds for changes in their positions
============
*/
void S_Respatialize( int entityNum, const vec3_t head, vec3_t v_forward, vec3_t v_right, vec3_t v_up )
void S_Respatialize( int entityNum, const vec3_t head, const vec3_t v_forward, const vec3_t v_right, const vec3_t v_up )
{
int i;
channel_t *ch;
@ -1665,36 +1673,6 @@ console functions
===============================================================================
*/
void S_Play_f( void )
{
int i = 1;
char name[256];
while ( i < Cmd_Argc())
{
if ( !com.strrchr(Cmd_Argv(i), '.')) com.sprintf( name, "%s.wav", Cmd_Argv(1) );
else com.strncpy( name, Cmd_Argv(i), sizeof(name) );
S_StartLocalSound( name );
i++;
}
}
void S_Music_f( void )
{
int c = Cmd_Argc();
if ( c == 2 )
{
S_StartBackgroundTrack( Cmd_Argv(1), Cmd_Argv(1) );
s_backgroundLoop[0] = 0;
}
else if ( c == 3 )
{
S_StartBackgroundTrack( Cmd_Argv(1), Cmd_Argv(2) );
}
else Msg("music <musicfile> [loopfile]\n");
}
void S_SoundList_f( void )
{
sfx_t *sfx;
@ -2264,11 +2242,11 @@ of a forced fallback of a player specific sound
*/
bool S_LoadSound( sfx_t *sfx )
{
byte *data;
short *samples;
wavinfo_t info;
int size;
char namebuffer[MAX_QPATH];
byte *data;
short *samples;
wavinfo_t info;
int size;
string namebuffer;
// player specific sounds are never directly loaded
if ( sfx->soundName[0] == '*') return false;

207
vsound/sound.h Normal file
View File

@ -0,0 +1,207 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// sound.h - sndlib main header
//=======================================================================
#ifndef SOUND_H
#define SOUND_H
#include <windows.h>
#include <dsound.h>
#include "basetypes.h"
#include "stdapi.h"
#include "stdref.h"
#include "basefiles.h"
#include "dllapi.h"
#include "mathlib.h"
#include "s_openal.h"
extern stdlib_api_t com;
extern vsound_imp_t si;
extern byte *sndpool;
typedef struct
{
int rate;
int width;
int channels;
int samples;
} wavinfo_t;
typedef struct sfx_s
{
string name;
bool default_snd;
bool loaded;
int samples;
int rate;
uint format;
uint bufferNum;
struct sfx_s *nextHash;
} sfx_t;
typedef struct
{
string introName;
string loopName;
bool looping;
file_t *file;
int start;
int rate;
uint format;
void *vorbisFile;
} bg_track_t;
// A playSound will be generated by each call to S_StartSound.
// When the mixer reaches playSound->beginTime, the playSound will be
// assigned to a channel.
typedef struct playsound_s
{
struct playsound_s *prev, *next;
sfx_t *sfx;
int entnum;
int entchannel;
bool fixedPosition; // Use position instead of fetching entity's origin
vec3_t position; // Only use if fixedPosition is set
float volume;
float attenuation;
int beginTime; // Begin at this time
} playSound_t;
typedef struct
{
bool streaming;
sfx_t *sfx; // NULL if unused
int entnum; // To allow overriding a specific sound
int entchannel;
int startTime; // For overriding oldest sounds
bool loopsound; // Looping sound
int loopnum; // Looping entity number
int loopframe; // For stopping looping sounds
bool fixedPosition; // Use position instead of fetching entity's origin
vec3_t position; // Only use if fixedPosition is set
float volume;
float distanceMult;
uint sourceNum; // OpenAL source
} channel_t;
typedef struct
{
vec3_t position;
vec3_t velocity;
float orientation[6];
} listener_t;
typedef struct
{
const char *vendor_string;
const char *renderer_string;
const char *version_string;
const char *extensions_string;
string deviceList[4];
const char *defDevice;
uint device_count;
uint num_slots;
uint num_sends;
bool allow_3DMode;
// 3d mode extension (eax or i3d)
int (*Set3DMode)( const guid_t*, uint, uint, void*, uint );
int (*Get3DMode)( const guid_t*, uint, uint, void*, uint );
} alconfig_t;
typedef struct
{
aldevice *hDevice;
alcontext *hALC;
bool initialized;
bool active;
uint framecount;
int num_channels;
int clientnum;
} alstate_t;
extern alconfig_t al_config;
extern alstate_t al_state;
#define Host_Error com.error
#define Z_Malloc( size ) Mem_Alloc( sndpool, size )
// cvars
extern cvar_t *s_initSound;
extern cvar_t *s_show;
extern cvar_t *s_alDevice;
extern cvar_t *s_allowExtensions;
extern cvar_t *s_soundfx;
extern cvar_t *s_ignoreALErrors;
extern cvar_t *s_masterVolume;
extern cvar_t *s_sfxVolume;
extern cvar_t *s_musicVolume;
extern cvar_t *s_minDistance;
extern cvar_t *s_maxDistance;
extern cvar_t *s_rolloffFactor;
extern cvar_t *s_dopplerFactor;
extern cvar_t *s_dopplerVelocity;
extern int s_rawend;
extern int s_soundtime;
void S_Init( void *hInst );
void S_Shutdown( void );
void S_Activate( bool active );
void S_SoundList_f( void );
// if origin is NULL, the sound will be dynamically sourced from the entity
void S_StartSound( const vec3_t origin, int entnum, int entchannel, sound_t sfx, float vol, float attn );
int S_StartLocalSound( const char *name );
void S_StartBackgroundTrack( const char *intro, const char *loop );
void S_StopBackgroundTrack( void );
sfx_t *S_GetSfxByHandle( sound_t handle );
bool S_LoadSound( sfx_t *sfx );
channel_t *S_PickChannel( int entNum, int entChannel );
void S_StartStreaming( void );
void S_StreamBackgroundTrack( void );
void S_StopStreaming( void );
// cinematics and voice-over-network will send raw samples
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data );
// stop all sounds and the background track
void S_StopAllSounds( void );
void S_FreeSounds( void );
// all continuous looping sounds must be added before calling S_Update
bool S_AddLoopingSound( int entnum, sound_t handle, float volume, float attn );
void S_StopLoopingSound(int entityNum );
// recompute the reletive volumes for all running sounds
// reletive to the given entityNum / orientation
void S_Respatialize( int entityNum, const vec3_t origin, const vec3_t v_forward, const vec3_t v_left, const vec3_t v_up );
// let the sound system know where an entity currently is
void S_UpdateEntityPosition( int entityNum, const vec3_t origin );
void S_Update( int clientnum, const vec3_t pos, const vec3_t vel, const vec3_t at, const vec3_t up );
void S_DisableSounds( void );
void S_EnableSounds( void );
void S_BeginRegistration( void );
void S_EndRegistration( void );
// RegisterSound will allways return a valid sample, even if it
// has to create a placeholder. This prevents continuous filesystem
// checks for missing files
sound_t S_RegisterSound( const char *sample );
void S_DisplayFreeMemory(void);
void S_ClearSoundBuffer( void );
void SNDDMA_Activate( void );
void S_UpdateBackgroundTrack( void );
#endif//SOUND_H

BIN
vsound/vorbis.lib Normal file

Binary file not shown.

148
vsound/vsound.dsp Normal file
View File

@ -0,0 +1,148 @@
# Microsoft Developer Studio Project File - Name="vsound" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=vsound - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "vsound.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "vsound.mak" CFG="vsound - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "vsound - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "vsound - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "vsound - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\temp\vsound\!release"
# PROP Intermediate_Dir "..\temp\vsound\!release"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PLATFORM_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../public" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /opt:nowin98
# ADD LINK32 libogg.lib vorbis.lib /nologo /dll /profile /machine:I386 /nodefaultlib:"libcmt.lib" /opt:nowin98
# Begin Custom Build
TargetDir=\Xash3D\src_main\temp\vsound\!release
InputPath=\Xash3D\src_main\temp\vsound\!release\vsound.dll
SOURCE="$(InputPath)"
"D:\Xash3D\bin\vsound.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\vsound.dll "D:\Xash3D\bin\vsound.dll"
# End Custom Build
!ELSEIF "$(CFG)" == "vsound - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\temp\vsound\!debug"
# PROP Intermediate_Dir "..\temp\vsound\!debug"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PLATFORM_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /Gi /GX /ZI /I "./" /I "../public" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 libogg.lib vorbis.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"libcmt.lib" /pdbtype:sept
# SUBTRACT LINK32 /incremental:no /nodefaultlib
# Begin Custom Build
TargetDir=\Xash3D\src_main\temp\vsound\!debug
InputPath=\Xash3D\src_main\temp\vsound\!debug\vsound.dll
SOURCE="$(InputPath)"
"D:\Xash3D\bin\vsound.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\vsound.dll "D:\Xash3D\bin\vsound.dll"
# End Custom Build
!ENDIF
# Begin Target
# Name "vsound - Win32 Release"
# Name "vsound - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\s_load.c
# End Source File
# Begin Source File
SOURCE=.\s_main.c
# End Source File
# Begin Source File
SOURCE=.\s_openal.c
# End Source File
# Begin Source File
SOURCE=.\s_stream.c
# End Source File
# Begin Source File
SOURCE=.\s_export.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\s_openal.h
# End Source File
# Begin Source File
SOURCE=.\sound.h
# End Source File
# End Group
# End Target
# End Project

View File

@ -61,6 +61,19 @@ Package=<4>
{{{
}}}
###############################################################################
Project: "vsound"=".\vsound\vsound.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "engine"=".\engine\engine.dsp" - Package Owner=<4>