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