16 Nov 2016
This commit is contained in:
parent
8bc12edbac
commit
ad1c92a0c0
|
@ -17,7 +17,7 @@
|
|||
static int context_id;
|
||||
|
||||
// Default master server address in case we can't read any from woncomm.lst file
|
||||
#define VALVE_MASTER_ADDRESS "half-life.east.won.net"
|
||||
#define VALVE_MASTER_ADDRESS "ms.xash.su"
|
||||
#define PORT_MASTER 27010
|
||||
#define PORT_SERVER 27015
|
||||
|
||||
|
@ -902,7 +902,7 @@ void CHudServers::RequestList( void )
|
|||
NET_API->InitNetworking();
|
||||
|
||||
// Kill off left overs if any
|
||||
NET_API->CancelAllRequests();
|
||||
CancelRequest();
|
||||
|
||||
// Request Server List from master
|
||||
NET_API->SendRequest( context_id++, NETAPI_REQUEST_SERVERLIST, 0, 5.0, &adr, ::ListResponse );
|
||||
|
@ -935,7 +935,7 @@ void CHudServers::RequestBroadcastList( int clearpending )
|
|||
if ( clearpending )
|
||||
{
|
||||
// Kill off left overs if any
|
||||
NET_API->CancelAllRequests();
|
||||
CancelRequest();
|
||||
}
|
||||
|
||||
adr.type = NA_BROADCAST;
|
||||
|
|
|
@ -2718,6 +2718,24 @@ void pfnSetLightmapScale( float scale )
|
|||
{
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnParseFile
|
||||
|
||||
handle colon separately
|
||||
=============
|
||||
*/
|
||||
char *pfnParseFile( char *data, char *token )
|
||||
{
|
||||
char *out;
|
||||
|
||||
host.com_handlecolon = true;
|
||||
out = COM_ParseFile( data, token );
|
||||
host.com_handlecolon = false;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnSPR_DrawGeneric
|
||||
|
@ -3128,7 +3146,7 @@ int TriSpriteTexture( model_t *pSpriteModel, int frame )
|
|||
if( psprite->texFormat == SPR_ALPHTEST )
|
||||
{
|
||||
pglEnable( GL_ALPHA_TEST );
|
||||
pglAlphaFunc( GL_GREATER, 0.0f );
|
||||
pglAlphaFunc( GL_GEQUAL, 0.5f );
|
||||
}
|
||||
|
||||
GL_Bind( GL_TEXTURE0, gl_texturenum );
|
||||
|
@ -3349,7 +3367,7 @@ void NetAPI_Status( net_status_t *status )
|
|||
status->connected = NET_IsLocalAddress( cls.netchan.remote_address ) ? false : true;
|
||||
status->connection_time = host.realtime - cls.netchan.connect_time;
|
||||
status->remote_address = cls.netchan.remote_address;
|
||||
status->packet_loss = cls.packet_loss / 100; // percent
|
||||
status->packet_loss = cls.packet_loss / 100.0; // percent
|
||||
status->latency = cl.frame.latency;
|
||||
status->local_address = net_local;
|
||||
status->rate = cls.netchan.rate;
|
||||
|
@ -3377,15 +3395,14 @@ void NetAPI_SendRequest( int context, int request, int flags, double timeout, ne
|
|||
for( i = 0; i < MAX_REQUESTS; i++ )
|
||||
{
|
||||
nr = &clgame.net_requests[i];
|
||||
if( !nr->pfnFunc || nr->timeout < host.realtime )
|
||||
break;
|
||||
if( !nr->pfnFunc ) break;
|
||||
}
|
||||
|
||||
if( i == MAX_REQUESTS )
|
||||
{
|
||||
double max_timeout = 0;
|
||||
|
||||
// no free requests? use older
|
||||
// no free requests? use oldest
|
||||
for( i = 0, nr = NULL; i < MAX_REQUESTS; i++ )
|
||||
{
|
||||
if(( host.realtime - clgame.net_requests[i].timesend ) > max_timeout )
|
||||
|
@ -3412,11 +3429,20 @@ void NetAPI_SendRequest( int context, int request, int flags, double timeout, ne
|
|||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
{
|
||||
// UNDONE: build request for master-server
|
||||
char fullquery[512] = "1\xFF" "0.0.0.0:0\0" "\\gamedir\\";
|
||||
|
||||
// make sure what port is specified
|
||||
if( !nr->resp.remote_address.port ) nr->resp.remote_address.port = MSG_BigShort( PORT_MASTER );
|
||||
|
||||
// grab the list from the master server
|
||||
Q_strcpy( &fullquery[22], GI->gamedir );
|
||||
NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 23, fullquery, nr->resp.remote_address );
|
||||
clgame.request_type = NET_REQUEST_CLIENT;
|
||||
clgame.master_request = nr; // holds the master request unitl the master acking
|
||||
}
|
||||
else
|
||||
{
|
||||
// send request over the net
|
||||
// local servers request
|
||||
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", PROTOCOL_VERSION, context, request );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, req );
|
||||
}
|
||||
|
@ -3430,15 +3456,31 @@ NetAPI_CancelRequest
|
|||
*/
|
||||
void NetAPI_CancelRequest( int context )
|
||||
{
|
||||
int i;
|
||||
net_request_t *nr;
|
||||
int i;
|
||||
|
||||
// find a specified request
|
||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
||||
{
|
||||
nr = &clgame.net_requests[i];
|
||||
|
||||
if( clgame.net_requests[i].resp.context == context )
|
||||
{
|
||||
MsgDev( D_NOTE, "Request with context %i cancelled\n", context );
|
||||
if( nr->pfnFunc )
|
||||
{
|
||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
nr->pfnFunc( &nr->resp );
|
||||
}
|
||||
|
||||
Q_memset( &clgame.net_requests[i], 0, sizeof( net_request_t ));
|
||||
|
||||
if( clgame.net_requests[i].resp.type == NETAPI_REQUEST_SERVERLIST && &clgame.net_requests[i] == clgame.master_request )
|
||||
{
|
||||
if( clgame.request_type == NET_REQUEST_CLIENT )
|
||||
clgame.request_type = NET_REQUEST_CANCEL;
|
||||
clgame.master_request = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3452,7 +3494,22 @@ NetAPI_CancelAllRequests
|
|||
*/
|
||||
void NetAPI_CancelAllRequests( void )
|
||||
{
|
||||
net_request_t *nr;
|
||||
int i;
|
||||
|
||||
// tell the user about cancel
|
||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
||||
{
|
||||
nr = &clgame.net_requests[i];
|
||||
if( !nr->pfnFunc ) continue; // not used
|
||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
nr->pfnFunc( &nr->resp );
|
||||
}
|
||||
|
||||
Q_memset( clgame.net_requests, 0, sizeof( clgame.net_requests ));
|
||||
clgame.request_type = NET_REQUEST_CANCEL;
|
||||
clgame.master_request = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3836,7 +3893,7 @@ static cl_enginefunc_t gEngfuncs =
|
|||
VGui_GetPanel,
|
||||
VGui_ViewportPaintBackground,
|
||||
COM_LoadFile,
|
||||
COM_ParseFile,
|
||||
pfnParseFile,
|
||||
COM_FreeFile,
|
||||
&gTriApi,
|
||||
&gEfxApi,
|
||||
|
|
|
@ -905,6 +905,7 @@ void CL_ClearState( void )
|
|||
cl.refdef.movevars = &clgame.movevars;
|
||||
cl.maxclients = 1; // allow to drawing player in menu
|
||||
cl.mtime[0] = cl.mtime[1] = 1.0f; // because level starts from 1.0f second
|
||||
NetAPI_CancelAllRequests();
|
||||
cl.scr_fov = 90.0f;
|
||||
|
||||
Cvar_SetFloat( "scr_download", 0.0f );
|
||||
|
@ -1044,6 +1045,11 @@ void CL_InternetServers_f( void )
|
|||
Q_strcpy( &fullquery[22], GI->gamedir );
|
||||
|
||||
NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 23, fullquery, adr );
|
||||
|
||||
// now we clearing the vgui request
|
||||
if( clgame.master_request != NULL )
|
||||
Q_memset( clgame.master_request, 0, sizeof( net_request_t ));
|
||||
clgame.request_type = NET_REQUEST_GAMEUI;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1164,6 +1170,70 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
|
|||
UI_AddServerToList( from, s );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_FixupColorStringsForInfoString
|
||||
|
||||
all the keys and values must be ends with ^7
|
||||
=================
|
||||
*/
|
||||
void CL_FixupColorStringsForInfoString( const char *in, char *out )
|
||||
{
|
||||
qboolean hasPrefix = false;
|
||||
qboolean endOfKeyVal = false;
|
||||
int color = 7;
|
||||
int count = 0;
|
||||
|
||||
if( *in == '\\' )
|
||||
{
|
||||
*out++ = *in++;
|
||||
count++;
|
||||
}
|
||||
|
||||
while( *in && count < MAX_INFO_STRING )
|
||||
{
|
||||
if( IsColorString( in ))
|
||||
color = ColorIndex( *(in+1));
|
||||
|
||||
// color the not reset while end of key (or value) was found!
|
||||
if( *in == '\\' && color != 7 )
|
||||
{
|
||||
if( IsColorString( out - 2 ))
|
||||
{
|
||||
*(out - 1) = '7';
|
||||
}
|
||||
else
|
||||
{
|
||||
*out++ = '^';
|
||||
*out++ = '7';
|
||||
count += 2;
|
||||
}
|
||||
color = 7;
|
||||
}
|
||||
|
||||
*out++ = *in++;
|
||||
count++;
|
||||
}
|
||||
|
||||
// check the remaining value
|
||||
if( color != 7 )
|
||||
{
|
||||
// if the ends with another color rewrite it
|
||||
if( IsColorString( out - 2 ))
|
||||
{
|
||||
*(out - 1) = '7';
|
||||
}
|
||||
else
|
||||
{
|
||||
*out++ = '^';
|
||||
*out++ = '7';
|
||||
count += 2;
|
||||
}
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_ParseNETInfoMessage
|
||||
|
@ -1173,14 +1243,26 @@ Handle a reply from a netinfo
|
|||
*/
|
||||
void CL_ParseNETInfoMessage( netadr_t from, sizebuf_t *msg )
|
||||
{
|
||||
char *s;
|
||||
char *s, *val;
|
||||
net_request_t *nr;
|
||||
static char infostring[MAX_INFO_STRING+8];
|
||||
int i, context, type;
|
||||
int errorBits = 0;
|
||||
|
||||
context = Q_atoi( Cmd_Argv( 1 ));
|
||||
type = Q_atoi( Cmd_Argv( 2 ));
|
||||
s = Cmd_Argv( 3 );
|
||||
|
||||
// check for errors
|
||||
val = Info_ValueForKey( s, "neterror" );
|
||||
|
||||
if( !Q_stricmp( val, "protocol" ))
|
||||
SetBits( errorBits, NET_ERROR_PROTO_UNSUPPORTED );
|
||||
else if( !Q_stricmp( val, "undefined" ))
|
||||
SetBits( errorBits, NET_ERROR_UNDEFINED );
|
||||
|
||||
CL_FixupColorStringsForInfoString( s, infostring );
|
||||
|
||||
// find a request with specified context
|
||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
||||
{
|
||||
|
@ -1188,27 +1270,55 @@ void CL_ParseNETInfoMessage( netadr_t from, sizebuf_t *msg )
|
|||
|
||||
if( nr->resp.context == context && nr->resp.type == type )
|
||||
{
|
||||
if( nr->timeout > host.realtime )
|
||||
{
|
||||
// setup the answer
|
||||
nr->resp.response = s;
|
||||
nr->resp.remote_address = from;
|
||||
nr->resp.error = NET_SUCCESS;
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
nr->pfnFunc( &nr->resp );
|
||||
// setup the answer
|
||||
nr->resp.response = infostring;
|
||||
nr->resp.remote_address = from;
|
||||
nr->resp.error = NET_SUCCESS;
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
|
||||
if(!( nr->flags & FNETAPI_MULTIPLE_RESPONSE ))
|
||||
Q_memset( nr, 0, sizeof( *nr )); // done
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_memset( nr, 0, sizeof( *nr ));
|
||||
}
|
||||
if( nr->timeout <= host.realtime )
|
||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
||||
SetBits( nr->resp.error, errorBits ); // misc error bits
|
||||
|
||||
nr->pfnFunc( &nr->resp );
|
||||
|
||||
if( !FBitSet( nr->flags, FNETAPI_MULTIPLE_RESPONSE ))
|
||||
Q_memset( nr, 0, sizeof( *nr )); // done
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_ProcessNetRequests
|
||||
|
||||
check for timeouts
|
||||
=================
|
||||
*/
|
||||
void CL_ProcessNetRequests( void )
|
||||
{
|
||||
net_request_t *nr;
|
||||
int i;
|
||||
|
||||
// find a request with specified context
|
||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
||||
{
|
||||
nr = &clgame.net_requests[i];
|
||||
if( !nr->pfnFunc ) continue; // not used
|
||||
|
||||
if( nr->timeout <= host.realtime )
|
||||
{
|
||||
// setup the answer
|
||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
|
||||
nr->pfnFunc( &nr->resp );
|
||||
Q_memset( nr, 0, sizeof( *nr )); // done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
/*
|
||||
===============
|
||||
|
@ -1450,18 +1560,66 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||
else if( !Q_strcmp( c, "f" ))
|
||||
{
|
||||
// serverlist got from masterserver
|
||||
while( !msg->bOverflow )
|
||||
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
||||
{
|
||||
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
|
||||
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
|
||||
servadr.type = NA_IP;
|
||||
// 4 bytes for IP
|
||||
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip ));
|
||||
// 2 bytes for Port
|
||||
servadr.port = MSG_ReadShort( msg );
|
||||
|
||||
if( !servadr.port ) break;
|
||||
// list is ends here
|
||||
if( !servadr.port )
|
||||
{
|
||||
if( clgame.request_type == NET_REQUEST_CLIENT && clgame.master_request != NULL )
|
||||
{
|
||||
net_request_t *nr = clgame.master_request;
|
||||
net_adrlist_t *list, **prev;
|
||||
|
||||
NET_Config( true ); // allow remote
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
|
||||
// setup the answer
|
||||
nr->resp.remote_address = from;
|
||||
nr->resp.error = NET_SUCCESS;
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
|
||||
if( nr->timeout <= host.realtime )
|
||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
||||
|
||||
MsgDev( D_INFO, "serverlist call: %s\n", NET_AdrToString( from ));
|
||||
nr->pfnFunc( &nr->resp );
|
||||
|
||||
// throw the list, now it will be stored in user area
|
||||
prev = &((net_adrlist_t *)nr->resp.response);
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
list = *prev;
|
||||
if( !list ) break;
|
||||
|
||||
// throw out any variables the game created
|
||||
*prev = list->next;
|
||||
Mem_Free( list );
|
||||
}
|
||||
Q_memset( nr, 0, sizeof( *nr )); // done
|
||||
clgame.request_type = NET_REQUEST_CANCEL;
|
||||
clgame.master_request = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if( clgame.request_type == NET_REQUEST_CLIENT && clgame.master_request != NULL )
|
||||
{
|
||||
net_request_t *nr = clgame.master_request;
|
||||
net_adrlist_t *list;
|
||||
|
||||
// adding addresses into list
|
||||
list = Z_Malloc( sizeof( *list ));
|
||||
list->remote_address = servadr;
|
||||
list->next = nr->resp.response;
|
||||
nr->resp.response = list;
|
||||
}
|
||||
else if( clgame.request_type == NET_REQUEST_GAMEUI )
|
||||
{
|
||||
NET_Config( true ); // allow remote
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
|
||||
|
@ -1556,6 +1714,9 @@ void CL_ReadNetMessage( void )
|
|||
}
|
||||
|
||||
Netchan_UpdateProgress( &cls.netchan );
|
||||
|
||||
// check requests for time-expire
|
||||
CL_ProcessNetRequests();
|
||||
}
|
||||
|
||||
void CL_ReadPackets( void )
|
||||
|
|
|
@ -37,7 +37,7 @@ GNU General Public License for more details.
|
|||
#define MAX_CDTRACKS 32
|
||||
#define MAX_IMAGES 256 // SpriteTextures
|
||||
#define MAX_EFRAGS 4096
|
||||
#define MAX_REQUESTS 32
|
||||
#define MAX_REQUESTS 128
|
||||
|
||||
// screenshot types
|
||||
#define VID_SCREENSHOT 0
|
||||
|
@ -354,6 +354,13 @@ typedef struct
|
|||
model_t *model; // for catch model changes
|
||||
} remap_info_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NET_REQUEST_CANCEL = 0, // request was cancelled for some reasons
|
||||
NET_REQUEST_GAMEUI, // called from GameUI
|
||||
NET_REQUEST_CLIENT, // called from Client
|
||||
} net_request_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
net_response_t resp;
|
||||
|
@ -415,7 +422,9 @@ typedef struct
|
|||
client_textmessage_t *titles; // title messages, not network messages
|
||||
int numTitles;
|
||||
|
||||
net_request_type_t request_type; // filter the requests
|
||||
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
|
||||
net_request_t *master_request; // queued master request
|
||||
|
||||
efrag_t *free_efrags; // linked efrags
|
||||
cl_entity_t viewent; // viewmodel
|
||||
|
@ -677,6 +686,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
|||
client_textmessage_t *CL_TextMessageGet( const char *pName );
|
||||
int pfnDecalIndexFromName( const char *szDecalName );
|
||||
int pfnIndexFromTrace( struct pmtrace_s *pTrace );
|
||||
void NetAPI_CancelAllRequests( void );
|
||||
int CL_FindModelIndex( const char *m );
|
||||
HSPRITE pfnSPR_Load( const char *szPicName );
|
||||
HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags );
|
||||
|
|
|
@ -1188,7 +1188,8 @@ void R_DrawEntitiesOnList( void )
|
|||
|
||||
R_DrawViewModel();
|
||||
|
||||
CL_ExtraUpdate();
|
||||
if( !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
|
||||
CL_ExtraUpdate();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1216,7 +1217,8 @@ void R_RenderScene( const ref_params_t *fd )
|
|||
R_CheckFog();
|
||||
R_DrawWorld();
|
||||
|
||||
CL_ExtraUpdate (); // don't let sound get messed up if going slow
|
||||
if( !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
|
||||
CL_ExtraUpdate (); // don't let sound get messed up if going slow
|
||||
|
||||
R_DrawEntitiesOnList();
|
||||
|
||||
|
@ -1269,7 +1271,8 @@ void R_BeginFrame( qboolean clearScene )
|
|||
// swapinterval stuff
|
||||
GL_UpdateSwapInterval();
|
||||
|
||||
CL_ExtraUpdate ();
|
||||
if( !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
|
||||
CL_ExtraUpdate ();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2021,7 +2021,7 @@ static void R_StudioDrawPoints( void )
|
|||
else if( g_nFaceFlags & STUDIO_NF_TRANSPARENT && R_StudioOpaque( g_iRenderMode ))
|
||||
{
|
||||
GL_SetRenderMode( kRenderTransAlpha );
|
||||
pglAlphaFunc( GL_GREATER, 0.0f );
|
||||
pglAlphaFunc( GL_GEQUAL, 0.5f );
|
||||
alpha = 1.0f;
|
||||
}
|
||||
else if( g_nFaceFlags & STUDIO_NF_ADDITIVE )
|
||||
|
@ -2574,7 +2574,7 @@ static void R_StudioSetupRenderer( int rendermode )
|
|||
if( glState.drawTrans && g_iRenderMode != kRenderTransAdd )
|
||||
pglDepthMask( GL_TRUE );
|
||||
|
||||
pglAlphaFunc( GL_GREATER, 0.0f );
|
||||
pglAlphaFunc( GL_GEQUAL, 0.5f );
|
||||
pglShadeModel( GL_SMOOTH );
|
||||
|
||||
if( g_iBackFaceCull )
|
||||
|
|
|
@ -1661,7 +1661,7 @@ static void GL_SetDefaults( void )
|
|||
pglDisable( GL_BLEND );
|
||||
pglDisable( GL_ALPHA_TEST );
|
||||
pglDisable( GL_POLYGON_OFFSET_FILL );
|
||||
pglAlphaFunc( GL_GREATER, 0.0f );
|
||||
pglAlphaFunc( GL_GEQUAL, 0.5f );
|
||||
pglEnable( GL_TEXTURE_2D );
|
||||
pglShadeModel( GL_SMOOTH );
|
||||
|
||||
|
|
|
@ -361,7 +361,7 @@ int SNDDMA_Init( void *hInst )
|
|||
else
|
||||
{
|
||||
if( snd_firsttime )
|
||||
MsgDev( D_ERROR, "SNDDMA_Init: can't initialize sound device\n" );
|
||||
MsgDev( D_ERROR, "Audio: can't initialize sound device\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,8 +68,8 @@ void S_SoundList_f( void )
|
|||
// return true if char 'c' is one of 1st 2 characters in pch
|
||||
qboolean S_TestSoundChar( const char *pch, char c )
|
||||
{
|
||||
int i;
|
||||
char *pcht = (char *)pch;
|
||||
int i;
|
||||
|
||||
if( !pch || !*pch )
|
||||
return false;
|
||||
|
@ -141,15 +141,11 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
|
|||
|
||||
if( sc->rate < SOUND_11k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
|
||||
#if SOUND_DMA_SPEED > SOUND_11k
|
||||
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
|
||||
#endif
|
||||
|
||||
#if SOUND_DMA_SPEED > SOUND_32k
|
||||
else if( sc->rate > SOUND_22k && sc->rate <= SOUND_32k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
|
||||
#endif
|
||||
|
||||
sfx->cache = sc;
|
||||
|
||||
return sfx->cache;
|
||||
|
@ -201,9 +197,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
|
|||
|
||||
// find a free sfx slot spot
|
||||
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++)
|
||||
{
|
||||
if( !sfx->name[0] ) break; // free spot
|
||||
}
|
||||
|
||||
if( i == s_numSfx )
|
||||
{
|
||||
|
|
|
@ -20,7 +20,6 @@ GNU General Public License for more details.
|
|||
#include "ref_params.h"
|
||||
#include "pm_local.h"
|
||||
|
||||
#define MAX_DUPLICATED_CHANNELS 4 // threshold for identical static channels (probably error)
|
||||
#define SND_CLIP_DISTANCE (float)(GI->soundclip_dist)
|
||||
|
||||
dma_t dma;
|
||||
|
@ -28,6 +27,7 @@ byte *sndpool;
|
|||
static soundfade_t soundfade;
|
||||
channel_t channels[MAX_CHANNELS];
|
||||
sound_t ambient_sfx[NUM_AMBIENTS];
|
||||
rawchan_t *raw_channels[MAX_RAW_CHANNELS];
|
||||
qboolean snd_ambient = false;
|
||||
listener_t s_listener;
|
||||
int total_channels;
|
||||
|
@ -35,6 +35,7 @@ int soundtime; // sample PAIRS
|
|||
int paintedtime; // sample PAIRS
|
||||
static int trace_count = 0;
|
||||
static int last_trace_chan = 0;
|
||||
static byte s_fatphs[MAX_MAP_LEAFS/8]; // PHS array for snd module
|
||||
|
||||
convar_t *s_volume;
|
||||
convar_t *s_musicvolume;
|
||||
|
@ -689,6 +690,13 @@ float SND_GetGain( channel_t *ch, qboolean fplayersound, qboolean flooping, floa
|
|||
return gain;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SND_CheckPHS
|
||||
|
||||
using a 'fat' radius
|
||||
=================
|
||||
*/
|
||||
qboolean SND_CheckPHS( channel_t *ch )
|
||||
{
|
||||
mleaf_t *leaf;
|
||||
|
@ -1355,7 +1363,7 @@ void S_UpdateAmbientSounds( void )
|
|||
if( !chan->sfx ) continue;
|
||||
|
||||
vol = s_ambient_level->value * leaf->ambient_sound_level[ambient_channel];
|
||||
if( vol < 8 ) vol = 0;
|
||||
if( vol < 0 ) vol = 0;
|
||||
|
||||
// don't adjust volume too fast
|
||||
if( chan->master_vol < vol )
|
||||
|
@ -1373,6 +1381,362 @@ void S_UpdateAmbientSounds( void )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
SOUND STREAM RAW SAMPLES
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
/*
|
||||
===================
|
||||
S_FindRawChannel
|
||||
===================
|
||||
*/
|
||||
rawchan_t *S_FindRawChannel( int entnum, qboolean create )
|
||||
{
|
||||
int i, free;
|
||||
int best, best_time;
|
||||
size_t raw_samples = 0;
|
||||
rawchan_t *ch;
|
||||
|
||||
if( !entnum ) return NULL; // world is unused
|
||||
|
||||
// check for replacement sound, or find the best one to replace
|
||||
best_time = 0x7fffffff;
|
||||
best = free = -1;
|
||||
|
||||
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
|
||||
{
|
||||
ch = raw_channels[i];
|
||||
|
||||
if( free < 0 && !ch )
|
||||
{
|
||||
free = i;
|
||||
}
|
||||
else if( ch )
|
||||
{
|
||||
int time;
|
||||
|
||||
// exact match
|
||||
if( ch->entnum == entnum )
|
||||
return ch;
|
||||
|
||||
time = ch->s_rawend - paintedtime;
|
||||
if( time < best_time )
|
||||
{
|
||||
best = i;
|
||||
best_time = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !create ) return NULL;
|
||||
|
||||
if( free >= 0 ) best = free;
|
||||
if( best < 0 ) return NULL; // no free slots
|
||||
|
||||
if( !raw_channels[best] )
|
||||
{
|
||||
raw_samples = MAX_RAW_SAMPLES;
|
||||
raw_channels[best] = Mem_Alloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * ( raw_samples - 1 ));
|
||||
}
|
||||
|
||||
ch = raw_channels[best];
|
||||
ch->max_samples = raw_samples;
|
||||
ch->entnum = entnum;
|
||||
ch->s_rawend = 0;
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_RawSamplesStereo
|
||||
===================
|
||||
*/
|
||||
static uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data )
|
||||
{
|
||||
uint fracstep, samplefrac;
|
||||
uint src, dst;
|
||||
|
||||
if( rawend < paintedtime )
|
||||
rawend = paintedtime;
|
||||
|
||||
fracstep = ((double) rate / (double)SOUND_DMA_SPEED) * (double)(1 << S_RAW_SAMPLES_PRECISION_BITS);
|
||||
samplefrac = 0;
|
||||
|
||||
if( width == 2 )
|
||||
{
|
||||
const short *in = (const short *)data;
|
||||
|
||||
if( channels == 2 )
|
||||
{
|
||||
for( src = 0; src < samples; samplefrac += fracstep, src = ( samplefrac >> S_RAW_SAMPLES_PRECISION_BITS ))
|
||||
{
|
||||
dst = rawend++ & ( max_samples - 1 );
|
||||
rawsamples[dst].left = in[src*2+0];
|
||||
rawsamples[dst].right = in[src*2+1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( src = 0; src < samples; samplefrac += fracstep, src = ( samplefrac >> S_RAW_SAMPLES_PRECISION_BITS ))
|
||||
{
|
||||
dst = rawend++ & ( max_samples - 1 );
|
||||
rawsamples[dst].left = in[src];
|
||||
rawsamples[dst].right = in[src];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( channels == 2 )
|
||||
{
|
||||
const char *in = (const char *)data;
|
||||
|
||||
for( src = 0; src < samples; samplefrac += fracstep, src = ( samplefrac >> S_RAW_SAMPLES_PRECISION_BITS ))
|
||||
{
|
||||
dst = rawend++ & ( max_samples - 1 );
|
||||
rawsamples[dst].left = in[src*2+0] << 8;
|
||||
rawsamples[dst].right = in[src*2+1] << 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( src = 0; src < samples; samplefrac += fracstep, src = ( samplefrac >> S_RAW_SAMPLES_PRECISION_BITS ))
|
||||
{
|
||||
dst = rawend++ & ( max_samples - 1 );
|
||||
rawsamples[dst].left = ( data[src] - 128 ) << 8;
|
||||
rawsamples[dst].right = ( data[src] - 128 ) << 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rawend;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_RawEntSamples
|
||||
===================
|
||||
*/
|
||||
static void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol )
|
||||
{
|
||||
rawchan_t *ch;
|
||||
|
||||
if( snd_vol < 0 )
|
||||
snd_vol = 0;
|
||||
|
||||
if( !( ch = S_FindRawChannel( entnum, true )))
|
||||
return;
|
||||
|
||||
ch->master_vol = snd_vol;
|
||||
ch->dist_mult = (ATTN_NONE / SND_CLIP_DISTANCE);
|
||||
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples, samples, rate, width, channels, data );
|
||||
ch->leftvol = ch->rightvol = snd_vol;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_RawSamples
|
||||
===================
|
||||
*/
|
||||
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum )
|
||||
{
|
||||
int snd_vol;
|
||||
|
||||
if( entnum < 0 ) snd_vol = 128; // bg track or movie track
|
||||
if( snd_vol < 0 ) snd_vol = 0; // fixup negative values
|
||||
|
||||
S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_PositionedRawSamples
|
||||
===================
|
||||
*/
|
||||
static void S_PositionedRawSamples( int entnum, float fvol, float attn, uint samples, uint rate, word width, word channels, const byte *data )
|
||||
{
|
||||
rawchan_t *ch;
|
||||
|
||||
if( entnum < 0 || entnum >= GI->max_edicts )
|
||||
return;
|
||||
|
||||
if( !( ch = S_FindRawChannel( entnum, true )))
|
||||
return;
|
||||
|
||||
ch->master_vol = bound( 0, fvol * 255, 255 );
|
||||
ch->dist_mult = (attn / SND_CLIP_DISTANCE);
|
||||
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples, samples, rate, width, channels, data );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_GetRawSamplesLength
|
||||
===================
|
||||
*/
|
||||
uint S_GetRawSamplesLength( int entnum )
|
||||
{
|
||||
rawchan_t *ch;
|
||||
|
||||
if( !( ch = S_FindRawChannel( entnum, false )))
|
||||
return 0;
|
||||
|
||||
return ch->s_rawend <= paintedtime ? 0 : (float)(ch->s_rawend - paintedtime) * DMA_MSEC_PER_SAMPLE;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_ClearRawChannel
|
||||
===================
|
||||
*/
|
||||
void S_ClearRawChannel( int entnum )
|
||||
{
|
||||
rawchan_t *ch;
|
||||
|
||||
if( !( ch = S_FindRawChannel( entnum, false )))
|
||||
return;
|
||||
|
||||
ch->s_rawend = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_FreeIdleRawChannels
|
||||
|
||||
Free raw channel that have been idling for too long.
|
||||
===================
|
||||
*/
|
||||
static void S_FreeIdleRawChannels( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
|
||||
{
|
||||
rawchan_t *ch = raw_channels[i];
|
||||
|
||||
if( !ch ) continue;
|
||||
|
||||
if( ch->s_rawend >= paintedtime )
|
||||
continue;
|
||||
|
||||
if(( paintedtime - ch->s_rawend ) / SOUND_DMA_SPEED >= S_RAW_SOUND_IDLE_SEC )
|
||||
{
|
||||
raw_channels[i] = NULL;
|
||||
Mem_Free( ch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_ClearRawChannels
|
||||
===================
|
||||
*/
|
||||
static void S_ClearRawChannels( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
|
||||
{
|
||||
rawchan_t *ch = raw_channels[i];
|
||||
|
||||
if( !ch ) continue;
|
||||
ch->s_rawend = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_SpatializeRawChannels
|
||||
===================
|
||||
*/
|
||||
static void S_SpatializeRawChannels( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
|
||||
{
|
||||
rawchan_t *ch = raw_channels[i];
|
||||
vec3_t source_vec;
|
||||
float dist, dot;
|
||||
|
||||
if( !ch ) continue;
|
||||
|
||||
if( ch->s_rawend < paintedtime )
|
||||
{
|
||||
ch->leftvol = ch->rightvol = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// spatialization
|
||||
if( !S_IsClient( ch->entnum ) && ch->dist_mult && ch->entnum >= 0 && ch->entnum < GI->max_edicts )
|
||||
{
|
||||
if( !CL_GetEntitySpatialization( ch->entnum, ch->origin, &ch->radius ))
|
||||
{
|
||||
// origin is null and entity not exist on client
|
||||
ch->leftvol = ch->rightvol = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSubtract( ch->origin, s_listener.origin, source_vec );
|
||||
|
||||
// normalize source_vec and get distance from listener to source
|
||||
dist = VectorNormalizeLength( source_vec );
|
||||
dot = DotProduct( s_listener.right, source_vec );
|
||||
|
||||
// for sounds with a radius, spatialize left/right evenly within the radius
|
||||
if( ch->radius > 0 && dist < ch->radius )
|
||||
{
|
||||
float interval = ch->radius * 0.5f;
|
||||
float blend = dist - interval;
|
||||
|
||||
if( blend < 0 ) blend = 0;
|
||||
blend /= interval;
|
||||
|
||||
// blend is 0.0 - 1.0, from 50% radius -> 100% radius
|
||||
// at radius * 0.5, dot is 0 (ie: sound centered left/right)
|
||||
// at radius dot == dot
|
||||
dot *= blend;
|
||||
}
|
||||
|
||||
// don't pan sounds with no attenuation
|
||||
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
|
||||
|
||||
// fill out channel volumes for single location
|
||||
S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, 1.0f, dot, dist * ch->dist_mult );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ch->leftvol = ch->rightvol = ch->master_vol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_FreeRawChannels
|
||||
===================
|
||||
*/
|
||||
static void S_FreeRawChannels( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
// free raw samples
|
||||
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
|
||||
{
|
||||
if( raw_channels[i] )
|
||||
Mem_Free( raw_channels[i] );
|
||||
}
|
||||
|
||||
memset( raw_channels, 0, sizeof( raw_channels ));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
S_ClearBuffer
|
||||
|
@ -1380,7 +1744,7 @@ S_ClearBuffer
|
|||
*/
|
||||
void S_ClearBuffer( void )
|
||||
{
|
||||
s_rawend = 0;
|
||||
S_ClearRawChannels();
|
||||
|
||||
SNDDMA_BeginPainting ();
|
||||
if( dma.buffer ) Q_memset( dma.buffer, 0, dma.samples * 2 );
|
||||
|
@ -1506,6 +1870,9 @@ void S_RenderFrame( ref_params_t *fd )
|
|||
// update any client side sound fade
|
||||
S_UpdateSoundFade();
|
||||
|
||||
// release raw-channels that no longer used more than 10 secs
|
||||
S_FreeIdleRawChannels();
|
||||
|
||||
s_listener.entnum = fd->viewentity; // can be camera entity too
|
||||
s_listener.frametime = fd->frametime;
|
||||
s_listener.waterlevel = fd->waterlevel;
|
||||
|
@ -1571,6 +1938,8 @@ void S_RenderFrame( ref_params_t *fd )
|
|||
}
|
||||
}
|
||||
|
||||
S_SpatializeRawChannels();
|
||||
|
||||
// debugging output
|
||||
if( s_show->value )
|
||||
{
|
||||
|
@ -1591,7 +1960,12 @@ void S_RenderFrame( ref_params_t *fd )
|
|||
}
|
||||
|
||||
// to differentiate modes
|
||||
if( s_cull->integer ) VectorSet( info.color, 0.0f, 1.0f, 0.0f );
|
||||
if( s_cull->integer && s_phs->integer )
|
||||
VectorSet( info.color, 1.0f, 1.0f, 0.0f );
|
||||
else if( s_phs->integer )
|
||||
VectorSet( info.color, 0.0f, 1.0f, 0.0f );
|
||||
else if( s_cull->integer )
|
||||
VectorSet( info.color, 1.0f, 0.0f, 0.0f );
|
||||
else VectorSet( info.color, 1.0f, 1.0f, 1.0f );
|
||||
info.index = 0;
|
||||
|
||||
|
@ -1759,8 +2133,8 @@ qboolean S_Init( void )
|
|||
s_mixahead = Cvar_Get( "_snd_mixahead", "0.12", 0, "how much sound to mix ahead of time" );
|
||||
s_show = Cvar_Get( "s_show", "0", CVAR_ARCHIVE, "show playing sounds" );
|
||||
s_lerping = Cvar_Get( "s_lerping", "0", CVAR_ARCHIVE, "apply interpolation to sound output" );
|
||||
s_ambient_level = Cvar_Get( "ambient_level", "0.3", 0, "volume of environment noises (water and wind)" );
|
||||
s_ambient_fade = Cvar_Get( "ambient_fade", "100", 0, "rate of volume fading when client is moving" );
|
||||
s_ambient_level = Cvar_Get( "ambient_level", "0.3", CVAR_ARCHIVE, "volume of environment noises (water and wind)" );
|
||||
s_ambient_fade = Cvar_Get( "ambient_fade", "1000", CVAR_ARCHIVE, "rate of volume fading when client is moving" );
|
||||
s_combine_sounds = Cvar_Get( "s_combine_channels", "1", CVAR_ARCHIVE, "combine channels with same sounds" );
|
||||
snd_foliage_db_loss = Cvar_Get( "snd_foliage_db_loss", "4", 0, "foliage loss factor" );
|
||||
snd_gain_max = Cvar_Get( "snd_gain_max", "1", 0, "gain maximal threshold" );
|
||||
|
@ -1821,10 +2195,11 @@ void S_Shutdown( void )
|
|||
Cmd_RemoveCommand( "s_info" );
|
||||
Cmd_RemoveCommand( "+voicerecord" );
|
||||
Cmd_RemoveCommand( "-voicerecord" );
|
||||
Cmd_RemoveCommand( "spk" );
|
||||
Cmd_RemoveCommand( "speak" );
|
||||
Cmd_RemoveCommand( "spk" );
|
||||
|
||||
S_StopAllSounds ();
|
||||
S_FreeRawChannels ();
|
||||
S_FreeSounds ();
|
||||
VOX_Shutdown ();
|
||||
FreeDsps ();
|
||||
|
|
|
@ -216,8 +216,8 @@ CHANNEL MIXING
|
|||
*/
|
||||
void S_PaintMonoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pData, int outCount )
|
||||
{
|
||||
int i, data;
|
||||
int *lscale, *rscale;
|
||||
int i, data;
|
||||
|
||||
lscale = snd_scaletable[volume[0] >> SND_SCALE_SHIFT];
|
||||
rscale = snd_scaletable[volume[1] >> SND_SCALE_SHIFT];
|
||||
|
@ -252,8 +252,8 @@ void S_PaintStereoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pData,
|
|||
|
||||
void S_PaintMonoFrom16( portable_samplepair_t *pbuf, int *volume, short *pData, int outCount )
|
||||
{
|
||||
int i, data;
|
||||
int left, right;
|
||||
int i, data;
|
||||
|
||||
for( i = 0; i < outCount; i++ )
|
||||
{
|
||||
|
@ -473,20 +473,13 @@ int S_MixDataToDevice( channel_t *pChannel, int sampleCount, int outputRate, int
|
|||
|
||||
for( i = 0; i < CPAINTBUFFERS; i++ )
|
||||
{
|
||||
if( paintbuffers[i].factive )
|
||||
{
|
||||
// mix chan into all active paintbuffers
|
||||
MIX_SetCurrentPaintbuffer( i );
|
||||
if( !paintbuffers[i].factive )
|
||||
continue;
|
||||
|
||||
S_MixChannel(
|
||||
pChannel, // Channel.
|
||||
pData, // Input buffer.
|
||||
outputOffset, // Output position.
|
||||
FIX_FLOAT( sampleFraction ), // Iterators.
|
||||
FIX_FLOAT( rate ),
|
||||
outputSampleCount
|
||||
);
|
||||
}
|
||||
// mix chan into all active paintbuffers
|
||||
MIX_SetCurrentPaintbuffer( i );
|
||||
|
||||
S_MixChannel( pChannel, pData, outputOffset, FIX_FLOAT( sampleFraction ), FIX_FLOAT( rate ), outputSampleCount );
|
||||
}
|
||||
|
||||
MIX_SetCurrentPaintbuffer( j );
|
||||
|
@ -692,7 +685,7 @@ void S_Interpolate2xCubic( portable_samplepair_t *pbuffer, portable_samplepair_t
|
|||
{
|
||||
// get source sample pointer
|
||||
psamp0 = S_GetNextpFilter( i-1, pbuffer, pfiltermem );
|
||||
psamp1 = S_GetNextpFilter( i, pbuffer, pfiltermem );
|
||||
psamp1 = S_GetNextpFilter( i+0, pbuffer, pfiltermem );
|
||||
psamp2 = S_GetNextpFilter( i+1, pbuffer, pfiltermem );
|
||||
psamp3 = S_GetNextpFilter( i+2, pbuffer, pfiltermem );
|
||||
|
||||
|
@ -778,9 +771,9 @@ void S_Interpolate2xLinear( portable_samplepair_t *pbuffer, portable_samplepair_
|
|||
// filtertype: FILTERTYPE_NONE, _LINEAR, _CUBIC etc. Must match prevfilter.
|
||||
void S_MixBufferUpsample2x( int count, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem, int cfltmem, int filtertype )
|
||||
{
|
||||
int i, j;
|
||||
int upCount = count<<1;
|
||||
|
||||
int i, j;
|
||||
|
||||
// reverse through buffer, duplicating contents for 'count' samples
|
||||
for( i = upCount - 1, j = count - 1; j >= 0; i-=2, j-- )
|
||||
{
|
||||
|
@ -893,57 +886,16 @@ void S_MixUpsample( int sampleCount, int filtertype )
|
|||
ppaint->ifilter++;
|
||||
}
|
||||
|
||||
// mix and upsample channels to 44khz 'ipaintbuffer'
|
||||
// mix channels matching 'flags' (SOUND_MIX_DRY or SOUND_MIX_WET) into specified paintbuffer
|
||||
// upsamples 11khz, 22khz channels to 44khz.
|
||||
|
||||
// NOTE: only call this on channels that will be mixed into only 1 paintbuffer
|
||||
// and that will not be mixed until the next mix pass! otherwise, MIX_MixChannelsToPaintbuffer
|
||||
// will advance any internal pointers on mixed channels; subsequent calls will be at
|
||||
// incorrect offset.
|
||||
void MIX_MixUpsampleBuffer( int ipaintbuffer, int end, int count )
|
||||
{
|
||||
int ipaintcur = MIX_GetCurrentPaintbufferIndex(); // save current paintbuffer
|
||||
|
||||
// reset paintbuffer upsampling filter index
|
||||
MIX_ResetPaintbufferFilterCounter( ipaintbuffer );
|
||||
|
||||
// prevent other paintbuffers from being mixed
|
||||
MIX_DeactivateAllPaintbuffers();
|
||||
|
||||
MIX_ActivatePaintbuffer( ipaintbuffer ); // operates on MIX_MixChannelsToPaintbuffer
|
||||
MIX_SetCurrentPaintbuffer( ipaintbuffer ); // operates on MixUpSample
|
||||
|
||||
// mix 11khz channels to buffer
|
||||
MIX_MixChannelsToPaintbuffer( end, SOUND_11k, SOUND_11k );
|
||||
|
||||
// upsample 11khz buffer by 2x
|
||||
S_MixUpsample( count / (SOUND_DMA_SPEED / SOUND_11k), FILTERTYPE_LINEAR );
|
||||
|
||||
// mix 22khz channels to buffer
|
||||
MIX_MixChannelsToPaintbuffer( end, SOUND_22k, SOUND_22k );
|
||||
|
||||
// upsample 22khz buffer by 2x
|
||||
#if (SOUND_DMA_SPEED > SOUND_22k)
|
||||
S_MixUpsample( count / (SOUND_DMA_SPEED / SOUND_22k), FILTERTYPE_LINEAR );
|
||||
#endif
|
||||
// mix 44khz channels to buffer
|
||||
MIX_MixChannelsToPaintbuffer( end, SOUND_44k, SOUND_DMA_SPEED );
|
||||
|
||||
MIX_DeactivateAllPaintbuffers();
|
||||
|
||||
// restore previous paintbuffer
|
||||
MIX_SetCurrentPaintbuffer( ipaintcur );
|
||||
}
|
||||
|
||||
void MIX_MixStreamBuffer( int end )
|
||||
{
|
||||
portable_samplepair_t *pbuf;
|
||||
rawchan_t *ch;
|
||||
|
||||
pbuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
|
||||
ch = S_FindRawChannel( S_RAW_SOUND_BACKGROUNDTRACK, false );
|
||||
|
||||
// clear the paint buffer
|
||||
if( s_listener.paused || s_rawend < paintedtime )
|
||||
if( s_listener.paused || !ch || ch->s_rawend < paintedtime )
|
||||
{
|
||||
Q_memset( pbuf, 0, (end - paintedtime) * sizeof( portable_samplepair_t ));
|
||||
}
|
||||
|
@ -952,18 +904,54 @@ void MIX_MixStreamBuffer( int end )
|
|||
int i, stop;
|
||||
|
||||
// copy from the streaming sound source
|
||||
stop = (end < s_rawend) ? end : s_rawend;
|
||||
stop = (end < ch->s_rawend) ? end : ch->s_rawend;
|
||||
|
||||
for( i = paintedtime; i < stop; i++ )
|
||||
pbuf[i - paintedtime] = s_rawsamples[i & (MAX_RAW_SAMPLES - 1)];
|
||||
|
||||
{
|
||||
pbuf[i-paintedtime].left = ( ch->rawsamples[i & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
|
||||
pbuf[i-paintedtime].right = ( ch->rawsamples[i & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
|
||||
}
|
||||
|
||||
for( ; i < end; i++ )
|
||||
pbuf[i-paintedtime].left = pbuf[i-paintedtime].right = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MIX_MixRawSamplesBuffer( int end )
|
||||
{
|
||||
portable_samplepair_t *pbuf;
|
||||
uint i, j, stop;
|
||||
|
||||
pbuf = MIX_GetCurrentPaintbufferPtr()->pbuf;
|
||||
|
||||
if( s_listener.paused ) return;
|
||||
|
||||
// paint in the raw channels
|
||||
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
|
||||
{
|
||||
// copy from the streaming sound source
|
||||
rawchan_t *ch = raw_channels[i];
|
||||
|
||||
// background track should be mixing into another buffer
|
||||
if( !ch || ch->entnum == S_RAW_SOUND_BACKGROUNDTRACK )
|
||||
continue;
|
||||
|
||||
// not audible
|
||||
if( !ch->leftvol && !ch->rightvol )
|
||||
continue;
|
||||
|
||||
stop = (end < ch->s_rawend) ? end : ch->s_rawend;
|
||||
|
||||
for( j = paintedtime; j < stop; j++ )
|
||||
{
|
||||
pbuf[j-paintedtime].left += ( ch->rawsamples[j & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
|
||||
pbuf[j-paintedtime].right += ( ch->rawsamples[j & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// upsample and mix sounds into final 44khz versions of:
|
||||
// IROOMBUFFER, IFACINGBUFFER, IFACINGAWAY, IDRYBUFFER
|
||||
// IROOMBUFFER, IFACINGBUFFER, IFACINGAWAY
|
||||
// dsp fx are then applied to these buffers by the caller.
|
||||
// caller also remixes all into final IPAINTBUFFER output.
|
||||
void MIX_UpsampleAllPaintbuffers( int end, int count )
|
||||
|
@ -1000,14 +988,17 @@ void MIX_UpsampleAllPaintbuffers( int end, int count )
|
|||
MIX_MixChannelsToPaintbuffer( end, SOUND_22k, SOUND_22k );
|
||||
|
||||
// upsample all 22khz buffers by 2x
|
||||
#if (SOUND_DMA_SPEED > SOUND_22k)
|
||||
// only upsample roombuffer if dsp fx are on KDB: perf
|
||||
MIX_SetCurrentPaintbuffer( IROOMBUFFER );
|
||||
S_MixUpsample( count / ( SOUND_DMA_SPEED / SOUND_22k ), FILTERTYPE_LINEAR );
|
||||
#endif
|
||||
|
||||
// mix all 44khz sounds to all active paintbuffers
|
||||
MIX_MixChannelsToPaintbuffer( end, SOUND_44k, SOUND_DMA_SPEED );
|
||||
|
||||
// mix raw samples from the video streams
|
||||
MIX_SetCurrentPaintbuffer( IROOMBUFFER );
|
||||
MIX_MixRawSamplesBuffer( end );
|
||||
|
||||
MIX_DeactivateAllPaintbuffers();
|
||||
MIX_SetCurrentPaintbuffer( IPAINTBUFFER );
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ void SND_InitMouth( int entnum, int entchannel )
|
|||
if( clientEntity )
|
||||
{
|
||||
clientEntity->mouth.mouthopen = 0;
|
||||
clientEntity->mouth.sndavg = 0;
|
||||
clientEntity->mouth.sndcount = 0;
|
||||
clientEntity->mouth.sndavg = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count )
|
|||
cl_entity_t *clientEntity;
|
||||
char *pdata = NULL;
|
||||
mouth_t *pMouth = NULL;
|
||||
int savg, data;
|
||||
int scount, pos = 0;
|
||||
int savg, data;
|
||||
uint i;
|
||||
|
||||
clientEntity = CL_GetEntityByIndex( ch->entnum );
|
||||
|
|
|
@ -17,11 +17,14 @@ GNU General Public License for more details.
|
|||
#include "sound.h"
|
||||
#include "client.h"
|
||||
|
||||
portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
||||
static bg_track_t s_bgTrack;
|
||||
static musicfade_t musicfade; // controlled by game dlls
|
||||
int s_rawend;
|
||||
|
||||
/*
|
||||
=================
|
||||
S_PrintBackgroundTrackState
|
||||
=================
|
||||
*/
|
||||
void S_PrintBackgroundTrackState( void )
|
||||
{
|
||||
if( s_bgTrack.current[0] && s_bgTrack.loopName[0] )
|
||||
|
@ -32,18 +35,6 @@ void S_PrintBackgroundTrackState( void )
|
|||
Msg( "BackgroundTrack: %s [loop]\n", s_bgTrack.loopName );
|
||||
}
|
||||
|
||||
void S_CheckLerpingState( void )
|
||||
{
|
||||
wavdata_t *info;
|
||||
|
||||
s_listener.lerping = false;
|
||||
if( !s_bgTrack.stream ) return;
|
||||
info = FS_StreamInfo( s_bgTrack.stream );
|
||||
|
||||
if( info && ((float)info->rate / SOUND_DMA_SPEED ) >= 1.0f )
|
||||
s_listener.lerping = s_lerping->integer;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_FadeMusicVolume
|
||||
|
@ -68,6 +59,7 @@ float S_GetMusicVolume( void )
|
|||
scale = bound( 0.0f, musicfade.percent / 100.0f, 1.0f );
|
||||
scale = 1.0f - scale;
|
||||
}
|
||||
|
||||
return s_musicvolume->value * scale;
|
||||
}
|
||||
|
||||
|
@ -109,10 +101,13 @@ void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, long
|
|||
// restore message, update song position
|
||||
FS_SetStreamPos( s_bgTrack.stream, position );
|
||||
}
|
||||
|
||||
S_CheckLerpingState();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_StopBackgroundTrack
|
||||
=================
|
||||
*/
|
||||
void S_StopBackgroundTrack( void )
|
||||
{
|
||||
s_listener.stream_paused = false;
|
||||
|
@ -123,10 +118,13 @@ void S_StopBackgroundTrack( void )
|
|||
FS_FreeStream( s_bgTrack.stream );
|
||||
Q_memset( &s_bgTrack, 0, sizeof( bg_track_t ));
|
||||
Q_memset( &musicfade, 0, sizeof( musicfade ));
|
||||
s_listener.lerping = false;
|
||||
s_rawend = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_StreamSetPause
|
||||
=================
|
||||
*/
|
||||
void S_StreamSetPause( int pause )
|
||||
{
|
||||
s_listener.stream_paused = pause;
|
||||
|
@ -175,10 +173,10 @@ void S_StreamBackgroundTrack( void )
|
|||
int fileSamples;
|
||||
byte raw[MAX_RAW_SAMPLES];
|
||||
int r, fileBytes;
|
||||
rawchan_t *ch = NULL;
|
||||
|
||||
if( !dma.initialized ) return;
|
||||
if( !s_bgTrack.stream ) return;
|
||||
if( s_listener.streaming ) return; // we are playing movie or somewhat
|
||||
if( !dma.initialized || !s_bgTrack.stream || s_listener.streaming )
|
||||
return;
|
||||
|
||||
// don't bother playing anything if musicvolume is 0
|
||||
if( !s_musicvolume->value || s_listener.paused || s_listener.stream_paused )
|
||||
|
@ -193,15 +191,19 @@ void S_StreamBackgroundTrack( void )
|
|||
else if( cls.key_dest == key_console )
|
||||
return;
|
||||
|
||||
// see how many samples should be copied into the raw buffer
|
||||
if( s_rawend < soundtime )
|
||||
s_rawend = soundtime;
|
||||
ch = S_FindRawChannel( S_RAW_SOUND_BACKGROUNDTRACK, true );
|
||||
|
||||
while( s_rawend < soundtime + MAX_RAW_SAMPLES )
|
||||
ASSERT( ch != NULL );
|
||||
|
||||
// see how many samples should be copied into the raw buffer
|
||||
if( ch->s_rawend < soundtime )
|
||||
ch->s_rawend = soundtime;
|
||||
|
||||
while( ch->s_rawend < soundtime + ch->max_samples )
|
||||
{
|
||||
wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
|
||||
|
||||
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - soundtime);
|
||||
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
|
||||
|
||||
// decide how much data needs to be read from the file
|
||||
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
|
||||
|
@ -228,7 +230,7 @@ void S_StreamBackgroundTrack( void )
|
|||
if( r > 0 )
|
||||
{
|
||||
// add to raw buffer
|
||||
S_StreamRawSamples( fileSamples, info->rate, info->width, info->channels, raw );
|
||||
S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_BACKGROUNDTRACK );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -240,7 +242,6 @@ void S_StreamBackgroundTrack( void )
|
|||
Q_strncpy( s_bgTrack.current, s_bgTrack.loopName, sizeof( s_bgTrack.current ));
|
||||
|
||||
if( !s_bgTrack.stream ) return;
|
||||
S_CheckLerpingState();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -262,7 +263,6 @@ void S_StartStreaming( void )
|
|||
if( !dma.initialized ) return;
|
||||
// begin streaming movie soundtrack
|
||||
s_listener.streaming = true;
|
||||
s_listener.lerping = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -274,8 +274,6 @@ void S_StopStreaming( void )
|
|||
{
|
||||
if( !dma.initialized ) return;
|
||||
s_listener.streaming = false;
|
||||
s_listener.lerping = false;
|
||||
s_rawend = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -289,19 +287,24 @@ void S_StreamSoundTrack( void )
|
|||
int fileSamples;
|
||||
byte raw[MAX_RAW_SAMPLES];
|
||||
int r, fileBytes;
|
||||
rawchan_t *ch = NULL;
|
||||
|
||||
if( !dma.initialized ) return;
|
||||
if( !s_listener.streaming || s_listener.paused ) return;
|
||||
if( !dma.initialized || !s_listener.streaming || s_listener.paused )
|
||||
return;
|
||||
|
||||
ch = S_FindRawChannel( S_RAW_SOUND_SOUNDTRACK, true );
|
||||
|
||||
ASSERT( ch != NULL );
|
||||
|
||||
// see how many samples should be copied into the raw buffer
|
||||
if( s_rawend < soundtime )
|
||||
s_rawend = soundtime;
|
||||
if( ch->s_rawend < soundtime )
|
||||
ch->s_rawend = soundtime;
|
||||
|
||||
while( s_rawend < soundtime + MAX_RAW_SAMPLES )
|
||||
while( ch->s_rawend < soundtime + ch->max_samples )
|
||||
{
|
||||
wavdata_t *info = SCR_GetMovieInfo();
|
||||
|
||||
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - soundtime);
|
||||
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
|
||||
|
||||
// decide how much data needs to be read from the file
|
||||
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
|
||||
|
@ -328,68 +331,8 @@ void S_StreamSoundTrack( void )
|
|||
if( r > 0 )
|
||||
{
|
||||
// add to raw buffer
|
||||
S_StreamRawSamples( fileSamples, info->rate, info->width, info->channels, raw );
|
||||
S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_SOUNDTRACK );
|
||||
}
|
||||
else break; // no more samples for this frame
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
S_StreamRawSamples
|
||||
|
||||
Cinematic streaming and voice over network
|
||||
============
|
||||
*/
|
||||
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data )
|
||||
{
|
||||
int i, a, b, src, dst;
|
||||
int fracstep, samplefrac;
|
||||
int incount, outcount;
|
||||
|
||||
src = 0;
|
||||
samplefrac = 0;
|
||||
fracstep = (((double)rate) / (double)SOUND_DMA_SPEED) * 256.0;
|
||||
outcount = (double)samples * (double)SOUND_DMA_SPEED / (double)rate;
|
||||
incount = samples * channels;
|
||||
|
||||
#define TAKE_SAMPLE( s ) (sizeof(*in) == 1 ? (a = (in[src+(s)]-128)<<8,\
|
||||
b = (src < incount - channels) ? (in[src+channels+(s)]-128)<<8 : 128) : \
|
||||
(a = in[src+(s)],\
|
||||
b = (src < incount - channels) ? (in[src+channels+(s)]) : 0))
|
||||
|
||||
// NOTE: disable lerping for cinematic sountracks
|
||||
#define LERP_SAMPLE s_listener.lerping ? (((((b - a) * (samplefrac & 255)) >> 8) + a)) : a
|
||||
|
||||
#define RESAMPLE_RAW \
|
||||
if( channels == 2 ) { \
|
||||
for( i = 0; i < outcount; i++, samplefrac += fracstep, src = (samplefrac >> 8) << 1 ) { \
|
||||
dst = s_rawend++ & (MAX_RAW_SAMPLES - 1); \
|
||||
TAKE_SAMPLE(0); \
|
||||
s_rawsamples[dst].left = LERP_SAMPLE; \
|
||||
TAKE_SAMPLE(1); \
|
||||
s_rawsamples[dst].right = LERP_SAMPLE; \
|
||||
} \
|
||||
} else { \
|
||||
for( i = 0; i < outcount; i++, samplefrac += fracstep, src = (samplefrac >> 8) << 0 ) { \
|
||||
dst = s_rawend++ & (MAX_RAW_SAMPLES - 1); \
|
||||
TAKE_SAMPLE(0); \
|
||||
s_rawsamples[dst].left = LERP_SAMPLE; \
|
||||
s_rawsamples[dst].right = s_rawsamples[dst].left; \
|
||||
} \
|
||||
}
|
||||
|
||||
if( s_rawend < paintedtime )
|
||||
s_rawend = paintedtime;
|
||||
|
||||
if( width == 2 )
|
||||
{
|
||||
short *in = (short *)data;
|
||||
RESAMPLE_RAW
|
||||
}
|
||||
else
|
||||
{
|
||||
byte *in = (unsigned char *)data;
|
||||
RESAMPLE_RAW
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ float S_SimpleSpline( float value )
|
|||
float valueSquared = value * value;
|
||||
|
||||
// nice little ease-in, ease-out spline-like curve
|
||||
return (3 * valueSquared - 2 * valueSquared * value);
|
||||
return (3.0f * valueSquared - 2.0f * valueSquared * value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -25,12 +25,13 @@ extern byte *sndpool;
|
|||
#define SND_STOP_LOOPING (1<<10) // stop all looping sounds on the entity.
|
||||
|
||||
// sound engine rate defines
|
||||
#define SOUND_DMA_SPEED 44100 // hardware playback rate
|
||||
#define SOUND_11k 11025 // 11khz sample rate
|
||||
#define SOUND_16k 16000 // 16khz sample rate
|
||||
#define SOUND_22k 22050 // 22khz sample rate
|
||||
#define SOUND_32k 32000 // 32khz sample rate
|
||||
#define SOUND_44k 44100 // 44khz sample rate
|
||||
#define SOUND_DMA_SPEED 44100 // hardware playback rate
|
||||
#define SOUND_11k 11025 // 11khz sample rate
|
||||
#define SOUND_16k 16000 // 16khz sample rate
|
||||
#define SOUND_22k 22050 // 22khz sample rate
|
||||
#define SOUND_32k 32000 // 32khz sample rate
|
||||
#define SOUND_44k 44100 // 44khz sample rate
|
||||
#define DMA_MSEC_PER_SAMPLE ((float)(1000.0 / SOUND_DMA_SPEED))
|
||||
|
||||
#define SND_TRACE_UPDATE_MAX 2 // max of N channels may be checked for obscured source per frame
|
||||
#define SND_RADIUS_MAX 240.0f // max sound source radius
|
||||
|
@ -50,14 +51,14 @@ extern byte *sndpool;
|
|||
#define SND_GAIN_PLAYER_WEAPON_DB 2.0f // increase player weapon gain by N dB
|
||||
|
||||
// fixed point stuff for real-time resampling
|
||||
#define FIX_BITS 28
|
||||
#define FIX_SCALE (1 << FIX_BITS)
|
||||
#define FIX_MASK ((1 << FIX_BITS)-1)
|
||||
#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE))
|
||||
#define FIX(a) (((int)(a)) << FIX_BITS)
|
||||
#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS)
|
||||
#define FIX_FRACTION(a,b) (FIX(a)/(b))
|
||||
#define FIX_FRACPART(a) ((a) & FIX_MASK)
|
||||
#define FIX_BITS 28
|
||||
#define FIX_SCALE (1 << FIX_BITS)
|
||||
#define FIX_MASK ((1 << FIX_BITS)-1)
|
||||
#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE))
|
||||
#define FIX(a) (((int)(a)) << FIX_BITS)
|
||||
#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS)
|
||||
#define FIX_FRACTION(a,b) (FIX(a)/(b))
|
||||
#define FIX_FRACPART(a) ((a) & FIX_MASK)
|
||||
|
||||
#define SNDLVL_TO_DIST_MULT( sndlvl ) \
|
||||
( sndlvl ? ((pow( 10, s_refdb->value / 20 ) / pow( 10, (float)sndlvl / 20 )) / s_refdist->value ) : 0 )
|
||||
|
@ -66,26 +67,30 @@ extern byte *sndpool;
|
|||
(int)( dist_mult ? ( 20 * log10( pow( 10, s_refdb->value / 20 ) / (dist_mult * s_refdist->value ))) : 0 )
|
||||
|
||||
// NOTE: clipped sound at 32760 to avoid overload
|
||||
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
|
||||
#define SWAP( a, b, t ) {(t) = (a); (a) = (b); (b) = (t);}
|
||||
#define AVG( a, b ) (((a) + (b)) >> 1 )
|
||||
#define AVG4( a, b, c, d ) (((a) + (b) + (c) + (d)) >> 2 )
|
||||
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
|
||||
#define SWAP( a, b, t ) {(t) = (a); (a) = (b); (b) = (t);}
|
||||
#define AVG( a, b ) (((a) + (b)) >> 1 )
|
||||
#define AVG4( a, b, c, d ) (((a) + (b) + (c) + (d)) >> 2 )
|
||||
|
||||
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
|
||||
#define PAINTBUFFER (g_curpaintbuffer)
|
||||
#define CPAINTBUFFERS 3
|
||||
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
|
||||
#define PAINTBUFFER (g_curpaintbuffer)
|
||||
#define CPAINTBUFFERS 3
|
||||
|
||||
// sound mixing buffer
|
||||
#define CPAINTFILTERMEM 3
|
||||
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
|
||||
|
||||
#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
|
||||
#define S_RAW_SOUND_BACKGROUNDTRACK -2
|
||||
#define S_RAW_SOUND_SOUNDTRACK -1
|
||||
#define S_RAW_SAMPLES_PRECISION_BITS 14
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int left;
|
||||
int right;
|
||||
int left;
|
||||
int right;
|
||||
} portable_samplepair_t;
|
||||
|
||||
// sound mixing buffer
|
||||
|
||||
#define CPAINTFILTERMEM 3
|
||||
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qboolean factive; // if true, mix to this paintbuffer using flags
|
||||
|
@ -104,7 +109,6 @@ typedef struct sfx_s
|
|||
struct sfx_s *hashNext;
|
||||
} sfx_t;
|
||||
|
||||
extern portable_samplepair_t drybuffer[];
|
||||
extern portable_samplepair_t paintbuffer[];
|
||||
extern portable_samplepair_t roombuffer[];
|
||||
extern portable_samplepair_t temppaintbuffer[];
|
||||
|
@ -146,6 +150,20 @@ typedef struct
|
|||
qboolean finished;
|
||||
} mixer_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int entnum;
|
||||
int master_vol;
|
||||
int leftvol; // 0-255 left volume
|
||||
int rightvol; // 0-255 right volume
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
float radius; // radius of this sound effect
|
||||
volatile uint s_rawend;
|
||||
size_t max_samples; // buffer length
|
||||
portable_samplepair_t rawsamples[1]; // variable sized
|
||||
} rawchan_t;
|
||||
|
||||
typedef struct channel_s
|
||||
{
|
||||
char name[16]; // keept sentence name
|
||||
|
@ -196,7 +214,6 @@ typedef struct
|
|||
qboolean inmenu; // listener in-menu ?
|
||||
qboolean paused;
|
||||
qboolean streaming; // playing AVI-file
|
||||
qboolean lerping; // lerp stream ?
|
||||
qboolean stream_paused; // pause only background track
|
||||
} listener_t;
|
||||
|
||||
|
@ -226,18 +243,19 @@ void SNDDMA_Submit( void );
|
|||
|
||||
#define MAX_DYNAMIC_CHANNELS (28 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (128 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
||||
#define MAX_RAW_CHANNELS 16
|
||||
#define MAX_RAW_SAMPLES 8192
|
||||
|
||||
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
||||
extern qboolean snd_ambient;
|
||||
extern channel_t channels[MAX_CHANNELS];
|
||||
extern rawchan_t *raw_channels[MAX_RAW_CHANNELS];
|
||||
extern int total_channels;
|
||||
extern int paintedtime;
|
||||
extern int s_rawend;
|
||||
extern int soundtime;
|
||||
extern dma_t dma;
|
||||
extern listener_t s_listener;
|
||||
extern int idsp_room;
|
||||
extern dma_t dma;
|
||||
|
||||
extern convar_t *s_volume;
|
||||
extern convar_t *s_musicvolume;
|
||||
|
@ -245,10 +263,7 @@ extern convar_t *s_show;
|
|||
extern convar_t *s_mixahead;
|
||||
extern convar_t *s_lerping;
|
||||
extern convar_t *dsp_off;
|
||||
extern convar_t *s_test;
|
||||
extern convar_t *s_phs;
|
||||
|
||||
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
||||
extern convar_t *s_test; // cvar to testify new effects
|
||||
|
||||
void S_InitScaletable( void );
|
||||
wavdata_t *S_LoadSound( sfx_t *sfx );
|
||||
|
@ -296,7 +311,11 @@ channel_t *SND_PickStaticChannel( int entnum, sfx_t *sfx, const vec3_t pos );
|
|||
int S_GetCurrentStaticSounds( soundlist_t *pout, int size );
|
||||
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size );
|
||||
sfx_t *S_GetSfxByHandle( sound_t handle );
|
||||
rawchan_t *S_FindRawChannel( int entnum, qboolean create );
|
||||
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum );
|
||||
void S_StopSound( int entnum, int channel, const char *soundname );
|
||||
uint S_GetRawSamplesLength( int entnum );
|
||||
void S_ClearRawChannel( int entnum );
|
||||
void S_StopAllSounds( void );
|
||||
void S_FreeSounds( void );
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ public:
|
|||
virtual void setTitle( const char *title ) { }
|
||||
virtual void createPopup( Panel* embeddedPanel ) { }
|
||||
virtual bool isWithin( int x, int y ) { return true; }
|
||||
virtual void GetMousePos( int &x, int &y );
|
||||
virtual bool hasFocus( void );
|
||||
protected:
|
||||
virtual int createNewTextureID( void );
|
||||
|
@ -158,6 +159,7 @@ protected:
|
|||
int _drawTextPos[2];
|
||||
int _drawColor[4];
|
||||
int _drawTextColor[4];
|
||||
bool _allowSetTextPos;
|
||||
friend class App;
|
||||
friend class Panel;
|
||||
};
|
||||
|
|
|
@ -56,6 +56,17 @@ void CEngineSurface :: setCursor( Cursor *cursor )
|
|||
VGUI_CursorSelect( cursor );
|
||||
}
|
||||
|
||||
void CEngineSurface :: GetMousePos( int &x, int &y )
|
||||
{
|
||||
POINT curpos;
|
||||
|
||||
GetCursorPos( &curpos );
|
||||
ScreenToClient( host.hWnd, &curpos );
|
||||
|
||||
x = curpos.x;
|
||||
y = curpos.y;
|
||||
}
|
||||
|
||||
void CEngineSurface :: SetupPaintState( const paintState_t &paintState )
|
||||
{
|
||||
_translateX = paintState.iTranslateX;
|
||||
|
|
|
@ -20,6 +20,25 @@ GNU General Public License for more details.
|
|||
#include "client.h"
|
||||
#include "library.h"
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_IsSingleChar
|
||||
|
||||
interpert this character as single
|
||||
==============
|
||||
*/
|
||||
|
||||
qboolean COM_IsSingleChar( char c )
|
||||
{
|
||||
if( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',' )
|
||||
return true;
|
||||
|
||||
if( host.com_handlecolon && c == ':' )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_ParseFile
|
||||
|
@ -74,7 +93,7 @@ skipwhite:
|
|||
}
|
||||
|
||||
// parse single characters
|
||||
if( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',' )
|
||||
if( COM_IsSingleChar( c ))
|
||||
{
|
||||
token[len] = c;
|
||||
len++;
|
||||
|
@ -90,7 +109,7 @@ skipwhite:
|
|||
len++;
|
||||
c = ((byte)*data);
|
||||
|
||||
if( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',' )
|
||||
if( COM_IsSingleChar( c ))
|
||||
break;
|
||||
} while( c > 32 );
|
||||
|
||||
|
|
|
@ -325,6 +325,7 @@ typedef struct host_parm_s
|
|||
qboolean key_overstrike; // key overstrike mode
|
||||
qboolean stuffcmdsrun; // execute stuff commands
|
||||
qboolean con_showalways; // show console always (developer and dedicated)
|
||||
qboolean com_handlecolon; // allow COM_ParseFile to handle colon as single char
|
||||
qboolean change_game; // initialize when game is changed
|
||||
qboolean mouse_visible; // vgui override cursor control
|
||||
qboolean input_enabled; // vgui override mouse & keyboard input
|
||||
|
|
|
@ -693,18 +693,26 @@ void SV_BuildNetAnswer( netadr_t from )
|
|||
type = Q_atoi( Cmd_Argv( 3 ));
|
||||
|
||||
if( version != PROTOCOL_VERSION )
|
||||
return;
|
||||
{
|
||||
// handle the unsupported protocol
|
||||
string[0] = '\0';
|
||||
Info_SetValueForKey( string, "neterror", "protocol" );
|
||||
|
||||
// send error unsupported protocol
|
||||
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, string );
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
|
||||
return;
|
||||
}
|
||||
if( type == NETAPI_REQUEST_PING )
|
||||
{
|
||||
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i\n", context, type );
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer ); // no info string
|
||||
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, "" );
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
|
||||
}
|
||||
else if( type == NETAPI_REQUEST_RULES )
|
||||
{
|
||||
// send serverinfo
|
||||
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, Cvar_Serverinfo( ));
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer ); // no info string
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
|
||||
}
|
||||
else if( type == NETAPI_REQUEST_PLAYERS )
|
||||
{
|
||||
|
@ -723,7 +731,7 @@ void SV_BuildNetAnswer( netadr_t from )
|
|||
|
||||
// send playernames
|
||||
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, string );
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer ); // no info string
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
|
||||
}
|
||||
else if( type == NETAPI_REQUEST_DETAILS )
|
||||
{
|
||||
|
@ -740,7 +748,16 @@ void SV_BuildNetAnswer( netadr_t from )
|
|||
|
||||
// send serverinfo
|
||||
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, string );
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer ); // no info string
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
|
||||
}
|
||||
else
|
||||
{
|
||||
string[0] = '\0';
|
||||
Info_SetValueForKey( string, "neterror", "undefined" );
|
||||
|
||||
// send error undefined request type
|
||||
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, string );
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,8 @@
|
|||
#ifdef _WIN32
|
||||
# define VGUIAPI __declspec( dllexport )
|
||||
#else
|
||||
# define VGUIAPI
|
||||
# define VGUIAPI __attribute__ ((visibility("default")))
|
||||
#include <sys/types.h> // size_t define
|
||||
#endif
|
||||
|
||||
#define null 0L
|
||||
|
@ -93,7 +94,7 @@ typedef unsigned long ulong;
|
|||
namespace vgui
|
||||
{
|
||||
|
||||
VGUIAPI void vgui_setMalloc(void* (*malloc)(size_t size));
|
||||
VGUIAPI void vgui_setMalloc(void *(*malloc)(size_t size) );
|
||||
VGUIAPI void vgui_setFree(void (*free)(void* memblock));
|
||||
VGUIAPI void vgui_strcpy(char* dst,int dstLen,const char* src);
|
||||
VGUIAPI char* vgui_strdup(const char* src);
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
namespace vgui
|
||||
{
|
||||
|
||||
enum MouseCode;
|
||||
enum KeyCode;
|
||||
class Panel;
|
||||
class TickSignal;
|
||||
class Scheme;
|
||||
|
@ -117,7 +115,7 @@ protected:
|
|||
bool _buildMode;
|
||||
bool _wantedBuildMode;
|
||||
Panel* _mouseArenaPanel;
|
||||
Cursor* _cursor[Cursor::DefaultCursor::dc_last];
|
||||
Cursor* _cursor[Cursor::dc_last];
|
||||
Cursor* _cursorOveride;
|
||||
private:
|
||||
long _nextTickMillis;
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
#include<VGUI.h>
|
||||
#include<VGUI_Dar.h>
|
||||
|
||||
#include <VGUI_MouseCode.h>
|
||||
#include <VGUI_KeyCode.h>
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
|
|
|
@ -166,6 +166,7 @@ protected:
|
|||
ELEMTYPE* _data;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
//forward referencing all the template types used so they get exported
|
||||
template class VGUIAPI Dar<char>;
|
||||
template class VGUIAPI Dar<char*>;
|
||||
|
@ -185,7 +186,7 @@ template class VGUIAPI Dar<class ChangeSignal*>;
|
|||
template class VGUIAPI Dar<class Panel*>;
|
||||
template class VGUIAPI Dar<class Label*>;
|
||||
template class VGUIAPI Dar<class RepaintSignal*>;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ class VGUIAPI Font
|
|||
virtual void getCharABCwide(int ch,int& a,int& b,int& c);
|
||||
virtual void getTextSize(const char* text,int& wide,int& tall);
|
||||
virtual int getTall();
|
||||
#ifndef _WIN32
|
||||
virtual int getWide();
|
||||
#endif
|
||||
virtual int getId();
|
||||
protected:
|
||||
char* _name;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include<VGUI.h>
|
||||
#include<VGUI_Panel.h>
|
||||
#include<VGUI_Scheme.h>
|
||||
#include<VGUI_Image.h>
|
||||
|
||||
//TODO: this should use a TextImage for the text
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@ TODO:
|
|||
#include<VGUI_Dar.h>
|
||||
#include<VGUI_Scheme.h>
|
||||
#include<VGUI_Color.h>
|
||||
#include<VGUI_Cursor.h>
|
||||
#include <VGUI_MouseCode.h>
|
||||
#include <VGUI_KeyCode.h>
|
||||
#include <VGUI_RepaintSignal.h>
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VGUI_Point_H
|
||||
#define VGUI_Point_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <VGUI.h>
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Basic handler for a Points in 2 dimensions
|
||||
// This class is fully inline
|
||||
//-----------------------------------------------------------------------------
|
||||
class Point
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
Point()
|
||||
{
|
||||
SetPoint(0, 0);
|
||||
}
|
||||
Point(int x,int y)
|
||||
{
|
||||
SetPoint(x,y);
|
||||
}
|
||||
|
||||
void SetPoint(int x1, int y1)
|
||||
{
|
||||
x=x1;
|
||||
y=y1;
|
||||
}
|
||||
|
||||
void GetPoint(int& x1,int& y1) const
|
||||
{
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
|
||||
}
|
||||
|
||||
bool operator == (Point &rhs) const
|
||||
{
|
||||
return ( x == rhs.x && y==rhs.y);
|
||||
}
|
||||
|
||||
private:
|
||||
int x,y;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // VGUI_Point_H
|
||||
|
||||
|
||||
|
||||
//## <b>class Point</b>
|
||||
//## Point is a class to handle Points in VGUI.
|
||||
|
||||
//## // The default Point is (0,0,0,0)
|
||||
//## Point()
|
||||
//##
|
||||
//## // A Point may be created with x,yvalues.
|
||||
//## Point(int x,int y)
|
||||
//##
|
||||
//## // Set the x,y components of the Point.
|
||||
//## void SetPoint(int x1, int y1)
|
||||
//##
|
||||
//## // Get the position of the Point
|
||||
//## void GetPoint(int& x1,int& y1) const
|
||||
//##
|
||||
//## // Point classes can be set equal to each other.
|
||||
//## bool operator == (Point &rhs) const
|
||||
//##
|
||||
//##
|
||||
//## <hr>
|
||||
//##
|
||||
//##
|
||||
//## <method>Point()
|
||||
//## Description: Default constructor. The default Point is (0,0,0,0)
|
||||
//##
|
||||
//##
|
||||
//## <method>Point(int x,int y)
|
||||
//## Description:
|
||||
//## A Point may be created with a x,y position.
|
||||
//## Arguments:
|
||||
//## x - x position (horizontal axis) (0-65535)
|
||||
//## y - y position (vertical axis) (0-65535)
|
||||
//##
|
||||
//##
|
||||
//## <method>void SetPoint(int x1, int x1)
|
||||
//## Description:
|
||||
//## Set the position of the Point.
|
||||
//## Arguments:
|
||||
//## x - x position (horizontal axis) (0-65535)
|
||||
//## y - y position (vertical axis) (0-65535)
|
||||
//##
|
||||
//##
|
||||
//## <method>void GetPoint(int& x1,int& y1) const
|
||||
//## Description:
|
||||
//## Get the x,y components of a Point
|
||||
//## Arguments:
|
||||
//## x - x position (horizontal axis) (0-65535)
|
||||
//## y - y position (vertical axis) (0-65535)
|
||||
//##
|
||||
//## <method>bool operator == (Point &rhs) const
|
||||
//## Description:
|
||||
//## Point classes can be set equal to each other.
|
||||
//##
|
||||
//##
|
|
@ -12,7 +12,8 @@
|
|||
|
||||
namespace vgui
|
||||
{
|
||||
|
||||
class Panel;
|
||||
|
||||
class RepaintSignal
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
virtual void createPopup(Panel* embeddedPanel);
|
||||
virtual bool hasFocus();
|
||||
virtual bool isWithin(int x,int y);
|
||||
virtual void GetMousePos( int &x, int &y );
|
||||
protected:
|
||||
virtual int createNewTextureID(void);
|
||||
virtual void drawSetColor(int r,int g,int b,int a);
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
virtual bool hasFocus()=0;
|
||||
virtual bool isWithin(int x,int y)=0;
|
||||
virtual int createNewTextureID(void)=0;
|
||||
virtual void GetMousePos( int &x, int &y ) = 0;
|
||||
protected:
|
||||
virtual void addModeInfo(int wide,int tall,int bpp);
|
||||
protected:
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include<VGUI_Panel.h>
|
||||
#include<VGUI_Dar.h>
|
||||
#include<VGUI_Button.h>
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
|
|
Binary file not shown.
Reference in New Issue