1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef SND_CHANNELS_H
#define SND_CHANNELS_H
#include "mathlib/vector.h"
#if defined( _WIN32 )
#pragma once
#endif
class CSfxTable;
class CAudioMixer;
typedef int SoundSource;
// DO NOT REORDER: indices to fvolume arrays in channel_t
#define IFRONT_LEFT 0 // NOTE: must correspond to order of fvolume array below!
#define IFRONT_RIGHT 1
#define IREAR_LEFT 2
#define IREAR_RIGHT 3
#define IFRONT_CENTER 4
#define IFRONT_CENTER0 5 // dummy slot - center channel is mono, but mixers reference volume[1] slot
#define IFRONT_LEFTD 6 // start of doppler right array
#define IFRONT_RIGHTD 7
#define IREAR_LEFTD 8
#define IREAR_RIGHTD 9
#define IFRONT_CENTERD 10
#define IFRONT_CENTERD0 11 // dummy slot - center channel is mono, but mixers reference volume[1] slot
#define CCHANVOLUMES 12
//-----------------------------------------------------------------------------
// Purpose: Each currently playing wave is stored in a channel
//-----------------------------------------------------------------------------
// NOTE: 128bytes. These are memset to zero at some points. Do not add virtuals without changing that pattern.
// UNDONE: now 300 bytes...
struct channel_t
{
int guid; // incremented each time a channel is allocated (to match with channel free in tools, etc.)
int userdata; // user specified data for syncing to tools
CSfxTable *sfx; // the actual sound
CAudioMixer *pMixer; // The sound's instance data for this channel
// speaker channel volumes, indexed using IFRONT_LEFT to IFRONT_CENTER.
// NOTE: never access these fvolume[] elements directly! Use channel helpers in snd_dma.cpp.
float fvolume[CCHANVOLUMES]; // 0.0-255.0 current output volumes
float fvolume_target[CCHANVOLUMES]; // 0.0-255.0 target output volumes
float fvolume_inc[CCHANVOLUMES]; // volume increment, per frame, moves volume[i] to vol_target[i] (per spatialization)
uint nFreeChannelAtSampleTime;
SoundSource soundsource; // see iclientsound.h for description.
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
int speakerentity; // if a sound is being played through a speaker entity (e.g., on a monitor,), this is the
// entity upon which to show the lips moving, if the sound has sentence data
short master_vol; // 0-255 master volume
short basePitch; // base pitch percent (100% is normal pitch playback)
float pitch; // real-time pitch after any modulation or shift by dynamic data
int mixgroups[8]; // sound belongs to these mixgroups: world, actor, player weapon, explosion etc.
int last_mixgroupid;// last mixgroupid selected
float last_vol; // last volume after spatialization
Vector origin; // origin of sound effect
Vector direction; // direction of the sound
float dist_mult; // distance multiplier (attenuation/clipK)
float dspmix; // 0 - 1.0 proportion of dsp to mix with original sound, based on distance
float dspface; // -1.0 - 1.0 (1.0 = facing listener)
float distmix; // 0 - 1.0 proportion based on distance from listner (1.0 - 100% wav right - far)
float dsp_mix_min; // for dspmix calculation - set by current preset in SND_GetDspMix
float dsp_mix_max; // for dspmix calculation - set by current preset in SND_GetDspMix
float radius; // Radius of this sound effect (spatialization is different within the radius)
float ob_gain; // gain drop if sound source obscured from listener
float ob_gain_target; // target gain while crossfading between ob_gain & ob_gain_target
float ob_gain_inc; // crossfade increment
short activeIndex;
char wavtype; // 0 default, CHAR_DOPPLER, CHAR_DIRECTIONAL, CHAR_DISTVARIANT
char pad;
char sample_prev[8]; // last sample(s) in previous input data buffer - space for 2, 16 bit, stereo samples
int initialStreamPosition;
int special_dsp;
union
{
unsigned int flagsword;
struct
{
bool bUpdatePositions : 1; // if true, assume sound source can move and update according to entity
bool isSentence : 1; // true if playing linked sentence
bool bdry : 1; // if true, bypass all dsp processing for this sound (ie: music)
bool bSpeaker : 1; // true if sound is playing through in-game speaker entity.
bool bstereowav : 1; // if true, a stereo .wav file is the sample data source
bool delayed_start : 1; // If true, sound had a delay and so same sound on same channel won't channel steal from it
bool fromserver : 1; // for snd_show, networked sounds get colored differently than local sounds
bool bfirstpass : 1; // true if this is first time sound is spatialized
bool bTraced : 1; // true if channel was already checked this frame for obscuring
bool bfast_pitch : 1; // true if using low quality pitch (fast, but no interpolation)
bool m_bIsFreeingChannel : 1; // true when inside S_FreeChannel - prevents reentrance
bool m_bCompatibilityAttenuation : 1; // True when we want to use goldsrc compatibility mode for the attenuation
// In that case, dist_mul is set to a relatively meaningful value in StartDynamic/StartStaticSound,
// but we interpret it totally differently in SND_GetGain.
bool m_bShouldPause : 1; // if true, sound should pause when the game is paused
bool m_bIgnorePhonemes : 1; // if true, we don't want to drive animation w/ phoneme data
} flags;
};
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define MAX_CHANNELS 128
#define MAX_DYNAMIC_CHANNELS 64
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
extern channel_t channels[MAX_CHANNELS];
// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds
// MAX_DYNAMIC_CHANNELS to total_channels = static sounds
extern int total_channels;
class CChannelList
{
public:
int Count();
int GetChannelIndex( int listIndex );
channel_t *GetChannel( int listIndex );
void RemoveChannelFromList( int listIndex );
bool IsQuashed( int listIndex );
int m_count;
short m_list[MAX_CHANNELS];
bool m_quashed[MAX_CHANNELS]; // if true, the channel should be advanced, but not mixed, because it's been heuristically suppressed
CUtlVector< int > m_nSpecialDSPs;
bool m_hasSpeakerChannels : 1;
bool m_hasDryChannels : 1;
bool m_has11kChannels : 1;
bool m_has22kChannels : 1;
bool m_has44kChannels : 1;
};
inline int CChannelList::Count()
{
return m_count;
}
inline int CChannelList::GetChannelIndex( int listIndex )
{
return m_list[listIndex];
}
inline channel_t *CChannelList::GetChannel( int listIndex )
{
return &channels[GetChannelIndex(listIndex)];
}
inline bool CChannelList::IsQuashed( int listIndex )
{
return m_quashed[listIndex];
}
inline void CChannelList::RemoveChannelFromList( int listIndex )
{
// decrease the count by one, and swap the deleted channel with
// the last one.
m_count--;
if ( m_count > 0 && listIndex != m_count )
{
m_list[listIndex] = m_list[m_count];
m_quashed[listIndex] = m_quashed[m_count];
}
}
class CActiveChannels
{
public:
void Add( channel_t *pChannel );
void Remove( channel_t *pChannel );
void GetActiveChannels( CChannelList &list );
void Init();
int GetActiveCount() { return m_count; }
private:
int m_count;
short m_list[MAX_CHANNELS];
};
extern CActiveChannels g_ActiveChannels;
//=============================================================================
#endif // SND_CHANNELS_H
|