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