summaryrefslogtreecommitdiff
path: root/engine/audio/private/snd_channels.h
blob: 06fd06506b603c352619f54a095b25f46dccf976 (plain) (blame)
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