25 Apr 2010

This commit is contained in:
g-cont 2010-04-25 00:00:00 +04:00 committed by Alibek Omarov
parent e95dfb116b
commit dac4b9eec0
42 changed files with 660 additions and 1111 deletions

View File

@ -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 )
{

View File

@ -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 ),

View File

@ -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 );

View File

@ -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)

View File

@ -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)

View File

@ -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 );

View File

@ -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 );
}
/*

View File

@ -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 );

View File

@ -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 );

View File

@ -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

View File

@ -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 },

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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, ... );

View File

@ -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 );

View File

@ -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)
@ -1477,9 +1477,9 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
MSG_WriteWord( &sv.multicast, sound_idx );
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_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol * 255 );
if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 );
if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
// plays from aiment
if( ent->v.aiment && !ent->v.aiment->free )
@ -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,14 +1549,14 @@ 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_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol * 255 );
if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 );
if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
// plays from fixed position
MSG_WriteWord( &sv.multicast, number );

View File

@ -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 ();

View File

@ -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 );
}
/*

View File

@ -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 )

View File

@ -7,11 +7,7 @@
#include "ref_params.h"
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 int sound_t;
typedef struct
{
@ -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 );

View File

@ -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;
}

View File

@ -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 );

View File

@ -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

View File

@ -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 )
{

View File

@ -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 ),

View File

@ -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 );

View File

@ -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;

View File

@ -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
@ -37,8 +30,8 @@ void S_SoundList_f( void )
int i, samples = 0;
int totalSfx = 0;
Msg("\n");
Msg(" -samples -hz-- -format- -name--------\n");
Msg( "\n" );
Msg( " -samples -hz-- -format- -name--------\n" );
for( i = 0; i < s_numSfx; i++ )
{
@ -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,377 +53,43 @@ 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++;
}
}
Msg("-------------------------------------------\n");
Msg("%i total samples\n", samples );
Msg("%i total sounds\n", totalSfx );
Msg("\n");
Msg( "-------------------------------------------\n" );
Msg( "%i total samples\n", samples );
Msg( "%i total sounds\n", totalSfx );
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;
// check first 2 characters
for( i = 0; i < 2; i++ )
{
if( *pcht == c )
return true;
pcht++;
}
return false;
}
/*
=================
S_GetLittleLong
=================
*/
static int S_GetLittleLong( void )
// return pointer to first valid character in file name
char *S_SkipSoundChar( const char *pch )
{
int val = 0;
char *pcht = (char *)pch;
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 );
return true;
}
/*
=======================================================================
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 )
{
MsgDev( D_ERROR, "S_LoadOGG: only mono OGG files supported (%s)\n", name );
ov_clear( &vf );
Mem_Free( data );
return false;
}
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
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;
}
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;

View File

@ -7,9 +7,9 @@
#include "const.h"
#include "trace_def.h"
#define MAX_PLAYSOUNDS 256
#define MAX_CHANNELS 64
#define CSXROOM 29
#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;
@ -87,7 +84,7 @@ bool S_CheckForErrors( void )
if( !s_check_errors->integer )
return false;
if((err = palGetError()) == AL_NO_ERROR)
if(( err = palGetError( )) == AL_NO_ERROR )
return false;
switch( err )
@ -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));
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 );
}
@ -294,25 +323,29 @@ S_SpatializeChannel
*/
static void S_SpatializeChannel( channel_t *ch )
{
vec3_t position, velocity;
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);
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);
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;
channel_t *ch;
int i;
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;
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 )
{
// jump to loopstart at next playing
ch->state = CHAN_FIRSTPLAY;
ch->loopstart = ps->sfx->loopstart;
}
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 );
}
// regular sound or streaming sound
for( i = 0, ch = s_channels; i < al_state.total_channels; i++, ch++ )
{
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;
}
}
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;
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 );
}
else ps->fixedPosition = false;
S_SpatializeChannel( target_chan );
S_PlayChannel( target_chan, sfx );
}
/*
=================
S_StartStaticSound
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
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;
ps->volume = vol;
ps->pitch = pitch / PITCH_NORM;
ps->attenuation = attn;
ps->beginTime = Sys_DoubleTime();
sfx = S_GetSfxByHandle( handle );
if( !sfx ) return;
// sort into the pending playSounds list
for( sort = s_pendingPlaySounds.next; sort != &s_pendingPlaySounds && sort->beginTime < ps->beginTime; sort = sort->next );
vol = bound( 0, fvol * 255, 255 );
ps->next = sort;
ps->prev = sort->prev;
ps->next->prev = ps;
ps->prev->next = ps;
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] );
@ -694,34 +839,32 @@ void S_Update( ref_params_t *fd )
// Set state
palDistanceModel( AL_INVERSE_DISTANCE_CLAMPED );
palDopplerFactor(s_dopplerFactor->value);
palDopplerVelocity(s_dopplerVelocity->value);
palDopplerFactor( s_dopplerFactor->value );
palDopplerVelocity( s_dopplerVelocity->value );
S_AddEnvironmentEffects ();
// Stream background track
S_StreamBackgroundTrack();
// Issue playSounds
S_IssuePlaySounds();
S_StreamBackgroundTrack ();
// 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 );
if( active ) palListenerf( AL_GAIN, S_GetMasterVolume( ));
else palListenerf( AL_GAIN, 0.0f );
}
/*
@ -805,22 +945,16 @@ S_SoundInfo_f
*/
void S_SoundInfo_f( void )
{
if(!al_state.initialized )
{
Msg("Sound system not started\n");
return;
}
Msg("\n");
Msg("AL_VENDOR: %s\n", al_config.vendor_string);
Msg("AL_RENDERER: %s\n", al_config.renderer_string);
Msg("AL_VERSION: %s\n", al_config.version_string);
Msg("AL_EXTENSIONS: %s\n", al_config.extensions_string);
Msg("\n");
Msg("DEVICE: %s\n", s_alDevice->string );
Msg("CHANNELS: %i\n", al_state.num_channels);
Msg("3D sound: %s\n", (al_config.allow_3DMode) ? "enabled" : "disabled" );
Msg("\n");
Msg( "\n" );
Msg( "AL_VENDOR: %s\n", al_config.vendor_string );
Msg( "AL_RENDERER: %s\n", al_config.renderer_string );
Msg( "AL_VERSION: %s\n", al_config.version_string );
Msg( "AL_EXTENSIONS: %s\n", al_config.extensions_string );
Msg( "\n" );
Msg( "DEVICE: %s\n", s_alDevice->string );
Msg( "CHANNELS: %i\n", al_state.max_channels );
Msg( "3D sound: %s\n", (al_config.allow_3DMode) ? "enabled" : "disabled" );
Msg( "\n" );
}
/*
@ -859,12 +993,11 @@ bool S_Init( void *hInst )
return false;
}
palcGetIntegerv( al_state.hDevice, ALC_MONO_SOURCES, sizeof(int), &num_mono_src );
palcGetIntegerv( al_state.hDevice, ALC_STEREO_SOURCES, sizeof(int), &num_stereo_src );
palcGetIntegerv( al_state.hDevice, ALC_MONO_SOURCES, sizeof( int ), &num_mono_src );
palcGetIntegerv( al_state.hDevice, ALC_STEREO_SOURCES, sizeof( int ), &num_stereo_src );
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;
}

View File

@ -132,27 +132,30 @@ S_InitDriver
*/
static bool S_InitDriver( void )
{
int attrlist[3] = { ALC_FREQUENCY, 44100, 0 };
int *al_contxt = attrlist;
int attrlist[3] = { ALC_FREQUENCY, 44100, 0 };
int *al_contxt = attrlist;
if((al_state.hDevice = palcOpenDevice( s_alDevice->string )) == NULL)
if(( al_state.hDevice = palcOpenDevice( s_alDevice->string )) == NULL )
{
Msg("alOpenDevice - failed\n" );
return false;
}
if((al_state.hALC = palcCreateContext( al_state.hDevice, al_contxt )) == NULL)
if(( al_state.hALC = palcCreateContext( al_state.hDevice, al_contxt )) == NULL )
goto failed;
if(!palcMakeContextCurrent(al_state.hALC))
if( !palcMakeContextCurrent( al_state.hALC ))
goto failed;
return true;
failed:
if(al_state.hALC)
if( al_state.hALC )
{
palcDestroyContext( al_state.hALC );
al_state.hALC = NULL;
}
if(al_state.hDevice)
if( al_state.hDevice )
{
palcCloseDevice( al_state.hDevice );
al_state.hDevice = NULL;
@ -171,11 +174,11 @@ static bool S_SetupEFX( void )
const dllfunc_t *func;
// get the function pointers
for(func = openal_effects; func && func->name != NULL; func++)
for( func = openal_effects; func && func->name != NULL; func++ )
{
if (!(*func->func = palGetProcAddress( func->name )))
if( !( *func->func = palGetProcAddress( func->name )))
{
MsgDev(D_ERROR, "S_InitEffects: %s missing or invalid function\n", func->name );
MsgDev( D_ERROR, "S_InitEffects: %s missing or invalid function\n", func->name );
return false;
}
}
@ -190,31 +193,31 @@ static void S_InitEffects( void )
if( palGetError() == AL_NO_ERROR )
{
MsgDev( D_NOTE, "S_InitEffects:" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_REVERB);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_REVERB );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_revrb" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_eaxrevrb" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_CHORUS);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_CHORUS );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_chorus" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_DISTORTION);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_DISTORTION );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_distortion" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_ECHO);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_ECHO );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_echo" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_FLANGER);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_FLANGER );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_flanger" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_FREQUENCY_SHIFTER);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_FREQUENCY_SHIFTER );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_frequency_shifter" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_VOCAL_MORPHER);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_VOCAL_MORPHER );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_vocal_morpher" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_pitch_shifter" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_ring_modulator" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_AUTOWAH);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_AUTOWAH );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_autowah" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_compressor" );
alEffecti(uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER);
alEffecti( uiEffects[0], AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_equalizer" );
MsgDev( D_NOTE, "\n" );
}
@ -229,15 +232,15 @@ static void S_InitFilters( void )
if( palGetError() == AL_NO_ERROR )
{
MsgDev( D_NOTE, "S_InitFilters:" );
alFilteri(uiFilters[0], AL_FILTER_TYPE, AL_FILTER_LOWPASS);
alFilteri( uiFilters[0], AL_FILTER_TYPE, AL_FILTER_LOWPASS );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_lowpass" );
alFilteri(uiFilters[0], AL_FILTER_TYPE, AL_FILTER_HIGHPASS);
alFilteri( uiFilters[0], AL_FILTER_TYPE, AL_FILTER_HIGHPASS );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_highpass" );
alFilteri(uiFilters[0], AL_FILTER_TYPE, AL_FILTER_BANDPASS);
alFilteri( uiFilters[0], AL_FILTER_TYPE, AL_FILTER_BANDPASS );
if(!palGetError()) MsgDev( D_NOTE, " ^3al_ext_bandpass" );
MsgDev( D_NOTE, "\n" );
}
alDeleteFilters(1, &uiFilters[0]);
alDeleteFilters( 1, &uiFilters[0] );
}
/*
@ -259,8 +262,8 @@ static void S_InitExtensions( void )
// check I3DL2 extension for NVidia's Sound Storm chips. I3DL2 is hidden and can be missed in extension list.
if( !com.strcmp( NVIDIA_DEVICE_NAME, al_config.deviceList[0] ))
{
I3DL2Get = (void *)palGetProcAddress("I3DL2Get");
I3DL2Set = (void *)palGetProcAddress("I3DL2Set");
I3DL2Get = (void *)palGetProcAddress( "I3DL2Get" );
I3DL2Set = (void *)palGetProcAddress( "I3DL2Set" );
if( I3DL2Get && I3DL2Set )
{
al_config.allow_3DMode = true;
@ -269,7 +272,7 @@ static void S_InitExtensions( void )
MsgDev( D_NOTE, "S_InitExtensions: enable I3DL2\n" );
}
}
if( palIsExtensionPresent("EAX3.0") && !al_config.allow_3DMode )
if( palIsExtensionPresent( "EAX3.0" ) && !al_config.allow_3DMode )
{
alEAXSet = (void *)palGetProcAddress( "EAXSet" );
alEAXGet = (void *)palGetProcAddress( "EAXGet" );
@ -281,7 +284,7 @@ static void S_InitExtensions( void )
MsgDev( D_NOTE, "S_InitExtensions: enable EAX 3.0\n" );
}
}
if( palIsExtensionPresent("EAX2.0") && !al_config.allow_3DMode )
if( palIsExtensionPresent( "EAX2.0" ) && !al_config.allow_3DMode )
{
alEAXSet = (void *)palGetProcAddress( "EAXSet" );
alEAXGet = (void *)palGetProcAddress( "EAXGet" );
@ -293,7 +296,7 @@ static void S_InitExtensions( void )
MsgDev( D_NOTE, "S_InitExtensions: enable EAX 2.0\n" );
}
}
if( palIsExtensionPresent("EAX") && !al_config.allow_3DMode )
if( palIsExtensionPresent( "EAX" ) && !al_config.allow_3DMode )
{
alEAXSet = (void *)palGetProcAddress( "EAXSet" );
alEAXGet = (void *)palGetProcAddress( "EAXGet" );
@ -306,18 +309,17 @@ static void S_InitExtensions( void )
}
}
if(palcIsExtensionPresent( al_state.hDevice, "ALC_EXT_EFX"))
if( palcIsExtensionPresent( al_state.hDevice, "ALC_EXT_EFX" ))
{
uint uiEffectSlots[MAX_EFFECTS] = { 0 };
if(!S_SetupEFX()) return;
if( !S_SetupEFX( )) return;
// testing effect slots
for( al_config.num_slots = 0; al_config.num_slots < MAX_EFFECTS; al_config.num_slots++ )
{
alGenAuxiliaryEffectSlots( 1, &uiEffectSlots[al_config.num_slots] );
if( palGetError() != AL_NO_ERROR) break;
if( palGetError() != AL_NO_ERROR ) break;
}
palcGetIntegerv( al_state.hDevice, ALC_MAX_AUXILIARY_SENDS, 1, &al_config.num_sends );
@ -340,7 +342,7 @@ bool S_Init_OpenAL( void )
}
// Get device list
if( palcIsExtensionPresent( NULL, "ALC_ENUMERATION_EXT"))
if( palcIsExtensionPresent( NULL, "ALC_ENUMERATION_EXT" ))
{
// get list of devices
const char *device_enum = palcGetString( NULL, ALC_DEVICE_SPECIFIER );
@ -361,13 +363,13 @@ bool S_Init_OpenAL( void )
}
// initialize the device, context, etc...
if(!S_InitDriver()) return false;
if( !S_InitDriver( )) return false;
// get some openal strings
al_config.vendor_string = palGetString(AL_VENDOR);
al_config.renderer_string = palGetString(AL_RENDERER); // stupid name :)
al_config.version_string = palGetString(AL_VERSION);
al_config.extensions_string = palGetString(AL_EXTENSIONS);
al_config.vendor_string = palGetString( AL_VENDOR );
al_config.renderer_string = palGetString( AL_RENDERER ); // stupid name :-)
al_config.version_string = palGetString( AL_VERSION );
al_config.extensions_string = palGetString( AL_EXTENSIONS );
MsgDev( D_INFO, "Audio: %s\n", al_config.renderer_string );
// Initialize extensions
@ -386,6 +388,7 @@ void S_Free_OpenAL( void )
palcDestroyContext( al_state.hALC );
al_state.hALC = NULL;
}
if( al_state.hDevice )
{
if( palcCloseDevice )
@ -394,6 +397,6 @@ void S_Free_OpenAL( void )
}
Sys_FreeLibrary( &openal_dll );
Mem_Set(&al_config, 0, sizeof(alconfig_t));
Mem_Set(&al_state, 0, sizeof(alstate_t));
Mem_Set( &al_config, 0, sizeof( alconfig_t ));
Mem_Set( &al_state, 0, sizeof( alstate_t ));
}

View File

@ -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);

View File

@ -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,14 +134,15 @@ 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;
extern alconfig_t al_config;
extern alstate_t al_state;
extern alconfig_t al_config;
extern alstate_t al_state;
#define Host_Error com.error
#define Host_Error com.error
#define Z_Malloc( size ) Mem_Alloc( sndpool, size )
// cvars
@ -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 );

View File

@ -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;

View File

@ -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 )
{
@ -438,7 +440,7 @@ int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pitch, int
if( flags & SND_CHANGE_VOL )
ch->master_vol = vol;
if( flags & SND_STOP )
S_FreeChannel( ch );
@ -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();
S_FreeSounds ();
SX_Free ();
SNDDMA_Shutdown ();
Mem_FreePool( &sndpool );
}

View File

@ -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 *lscale, *rscale;
byte *sfx;
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 left, right;
signed short *sfx;
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;

View File

@ -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 );

View File

@ -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;
}

View File

@ -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 )
{

View File

@ -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 ),

View File

@ -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
15. move loding sounds into launch.dll OK
14.re-design sound library OK
15. move loding sounds into launch.dll OK
16.implement generic streaming background track

View File

@ -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 )
@ -504,7 +506,7 @@ bool R_CreateWindow( int width, int height, bool fullscreen )
if( Cvar_VariableInteger( "r_mode" ) != glConfig.prev_mode )
{
if((x + w > glw_state.desktopWidth) || (y + h > glw_state.desktopHeight))
if(( x + w > glw_state.desktopWidth ) || ( y + h > glw_state.desktopHeight ))
{
x = ( glw_state.desktopWidth - w ) / 2;
y = ( glw_state.desktopHeight - h ) / 2;
@ -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;
}