Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

395 lines
8.7 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef SOUNDINFO_H
#define SOUNDINFO_H
#ifdef _WIN32
#pragma once
#endif
#include "bitbuf.h"
#include "const.h"
#include "soundflags.h"
#include "coordsize.h"
#include "mathlib/vector.h"
#define WRITE_DELTA_UINT( name, length ) \
if ( name == delta->name ) \
buffer.WriteOneBit(0); \
else \
{ \
buffer.WriteOneBit(1); \
buffer.WriteUBitLong( name, length ); \
}
#define READ_DELTA_UINT( name, length ) \
if ( buffer.ReadOneBit() != 0 ) \
{ name = buffer.ReadUBitLong( length ); }\
else { name = delta->name; }
#define WRITE_DELTA_SINT( name, length ) \
if ( name == delta->name ) \
buffer.WriteOneBit(0); \
else \
{ \
buffer.WriteOneBit(1); \
buffer.WriteSBitLong( name, length ); \
}
#define WRITE_DELTA_SINT_SCALE( name, scale, length ) \
if ( name == delta->name ) \
buffer.WriteOneBit(0); \
else \
{ \
buffer.WriteOneBit(1); \
buffer.WriteSBitLong( name / scale, length ); \
}
#define READ_DELTA_SINT( name, length ) \
if ( buffer.ReadOneBit() != 0 ) \
{ name = buffer.ReadSBitLong( length ); } \
else { name = delta->name; }
#define READ_DELTA_SINT_SCALE( name, scale, length ) \
if ( buffer.ReadOneBit() != 0 ) \
{ name = scale * buffer.ReadSBitLong( length ); } \
else { name = delta->name; }
#define SOUND_SEQNUMBER_BITS 10
#define SOUND_SEQNUMBER_MASK ( (1<<SOUND_SEQNUMBER_BITS) - 1 )
// offset sound delay encoding by 60ms since we encode negative sound delays with less precision
// This means any negative sound delay greater than -100ms will get encoded at full precision
#define SOUND_DELAY_OFFSET (0.100f)
#pragma pack(4)
//-----------------------------------------------------------------------------
struct SoundInfo_t
{
int nSequenceNumber;
int nEntityIndex;
int nChannel;
const char *pszName; // UNDONE: Make this a FilenameHandle_t to avoid bugs with arrays of these
Vector vOrigin;
Vector vDirection;
float fVolume;
soundlevel_t Soundlevel;
bool bLooping;
int nPitch;
int nSpecialDSP;
Vector vListenerOrigin;
int nFlags;
int nSoundNum;
float fDelay;
bool bIsSentence;
bool bIsAmbient;
int nSpeakerEntity;
//---------------------------------
SoundInfo_t()
{
SetDefault();
}
void Set(int newEntity, int newChannel, const char *pszNewName, const Vector &newOrigin, const Vector& newDirection,
float newVolume, soundlevel_t newSoundLevel, bool newLooping, int newPitch, const Vector &vecListenerOrigin, int speakerentity )
{
nEntityIndex = newEntity;
nChannel = newChannel;
pszName = pszNewName;
vOrigin = newOrigin;
vDirection = newDirection;
fVolume = newVolume;
Soundlevel = newSoundLevel;
bLooping = newLooping;
nPitch = newPitch;
vListenerOrigin = vecListenerOrigin;
nSpeakerEntity = speakerentity;
}
void SetDefault()
{
fDelay = DEFAULT_SOUND_PACKET_DELAY;
fVolume = DEFAULT_SOUND_PACKET_VOLUME;
Soundlevel = SNDLVL_NORM;
nPitch = DEFAULT_SOUND_PACKET_PITCH;
nSpecialDSP = 0;
nEntityIndex = 0;
nSpeakerEntity = -1;
nChannel = CHAN_STATIC;
nSoundNum = 0;
nFlags = 0;
nSequenceNumber = 0;
pszName = NULL;
bLooping = false;
bIsSentence = false;
bIsAmbient = false;
vOrigin.Init();
vDirection.Init();
vListenerOrigin.Init();
}
void ClearStopFields()
{
fVolume = 0;
Soundlevel = SNDLVL_NONE;
nPitch = PITCH_NORM;
nSpecialDSP = 0;
pszName = NULL;
fDelay = 0.0f;
nSequenceNumber = 0;
vOrigin.Init();
nSpeakerEntity = -1;
}
// this cries for Send/RecvTables:
void WriteDelta( SoundInfo_t *delta, bf_write &buffer)
{
if ( nEntityIndex == delta->nEntityIndex )
{
buffer.WriteOneBit( 0 );
}
else
{
buffer.WriteOneBit( 1 );
if ( nEntityIndex <= 31)
{
buffer.WriteOneBit( 1 );
buffer.WriteUBitLong( nEntityIndex, 5 );
}
else
{
buffer.WriteOneBit( 0 );
buffer.WriteUBitLong( nEntityIndex, MAX_EDICT_BITS );
}
}
WRITE_DELTA_UINT( nSoundNum, MAX_SOUND_INDEX_BITS );
WRITE_DELTA_UINT( nFlags, SND_FLAG_BITS_ENCODE );
WRITE_DELTA_UINT( nChannel, 3 );
buffer.WriteOneBit( bIsAmbient?1:0 );
buffer.WriteOneBit( bIsSentence?1:0 ); // NOTE: SND_STOP behavior is different depending on this flag
if ( nFlags != SND_STOP )
{
if ( nSequenceNumber == delta->nSequenceNumber )
{
// didn't change, most often case
buffer.WriteOneBit( 1 );
}
else if ( nSequenceNumber == (delta->nSequenceNumber+1) )
{
// increased by one
buffer.WriteOneBit( 0 );
buffer.WriteOneBit( 1 );
}
else
{
// send full seqnr
buffer.WriteUBitLong( 0, 2 ); // 2 zero bits
buffer.WriteUBitLong( nSequenceNumber, SOUND_SEQNUMBER_BITS );
}
if ( fVolume == delta->fVolume )
{
buffer.WriteOneBit( 0 );
}
else
{
buffer.WriteOneBit( 1 );
buffer.WriteUBitLong( (unsigned int)(fVolume*127.0f), 7 );
}
WRITE_DELTA_UINT( Soundlevel, MAX_SNDLVL_BITS );
WRITE_DELTA_UINT( nPitch, 8 );
WRITE_DELTA_UINT( nSpecialDSP, 8 );
if ( fDelay == delta->fDelay )
{
buffer.WriteOneBit( 0 );
}
else
{
buffer.WriteOneBit( 1 );
// skipahead works in 10 ms increments
// bias results so that we only incur the precision loss on relatively large skipaheads
fDelay += SOUND_DELAY_OFFSET;
// Convert to msecs
int iDelay = fDelay * 1000.0f;
iDelay = clamp( iDelay, (int)(-10 * MAX_SOUND_DELAY_MSEC), (int)(MAX_SOUND_DELAY_MSEC) );
if ( iDelay < 0 )
{
iDelay /=10;
}
buffer.WriteSBitLong( iDelay , MAX_SOUND_DELAY_MSEC_ENCODE_BITS );
}
// don't transmit sounds with high precision
WRITE_DELTA_SINT_SCALE( vOrigin.x, 8.0f, COORD_INTEGER_BITS - 2 );
WRITE_DELTA_SINT_SCALE( vOrigin.y, 8.0f, COORD_INTEGER_BITS - 2 );
WRITE_DELTA_SINT_SCALE( vOrigin.z, 8.0f, COORD_INTEGER_BITS - 2 );
WRITE_DELTA_SINT( nSpeakerEntity, MAX_EDICT_BITS + 1 );
}
else
{
ClearStopFields();
}
};
void ReadDelta( SoundInfo_t *delta, bf_read &buffer, int nProtoVersion )
{
if ( !buffer.ReadOneBit() )
{
nEntityIndex = delta->nEntityIndex;
}
else
{
if ( buffer.ReadOneBit() )
{
nEntityIndex = buffer.ReadUBitLong( 5 );
}
else
{
nEntityIndex = buffer.ReadUBitLong( MAX_EDICT_BITS );
}
}
if ( nProtoVersion > 22 )
{
READ_DELTA_UINT( nSoundNum, MAX_SOUND_INDEX_BITS );
}
else
{
READ_DELTA_UINT( nSoundNum, 13 );
}
if ( nProtoVersion > 18 )
{
READ_DELTA_UINT( nFlags, SND_FLAG_BITS_ENCODE );
}
else
{
// There was 9 flag bits for version 18 and below (prior to Halloween 2011)
READ_DELTA_UINT( nFlags, 9 );
}
READ_DELTA_UINT( nChannel, 3 );
bIsAmbient = buffer.ReadOneBit() != 0;
bIsSentence = buffer.ReadOneBit() != 0; // NOTE: SND_STOP behavior is different depending on this flag
if ( nFlags != SND_STOP )
{
if ( buffer.ReadOneBit() != 0 )
{
nSequenceNumber = delta->nSequenceNumber;
}
else if ( buffer.ReadOneBit() != 0 )
{
nSequenceNumber = delta->nSequenceNumber + 1;
}
else
{
nSequenceNumber = buffer.ReadUBitLong( SOUND_SEQNUMBER_BITS );
}
if ( buffer.ReadOneBit() != 0 )
{
fVolume = (float)buffer.ReadUBitLong( 7 )/127.0f;
}
else
{
fVolume = delta->fVolume;
}
if ( buffer.ReadOneBit() != 0 )
{
Soundlevel = (soundlevel_t)buffer.ReadUBitLong( MAX_SNDLVL_BITS );
}
else
{
Soundlevel = delta->Soundlevel;
}
READ_DELTA_UINT( nPitch, 8 );
if ( nProtoVersion > 21 )
{
// These bit weren't written in version 19 and below
READ_DELTA_UINT( nSpecialDSP, 8 );
}
if ( buffer.ReadOneBit() != 0 )
{
// Up to 4096 msec delay
fDelay = (float)buffer.ReadSBitLong( MAX_SOUND_DELAY_MSEC_ENCODE_BITS ) / 1000.0f; ;
if ( fDelay < 0 )
{
fDelay *= 10.0f;
}
// bias results so that we only incur the precision loss on relatively large skipaheads
fDelay -= SOUND_DELAY_OFFSET;
}
else
{
fDelay = delta->fDelay;
}
READ_DELTA_SINT_SCALE( vOrigin.x, 8.0f, COORD_INTEGER_BITS - 2 );
READ_DELTA_SINT_SCALE( vOrigin.y, 8.0f, COORD_INTEGER_BITS - 2 );
READ_DELTA_SINT_SCALE( vOrigin.z, 8.0f, COORD_INTEGER_BITS - 2 );
READ_DELTA_SINT( nSpeakerEntity, MAX_EDICT_BITS + 1 );
}
else
{
ClearStopFields();
}
}
};
struct SpatializationInfo_t
{
typedef enum
{
SI_INCREATION = 0,
SI_INSPATIALIZATION
} SPATIALIZATIONTYPE;
// Inputs
SPATIALIZATIONTYPE type;
// Info about the sound, channel, origin, direction, etc.
SoundInfo_t info;
// Requested Outputs ( NULL == not requested )
Vector *pOrigin;
QAngle *pAngles;
float *pflRadius;
};
#pragma pack()
#endif // SOUNDINFO_H