csgo-2018-source/public/soundinfo.h
2021-07-24 21:11:47 -07:00

326 lines
8.2 KiB
C

//========= Copyright (c) 1996-2005, 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"
#include "netmessages.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)
// the full float time for now.
#define SEND_SOUND_TIME 1
//-----------------------------------------------------------------------------
struct SoundInfo_t
{
Vector vOrigin;
Vector vDirection;
Vector vListenerOrigin;
const char *pszName; // UNDONE: Make this a FilenameHandle_t to avoid bugs with arrays of these
float fVolume;
float fDelay;
float fTickTime; // delay is encoded relative to this tick, fix up if packet is delayed
int nSequenceNumber;
int nEntityIndex;
int nChannel;
int nPitch;
int nFlags;
unsigned int nSoundNum;
int nSpeakerEntity;
int nRandomSeed;
soundlevel_t Soundlevel;
bool bIsSentence;
bool bIsAmbient;
bool bLooping;
//---------------------------------
enum SoundInfoInit_t
{
SOUNDINFO_SETDEFAULT,
SOUNDINFO_NO_SETDEFAULT,
};
SoundInfo_t( SoundInfoInit_t Init = SOUNDINFO_SETDEFAULT )
{
if( Init == SOUNDINFO_SETDEFAULT )
{
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, int nSeed )
{
nEntityIndex = newEntity;
nChannel = newChannel;
pszName = pszNewName;
vOrigin = newOrigin;
vDirection = newDirection;
fVolume = newVolume;
Soundlevel = newSoundLevel;
bLooping = newLooping;
nPitch = newPitch;
vListenerOrigin = vecListenerOrigin;
nSpeakerEntity = speakerentity;
nRandomSeed = nSeed;
}
void SetDefault()
{
fDelay = DEFAULT_SOUND_PACKET_DELAY;
fTickTime = 0;
fVolume = DEFAULT_SOUND_PACKET_VOLUME;
Soundlevel = SNDLVL_NORM;
nPitch = DEFAULT_SOUND_PACKET_PITCH;
nEntityIndex = 0;
nSpeakerEntity = -1;
nChannel = CHAN_STATIC;
nSoundNum = 0;
nFlags = 0;
nSequenceNumber = 0;
nRandomSeed = 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;
pszName = NULL;
fDelay = 0.0f;
nSequenceNumber = 0;
vOrigin.Init();
nSpeakerEntity = -1;
}
// this cries for Send/RecvTables:
void WriteDelta( const SoundInfo_t *delta, CSVCMsg_Sounds& Msg, float finalTickTime )
{
#define WRITE_DELTA_FIELD( _name, _protobufname) \
if( delta->_name != _name ) pSoundData->set_ ## _protobufname( _name );
#define WRITE_DELTA_FIELD_SCALED( _name, _protobufname, _scaled_val ) \
if( delta->_name != _name ) pSoundData->set_ ## _protobufname( _scaled_val );
SoundInfo_t defaultSound( SOUNDINFO_NO_SETDEFAULT );
CSVCMsg_Sounds::sounddata_t *pSoundData = Msg.add_sounds();
if( !delta )
{
defaultSound.SetDefault();
delta = &defaultSound;
}
WRITE_DELTA_FIELD( nEntityIndex, entity_index );
WRITE_DELTA_FIELD( nFlags, flags );
// Scriptable sounds are written as a hash, uses full 32 bits
if( nFlags & SND_IS_SCRIPTHANDLE )
{
WRITE_DELTA_FIELD( nSoundNum, sound_num_handle );
}
else
{
WRITE_DELTA_FIELD( nSoundNum, sound_num );
}
WRITE_DELTA_FIELD( nChannel, channel );
WRITE_DELTA_FIELD( bIsAmbient, is_ambient );
WRITE_DELTA_FIELD( bIsSentence, is_sentence ); // NOTE: SND_STOP behavior is different depending on this flag
if ( nFlags != SND_STOP )
{
WRITE_DELTA_FIELD_SCALED( nSequenceNumber, sequence_number, ( nSequenceNumber & SOUND_SEQNUMBER_MASK ) )
WRITE_DELTA_FIELD_SCALED( fVolume, volume, ( int )( fVolume * 127.0f ) );
WRITE_DELTA_FIELD( Soundlevel, sound_level );
WRITE_DELTA_FIELD( nPitch, pitch );
WRITE_DELTA_FIELD( nRandomSeed, random_seed );
float delayValue = fDelay;
if ( ( nFlags & SND_DELAY ) && ( fTickTime != finalTickTime ) )
{
delayValue += fTickTime - finalTickTime;
}
if ( delayValue != delta->fDelay )
{
pSoundData->set_delay_value( delayValue );
}
// don't transmit sounds with high precision
WRITE_DELTA_FIELD_SCALED( vOrigin.x, origin_x, ( int )( vOrigin.x * ( 1.0f / 8.0f ) ) );
WRITE_DELTA_FIELD_SCALED( vOrigin.y, origin_y, ( int )( vOrigin.y * ( 1.0f / 8.0f ) ) );
WRITE_DELTA_FIELD_SCALED( vOrigin.z, origin_z, ( int )( vOrigin.z * ( 1.0f / 8.0f ) ) );
WRITE_DELTA_FIELD( nSpeakerEntity, speaker_entity );
}
else
{
ClearStopFields();
}
#undef WRITE_DELTA_FIELD
#undef WRITE_DELTA_FIELD_SCALED
};
void ReadDelta( const SoundInfo_t *delta, const CSVCMsg_Sounds::sounddata_t& SoundData)
{
#define READ_DELTA_FIELD( _name, _protobufname ) \
_name = ( SoundData.has_ ## _protobufname() ) ? SoundData._protobufname() : delta->_name;
#define READ_DELTA_FIELD_SCALED( _name, _protobufname, _scale ) \
_name = ( SoundData.has_ ## _protobufname() ) ? ( SoundData._protobufname() * ( _scale ) ) : delta->_name;
READ_DELTA_FIELD( nEntityIndex, entity_index );
READ_DELTA_FIELD( nFlags, flags );
// Scriptable sounds are written as a hash, uses full 32 bits
if( nFlags & SND_IS_SCRIPTHANDLE )
{
READ_DELTA_FIELD( nSoundNum, sound_num_handle );
}
else
{
READ_DELTA_FIELD( nSoundNum, sound_num );
}
READ_DELTA_FIELD( nChannel, channel );
READ_DELTA_FIELD( bIsAmbient, is_ambient );
READ_DELTA_FIELD( bIsSentence, is_sentence ); // NOTE: SND_STOP behavior is different depending on this flag
if ( nFlags != SND_STOP )
{
READ_DELTA_FIELD( nSequenceNumber, sequence_number );
READ_DELTA_FIELD_SCALED( fVolume, volume, ( 1.0f / 127.0f ) );
Soundlevel = ( soundlevel_t )( SoundData.has_sound_level() ? SoundData.sound_level() : delta->Soundlevel );
READ_DELTA_FIELD( nPitch, pitch );
READ_DELTA_FIELD( nRandomSeed, random_seed );
READ_DELTA_FIELD( fDelay, delay_value );
READ_DELTA_FIELD_SCALED( vOrigin.x, origin_x, 8.0f );
READ_DELTA_FIELD_SCALED( vOrigin.y, origin_y, 8.0f );
READ_DELTA_FIELD_SCALED( vOrigin.z, origin_z, 8.0f );
READ_DELTA_FIELD( nSpeakerEntity, speaker_entity );
}
else
{
ClearStopFields();
}
#undef READ_DELTA_FIELD
#undef READ_DELTA_FIELD_SCALED
}
};
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;
CUtlVector< Vector > *m_pUtlVecMultiOrigins;
CUtlVector< QAngle > *m_pUtlVecMultiAngles;
};
#pragma pack()
#endif // SOUNDINFO_H