25 Apr 2010
This commit is contained in:
parent
e95dfb116b
commit
dac4b9eec0
|
@ -942,11 +942,11 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
|
|||
to->skin = pNet->pev->skin; // studio model skin
|
||||
to->body = pNet->pev->body; // studio model submodel
|
||||
to->effects = pNet->pev->effects; // shared client and render flags
|
||||
to->soundindex = pNet->pev->soundindex; // soundindex
|
||||
to->renderfx = pNet->pev->renderfx; // renderer flags
|
||||
to->rendermode = pNet->pev->rendermode; // rendering mode
|
||||
to->renderamt = pNet->pev->renderamt; // alpha value
|
||||
to->animtime = (int)(1000.0 * pNet->pev->animtime) * 0.001; // sequence time
|
||||
to->localtime = (int)(1000.0 * pNet->pev->ltime) * 0.001; // movement time
|
||||
to->scale = pNet->pev->scale; // shared client and render flags
|
||||
to->movetype = (movetype_t)pNet->pev->movetype;
|
||||
to->frame = pNet->pev->frame; // any model current frame
|
||||
|
@ -1019,16 +1019,7 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
|
|||
}
|
||||
else if( to->ed_type == ED_AMBIENT )
|
||||
{
|
||||
to->soundindex = pNet->pev->soundindex;
|
||||
|
||||
if( pNet->pev->solid == SOLID_TRIGGER )
|
||||
{
|
||||
Vector midPoint;
|
||||
|
||||
// NOTE: no reason to compute this shit on the client - save bandwidth
|
||||
midPoint = pNet->pev->mins + pNet->pev->maxs * 0.5f;
|
||||
to->origin += midPoint;
|
||||
}
|
||||
// add here specified fiels e.g for trigger_teleport wind sound etc
|
||||
}
|
||||
else if( to->ed_type == ED_MOVER || to->ed_type == ED_BSPBRUSH || to->ed_type == ED_PORTAL )
|
||||
{
|
||||
|
|
|
@ -267,8 +267,6 @@ TYPEDESCRIPTION gEntvarsDescription[] =
|
|||
DEFINE_ENTITY_FIELD( modelindex, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( model, FIELD_MODELNAME ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( soundindex, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( viewmodel, FIELD_MODELNAME ),
|
||||
DEFINE_ENTITY_FIELD( weaponmodel, FIELD_MODELNAME ),
|
||||
|
||||
|
|
|
@ -224,6 +224,7 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
|
|||
ent->v.flags = state->flags;
|
||||
ent->v.ideal_pitch = state->idealpitch;
|
||||
ent->v.animtime = state->animtime;
|
||||
ent->v.ltime = state->localtime;
|
||||
|
||||
if( state->groundent != -1 )
|
||||
ent->v.groundentity = GetEntityByIndex( state->groundent );
|
||||
|
|
|
@ -41,7 +41,6 @@ typedef struct entvars_s
|
|||
float yaw_speed;
|
||||
|
||||
int modelindex; // ENG [all], NET [all]
|
||||
int soundindex; // ENG [all], NET [all]
|
||||
|
||||
string_t model; // model name
|
||||
string_t viewmodel; // player's viewmodel (no network updates)
|
||||
|
|
|
@ -39,7 +39,6 @@ typedef struct entity_state_s
|
|||
uint number; // edict index
|
||||
edtype_t ed_type; // edict type
|
||||
string_t classname; // edict classname
|
||||
int soundindex; // looped ambient sound
|
||||
int ed_flags; // engine clearing this at end of server frame
|
||||
|
||||
// physics information
|
||||
|
@ -65,6 +64,7 @@ typedef struct entity_state_s
|
|||
float frame; // % playback position in animation sequences (0..255)
|
||||
int skin; // skin for studiomodels
|
||||
int body; // sub-model selection for studiomodels
|
||||
float localtime; // pev->ltime for monsters for right lerping on platforms, trains etc
|
||||
float animtime; // auto-animating time
|
||||
float framerate; // custom framerate, specified by QC
|
||||
int sequence; // animation sequence (0 - 255)
|
||||
|
|
|
@ -93,7 +93,7 @@ void CL_WriteDemoHeader( const char *name )
|
|||
for( i = 0; i < clgame.globals->maxEntities; i++ )
|
||||
{
|
||||
state = &clgame.baselines[i];
|
||||
if( !state->modelindex && !state->soundindex && !state->effects )
|
||||
if( !state->modelindex && !state->effects )
|
||||
continue;
|
||||
|
||||
MSG_WriteByte( &buf, svc_spawnbaseline );
|
||||
|
|
|
@ -1943,7 +1943,7 @@ pfnStopSound
|
|||
*/
|
||||
void pfnStopSound( int ent, int channel, const char *sample )
|
||||
{
|
||||
S_StartSound( vec3_origin, ent, channel, S_RegisterSound( sample ), 0, 0, PITCH_NORM, SND_STOP );
|
||||
S_StopSound( ent, channel, sample );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1999,7 +1999,7 @@ pfnStopAllSounds
|
|||
void pfnStopAllSounds( edict_t *ent, int entchannel )
|
||||
{
|
||||
if( !CL_IsValidEdict( ent )) return;
|
||||
S_StopSound( ent->serialnumber, entchannel );
|
||||
S_StopSound( ent->serialnumber, entchannel, NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -29,6 +29,7 @@ char *svc_strings[256] =
|
|||
"svc_packetentities",
|
||||
"svc_frame",
|
||||
"svc_sound",
|
||||
"svc_ambientsound",
|
||||
"svc_setangle",
|
||||
"svc_addangle",
|
||||
"svc_setview",
|
||||
|
@ -324,28 +325,25 @@ CL_ParseSoundPacket
|
|||
|
||||
==================
|
||||
*/
|
||||
void CL_ParseSoundPacket( sizebuf_t *msg )
|
||||
void CL_ParseSoundPacket( sizebuf_t *msg, bool is_ambient )
|
||||
{
|
||||
vec3_t pos_;
|
||||
float *pos = NULL;
|
||||
int channel, sound_num;
|
||||
float volume, attenuation;
|
||||
int chan, sound;
|
||||
float volume, attn;
|
||||
int flags, pitch, entnum;
|
||||
|
||||
flags = MSG_ReadWord( msg );
|
||||
sound_num = MSG_ReadWord( msg );
|
||||
channel = MSG_ReadByte( msg );
|
||||
sound = MSG_ReadWord( msg );
|
||||
chan = MSG_ReadByte( msg );
|
||||
|
||||
if( flags & SND_VOLUME )
|
||||
volume = MSG_ReadByte( msg ) / 255.0f;
|
||||
else volume = VOL_NORM;
|
||||
|
||||
if( flags & SND_SOUNDLEVEL )
|
||||
{
|
||||
int soundlevel = MSG_ReadByte( msg );
|
||||
attenuation = SNDLVL_TO_ATTN( soundlevel );
|
||||
}
|
||||
else attenuation = ATTN_NONE;
|
||||
if( flags & SND_ATTENUATION )
|
||||
attn = MSG_ReadByte( msg ) / 64.0f;
|
||||
else attn = ATTN_NONE;
|
||||
|
||||
if( flags & SND_PITCH )
|
||||
pitch = MSG_ReadByte( msg );
|
||||
|
@ -361,7 +359,14 @@ void CL_ParseSoundPacket( sizebuf_t *msg )
|
|||
MSG_ReadPos( msg, pos );
|
||||
}
|
||||
|
||||
S_StartSound( pos, entnum, channel, cl.sound_precache[sound_num], volume, attenuation, pitch, flags );
|
||||
if( is_ambient )
|
||||
{
|
||||
S_AmbientSound( pos, entnum, chan, cl.sound_precache[sound], volume, attn, pitch, flags );
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound( pos, entnum, chan, cl.sound_precache[sound], volume, attn, pitch, flags );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -815,7 +820,10 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
|||
CL_ParseDownload( msg );
|
||||
break;
|
||||
case svc_sound:
|
||||
CL_ParseSoundPacket( msg );
|
||||
CL_ParseSoundPacket( msg, false );
|
||||
break;
|
||||
case svc_ambientsound:
|
||||
CL_ParseSoundPacket( msg, true );
|
||||
break;
|
||||
case svc_setangle:
|
||||
CL_ParseSetAngle( msg );
|
||||
|
|
|
@ -221,7 +221,6 @@ void Tri_DrawTriangles( int fTrans );
|
|||
int CL_PointContents( const vec3_t point );
|
||||
void CL_StudioFxTransform( edict_t *ent, float transform[4][4] );
|
||||
bool CL_GetEntitySpatialization( int entnum, soundinfo_t *info );
|
||||
void CL_GetEntitySoundSpatialization( int ent, vec3_t origin, vec3_t velocity );
|
||||
bool CL_GetAttachment( int entityIndex, int number, vec3_t origin, vec3_t angles );
|
||||
bool CL_SetAttachment( int entityIndex, int number, vec3_t origin, vec3_t angles );
|
||||
void CL_StudioEvent( dstudioevent_t *event, edict_t *ent );
|
||||
|
|
|
@ -200,6 +200,7 @@ _inline bool CM_BoxVisible( const vec3_t mins, const vec3_t maxs )
|
|||
#define S_Shutdown if( se ) se->Shutdown
|
||||
#define S_StartStreaming if( se ) se->StartStreaming
|
||||
#define S_StartSound if( se ) se->StartSound
|
||||
#define S_AmbientSound if( se ) se->StaticSound
|
||||
#define S_StartLocalSound if( se ) se->StartLocalSound
|
||||
#define S_StartBackgroundTrack if( se ) se->StartBackgroundTrack
|
||||
#define S_StopBackgroundTrack if( se ) se->StopBackgroundTrack
|
||||
|
|
|
@ -18,7 +18,6 @@ static net_field_t ent_fields[] =
|
|||
{ ES_FIELD(ed_type), NET_BYTE, true }, // stateflags_t #0 (4 bytes)
|
||||
{ ES_FIELD(ed_flags), NET_BYTE, false }, // stateflags_t #0 (4 bytes)
|
||||
{ ES_FIELD(classname), NET_WORD, true },
|
||||
{ ES_FIELD(soundindex), NET_WORD, false }, // 512 sounds ( OpenAL software limit is 255 )
|
||||
{ ES_FIELD(angles[0]), NET_FLOAT, false },
|
||||
{ ES_FIELD(angles[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(angles[2]), NET_FLOAT, false },
|
||||
|
|
|
@ -65,6 +65,7 @@ enum svc_ops_e
|
|||
svc_packetentities, // [...]
|
||||
svc_frame, // server frame
|
||||
svc_sound, // <see code>
|
||||
svc_ambientsound, // <see code>
|
||||
svc_setangle, // [short short short] set the view angle to this absolute value
|
||||
svc_addangle, // [short short] add angles when client turn on mover
|
||||
svc_setview, // [short] entity number
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#define SND_SENTENCE (1<<7) // set if sound num is actually a sentence num
|
||||
#define SND_VOLUME (1<<8) // a scaled byte
|
||||
#define SND_SOUNDLEVEL (1<<9) // a byte
|
||||
#define SND_ATTENUATION (1<<9) // a byte
|
||||
#define SND_PITCH (1<<10) // a byte
|
||||
#define SND_FIXED_ORIGIN (1<<11) // a vector
|
||||
|
||||
|
|
|
@ -71,8 +71,6 @@ bool Host_NewGame( const char *mapName, bool loadGame )
|
|||
{
|
||||
bool iRet;
|
||||
|
||||
S_StopAllSounds ();
|
||||
|
||||
iRet = SV_NewGame( mapName, loadGame );
|
||||
|
||||
return iRet;
|
||||
|
@ -224,7 +222,6 @@ bool Host_InitSound( void )
|
|||
|
||||
// sound callbacks
|
||||
si.GetEntitySpatialization = CL_GetEntitySpatialization;
|
||||
si.GetSoundSpatialization = CL_GetEntitySoundSpatialization;
|
||||
si.TraceLine = CL_TraceLine;
|
||||
si.PointContents = CL_PointContents;
|
||||
si.GetClientEdict = CL_GetEdictByIndex;
|
||||
|
|
|
@ -345,7 +345,6 @@ float SV_VecToYaw( const vec3_t src );
|
|||
// sv_send.c
|
||||
//
|
||||
void SV_SendClientMessages( void );
|
||||
void SV_AmbientSound( edict_t *entity, int soundindex, float volume, float attenuation );
|
||||
void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... );
|
||||
void SV_BroadcastPrintf( int level, char *fmt, ... );
|
||||
void SV_BroadcastCommand( char *fmt, ... );
|
||||
|
|
|
@ -856,7 +856,7 @@ void SV_Baselines_f( sv_client_t *cl )
|
|||
while( cl->netchan.message.cursize < MAX_MSGLEN / 2 && start < GI->max_edicts )
|
||||
{
|
||||
base = &svs.baselines[start];
|
||||
if( base->modelindex || base->soundindex || base->effects )
|
||||
if( base->modelindex || base->effects )
|
||||
{
|
||||
MSG_WriteByte( &cl->netchan.message, svc_spawnbaseline );
|
||||
MSG_WriteDeltaEntity( &nullstate, base, &cl->netchan.message, true, true );
|
||||
|
|
|
@ -596,14 +596,14 @@ void SV_BaselineForEntity( const edict_t *pEdict )
|
|||
|
||||
base = &sv_ent->s;
|
||||
|
||||
if( pEdict->v.modelindex || base->soundindex || pEdict->v.effects )
|
||||
if( pEdict->v.modelindex || pEdict->v.effects )
|
||||
{
|
||||
// take current state as baseline
|
||||
SV_UpdateEntityState( pEdict, true );
|
||||
svs.baselines[pEdict->serialnumber] = *base;
|
||||
}
|
||||
|
||||
if( sv.state == ss_active && ( base->modelindex || base->soundindex || base->effects ))
|
||||
if( sv.state == ss_active && ( base->modelindex || base->effects ))
|
||||
{
|
||||
entity_state_t nullstate;
|
||||
|
||||
|
@ -1420,7 +1420,7 @@ SV_StartSound
|
|||
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch )
|
||||
{
|
||||
int sound_idx;
|
||||
int msg_dest = MSG_PAS_R;
|
||||
int msg_dest;
|
||||
vec3_t origin;
|
||||
|
||||
if( attn < ATTN_NONE || attn > ATTN_IDLE )
|
||||
|
@ -1443,7 +1443,7 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
|
|||
|
||||
if( sv.state == ss_loading ) flags |= SND_SPAWNING;
|
||||
if( vol != VOL_NORM ) flags |= SND_VOLUME;
|
||||
if( attn != ATTN_NONE ) flags |= SND_SOUNDLEVEL;
|
||||
if( attn != ATTN_NONE ) flags |= SND_ATTENUATION;
|
||||
if( pitch != PITCH_NORM ) flags |= SND_PITCH;
|
||||
|
||||
// ultimate method for detect bsp models with invalid solidity (e.g. func_pushable)
|
||||
|
@ -1478,7 +1478,7 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
|
|||
MSG_WriteByte( &sv.multicast, chan );
|
||||
|
||||
if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol * 255 );
|
||||
if ( flags & SND_SOUNDLEVEL ) MSG_WriteByte( &sv.multicast, ATTN_TO_SNDLVL( attn ));
|
||||
if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 );
|
||||
if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
|
||||
|
||||
// plays from aiment
|
||||
|
@ -1515,7 +1515,7 @@ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *samp, float vol,
|
|||
|
||||
if( sv.state == ss_loading ) flags |= SND_SPAWNING;
|
||||
if( vol != VOL_NORM ) flags |= SND_VOLUME;
|
||||
if( attn != ATTN_NONE ) flags |= SND_SOUNDLEVEL;
|
||||
if( attn != ATTN_NONE ) flags |= SND_ATTENUATION;
|
||||
if( pitch != PITCH_NORM ) flags |= SND_PITCH;
|
||||
|
||||
if( flags & SND_SPAWNING )
|
||||
|
@ -1549,13 +1549,13 @@ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *samp, float vol,
|
|||
// and return sound index when server is active
|
||||
sound_idx = SV_SoundIndex( samp );
|
||||
|
||||
MSG_Begin( svc_sound );
|
||||
MSG_Begin( svc_ambientsound );
|
||||
MSG_WriteWord( &sv.multicast, flags );
|
||||
MSG_WriteWord( &sv.multicast, sound_idx );
|
||||
MSG_WriteByte( &sv.multicast, CHAN_AUTO );
|
||||
|
||||
if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol * 255 );
|
||||
if ( flags & SND_SOUNDLEVEL ) MSG_WriteByte( &sv.multicast, ATTN_TO_SNDLVL( attn ));
|
||||
if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 );
|
||||
if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
|
||||
|
||||
// plays from fixed position
|
||||
|
|
|
@ -528,6 +528,13 @@ void SV_ForceError( void )
|
|||
|
||||
bool SV_NewGame( const char *mapName, bool loadGame )
|
||||
{
|
||||
if( !loadGame )
|
||||
{
|
||||
if( !SV_MapIsValid( mapName, GI->sp_entity, NULL ))
|
||||
return false;
|
||||
}
|
||||
|
||||
S_StopAllSounds ();
|
||||
SV_InactivateClients ();
|
||||
SV_DeactivateServer ();
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ static void UI_Main_HazardCourse( void )
|
|||
Cvar_SetValue( "pausable", 1.0f ); // singleplayer is always allowing pause
|
||||
Cvar_SetValue( "coop", 0.0f );
|
||||
|
||||
Cbuf_ExecuteText( EXEC_APPEND, va( "loading; killserver; wait; map %s\n", GI->trainmap ));
|
||||
Host_NewGame( GI->trainmap, false );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -76,7 +76,7 @@ static void UI_NewGame_StartGame( float skill )
|
|||
Cvar_SetValue( "pausable", 1 ); // singleplayer is always allowing pause
|
||||
Cvar_SetValue( "coop", 0 );
|
||||
|
||||
Cbuf_ExecuteText( EXEC_APPEND, "loading; killserver; wait; newgame\n" );
|
||||
Host_NewGame( GI->startmap, false );
|
||||
}
|
||||
|
||||
static void UI_PromptDialog( float skill )
|
||||
|
|
|
@ -9,10 +9,6 @@
|
|||
|
||||
typedef int sound_t;
|
||||
|
||||
// snd internal flags (lower bits are used for snd channels)
|
||||
#define CHAN_NO_PHS_ADD (1<<3) // send to all clients, not just ones in PHS (ATTN 0 will also do this)
|
||||
#define CHAN_RELIABLE (1<<4) // send by reliable message, not datagram
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte mouthopen; // 0 = mouth closed, 255 = mouth agape
|
||||
|
@ -49,6 +45,7 @@ typedef struct vsound_exp_s
|
|||
void (*EndRegistration)( void );
|
||||
|
||||
void (*StartSound)( const vec3_t pos, int ent, int chan, sound_t sfx, float vol, float attn, int pitch, int flags );
|
||||
void (*StaticSound)( const vec3_t pos, int ent, int chan, sound_t sfx, float vol, float attn, int pitch, int flags );
|
||||
void (*StreamRawSamples)( int samples, int rate, int width, int channels, const byte *data );
|
||||
bool (*StartLocalSound)( const char *name, float volume, int pitch, const float *origin );
|
||||
void (*FadeClientVolume)( float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds );
|
||||
|
@ -59,7 +56,7 @@ typedef struct vsound_exp_s
|
|||
void (*StopStreaming)( void );
|
||||
|
||||
void (*RenderFrame)( ref_params_t *fd );
|
||||
void (*StopSound)( int entnum, int channel );
|
||||
void (*StopSound)( int entnum, int channel, const char *soundname );
|
||||
void (*StopAllSounds)( void );
|
||||
void (*FreeSounds)( void );
|
||||
|
||||
|
@ -74,7 +71,6 @@ typedef struct vsound_imp_s
|
|||
|
||||
trace_t (*TraceLine)( const vec3_t start, const vec3_t end );
|
||||
bool (*GetEntitySpatialization)( int entnum, soundinfo_t *info );
|
||||
void (*GetSoundSpatialization)( int entnum, vec3_t origin, vec3_t velocity );
|
||||
int (*PointContents)( const vec3_t point );
|
||||
edict_t *(*GetClientEdict)( int index );
|
||||
mouth_t *(*GetEntityMouth)( edict_t *ent );
|
||||
|
|
|
@ -860,13 +860,6 @@ int CBaseEntity :: Restore( CRestore &restore )
|
|||
UTIL_SetModel( ENT( pev ), pev->model );
|
||||
UTIL_SetSize( pev, mins, maxs );
|
||||
}
|
||||
|
||||
if( pev->soundindex != 0 && !FStringNull( pev->noise ))
|
||||
{
|
||||
UTIL_PrecacheSound( pev->noise );
|
||||
LINK_ENTITY( ENT( pev ), false );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,27 +49,20 @@ class CWallTorch : public CBaseEntity
|
|||
public:
|
||||
void Precache( void )
|
||||
{
|
||||
// if sound is missing just reset soundindex
|
||||
pev->impulse = PRECACHE_SOUND( "ambience/fire1.wav" );
|
||||
PRECACHE_SOUND( "ambience/fire1.wav" );
|
||||
UTIL_PrecacheModel( "models/props/torch1.mdl" );
|
||||
UTIL_EmitAmbientSound( ENT(pev), pev->origin, "ambience/fire1.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM );
|
||||
}
|
||||
void Spawn( void )
|
||||
{
|
||||
Precache ();
|
||||
|
||||
if( !pev->impulse )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
// SetObjectClass( ED_NORMAL );
|
||||
pev->flags |= FL_PHS_FILTER; // allow phs filter instead pvs
|
||||
|
||||
// setup attenuation radius
|
||||
pev->armorvalue = 384.0f * ATTN_STATIC;
|
||||
|
||||
pev->soundindex = pev->impulse;
|
||||
UTIL_SetModel( ENT( pev ), "models/props/torch1.mdl" );
|
||||
UTIL_SetSize(pev, g_vecZero, g_vecZero);
|
||||
SetBits( pFlags, PF_POINTENTITY );
|
||||
|
|
|
@ -906,113 +906,6 @@ void CAmbientGeneric :: KeyValue( KeyValueData *pkvd )
|
|||
CBaseEntity::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
/*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off reliable
|
||||
"noise" wav file to play
|
||||
"attenuation"
|
||||
-1 = none, send to whole level
|
||||
1 = normal fighting sounds
|
||||
2 = idle sound level
|
||||
3 = ambient sound level
|
||||
"volume" 0.0 to 1.0
|
||||
|
||||
Normal sounds play each time the target is used. The reliable flag can be set for crucial voiceovers.
|
||||
|
||||
Looped sounds are always atten 3 / vol 1, and the use function toggles it on/off.
|
||||
Multiple identical looping sounds will just increase volume without any speed cost.
|
||||
*/
|
||||
#define SF_SPEAKER_LOOPED_ON 1
|
||||
#define SF_SPEAKER_LOOPED_OFF 2
|
||||
#define SF_SPEAKER_GLOBAL 4
|
||||
#define SF_SPEAKER_ACTIVATOR 8
|
||||
|
||||
class CTargetSpeaker : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
void KeyValue( KeyValueData* pkvd );
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void EXPORT ToggleUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
};
|
||||
LINK_ENTITY_TO_CLASS( target_speaker, CTargetSpeaker );
|
||||
|
||||
void CTargetSpeaker :: KeyValue( KeyValueData *pkvd )
|
||||
{
|
||||
if ( FStrEq( pkvd->szKeyName, "volume" ))
|
||||
{
|
||||
pev->health = atof( pkvd->szValue );
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
if ( FStrEq( pkvd->szKeyName, "attenuation" ))
|
||||
{
|
||||
switch( atoi( pkvd->szValue ))
|
||||
{
|
||||
case -1: pev->frags = ATTN_NONE; break;
|
||||
case 1: pev->frags = ATTN_NORM; break;
|
||||
case 2: pev->frags = ATTN_IDLE; break;
|
||||
default: pev->frags = ATTN_STATIC; break;
|
||||
}
|
||||
pkvd->fHandled = TRUE;
|
||||
}
|
||||
else CBaseEntity::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
void CTargetSpeaker :: Precache( void )
|
||||
{
|
||||
// if sound is missing just reset soundindex
|
||||
pev->impulse = PRECACHE_SOUND( STRING( pev->noise ));
|
||||
}
|
||||
|
||||
void CTargetSpeaker :: ToggleUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
if ( pev->spawnflags & (SF_SPEAKER_LOOPED_ON|SF_SPEAKER_LOOPED_OFF))
|
||||
{
|
||||
// looping sound toggles
|
||||
if ( pev->soundindex ) pev->soundindex = 0; // turn it off
|
||||
else pev->soundindex = pev->impulse; // start it
|
||||
}
|
||||
else
|
||||
{ // normal sound
|
||||
if( pev->spawnflags & SF_SPEAKER_ACTIVATOR )
|
||||
EMIT_SOUND_DYN( pActivator->edict(), CHAN_AUTO, STRING (pev->noise ), pev->health, pev->frags, SND_SPAWNING, PITCH_NORM );
|
||||
// use a G_PositionedSound, because this entity won't normally be
|
||||
// sent to any clients because it is invisible
|
||||
else if( pev->spawnflags & SF_SPEAKER_GLOBAL )
|
||||
UTIL_EmitAmbientSound( NULL, pev->origin, STRING (pev->noise ), pev->health, pev->frags, SND_SPAWNING, PITCH_NORM );
|
||||
else UTIL_EmitAmbientSound( ENT( pev ), pev->origin, STRING (pev->noise ), pev->health, pev->frags, 0, PITCH_NORM );
|
||||
}
|
||||
}
|
||||
|
||||
void CTargetSpeaker :: Spawn( void )
|
||||
{
|
||||
Precache ();
|
||||
|
||||
if( !pev->impulse )
|
||||
{
|
||||
ALERT( at_error, "%s with no noise set at %g %g %g\n", STRING( pev->classname ), pev->origin.x, pev->origin.y, pev->origin.z );
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
SetObjectClass( ED_AMBIENT );
|
||||
pev->flags |= FL_PHS_FILTER; // allow phs filter instead pvs
|
||||
|
||||
if( !pev->health ) pev->health = 1.0f;
|
||||
if( !pev->frags ) pev->frags = ATTN_NORM;
|
||||
|
||||
// setup attenuation radius
|
||||
pev->armorvalue = 512.0f * pev->frags;
|
||||
|
||||
// check for prestarted looping sound
|
||||
if ( pev->spawnflags & SF_SPEAKER_LOOPED_ON )
|
||||
pev->soundindex = pev->impulse;
|
||||
|
||||
SetUse( ToggleUse );
|
||||
|
||||
// must link the entity so we get areas and clusters so
|
||||
// the server can determine who to send updates to
|
||||
LINK_ENTITY( ENT( pev ), false );
|
||||
}
|
||||
|
||||
// ==================== SENTENCE GROUPS, UTILITY FUNCTIONS ======================================
|
||||
|
||||
#define CSENTENCE_LRU_MAX 32 // max number of elements per sentence group
|
||||
|
|
|
@ -1132,11 +1132,11 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
|
|||
to->skin = pNet->pev->skin; // studio model skin
|
||||
to->body = pNet->pev->body; // studio model submodel
|
||||
to->effects = pNet->pev->effects; // shared client and render flags
|
||||
to->soundindex = pNet->pev->soundindex; // soundindex
|
||||
to->renderfx = pNet->pev->renderfx; // renderer flags
|
||||
to->rendermode = pNet->pev->rendermode; // rendering mode
|
||||
to->renderamt = pNet->pev->renderamt; // alpha value
|
||||
to->animtime = (int)(1000.0 * pNet->pev->animtime) * 0.001; // sequence time
|
||||
to->localtime = (int)(1000.0 * pNet->pev->ltime) * 0.001; // movement time
|
||||
to->scale = pNet->pev->scale; // shared client and render flags
|
||||
to->movetype = (movetype_t)pNet->pev->movetype;
|
||||
to->frame = pNet->pev->frame; // any model current frame
|
||||
|
@ -1209,16 +1209,6 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
|
|||
}
|
||||
else if( to->ed_type == ED_AMBIENT )
|
||||
{
|
||||
to->soundindex = pNet->pev->soundindex;
|
||||
|
||||
if( pNet->pev->solid == SOLID_TRIGGER )
|
||||
{
|
||||
Vector midPoint;
|
||||
|
||||
// NOTE: no reason to compute this shit on the client - save bandwidth
|
||||
midPoint = pNet->pev->mins + pNet->pev->maxs * 0.5f;
|
||||
to->origin += midPoint;
|
||||
}
|
||||
}
|
||||
else if( to->ed_type == ED_MOVER || to->ed_type == ED_BSPBRUSH || to->ed_type == ED_PORTAL )
|
||||
{
|
||||
|
|
|
@ -43,8 +43,6 @@ TYPEDESCRIPTION gEntvarsDescription[] =
|
|||
DEFINE_ENTITY_FIELD( modelindex, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( model, FIELD_MODELNAME ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( soundindex, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( viewmodel, FIELD_MODELNAME ),
|
||||
DEFINE_ENTITY_FIELD( weaponmodel, FIELD_MODELNAME ),
|
||||
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
class CWallTorch : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
void Precache( void )
|
||||
{
|
||||
// if sound is missing just reset soundindex
|
||||
pev->impulse = PRECACHE_SOUND( "ambience/fire1.wav" );
|
||||
UTIL_PrecacheModel( "models/props/torch1.mdl" );
|
||||
}
|
||||
void Spawn( void )
|
||||
{
|
||||
Precache ();
|
||||
|
||||
if( !pev->impulse )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
// SetObjectClass( ED_NORMAL );
|
||||
pev->flags |= FL_PHS_FILTER; // allow phs filter instead pvs
|
||||
|
||||
// setup attenuation radius
|
||||
pev->armorvalue = 384.0f * ATTN_STATIC;
|
||||
|
||||
pev->soundindex = pev->impulse;
|
||||
UTIL_SetModel( ENT( pev ), "models/props/torch1.mdl" );
|
||||
UTIL_SetSize(pev, g_vecZero, g_vecZero);
|
||||
SetBits( pFlags, PF_POINTENTITY );
|
||||
pev->animtime = gpGlobals->time + 0.2; // enable animation
|
||||
pev->framerate = 0.5f;
|
||||
}
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( light_torch_small_walltorch, CWallTorch );
|
|
@ -34,6 +34,7 @@ vsound_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, vsound_imp_t *engfuncs )
|
|||
|
||||
snd.FadeClientVolume = S_FadeClientVolume;
|
||||
snd.StartSound = S_StartSound;
|
||||
snd.StaticSound = S_StaticSound;
|
||||
snd.StreamRawSamples = S_StreamRawSamples;
|
||||
snd.StartLocalSound = S_StartLocalSound;
|
||||
snd.StartBackgroundTrack = S_StartBackgroundTrack;
|
||||
|
|
479
snd_al/s_load.c
479
snd_al/s_load.c
|
@ -13,19 +13,12 @@
|
|||
#define MAX_SFX 4096
|
||||
#define MAX_SFX_HASH (MAX_SFX/4)
|
||||
|
||||
static int s_numSfx = 0;
|
||||
static sfx_t s_knownSfx[MAX_SFX];
|
||||
static sfx_t *s_sfxHashList[MAX_SFX_HASH];
|
||||
static int s_numSfx = 0;
|
||||
bool s_registering = false;
|
||||
int s_registration_sequence = 0;
|
||||
|
||||
typedef struct loadformat_s
|
||||
{
|
||||
char *formatstring;
|
||||
char *ext;
|
||||
bool (*loadfunc)( const char *name, byte **wav, wavinfo_t *info );
|
||||
} loadformat_t;
|
||||
|
||||
/*
|
||||
=================
|
||||
S_SoundList_f
|
||||
|
@ -46,7 +39,7 @@ void S_SoundList_f( void )
|
|||
if( sfx->loaded )
|
||||
{
|
||||
samples += sfx->samples;
|
||||
if( sfx->loopstart >= 0 ) Msg( "L" );
|
||||
if( sfx->loopStart >= 0 ) Msg( "L" );
|
||||
else Msg( " " );
|
||||
Msg( "%8i ", sfx->samples );
|
||||
Msg( "%5i ", sfx->rate );
|
||||
|
@ -60,8 +53,7 @@ void S_SoundList_f( void )
|
|||
default: Msg( "???????? " ); break;
|
||||
}
|
||||
|
||||
if( sfx->name[0] == '#' ) Msg( "%s", &sfx->name[1] );
|
||||
else Msg( "sound/%s", sfx->name );
|
||||
Msg( "sound/%s", sfx->name );
|
||||
Msg( "\n" );
|
||||
totalSfx++;
|
||||
}
|
||||
|
@ -73,364 +65,31 @@ void S_SoundList_f( void )
|
|||
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 )
|
||||
// return true if char 'c' is one of 1st 2 characters in pch
|
||||
bool S_TestSoundChar( const char *pch, char c )
|
||||
{
|
||||
short val = 0;
|
||||
int i;
|
||||
char *pcht = (char *)pch;
|
||||
|
||||
val += (*(iff_dataPtr+0) << 0);
|
||||
val += (*(iff_dataPtr+1) << 8);
|
||||
iff_dataPtr += 2;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_GetLittleLong
|
||||
=================
|
||||
*/
|
||||
static int S_GetLittleLong( void )
|
||||
// check first 2 characters
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
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, samples;
|
||||
|
||||
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 && info->channels != 2 )
|
||||
{
|
||||
MsgDev( D_WARN, "S_LoadWAV: only mono and stereo 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;
|
||||
}
|
||||
|
||||
// get cue chunk
|
||||
S_FindChunk( "cue " );
|
||||
if( iff_dataPtr )
|
||||
{
|
||||
iff_dataPtr += 32;
|
||||
info->loopstart = S_GetLittleLong();
|
||||
S_FindNextChunk( "LIST" ); // if the next chunk is a LIST chunk, look for a cue length marker
|
||||
if( iff_dataPtr )
|
||||
{
|
||||
if( !com.strncmp((const char *)iff_dataPtr + 28, "mark", 4 ))
|
||||
{
|
||||
// this is not a proper parse, but it works with CoolEdit...
|
||||
iff_dataPtr += 24;
|
||||
info->samples = info->loopstart + S_GetLittleLong(); // samples in loop
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
info->loopstart = -1;
|
||||
info->samples = 0;
|
||||
}
|
||||
|
||||
// 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;
|
||||
samples = S_GetLittleLong() / info->width;
|
||||
|
||||
if( info->samples )
|
||||
{
|
||||
if( samples < info->samples )
|
||||
{
|
||||
MsgDev( D_ERROR, "S_LoadWAV: %s has a bad loop length\n", name );
|
||||
Mem_Free( buffer );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else info->samples = samples;
|
||||
|
||||
if( info->samples <= 0 )
|
||||
{
|
||||
MsgDev( D_WARN, "S_LoadWAV: file with %i samples (%s)\n", info->samples, name );
|
||||
Mem_Free( buffer );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the data
|
||||
*wav = out = Z_Malloc( info->samples * info->width * info->channels );
|
||||
Mem_Copy( out, buffer + (iff_dataPtr - buffer), info->samples * info->width * info->channels );
|
||||
Mem_Free( buffer );
|
||||
|
||||
if( *pcht == c )
|
||||
return true;
|
||||
pcht++;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
OGG LOADING
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
byte *buffer;
|
||||
ogg_int64_t ind;
|
||||
ogg_int64_t buffsize;
|
||||
} ov_decode_t;
|
||||
|
||||
static size_t ovc_read( void *ptr, size_t size, size_t nb, void *datasource )
|
||||
{
|
||||
ov_decode_t *sound = (ov_decode_t *)datasource;
|
||||
size_t remain, length;
|
||||
|
||||
remain = sound->buffsize - sound->ind;
|
||||
length = size * nb;
|
||||
if( remain < length ) length = remain - remain % size;
|
||||
|
||||
Mem_Copy( ptr, sound->buffer + sound->ind, length );
|
||||
sound->ind += length;
|
||||
|
||||
return length / size;
|
||||
}
|
||||
|
||||
static int ovc_seek ( void *datasource, ogg_int64_t offset, int whence )
|
||||
{
|
||||
ov_decode_t *sound = (ov_decode_t*)datasource;
|
||||
|
||||
switch( whence )
|
||||
{
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset += sound->ind;
|
||||
break;
|
||||
case SEEK_END:
|
||||
offset += sound->buffsize;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if( offset < 0 || offset > sound->buffsize )
|
||||
return -1;
|
||||
|
||||
sound->ind = offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ovc_close( void *datasource )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long ovc_tell (void *datasource)
|
||||
{
|
||||
return ((ov_decode_t*)datasource)->ind;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_LoadOGG
|
||||
=================
|
||||
*/
|
||||
static bool S_LoadOGG( const char *name, byte **wav, wavinfo_t *info )
|
||||
{
|
||||
vorbisfile_t vf;
|
||||
vorbis_info_t *vi;
|
||||
vorbis_comment_t *vc;
|
||||
fs_offset_t filesize;
|
||||
ov_decode_t ov_decode;
|
||||
ogg_int64_t length, done = 0;
|
||||
ov_callbacks_t ov_callbacks = { ovc_read, ovc_seek, ovc_close, ovc_tell };
|
||||
byte *data, *buffer;
|
||||
const char *comm;
|
||||
int dummy;
|
||||
long ret;
|
||||
|
||||
// load the file
|
||||
data = FS_LoadFile( name, &filesize );
|
||||
if( !data ) return false;
|
||||
|
||||
// Open it with the VorbisFile API
|
||||
ov_decode.buffer = data;
|
||||
ov_decode.ind = 0;
|
||||
ov_decode.buffsize = filesize;
|
||||
if( ov_open_callbacks( &ov_decode, &vf, NULL, 0, ov_callbacks ) < 0 )
|
||||
{
|
||||
MsgDev( D_ERROR, "S_LoadOGG: couldn't open ogg stream %s\n", name );
|
||||
Mem_Free( data );
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the stream information
|
||||
vi = ov_info( &vf, -1 );
|
||||
if( vi->channels != 1 )
|
||||
// return pointer to first valid character in file name
|
||||
char *S_SkipSoundChar( const char *pch )
|
||||
{
|
||||
MsgDev( D_ERROR, "S_LoadOGG: only mono OGG files supported (%s)\n", name );
|
||||
ov_clear( &vf );
|
||||
Mem_Free( data );
|
||||
return false;
|
||||
}
|
||||
char *pcht = (char *)pch;
|
||||
|
||||
info->channels = vi->channels;
|
||||
info->rate = vi->rate;
|
||||
info->width = 2; // always 16-bit PCM
|
||||
info->loopstart = -1;
|
||||
length = ov_pcm_total( &vf, -1 ) * vi->channels * 2; // 16 bits => "* 2"
|
||||
if( !length )
|
||||
{
|
||||
// bad ogg file
|
||||
MsgDev( D_ERROR, "S_LoadOGG: (%s) is probably corrupted\n", name );
|
||||
ov_clear( &vf );
|
||||
Mem_Free( data );
|
||||
return false;
|
||||
}
|
||||
buffer = (byte *)Z_Malloc( length );
|
||||
|
||||
// decompress ogg into pcm wav format
|
||||
while((ret = ov_read( &vf, &buffer[done], (int)(length - done), big_endian, 2, 1, &dummy )) > 0)
|
||||
done += ret;
|
||||
info->samples = done / ( vi->channels * 2 );
|
||||
vc = ov_comment( &vf, -1 );
|
||||
|
||||
if( vc )
|
||||
{
|
||||
comm = vorbis_comment_query( vc, "LOOP_START", 0 );
|
||||
if( comm )
|
||||
{
|
||||
//FXIME: implement
|
||||
Msg("ogg 'cue' %d\n", com.atoi(comm) );
|
||||
//info->loopstart = bound( 0, com.atoi(comm), info->samples );
|
||||
}
|
||||
}
|
||||
|
||||
// close file
|
||||
ov_clear( &vf );
|
||||
Mem_Free( data );
|
||||
*wav = buffer; // load the data
|
||||
|
||||
return true;
|
||||
// check first character
|
||||
if( *pcht == '!' )
|
||||
pcht++;
|
||||
return pcht;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -438,31 +97,31 @@ static bool S_LoadOGG( const char *name, byte **wav, wavinfo_t *info )
|
|||
S_UploadSound
|
||||
=================
|
||||
*/
|
||||
static void S_UploadSound( byte *data, wavinfo_t *info, sfx_t *sfx )
|
||||
static void S_UploadSound( wavdata_t *sc, sfx_t *sfx )
|
||||
{
|
||||
int size;
|
||||
|
||||
// calculate buffer size
|
||||
size = info->samples * info->width * info->channels;
|
||||
sfx->loopstart = info->loopstart;
|
||||
sfx->samples = info->samples;
|
||||
sfx->rate = info->rate;
|
||||
sfx->loopStart = sc->loopStart;
|
||||
sfx->samples = sc->samples;
|
||||
sfx->rate = sc->rate;
|
||||
sfx->sampleStep = 1000 * ( sfx->rate / (float)sfx->samples ); // samples per second
|
||||
|
||||
// Set buffer format
|
||||
if( info->width == 2 )
|
||||
if( sc->width == 2 )
|
||||
{
|
||||
if( info->channels == 2 ) sfx->format = AL_FORMAT_STEREO16;
|
||||
if( sc->channels == 2 )
|
||||
sfx->format = AL_FORMAT_STEREO16;
|
||||
else sfx->format = AL_FORMAT_MONO16;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( info->channels == 2 ) sfx->format = AL_FORMAT_STEREO8;
|
||||
if( sc->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 );
|
||||
palBufferData( sfx->bufferNum, sfx->format, sc->buffer, sc->size, sfx->rate );
|
||||
FS_FreeSound( sc ); // don't need to keep this data
|
||||
S_CheckForErrors();
|
||||
|
||||
sfx->loaded = true;
|
||||
|
@ -473,30 +132,35 @@ static void S_UploadSound( byte *data, wavinfo_t *info, sfx_t *sfx )
|
|||
S_CreateDefaultSound
|
||||
=================
|
||||
*/
|
||||
static void S_CreateDefaultSound( byte **wav, wavinfo_t *info )
|
||||
static wavdata_t *S_CreateDefaultSound( void )
|
||||
{
|
||||
byte *out;
|
||||
wavdata_t *sc;
|
||||
int i;
|
||||
|
||||
info->rate = 22050;
|
||||
info->width = 2;
|
||||
info->channels = 1;
|
||||
info->samples = 11025;
|
||||
sc = Z_Malloc( sizeof( wavdata_t ));
|
||||
|
||||
*wav = out = Z_Malloc( info->samples * info->width );
|
||||
sc->rate = 22050;
|
||||
sc->width = 2;
|
||||
sc->channels = 1;
|
||||
sc->samples = 11025;
|
||||
sc->loopStart = -1;
|
||||
sc->size = sc->samples * sc->width * sc->channels;
|
||||
sc->buffer = Z_Malloc( sc->size );
|
||||
|
||||
if( s_check_errors->integer )
|
||||
{
|
||||
// create 1 kHz tone as default sound
|
||||
for( i = 0; i < info->samples; i++ )
|
||||
((short *)out)[i] = sin(i * 0.1f) * 20000;
|
||||
for( i = 0; i < sc->samples; i++ )
|
||||
((short *)sc->buffer)[i] = com.sin( i * 0.1f ) * 20000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create silent sound
|
||||
for( i = 0; i < info->samples; i++ )
|
||||
((short *)out)[i] = i;
|
||||
for( i = 0; i < sc->samples; i++ )
|
||||
((short *)sc->buffer)[i] = i;
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -504,59 +168,25 @@ static void S_CreateDefaultSound( byte **wav, wavinfo_t *info )
|
|||
S_LoadSound
|
||||
=================
|
||||
*/
|
||||
loadformat_t load_formats[] =
|
||||
{
|
||||
{ "sound/%s.%s", "ogg", S_LoadOGG },
|
||||
{ "sound/%s.%s", "wav", S_LoadWAV },
|
||||
{ "%s.%s", "ogg", S_LoadOGG },
|
||||
{ "%s.%s", "wav", S_LoadWAV },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
bool S_LoadSound( sfx_t *sfx )
|
||||
{
|
||||
byte *data;
|
||||
wavinfo_t info;
|
||||
const char *ext;
|
||||
string loadname, path;
|
||||
loadformat_t *format;
|
||||
bool anyformat;
|
||||
wavdata_t *sc;
|
||||
|
||||
if( !sfx ) return false;
|
||||
if( sfx->name[0] == '*' ) return false;
|
||||
if( sfx->loaded ) return true; // see if still in memory
|
||||
|
||||
// load it from disk
|
||||
ext = FS_FileExtension( sfx->name );
|
||||
anyformat = !com.stricmp( ext, "" ) ? true : false;
|
||||
sc = FS_LoadSound( sfx->name, NULL, 0 );
|
||||
|
||||
com.strncpy( loadname, sfx->name, sizeof( loadname ));
|
||||
FS_StripExtension( loadname ); // remove extension if needed
|
||||
Mem_Set( &info, 0, sizeof( info ));
|
||||
|
||||
// developer warning
|
||||
if( !anyformat ) MsgDev( D_NOTE, "Note: %s will be loading only with ext .%s\n", loadname, ext );
|
||||
|
||||
// now try all the formats in the selected list
|
||||
for( format = load_formats; format->formatstring; format++ )
|
||||
if( sc == NULL )
|
||||
{
|
||||
if( anyformat || !com.stricmp( ext, format->ext ))
|
||||
{
|
||||
com.sprintf( path, format->formatstring, loadname, format->ext );
|
||||
if( format->loadfunc( path, &data, &info ))
|
||||
goto snd_loaded;
|
||||
}
|
||||
}
|
||||
|
||||
sc = S_CreateDefaultSound();
|
||||
sfx->default_sound = true;
|
||||
MsgDev( D_WARN, "FS_LoadSound: couldn't load %s\n", sfx->name );
|
||||
S_CreateDefaultSound( &data, &info );
|
||||
info.loopstart = -1;
|
||||
}
|
||||
|
||||
snd_loaded:
|
||||
// load it in
|
||||
S_UploadSound( data, &info, sfx );
|
||||
Mem_Free( data );
|
||||
// upload and resample
|
||||
S_UploadSound( sc, sfx );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -702,9 +332,6 @@ sound_t S_RegisterSound( const char *name )
|
|||
{
|
||||
sfx_t *sfx;
|
||||
|
||||
if( !al_state.initialized )
|
||||
return -1;
|
||||
|
||||
sfx = S_FindSound( name );
|
||||
if( !sfx ) return -1;
|
||||
|
||||
|
|
559
snd_al/s_main.c
559
snd_al/s_main.c
|
@ -7,9 +7,9 @@
|
|||
#include "const.h"
|
||||
#include "trace_def.h"
|
||||
|
||||
#define MAX_PLAYSOUNDS 256
|
||||
#define MAX_CHANNELS 64
|
||||
#define MAX_CHANNELS 128
|
||||
#define CSXROOM 29
|
||||
int MAX_DYNAMIC_CHANNELS = 24; // can be reduced by openAL limitations
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -20,9 +20,6 @@ typedef struct
|
|||
} dsproom_t;
|
||||
|
||||
static soundfade_t soundfade;
|
||||
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 listener_t s_listener;
|
||||
|
||||
|
@ -196,6 +193,16 @@ void S_UpdateSoundFade( void )
|
|||
soundfade.percent = soundfade.initial_percent * f;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_IsClient
|
||||
=================
|
||||
*/
|
||||
bool S_IsClient( int entnum )
|
||||
{
|
||||
return ( entnum == al_state.clientnum );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_AllocChannels
|
||||
|
@ -211,8 +218,16 @@ static void S_AllocChannels( void )
|
|||
palGenSources( 1, &ch->sourceNum );
|
||||
if( palGetError() != AL_NO_ERROR )
|
||||
break;
|
||||
al_state.num_channels++;
|
||||
al_state.max_channels++;
|
||||
}
|
||||
|
||||
if( al_state.max_channels <= MAX_DYNAMIC_CHANNELS )
|
||||
{
|
||||
// there are not enough channels!
|
||||
MAX_DYNAMIC_CHANNELS = (int)(al_state.max_channels / 3);
|
||||
MsgDev( D_WARN, "S_AllocChannels: reduced dynamic channels count from 24 to %i\n", MAX_DYNAMIC_CHANNELS );
|
||||
}
|
||||
al_state.initialized = true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -225,12 +240,12 @@ static void S_FreeChannels( void )
|
|||
channel_t *ch;
|
||||
int i;
|
||||
|
||||
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
|
||||
for( i = 0, ch = s_channels; i < al_state.max_channels; i++, ch++ )
|
||||
{
|
||||
palDeleteSources( 1, &ch->sourceNum );
|
||||
Mem_Set( ch, 0, sizeof( *ch ));
|
||||
}
|
||||
al_state.num_channels = 0;
|
||||
al_state.max_channels = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -266,23 +281,37 @@ S_PlayChannel
|
|||
*/
|
||||
static void S_PlayChannel( channel_t *ch, sfx_t *sfx )
|
||||
{
|
||||
if( sfx == NULL )
|
||||
{
|
||||
S_StopChannel( ch );
|
||||
return;
|
||||
}
|
||||
ch->sfx = sfx;
|
||||
|
||||
palSourcei( ch->sourceNum, AL_BUFFER, sfx->bufferNum );
|
||||
palSourcei( ch->sourceNum, AL_LOOPING, ch->loopsound );
|
||||
palSourcei( ch->sourceNum, AL_LOOPING, false );
|
||||
palSourcei( ch->sourceNum, AL_SOURCE_RELATIVE, false );
|
||||
palSourcei( ch->sourceNum, AL_SAMPLE_OFFSET, 0 );
|
||||
|
||||
if( ch->loopstart >= 0 )
|
||||
if( ch->use_loop )
|
||||
{
|
||||
// kill any looping sounds
|
||||
if( al_state.paused )
|
||||
if( ch->sfx->loopStart >= 0 )
|
||||
{
|
||||
palSourceStop( ch->sourceNum );
|
||||
return;
|
||||
if( ch->state == CHAN_FIRSTPLAY )
|
||||
{
|
||||
// play first from start, then from loopOffset
|
||||
ch->state = CHAN_LOOPED;
|
||||
}
|
||||
else if( ch->state == CHAN_LOOPED )
|
||||
{
|
||||
palSourcei( ch->sourceNum, AL_SAMPLE_OFFSET, sfx->loopStart );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ch->state = CHAN_LOOPED;
|
||||
palSourcei( ch->sourceNum, AL_LOOPING, true );
|
||||
}
|
||||
if( ch->state == CHAN_FIRSTPLAY ) ch->state = CHAN_LOOPED;
|
||||
else if( ch->state == CHAN_LOOPED ) palSourcei( ch->sourceNum, AL_SAMPLE_OFFSET, sfx->loopstart );
|
||||
}
|
||||
palSourcePlay( ch->sourceNum );
|
||||
}
|
||||
|
@ -295,24 +324,28 @@ S_SpatializeChannel
|
|||
static void S_SpatializeChannel( channel_t *ch )
|
||||
{
|
||||
vec3_t position, velocity;
|
||||
soundinfo_t SndInfo;
|
||||
|
||||
// update position and velocity
|
||||
if( ch->entnum == al_state.clientnum || !ch->distanceMult )
|
||||
if( ch->entnum == al_state.clientnum || !ch->dist_mult )
|
||||
{
|
||||
palSourcefv( ch->sourceNum, AL_POSITION, s_listener.position );
|
||||
palSourcefv( ch->sourceNum, AL_VELOCITY, s_listener.velocity );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ch->fixedPosition )
|
||||
if( ch->staticsound )
|
||||
{
|
||||
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 );
|
||||
SndInfo.pOrigin = position;
|
||||
SndInfo.pAngles = velocity; // FIXME: this is angles, not velocity
|
||||
SndInfo.pflRadius = NULL;
|
||||
|
||||
si.GetEntitySpatialization( ch->entnum, &SndInfo );
|
||||
|
||||
palSource3f( ch->sourceNum, AL_POSITION, position[1], position[2], -position[0] );
|
||||
palSource3f( ch->sourceNum, AL_VELOCITY, velocity[1], velocity[2], -velocity[0] );
|
||||
|
@ -320,8 +353,8 @@ static void S_SpatializeChannel( channel_t *ch )
|
|||
}
|
||||
|
||||
// update min/max distance
|
||||
if( ch->distanceMult )
|
||||
palSourcef( ch->sourceNum, AL_REFERENCE_DISTANCE, s_minDistance->value * ch->distanceMult );
|
||||
if( ch->dist_mult )
|
||||
palSourcef( ch->sourceNum, AL_REFERENCE_DISTANCE, s_minDistance->value * ch->dist_mult );
|
||||
else palSourcef( ch->sourceNum, AL_REFERENCE_DISTANCE, s_maxDistance->value );
|
||||
|
||||
palSourcef( ch->sourceNum, AL_MAX_DISTANCE, s_maxDistance->value );
|
||||
|
@ -334,162 +367,186 @@ static void S_SpatializeChannel( channel_t *ch )
|
|||
|
||||
/*
|
||||
=================
|
||||
S_PickChannel
|
||||
SND_PickDynamicChannel
|
||||
|
||||
Tries to find a free channel, or tries to replace an active channel
|
||||
Select a channel from the dynamic channel allocation area. For the given entity,
|
||||
override any other sound playing on the same channel (see code comments below for
|
||||
exceptions).
|
||||
=================
|
||||
*/
|
||||
channel_t *S_PickChannel( int entnum, int channel )
|
||||
channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx )
|
||||
{
|
||||
channel_t *ch;
|
||||
int i;
|
||||
int firstToDie = -1;
|
||||
float oldestTime = Sys_DoubleTime();
|
||||
int ch_idx;
|
||||
int first_to_die;
|
||||
int life_left;
|
||||
|
||||
if( entnum < 0 || channel < 0 ) return NULL; // invalid channel or entnum
|
||||
// check for replacement sound, or find the best one to replace
|
||||
first_to_die = -1;
|
||||
life_left = 0x7fffffff;
|
||||
|
||||
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
|
||||
for( ch_idx = 0; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++ )
|
||||
{
|
||||
// don't let game sounds override streaming sounds
|
||||
if( ch->streaming ) continue;
|
||||
channel_t *ch = &s_channels[ch_idx];
|
||||
|
||||
// check if this channel is active
|
||||
if( channel == CHAN_AUTO && !ch->sfx )
|
||||
// Never override a streaming sound that is currently playing or
|
||||
// voice over IP data that is playing or any sound on CHAN_VOICE( acting )
|
||||
if( ch->sfx && ( ch->entchannel == CHAN_STREAM ))
|
||||
{
|
||||
// free channel
|
||||
firstToDie = i;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
// channel 0 never overrides
|
||||
if( channel != CHAN_AUTO && (ch->entnum == entnum && ch->entchannel == channel))
|
||||
if( channel != 0 && ch->entnum == entnum && ( ch->entchannel == channel || channel == -1 ))
|
||||
{
|
||||
// always override sound from same entity
|
||||
firstToDie = i;
|
||||
first_to_die = ch_idx;
|
||||
break;
|
||||
}
|
||||
|
||||
// don't let monster sounds override player sounds
|
||||
if( ch->sfx && S_IsClient( ch->entnum ) && !S_IsClient( entnum ))
|
||||
continue;
|
||||
|
||||
// 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 )
|
||||
if( ch->startTime < life_left )
|
||||
{
|
||||
oldestTime = ch->startTime;
|
||||
firstToDie = i;
|
||||
life_left = ch->startTime;
|
||||
first_to_die = ch_idx;
|
||||
}
|
||||
}
|
||||
|
||||
if( firstToDie == -1 ) return NULL;
|
||||
ch = &s_channels[firstToDie];
|
||||
if( first_to_die == -1 )
|
||||
return NULL;
|
||||
|
||||
ch->entnum = entnum;
|
||||
ch->entchannel = channel;
|
||||
ch->startTime = Sys_DoubleTime();
|
||||
ch->state = CHAN_NORMAL; // remove any loop sound
|
||||
ch->loopsound = false; // clear loopstate
|
||||
ch->loopstart = -1;
|
||||
if( s_channels[first_to_die].sfx )
|
||||
{
|
||||
// don't restart looping sounds for the same entity
|
||||
if( sfx->loopStart != -1 )
|
||||
{
|
||||
channel_t *ch = &s_channels[first_to_die];
|
||||
|
||||
// make sure this channel is stopped
|
||||
S_StopChannel( ch );
|
||||
if( ch->entnum == entnum && ch->entchannel == channel && ch->sfx == sfx )
|
||||
{
|
||||
// same looping sound, same ent, same channel, don't restart the sound
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// be sure and release previous channel if sentence.
|
||||
S_StopChannel( &( s_channels[first_to_die] ));
|
||||
}
|
||||
|
||||
return &s_channels[first_to_die];
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
SND_PickStaticChannel
|
||||
|
||||
Pick an empty channel from the static sound area, or allocate a new
|
||||
channel. Only fails if we're at max_channels (128!!!) or if
|
||||
we're trying to allocate a channel for a stream sound that is
|
||||
already playing.
|
||||
=====================
|
||||
*/
|
||||
channel_t *SND_PickStaticChannel( int entnum, sfx_t *sfx )
|
||||
{
|
||||
channel_t *ch = NULL;
|
||||
int i;
|
||||
|
||||
// check for replacement sound, or find the best one to replace
|
||||
for( i = MAX_DYNAMIC_CHANNELS; i < al_state.total_channels; i++ )
|
||||
{
|
||||
if( s_channels[i].sfx == NULL )
|
||||
break;
|
||||
}
|
||||
|
||||
if( i < al_state.total_channels )
|
||||
{
|
||||
// reuse an empty static sound channel
|
||||
ch = &s_channels[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// no empty slots, alloc a new static sound channel
|
||||
if( al_state.total_channels >= al_state.max_channels )
|
||||
{
|
||||
MsgDev( D_ERROR, "S_PickChannel: no free channels\n" );
|
||||
return NULL;
|
||||
}
|
||||
// get a channel for the static sound
|
||||
ch = &s_channels[al_state.total_channels];
|
||||
al_state.total_channels++;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_AllocPlaySound
|
||||
S_AlterChannel
|
||||
|
||||
search through all channels for a channel that matches this
|
||||
soundsource, entchannel and sfx, and perform alteration on channel
|
||||
as indicated by 'flags' parameter. If shut down request and
|
||||
sfx contains a sentence name, shut off the sentence.
|
||||
returns TRUE if sound was altered,
|
||||
returns FALSE if sound was not found (sound is not playing)
|
||||
=================
|
||||
*/
|
||||
static playSound_t *S_AllocPlaySound( void )
|
||||
int S_AlterChannel( int entnum, int channel, sfx_t *sfx, float vol, int pitch, int flags )
|
||||
{
|
||||
playSound_t *ps;
|
||||
|
||||
ps = s_freePlaySounds.next;
|
||||
if( ps == &s_freePlaySounds )
|
||||
return NULL; // No free playSounds
|
||||
|
||||
// unlink from freelist
|
||||
ps->prev->next = ps->next;
|
||||
ps->next->prev = ps->prev;
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_FreePlaySound
|
||||
=================
|
||||
*/
|
||||
static void S_FreePlaySound( playSound_t *ps )
|
||||
{
|
||||
// unlink from channel
|
||||
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;
|
||||
int i;
|
||||
|
||||
while( 1 )
|
||||
if( S_TestSoundChar( sfx->name, '!' ))
|
||||
{
|
||||
ps = s_pendingPlaySounds.next;
|
||||
// This is a sentence name.
|
||||
// For sentences: assume that the entity is only playing one sentence
|
||||
// at a time, so we can just shut off
|
||||
// any channel that has ch->isSentence >= 0 and matches the entnum.
|
||||
|
||||
if( ps == &s_pendingPlaySounds )
|
||||
break; // no more pending playSounds
|
||||
|
||||
if( ps->beginTime > Sys_DoubleTime( ))
|
||||
break; // No more pending playSounds this frame
|
||||
|
||||
// pick a channel and start the sound effect
|
||||
ch = S_PickChannel( ps->entnum, ps->entchannel );
|
||||
if( !ch )
|
||||
for( i = 0, ch = s_channels; i < al_state.total_channels; i++, 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;
|
||||
if( ch->entnum == entnum && ch->entchannel == channel && ch->sfx && ch->isSentence )
|
||||
{
|
||||
if( flags & SND_CHANGE_PITCH )
|
||||
ch->pitch = pitch / (float)PITCH_NORM;
|
||||
|
||||
if( flags & SND_CHANGE_VOL )
|
||||
ch->volume = vol;
|
||||
|
||||
if( flags & SND_STOP )
|
||||
S_StopChannel( ch );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// channel not found
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// check for looping sounds with "cue " marker
|
||||
if( ps->use_loop && ps->sfx->loopstart >= 0 )
|
||||
// regular sound or streaming sound
|
||||
for( i = 0, ch = s_channels; i < al_state.total_channels; i++, ch++ )
|
||||
{
|
||||
// jump to loopstart at next playing
|
||||
ch->state = CHAN_FIRSTPLAY;
|
||||
ch->loopstart = ps->sfx->loopstart;
|
||||
if( ch->entnum == entnum && ch->entchannel == channel && ch->sfx )
|
||||
{
|
||||
if( flags & SND_CHANGE_PITCH )
|
||||
ch->pitch = pitch / (float)PITCH_NORM;
|
||||
|
||||
if( flags & SND_CHANGE_VOL )
|
||||
ch->volume = vol;
|
||||
|
||||
if( flags & SND_STOP )
|
||||
S_StopChannel( ch );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ch->fixedPosition = ps->fixedPosition;
|
||||
VectorCopy( ps->position, ch->position );
|
||||
ch->volume = ps->volume;
|
||||
ch->pitch = ps->pitch;
|
||||
|
||||
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 );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -501,53 +558,146 @@ 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 pos, int entnum, int channel, sound_t handle, float vol, float attn, int pitch, int flags )
|
||||
void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fvol, float attn, int pitch, int flags )
|
||||
{
|
||||
playSound_t *ps, *sort;
|
||||
sfx_t *sfx = NULL;
|
||||
channel_t *target_chan;
|
||||
int vol, fsentence = 0;
|
||||
|
||||
if( !al_state.initialized )
|
||||
return;
|
||||
sfx = S_GetSfxByHandle( handle );
|
||||
if( !sfx ) return;
|
||||
|
||||
vol = bound( 0, fvol * 255, 255 );
|
||||
|
||||
if( flags & ( SND_STOP|SND_CHANGE_VOL|SND_CHANGE_PITCH ))
|
||||
{
|
||||
if( S_AlterChannel( ent, chan, sfx, vol, pitch, flags ))
|
||||
return;
|
||||
|
||||
if( flags & SND_STOP ) return;
|
||||
// fall through - if we're not trying to stop the sound,
|
||||
// and we didn't find it (it's not playing), go ahead and start it up
|
||||
}
|
||||
|
||||
if( pitch == 0 )
|
||||
{
|
||||
MsgDev( D_WARN, "S_StartSound: ( %s ) ignored, called with pitch 0\n", sfx->name );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !pos ) pos = vec3_origin;
|
||||
|
||||
// pick a channel to play on
|
||||
target_chan = SND_PickDynamicChannel( ent, chan, sfx );
|
||||
if( !target_chan )
|
||||
{
|
||||
MsgDev( D_ERROR, "dropped sound \"sound/%s\"\n", sfx->name );
|
||||
return;
|
||||
}
|
||||
|
||||
target_chan->entnum = ent;
|
||||
target_chan->entchannel = chan;
|
||||
target_chan->startTime = Sys_Milliseconds();
|
||||
VectorCopy( pos, target_chan->position );
|
||||
target_chan->volume = vol;
|
||||
target_chan->entnum = ent;
|
||||
target_chan->entchannel = chan;
|
||||
target_chan->isSentence = false;
|
||||
target_chan->dist_mult = (attn / 1000.0f);
|
||||
target_chan->state = CHAN_FIRSTPLAY;
|
||||
target_chan->sfx = sfx;
|
||||
target_chan->pitch = pitch / (float)PITCH_NORM;
|
||||
|
||||
// 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 );
|
||||
S_StopChannel( target_chan );
|
||||
return;
|
||||
}
|
||||
|
||||
ps->sfx = sfx;
|
||||
ps->entnum = entnum;
|
||||
ps->entchannel = channel;
|
||||
ps->use_loop = (flags & (SND_STOP_LOOPING|SND_STOP)) ? false : true;
|
||||
// only using loop for looped sounds
|
||||
if( flags & SND_STOP_LOOPING )
|
||||
target_chan->use_loop = false;
|
||||
else target_chan->use_loop = ( sfx->loopStart == -1 ) ? false : true;
|
||||
|
||||
if( pos )
|
||||
{
|
||||
ps->fixedPosition = true;
|
||||
VectorCopy( pos, ps->position );
|
||||
S_SpatializeChannel( target_chan );
|
||||
S_PlayChannel( target_chan, sfx );
|
||||
}
|
||||
else ps->fixedPosition = false;
|
||||
|
||||
ps->volume = vol;
|
||||
ps->pitch = pitch / PITCH_NORM;
|
||||
ps->attenuation = attn;
|
||||
ps->beginTime = Sys_DoubleTime();
|
||||
/*
|
||||
=================
|
||||
S_StartStaticSound
|
||||
|
||||
// sort into the pending playSounds list
|
||||
for( sort = s_pendingPlaySounds.next; sort != &s_pendingPlaySounds && sort->beginTime < ps->beginTime; sort = sort->next );
|
||||
Start playback of a sound, loaded into the static portion of the channel array.
|
||||
Currently, this should be used for looping ambient sounds, looping sounds
|
||||
that should not be interrupted until complete, non-creature sentences,
|
||||
and one-shot ambient streaming sounds. Can also play 'regular' sounds one-shot,
|
||||
in case designers want to trigger regular game sounds.
|
||||
Pitch changes playback pitch of wave by % above or below 100. Ignored if pitch == 100
|
||||
|
||||
ps->next = sort;
|
||||
ps->prev = sort->prev;
|
||||
ps->next->prev = ps;
|
||||
ps->prev->next = ps;
|
||||
NOTE: volume is 0.0 - 1.0 and attenuation is 0.0 - 1.0 when passed in.
|
||||
=================
|
||||
*/
|
||||
void S_StaticSound( const vec3_t pos, int ent, int chan, sound_t handle, float fvol, float attn, int pitch, int flags )
|
||||
{
|
||||
channel_t *ch;
|
||||
sfx_t *sfx = NULL;
|
||||
int vol, fvox = 0;
|
||||
|
||||
sfx = S_GetSfxByHandle( handle );
|
||||
if( !sfx ) return;
|
||||
|
||||
vol = bound( 0, fvol * 255, 255 );
|
||||
|
||||
if( flags & (SND_STOP|SND_CHANGE_VOL|SND_CHANGE_PITCH))
|
||||
{
|
||||
if( S_AlterChannel( ent, chan, sfx, vol, pitch, flags ))
|
||||
return;
|
||||
if( flags & SND_STOP ) return;
|
||||
}
|
||||
|
||||
if( pitch == 0 )
|
||||
{
|
||||
MsgDev( D_WARN, "S_StartStaticSound: ( %s ) ignored, called with pitch 0\n", sfx->name );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !pos ) pos = vec3_origin;
|
||||
|
||||
// pick a channel to play on from the static area
|
||||
ch = SND_PickStaticChannel( ent, sfx ); // autolooping sounds are always fixed origin(?)
|
||||
if( !ch ) return;
|
||||
|
||||
// make sure the sound is loaded
|
||||
if( !S_LoadSound( sfx ))
|
||||
{
|
||||
S_StopChannel( ch );
|
||||
return;
|
||||
}
|
||||
|
||||
VectorCopy( pos, ch->position );
|
||||
|
||||
ch->entnum = ent;
|
||||
ch->entchannel = chan;
|
||||
ch->startTime = Sys_Milliseconds();
|
||||
ch->state = CHAN_FIRSTPLAY;
|
||||
VectorCopy( pos, ch->position );
|
||||
ch->volume = vol;
|
||||
ch->entnum = ent;
|
||||
ch->entchannel = chan;
|
||||
ch->isSentence = false;
|
||||
ch->dist_mult = (attn / 1000.0f);
|
||||
ch->sfx = sfx;
|
||||
ch->pitch = pitch / (float)PITCH_NORM;
|
||||
ch->staticsound = true;
|
||||
|
||||
// only using loop for looped sounds
|
||||
if( flags & SND_STOP_LOOPING )
|
||||
ch->use_loop = false;
|
||||
else ch->use_loop = ( sfx->loopStart == -1 ) ? false : true;
|
||||
|
||||
S_SpatializeChannel( ch );
|
||||
S_PlayChannel( ch, sfx );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -561,9 +711,6 @@ bool S_StartLocalSound( const char *name, float volume, int pitch, const float *
|
|||
{
|
||||
sound_t sfxHandle;
|
||||
|
||||
if( !al_state.initialized )
|
||||
return false;
|
||||
|
||||
sfxHandle = S_RegisterSound( name );
|
||||
S_StartSound( origin, al_state.clientnum, CHAN_AUTO, sfxHandle, volume, ATTN_NONE, pitch, SND_STOP_LOOPING );
|
||||
return true;
|
||||
|
@ -576,9 +723,22 @@ S_StopAllSounds
|
|||
stop all sounds for entity on a channel.
|
||||
==================
|
||||
*/
|
||||
void S_StopSound( int entnum, int channel )
|
||||
void S_StopSound( int entnum, int channel, const char *soundname )
|
||||
{
|
||||
S_StopAllSounds(); // FIXME: this is incorrect!
|
||||
int i;
|
||||
|
||||
for( i = 0; i < al_state.total_channels; i++ )
|
||||
{
|
||||
channel_t *ch = &s_channels[i];
|
||||
|
||||
if( !ch->sfx ) continue; // already freed
|
||||
if( ch->entnum == entnum && ch->entchannel == channel )
|
||||
{
|
||||
if( soundname && com.strcmp( ch->sfx->name, soundname ))
|
||||
continue;
|
||||
S_StopChannel( ch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -591,25 +751,10 @@ void S_StopAllSounds( void )
|
|||
channel_t *ch;
|
||||
int i;
|
||||
|
||||
if( !al_state.initialized )
|
||||
return;
|
||||
|
||||
// Clear all the playSounds
|
||||
Mem_Set( 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];
|
||||
}
|
||||
al_state.total_channels = MAX_DYNAMIC_CHANNELS; // no statics
|
||||
|
||||
// Stop all the channels
|
||||
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
|
||||
for( i = 0, ch = s_channels; i < al_state.max_channels; i++, ch++ )
|
||||
{
|
||||
if( !ch->sfx ) continue;
|
||||
S_StopChannel( ch );
|
||||
|
@ -661,8 +806,7 @@ void S_Update( ref_params_t *fd )
|
|||
channel_t *ch;
|
||||
int i;
|
||||
|
||||
if( !al_state.initialized || !fd )
|
||||
return;
|
||||
if( !fd ) return;
|
||||
|
||||
// bump frame count
|
||||
al_state.framecount++;
|
||||
|
@ -671,7 +815,8 @@ void S_Update( ref_params_t *fd )
|
|||
al_state.refdef = fd; // for using everthing else
|
||||
|
||||
// update any client side sound fade
|
||||
if( !fd->paused ) S_UpdateSoundFade();
|
||||
if( !fd->paused && si.IsInGame( ))
|
||||
S_UpdateSoundFade();
|
||||
|
||||
// set up listener
|
||||
VectorSet( s_listener.position, fd->simorg[1], fd->simorg[2], -fd->simorg[0] );
|
||||
|
@ -702,26 +847,24 @@ void S_Update( ref_params_t *fd )
|
|||
// Stream background track
|
||||
S_StreamBackgroundTrack ();
|
||||
|
||||
// Issue playSounds
|
||||
S_IssuePlaySounds();
|
||||
|
||||
// update spatialization for all sounds
|
||||
for( i = 0, ch = s_channels; i < al_state.num_channels; i++, ch++ )
|
||||
for( i = 0, ch = s_channels; i < al_state.total_channels; i++, ch++ )
|
||||
{
|
||||
if( !ch->sfx ) continue; // not active
|
||||
|
||||
// check for stop
|
||||
if( ch->loopsound )
|
||||
if( ch->use_loop && ch->sfx->loopStart >= 0 )
|
||||
{
|
||||
if( ch->loopframe != al_state.framecount )
|
||||
int samplePos;
|
||||
|
||||
palGetSourcei( ch->sourceNum, AL_SAMPLE_OFFSET, &samplePos );
|
||||
|
||||
if( samplePos + ch->sfx->sampleStep >= ch->sfx->samples )
|
||||
{
|
||||
S_StopChannel( ch );
|
||||
continue;
|
||||
Msg( "restart %s\n", ch->sfx->name );
|
||||
palSourcei( ch->sourceNum, AL_SAMPLE_OFFSET, ch->sfx->loopStart );
|
||||
}
|
||||
}
|
||||
else if( ch->loopstart >= 0 && ch->volume > 0.0f )
|
||||
{
|
||||
if( S_ChannelState( ch ) == AL_STOPPED )
|
||||
else if( S_ChannelState( ch ) == AL_STOPPED )
|
||||
{
|
||||
S_PlayChannel( ch, ch->sfx );
|
||||
}
|
||||
|
@ -751,12 +894,9 @@ and an activate.
|
|||
*/
|
||||
void S_Activate( bool active )
|
||||
{
|
||||
if(!al_state.initialized )
|
||||
return;
|
||||
|
||||
al_state.active = active;
|
||||
if( active ) palListenerf( AL_GAIN, S_GetMasterVolume( ));
|
||||
else palListenerf( AL_GAIN, 0.0 );
|
||||
else palListenerf( AL_GAIN, 0.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -805,12 +945,6 @@ 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 );
|
||||
|
@ -818,7 +952,7 @@ void S_SoundInfo_f( void )
|
|||
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( "CHANNELS: %i\n", al_state.max_channels );
|
||||
Msg( "3D sound: %s\n", (al_config.allow_3DMode) ? "enabled" : "disabled" );
|
||||
Msg( "\n" );
|
||||
}
|
||||
|
@ -864,7 +998,6 @@ bool S_Init( void *hInst )
|
|||
MsgDev( D_NOTE, "S_Init: mono sources %d, stereo %d\n", num_mono_src, num_stereo_src );
|
||||
|
||||
sndpool = Mem_AllocPool( "Sound Zone" );
|
||||
al_state.initialized = true;
|
||||
|
||||
S_AllocChannels();
|
||||
S_StopAllSounds();
|
||||
|
@ -892,13 +1025,9 @@ void S_Shutdown( void )
|
|||
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;
|
||||
}
|
|
@ -140,8 +140,10 @@ static bool S_InitDriver( void )
|
|||
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;
|
||||
|
@ -152,6 +154,7 @@ failed:
|
|||
palcDestroyContext( al_state.hALC );
|
||||
al_state.hALC = NULL;
|
||||
}
|
||||
|
||||
if( al_state.hDevice )
|
||||
{
|
||||
palcCloseDevice( al_state.hDevice );
|
||||
|
@ -308,7 +311,6 @@ static void S_InitExtensions( void )
|
|||
|
||||
if( palcIsExtensionPresent( al_state.hDevice, "ALC_EXT_EFX" ))
|
||||
{
|
||||
|
||||
uint uiEffectSlots[MAX_EFFECTS] = { 0 };
|
||||
|
||||
if( !S_SetupEFX( )) return;
|
||||
|
@ -365,7 +367,7 @@ bool S_Init_OpenAL( void )
|
|||
|
||||
// get some openal strings
|
||||
al_config.vendor_string = palGetString( AL_VENDOR );
|
||||
al_config.renderer_string = palGetString(AL_RENDERER); // stupid name :)
|
||||
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 );
|
||||
|
@ -386,6 +388,7 @@ void S_Free_OpenAL( void )
|
|||
palcDestroyContext( al_state.hALC );
|
||||
al_state.hALC = NULL;
|
||||
}
|
||||
|
||||
if( al_state.hDevice )
|
||||
{
|
||||
if( palcCloseDevice )
|
||||
|
|
|
@ -210,8 +210,6 @@ S_StartBackgroundTrack
|
|||
*/
|
||||
void S_StartBackgroundTrack( const char *introTrack, const char *loopTrack )
|
||||
{
|
||||
if( !al_state.initialized ) return;
|
||||
|
||||
// stop any playing tracks
|
||||
S_StopBackgroundTrack();
|
||||
|
||||
|
@ -237,8 +235,6 @@ S_StopBackgroundTrack
|
|||
*/
|
||||
void S_StopBackgroundTrack( void )
|
||||
{
|
||||
if( !al_state.initialized ) return;
|
||||
|
||||
S_StopStreaming();
|
||||
S_CloseBackgroundTrack(&s_bgTrack);
|
||||
Mem_Set(&s_bgTrack, 0, sizeof(bg_track_t));
|
||||
|
@ -251,13 +247,12 @@ S_StartStreaming
|
|||
*/
|
||||
void S_StartStreaming( void )
|
||||
{
|
||||
if( !al_state.initialized ) return;
|
||||
if( s_streamingChannel ) return; // already started
|
||||
|
||||
s_streamingChannel = S_PickChannel( 0, 0 );
|
||||
s_streamingChannel = SND_PickStaticChannel( 0, NULL );
|
||||
if( !s_streamingChannel ) return;
|
||||
|
||||
s_streamingChannel->streaming = true;
|
||||
s_streamingChannel->entchannel = CHAN_STREAM;
|
||||
|
||||
// FIXME: OpenAL bug?
|
||||
//palDeleteSources(1, &s_streamingChannel->sourceNum);
|
||||
|
@ -287,7 +282,7 @@ void S_StopStreaming( void )
|
|||
if( !al_state.initialized ) return;
|
||||
if( !s_streamingChannel ) return; // already stopped
|
||||
|
||||
s_streamingChannel->streaming = false;
|
||||
s_streamingChannel->entchannel = CHAN_AUTO;
|
||||
// clean up the source
|
||||
palSourceStop(s_streamingChannel->sourceNum);
|
||||
|
||||
|
|
|
@ -37,22 +37,14 @@ enum
|
|||
CHAN_NORMAL,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int rate;
|
||||
int width;
|
||||
int loopstart;
|
||||
int channels;
|
||||
int samples;
|
||||
} wavinfo_t;
|
||||
|
||||
typedef struct sfx_s
|
||||
{
|
||||
string name;
|
||||
bool loaded;
|
||||
int loopstart; // looping point (in samples)
|
||||
int loopStart; // looping point (in samples)
|
||||
int samples;
|
||||
int rate;
|
||||
int sampleStep; // ( samples / rate ) * 100
|
||||
uint format;
|
||||
uint bufferNum;
|
||||
|
||||
|
@ -74,24 +66,6 @@ typedef struct
|
|||
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
|
||||
bool use_loop; // ignore looping sounds for local sound
|
||||
vec3_t position; // Only use if fixedPosition is set
|
||||
float volume;
|
||||
float attenuation;
|
||||
float beginTime; // Begin at this time
|
||||
float pitch;
|
||||
} playSound_t;
|
||||
|
||||
// structure used for fading in and out client sound volume.
|
||||
typedef struct
|
||||
{
|
||||
|
@ -105,24 +79,20 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
bool streaming;
|
||||
sfx_t *sfx; // NULL if unused
|
||||
int state; // channel state
|
||||
|
||||
int entnum; // to allow overriding a specific sound
|
||||
int entchannel;
|
||||
float startTime; // for overriding oldest sounds
|
||||
|
||||
bool loopsound; // is looping sound ?
|
||||
int loopnum; // looping entity number
|
||||
int loopframe; // for stopping looping sounds
|
||||
int loopstart; // check it for set properly offset in samples
|
||||
|
||||
bool fixedPosition; // use position instead of fetching entity's origin
|
||||
uint startTime; // for overriding oldest sounds
|
||||
bool staticsound; // use position instead of fetching entity's origin
|
||||
vec3_t position; // only use if fixedPosition is set
|
||||
float volume;
|
||||
float pitch;
|
||||
float distanceMult;
|
||||
float pitch; // real-time pitch after any modulation or shift by dynamic data
|
||||
float dist_mult;
|
||||
uint sourceNum; // openAL source
|
||||
bool use_loop; // don't loop default and local sounds
|
||||
bool isSentence; // bit who indicated sentence
|
||||
} channel_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -164,7 +134,8 @@ typedef struct
|
|||
bool active;
|
||||
bool paused;
|
||||
uint framecount;
|
||||
int num_channels;
|
||||
int max_channels; // max channels that can be allocated by openAL
|
||||
int total_channels; // total playing channels at current time
|
||||
int clientnum;
|
||||
} alstate_t;
|
||||
|
||||
|
@ -180,6 +151,12 @@ extern cvar_t *s_allowEAX;
|
|||
extern cvar_t *s_musicvolume;
|
||||
extern cvar_t *s_check_errors;
|
||||
|
||||
//
|
||||
// s_load.c
|
||||
//
|
||||
bool S_TestSoundChar( const char *pch, char c );
|
||||
char *S_SkipSoundChar( const char *pch );
|
||||
|
||||
bool S_Init( void *hInst );
|
||||
void S_Shutdown( void );
|
||||
void S_Activate( bool active );
|
||||
|
@ -187,13 +164,15 @@ void S_SoundList_f( void );
|
|||
bool S_CheckForErrors( void );
|
||||
void S_Update( ref_params_t *fd );
|
||||
void S_StartSound( const vec3_t pos, int ent, int chan, sound_t sfx, float vol, float attn, int pitch, int flags );
|
||||
void S_StaticSound( const vec3_t pos, int ent, int chan, sound_t handle, float fvol, float attn, int pitch, int flags );
|
||||
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data );
|
||||
void S_StartBackgroundTrack( const char *intro, const char *loop );
|
||||
channel_t *S_PickChannel( int entNum, int entChannel );
|
||||
channel_t *SND_PickStaticChannel( int entnum, sfx_t *sfx );
|
||||
channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx );
|
||||
void S_FadeClientVolume( float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds );
|
||||
int S_StartLocalSound( const char *name, float volume, int pitch, const float *org );
|
||||
sfx_t *S_GetSfxByHandle( sound_t handle );
|
||||
void S_StopSound( int entnum, int channel );
|
||||
void S_StopSound( int entnum, int channel, const char *soundname );
|
||||
void S_StreamBackgroundTrack( void );
|
||||
void S_StopBackgroundTrack( void );
|
||||
void S_ClearSoundBuffer( void );
|
||||
|
|
|
@ -33,6 +33,7 @@ vsound_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, vsound_imp_t *engfuncs )
|
|||
|
||||
snd.FadeClientVolume = S_FadeClientVolume;
|
||||
snd.StartSound = S_StartSound;
|
||||
snd.StaticSound = S_StartStaticSound;
|
||||
snd.StreamRawSamples = S_StreamRawSamples;
|
||||
snd.StartLocalSound = S_StartLocalSound;
|
||||
snd.StartBackgroundTrack = S_StartBackgroundTrack;
|
||||
|
|
|
@ -374,8 +374,10 @@ channel_t *SND_PickStaticChannel( int entnum, sfx_t *sfx )
|
|||
{
|
||||
// no empty slots, alloc a new static sound channel
|
||||
if( total_channels == MAX_CHANNELS )
|
||||
{
|
||||
MsgDev( D_ERROR, "S_PickChannel: no free channels\n" );
|
||||
return NULL;
|
||||
|
||||
}
|
||||
// get a channel for the static sound
|
||||
ch = &channels[total_channels];
|
||||
total_channels++;
|
||||
|
@ -407,7 +409,7 @@ int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pitch, int
|
|||
// at a time, so we can just shut off
|
||||
// any channel that has ch->isSentence >= 0 and matches the entnum.
|
||||
|
||||
for( i = 0, ch = channels; i < total_channels; i++ )
|
||||
for( i = 0, ch = channels; i < total_channels; i++, ch++ )
|
||||
{
|
||||
if( ch->entnum == entnum && ch->entchannel == channel && ch->sfx && ch->isSentence )
|
||||
{
|
||||
|
@ -429,7 +431,7 @@ int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pitch, int
|
|||
}
|
||||
|
||||
// regular sound or streaming sound
|
||||
for( i = 0, ch = channels; i < total_channels; i++ )
|
||||
for( i = 0, ch = channels; i < total_channels; i++, ch++ )
|
||||
{
|
||||
if( ch->entnum == entnum && ch->entchannel == channel && ch->sfx )
|
||||
{
|
||||
|
@ -986,13 +988,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
|
|||
sfx_t *sfx = NULL;
|
||||
channel_t *target_chan, *check;
|
||||
int vol, fsentence = 0;
|
||||
int soundlevel, ch_idx;
|
||||
|
||||
if( pos )
|
||||
{
|
||||
S_StartStaticSound( pos, ent, chan, handle, fvol, attn, pitch, flags );
|
||||
return;
|
||||
}
|
||||
int ch_idx;
|
||||
|
||||
sfx = S_GetSfxByHandle( handle );
|
||||
if( !sfx ) return;
|
||||
|
@ -1027,7 +1023,6 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
|
|||
|
||||
if( S_TestSoundChar( sfx->name, '!' ))
|
||||
fsentence = true;
|
||||
soundlevel = ATTN_TO_SNDLVL( attn );
|
||||
|
||||
// spatialize
|
||||
Mem_Set( target_chan, 0, sizeof( *target_chan ));
|
||||
|
@ -1036,7 +1031,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
|
|||
VectorCopy( vec3_origin, target_chan->direction ); // initially unused
|
||||
target_chan->staticsound = ( ent == 0 ) ? true : false; // world static sound
|
||||
target_chan->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
|
||||
target_chan->dist_mult = SNDLVL_TO_DIST_MULT( soundlevel );
|
||||
target_chan->dist_mult = (attn / 1000.0f);
|
||||
target_chan->master_vol = vol;
|
||||
target_chan->entnum = ent;
|
||||
target_chan->entchannel = chan;
|
||||
|
@ -1141,7 +1136,6 @@ void S_StartStaticSound( const vec3_t pos, int ent, int chan, sound_t handle, fl
|
|||
int vol, fvox = 0;
|
||||
float flSoundRadius = 0.0f;
|
||||
bool looping = false;
|
||||
int soundlevel;
|
||||
|
||||
sfx = S_GetSfxByHandle( handle );
|
||||
if( !sfx ) return;
|
||||
|
@ -1161,6 +1155,8 @@ void S_StartStaticSound( const vec3_t pos, int ent, int chan, sound_t handle, fl
|
|||
return;
|
||||
}
|
||||
|
||||
if( !pos ) pos = vec3_origin;
|
||||
|
||||
// First, make sure the sound source entity is even in the PVS.
|
||||
SndInfo.pOrigin = NULL;
|
||||
SndInfo.pAngles = NULL;
|
||||
|
@ -1172,8 +1168,6 @@ void S_StartStaticSound( const vec3_t pos, int ent, int chan, sound_t handle, fl
|
|||
ch = SND_PickStaticChannel( ent, sfx ); // autolooping sounds are always fixed origin(?)
|
||||
if( !ch ) return;
|
||||
|
||||
soundlevel = ATTN_TO_SNDLVL( attn );
|
||||
|
||||
if( S_TestSoundChar( sfx->name, '!' ))
|
||||
{
|
||||
// this is a sentence. link words to play in sequence.
|
||||
|
@ -1198,8 +1192,9 @@ void S_StartStaticSound( const vec3_t pos, int ent, int chan, sound_t handle, fl
|
|||
|
||||
// never update positions if source entity is 0
|
||||
ch->staticsound = ( ent == 0 ) ? true : false;
|
||||
ch->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
|
||||
ch->master_vol = vol;
|
||||
ch->dist_mult = SNDLVL_TO_DIST_MULT( soundlevel );
|
||||
ch->dist_mult = (attn / 1000.0f);
|
||||
ch->basePitch = pitch;
|
||||
ch->entnum = ent;
|
||||
ch->entchannel = chan;
|
||||
|
@ -1213,6 +1208,8 @@ void S_StartStaticSound( const vec3_t pos, int ent, int chan, sound_t handle, fl
|
|||
ch->ob_gain_inc = 0.0;
|
||||
ch->ob_gain_target = 0.0;
|
||||
ch->bTraced = false;
|
||||
ch->pos = 0;
|
||||
ch->end = paintedtime + sfx->cache->samples;
|
||||
|
||||
SND_Spatialize( ch );
|
||||
}
|
||||
|
@ -1254,19 +1251,26 @@ void S_ClearBuffer( void )
|
|||
|
||||
/*
|
||||
==================
|
||||
S_StopAllSounds
|
||||
S_StopSound
|
||||
|
||||
stop all sounds for entity on a channel.
|
||||
==================
|
||||
*/
|
||||
void S_StopSound( int entnum, int channel )
|
||||
void S_StopSound( int entnum, int channel, const char *soundname )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < total_channels; i++ )
|
||||
{
|
||||
if( channels[i].entnum == entnum && channels[i].entchannel == channel )
|
||||
S_FreeChannel( &channels[i] );
|
||||
channel_t *ch = &channels[i];
|
||||
|
||||
if( !ch->sfx ) continue; // already freed
|
||||
if( ch->entnum == entnum && ch->entchannel == channel )
|
||||
{
|
||||
if( soundname && com.strcmp( ch->sfx->name, soundname ))
|
||||
continue;
|
||||
S_FreeChannel( ch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1346,10 +1350,9 @@ void S_RenderFrame( ref_params_t *fd )
|
|||
// if the loading plaque is up, clear everything
|
||||
// out to make sure we aren't looping a dirty
|
||||
// dma buffer while loading
|
||||
if( fd->paused )
|
||||
if( fd->paused && !s_listener.paused )
|
||||
{
|
||||
S_ClearBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
// update any client side sound fade
|
||||
|
@ -1365,6 +1368,9 @@ void S_RenderFrame( ref_params_t *fd )
|
|||
s_listener.frametime = fd->frametime;
|
||||
s_listener.waterlevel = fd->waterlevel;
|
||||
s_listener.ingame = si.IsInGame();
|
||||
s_listener.paused = fd->paused;
|
||||
|
||||
if( s_listener.paused ) return;
|
||||
|
||||
VectorCopy( fd->simorg, s_listener.origin );
|
||||
VectorCopy( fd->vieworg, s_listener.vieworg );
|
||||
|
@ -1508,10 +1514,9 @@ void S_Shutdown( void )
|
|||
Cmd_RemoveCommand( "s_info" );
|
||||
|
||||
S_StopAllSounds ();
|
||||
SNDDMA_Shutdown ();
|
||||
|
||||
S_FreeSounds ();
|
||||
SX_Free ();
|
||||
|
||||
SNDDMA_Shutdown ();
|
||||
Mem_FreePool( &sndpool );
|
||||
}
|
|
@ -128,45 +128,54 @@ CHANNEL MIXING
|
|||
|
||||
===============================================================================
|
||||
*/
|
||||
void S_PaintChannelFrom8( channel_t *ch, wavdata_t *sc, int count )
|
||||
void S_PaintChannelFrom8( channel_t *ch, wavdata_t *sc, int count, int offset )
|
||||
{
|
||||
int i, data;
|
||||
int data;
|
||||
int *lscale, *rscale;
|
||||
byte *sfx;
|
||||
portable_samplepair_t *samp;
|
||||
int i;
|
||||
|
||||
ch->leftvol = bound( 0, ch->leftvol, 255 );
|
||||
ch->rightvol = bound( 0, ch->rightvol, 255 );
|
||||
if( ch->leftvol > 255 ) ch->leftvol = 255;
|
||||
if( ch->rightvol > 255 ) ch->rightvol = 255;
|
||||
|
||||
lscale = snd_scaletable[ch->leftvol>>3];
|
||||
rscale = snd_scaletable[ch->rightvol>>3];
|
||||
sfx = (signed char *)sc->buffer + ch->pos;
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
samp = &paintbuffer[offset];
|
||||
|
||||
for( i = 0; i < count; i++, samp++ )
|
||||
{
|
||||
data = sfx[i];
|
||||
paintbuffer[i].left += lscale[data];
|
||||
paintbuffer[i].right += rscale[data];
|
||||
samp->left += lscale[data];
|
||||
samp->right += rscale[data];
|
||||
}
|
||||
ch->pos += count;
|
||||
}
|
||||
|
||||
void S_PaintChannelFrom16( channel_t *ch, wavdata_t *sc, int count )
|
||||
void S_PaintChannelFrom16( channel_t *ch, wavdata_t *sc, int count, int offset )
|
||||
{
|
||||
int i, data;
|
||||
int data;
|
||||
int left, right;
|
||||
int leftvol, rightvol;
|
||||
signed short *sfx;
|
||||
portable_samplepair_t *samp;
|
||||
int i;
|
||||
|
||||
ch->leftvol = bound( 0, ch->leftvol, 255 );
|
||||
ch->rightvol = bound( 0, ch->rightvol, 255 );
|
||||
leftvol = ch->leftvol * snd_vol;
|
||||
rightvol = ch->rightvol * snd_vol;
|
||||
sfx = (signed short *)sc->buffer + ch->pos;
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
samp = &paintbuffer[offset];
|
||||
|
||||
for( i = 0; i < count; i++, samp++ )
|
||||
{
|
||||
data = sfx[i];
|
||||
left = ( data * ch->leftvol ) >> 8;
|
||||
right = (data * ch->rightvol) >> 8;
|
||||
paintbuffer[i].left += left;
|
||||
paintbuffer[i].right += right;
|
||||
left = ( data * leftvol ) >> 8;
|
||||
right = (data * rightvol) >> 8;
|
||||
samp->left += left;
|
||||
samp->right += right;
|
||||
}
|
||||
ch->pos += count;
|
||||
}
|
||||
|
@ -192,16 +201,17 @@ void S_MixAllChannels( int endtime, int end )
|
|||
|
||||
while( ltime < end )
|
||||
{
|
||||
// paint up to end
|
||||
if( ch->end < end )
|
||||
count = ch->end - ltime;
|
||||
else count = end - ltime;
|
||||
// max painting is to the end of the buffer
|
||||
count = end - ltime;
|
||||
|
||||
// might be stopped by running out of data
|
||||
if( ch->end - ltime < count ) count = ch->end - ltime;
|
||||
|
||||
if( count > 0 )
|
||||
{
|
||||
if( sc->width == 1 )
|
||||
S_PaintChannelFrom8( ch, sc, count );
|
||||
else S_PaintChannelFrom16( ch, sc, count );
|
||||
S_PaintChannelFrom8( ch, sc, count, ltime - paintedtime );
|
||||
else S_PaintChannelFrom16( ch, sc, count, ltime - paintedtime );
|
||||
|
||||
ltime += count;
|
||||
}
|
||||
|
@ -209,13 +219,7 @@ void S_MixAllChannels( int endtime, int end )
|
|||
// if at end of loop, restart
|
||||
if( ltime >= ch->end )
|
||||
{
|
||||
if( ch->autosound && ch->use_loop )
|
||||
{
|
||||
// autolooped sounds always go back to start
|
||||
ch->pos = 0;
|
||||
ch->end = ltime + sc->samples;
|
||||
}
|
||||
else if( sc->loopStart >= 0 && ch->use_loop )
|
||||
if( sc->loopStart >= 0 && ch->use_loop )
|
||||
{
|
||||
ch->pos = sc->loopStart;
|
||||
ch->end = ltime + sc->samples - ch->pos;
|
||||
|
|
|
@ -86,14 +86,6 @@ typedef struct
|
|||
bool bTraced; // true if channel was already checked this frame for obscuring
|
||||
float radius; // radius of this sound effect
|
||||
bool doppler_effect; // this chanel has doppler effect
|
||||
|
||||
// obsolete. remove ?
|
||||
int looping; // where to loop, -1 = no looping OBSOLETE?
|
||||
|
||||
int loopnum; // entity num that playing autosound
|
||||
int loopframe; // for stopping looping sounds
|
||||
|
||||
bool autosound; // from an entity->sound, cleared each frame
|
||||
bool use_loop; // don't loop default and local sounds
|
||||
} channel_t;
|
||||
|
||||
|
@ -110,6 +102,7 @@ typedef struct
|
|||
int waterlevel;
|
||||
float frametime; // used for sound fade
|
||||
bool ingame; // listener in-game ?
|
||||
bool paused;
|
||||
} listener_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -206,7 +199,7 @@ channel_t *SND_PickStaticChannel( int entnum, sfx_t *sfx );
|
|||
void S_FadeClientVolume( float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds );
|
||||
int S_StartLocalSound( const char *name, float volume, int pitch, const float *org );
|
||||
sfx_t *S_GetSfxByHandle( sound_t handle );
|
||||
void S_StopSound( int entnum, int channel );
|
||||
void S_StopSound( int entnum, int channel, const char *soundname );
|
||||
void S_StopBackgroundTrack( void );
|
||||
void S_RenderFrame( ref_params_t *fd );
|
||||
void S_StartStreaming( void );
|
||||
|
|
|
@ -1039,13 +1039,6 @@ int CBaseEntity::Restore( CRestore &restore )
|
|||
SET_MODEL(ENT(pev), STRING(pev->model));
|
||||
UTIL_SetSize(pev, mins, maxs); // Reset them
|
||||
}
|
||||
|
||||
if( pev->soundindex != 0 && !FStringNull( pev->noise ))
|
||||
{
|
||||
PRECACHE_SOUND( (char *)STRING( pev->noise ));
|
||||
LINK_ENTITY( ENT( pev ), false );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -1100,11 +1100,11 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
|
|||
to->skin = pNet->pev->skin; // studio model skin
|
||||
to->body = pNet->pev->body; // studio model submodel
|
||||
to->effects = pNet->pev->effects; // shared client and render flags
|
||||
to->soundindex = pNet->pev->soundindex; // soundindex
|
||||
to->renderfx = pNet->pev->renderfx; // renderer flags
|
||||
to->rendermode = pNet->pev->rendermode; // rendering mode
|
||||
to->renderamt = pNet->pev->renderamt; // alpha value
|
||||
to->animtime = (int)(1000.0 * pNet->pev->animtime) * 0.001; // sequence time
|
||||
to->localtime = (int)(1000.0 * pNet->pev->ltime) * 0.001; // movement time
|
||||
to->scale = pNet->pev->scale; // shared client and render flags
|
||||
to->movetype = (movetype_t)pNet->pev->movetype;
|
||||
to->frame = pNet->pev->frame; // any model current frame
|
||||
|
@ -1177,16 +1177,6 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
|
|||
}
|
||||
else if( to->ed_type == ED_AMBIENT )
|
||||
{
|
||||
to->soundindex = pNet->pev->soundindex;
|
||||
|
||||
if( pNet->pev->solid == SOLID_TRIGGER )
|
||||
{
|
||||
Vector midPoint;
|
||||
|
||||
// NOTE: no reason to compute this shit on the client - save bandwidth
|
||||
midPoint = pNet->pev->mins + pNet->pev->maxs * 0.5f;
|
||||
to->origin += midPoint;
|
||||
}
|
||||
}
|
||||
else if( to->ed_type == ED_MOVER || to->ed_type == ED_BSPBRUSH || to->ed_type == ED_PORTAL )
|
||||
{
|
||||
|
|
|
@ -471,8 +471,6 @@ TYPEDESCRIPTION gEntvarsDescription[] =
|
|||
DEFINE_ENTITY_FIELD( modelindex, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( model, FIELD_MODELNAME ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( soundindex, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( viewmodel, FIELD_MODELNAME ),
|
||||
DEFINE_ENTITY_FIELD( weaponmodel, FIELD_MODELNAME ),
|
||||
|
||||
|
|
3
todo.log
3
todo.log
|
@ -35,5 +35,6 @@ Xash 0.71 Beta 05.05.10
|
|||
11.rewrite EntitiesInPVS check OK
|
||||
12.revision MOVETYPE_BOUNCE physic OK
|
||||
13.revision MOVETYPE_COMPOUND physic OK
|
||||
14.re-design sound library
|
||||
14.re-design sound library OK
|
||||
15. move loding sounds into launch.dll OK
|
||||
16.implement generic streaming background track
|
|
@ -242,7 +242,7 @@ bool R_SetPixelformat( void )
|
|||
Sys_LoadLibrary( NULL, &opengl_dll ); // load opengl32.dll
|
||||
if( !opengl_dll.link ) return false;
|
||||
|
||||
glw_state.minidriver = false; // FIXME
|
||||
glw_state.minidriver = false; // FIXME: allow 3dfx drivers too
|
||||
|
||||
if( glw_state.minidriver )
|
||||
{
|
||||
|
@ -417,6 +417,7 @@ void R_Free_OpenGL( void )
|
|||
DestroyWindow ( glw_state.hWnd );
|
||||
glw_state.hWnd = NULL;
|
||||
}
|
||||
|
||||
UnregisterClass( "Xash Window", glw_state.hInst );
|
||||
|
||||
if( glState.fullScreen )
|
||||
|
@ -433,16 +434,17 @@ void R_Free_OpenGL( void )
|
|||
|
||||
void R_SaveVideoMode( int vid_mode )
|
||||
{
|
||||
int i = bound( 0, vid_mode, num_vidmodes ); // check range
|
||||
int mode = bound( 0, vid_mode, num_vidmodes ); // check range
|
||||
|
||||
glState.width = vidmode[i].width;
|
||||
glState.height = vidmode[i].height;
|
||||
glState.wideScreen = vidmode[i].wideScreen;
|
||||
glState.width = vidmode[mode].width;
|
||||
glState.height = vidmode[mode].height;
|
||||
glState.wideScreen = vidmode[mode].wideScreen;
|
||||
|
||||
Cvar_FullSet( "width", va( "%i", vidmode[i].width ), CVAR_READ_ONLY );
|
||||
Cvar_FullSet( "height", va( "%i", vidmode[i].height ), CVAR_READ_ONLY );
|
||||
Cvar_SetValue( "r_mode", i ); // merge if out of bounds
|
||||
MsgDev( D_NOTE, "Set: %s [%dx%d]\n", vidmode[i].desc, vidmode[i].width, vidmode[i].height );
|
||||
Cvar_FullSet( "width", va( "%i", vidmode[mode].width ), CVAR_READ_ONLY );
|
||||
Cvar_FullSet( "height", va( "%i", vidmode[mode].height ), CVAR_READ_ONLY );
|
||||
Cvar_SetValue( "r_mode", mode ); // merge if it out of bounds
|
||||
|
||||
MsgDev( D_NOTE, "Set: %s [%dx%d]\n", vidmode[mode].desc, vidmode[mode].width, vidmode[mode].height );
|
||||
}
|
||||
|
||||
bool R_CreateWindow( int width, int height, bool fullscreen )
|
||||
|
@ -516,7 +518,7 @@ bool R_CreateWindow( int width, int height, bool fullscreen )
|
|||
|
||||
if( !glw_state.hWnd )
|
||||
{
|
||||
MsgDev( D_ERROR, "R_CreateWindow: couldn't create window %s\n", wndname );
|
||||
MsgDev( D_ERROR, "R_CreateWindow: couldn't create '%s'\n", wndname );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue