This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

347 lines
11 KiB
C

//========= 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 "coordsize.h"
#include "mathlib/vector.h"
#include "soundflags.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