1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #ifndef __SND_LOCAL_H__
30 #define __SND_LOCAL_H__
31 
32 #ifdef ID_DEDICATED
33 // stub-only mode: AL_API and ALC_API shouldn't refer to any dll-stuff
34 // because the implemenations are in openal_stub.cpp
35 // this is ensured by defining AL_LIBTYPE_STATIC before including the AL headers
36 #define AL_LIBTYPE_STATIC
37 #endif
38 
39 #include <AL/al.h>
40 #include <AL/alc.h>
41 #include <AL/alext.h>
42 
43 #include "framework/UsercmdGen.h"
44 #include "sound/efxlib.h"
45 #include "sound/sound.h"
46 
47 // demo sound commands
48 typedef enum {
49 	SCMD_STATE,				// followed by a load game state
50 	SCMD_PLACE_LISTENER,
51 	SCMD_ALLOC_EMITTER,
52 
53 	SCMD_FREE,
54 	SCMD_UPDATE,
55 	SCMD_START,
56 	SCMD_MODIFY,
57 	SCMD_STOP,
58 	SCMD_FADE
59 } soundDemoCommand_t;
60 
61 const int SOUND_MAX_CHANNELS		= 8;
62 const int SOUND_DECODER_FREE_DELAY	= 1000 * MIXBUFFER_SAMPLES / USERCMD_MSEC;		// four seconds
63 
64 const int PRIMARYFREQ				= 44100;			// samples per second
65 const float SND_EPSILON				= 1.0f / 32768.0f;	// if volume is below this, it will always multiply to zero
66 
67 const int ROOM_SLICES_IN_BUFFER		= 10;
68 
69 class idAudioBuffer;
70 class idWaveFile;
71 class idSoundCache;
72 class idSoundSample;
73 class idSampleDecoder;
74 class idSoundWorldLocal;
75 
76 
77 /*
78 ===================================================================================
79 
80 	General extended waveform format structure.
81 	Use this for all NON PCM formats.
82 
83 ===================================================================================
84 */
85 
86 #ifdef WIN32
87 #pragma pack(1)
88 #endif
89 struct waveformatex_s {
90 	word    wFormatTag;        /* format type */
91 	word    nChannels;         /* number of channels (i.e. mono, stereo...) */
92 	dword   nSamplesPerSec;    /* sample rate */
93 	dword   nAvgBytesPerSec;   /* for buffer estimation */
94 	word    nBlockAlign;       /* block size of data */
95 	word    wBitsPerSample;    /* Number of bits per sample of mono data */
96 	word    cbSize;            /* The count in bytes of the size of
97 									extra information (after cbSize) */
98 } PACKED;
99 
100 typedef waveformatex_s waveformatex_t;
101 
102 /* OLD general waveform format structure (information common to all formats) */
103 struct waveformat_s {
104 	word    wFormatTag;        /* format type */
105 	word    nChannels;         /* number of channels (i.e. mono, stereo, etc.) */
106 	dword   nSamplesPerSec;    /* sample rate */
107 	dword   nAvgBytesPerSec;   /* for buffer estimation */
108 	word    nBlockAlign;       /* block size of data */
109 } PACKED;
110 
111 typedef waveformat_s waveformat_t;
112 
113 /* flags for wFormatTag field of WAVEFORMAT */
114 enum {
115 	WAVE_FORMAT_TAG_PCM		= 1,
116 	WAVE_FORMAT_TAG_OGG		= 2
117 };
118 
119 /* specific waveform format structure for PCM data */
120 struct pcmwaveformat_s {
121 	waveformat_t	wf;
122 	word			wBitsPerSample;
123 } PACKED;
124 
125 typedef pcmwaveformat_s pcmwaveformat_t;
126 
127 #ifndef mmioFOURCC
128 #define mmioFOURCC( ch0, ch1, ch2, ch3 )				\
129 		( (dword)(byte)(ch0) | ( (dword)(byte)(ch1) << 8 ) |	\
130 		( (dword)(byte)(ch2) << 16 ) | ( (dword)(byte)(ch3) << 24 ) )
131 #endif
132 
133 #define fourcc_riff     mmioFOURCC('R', 'I', 'F', 'F')
134 
135 struct waveformatextensible_s {
136 	waveformatex_t    Format;
137 	union {
138 		word wValidBitsPerSample;       /* bits of precision  */
139 		word wSamplesPerBlock;          /* valid if wBitsPerSample==0*/
140 		word wReserved;                 /* If neither applies, set to zero*/
141 	} Samples;
142 	dword           dwChannelMask;      /* which channels are */
143 										/* present in stream  */
144 	int            SubFormat;
145 } PACKED;
146 
147 typedef waveformatextensible_s waveformatextensible_t;
148 
149 typedef dword fourcc;
150 
151 /* RIFF chunk information data structure */
152 struct mminfo_s {
153 	fourcc			ckid;           /* chunk ID */
154 	dword			cksize;         /* chunk size */
155 	fourcc			fccType;        /* form type or list type */
156 	dword			dwDataOffset;   /* offset of data portion of chunk */
157 } PACKED;
158 
159 typedef mminfo_s mminfo_t;
160 
161 #ifdef WIN32
162 #pragma pack()
163 #endif
164 
165 /*
166 ===================================================================================
167 
168 idWaveFile
169 
170 ===================================================================================
171 */
172 
173 class idWaveFile {
174 public:
175 					idWaveFile( void );
176 					~idWaveFile( void );
177 
178 	int				Open( const char* strFileName, waveformatex_t* pwfx = NULL );
179 	int				OpenFromMemory( short* pbData, int ulDataSize, waveformatextensible_t* pwfx );
180 	int				Read( byte* pBuffer, int dwSizeToRead, int *pdwSizeRead );
181 	int				Seek( int offset );
182 	int				Close( void );
183 	int				ResetFile( void );
184 
GetOutputSize(void)185 	int				GetOutputSize( void ) { return mdwSize; }
GetMemorySize(void)186 	int				GetMemorySize( void ) { return mMemSize; }
187 
188 	waveformatextensible_t	mpwfx;        // Pointer to waveformatex structure
189 
190 private:
191 	idFile *		mhmmio;			// I/O handle for the WAVE
192 	mminfo_t		mck;			// Multimedia RIFF chunk
193 	mminfo_t		mckRiff;		// used when opening a WAVE file
194 	dword			mdwSize;		// size in samples
195 	dword			mMemSize;		// size of the wave data in memory
196 	dword			mseekBase;
197 	ID_TIME_T			mfileTime;
198 
199 	bool			mbIsReadingFromMemory;
200 	short *			mpbData;
201 	short *			mpbDataCur;
202 	dword			mulDataSize;
203 
204 	void *			ogg;			// only !NULL when !s_realTimeDecoding
205 	bool			isOgg;
206 
207 private:
208 	int				ReadMMIO( void );
209 
210 	int				OpenOGG( const char* strFileName, waveformatex_t* pwfx = NULL );
211 	int				ReadOGG( byte* pBuffer, int dwSizeToRead, int *pdwSizeRead );
212 	int				CloseOGG( void );
213 };
214 
215 
216 /*
217 ===================================================================================
218 
219 Encapsulates functionality of a DirectSound buffer.
220 
221 ===================================================================================
222 */
223 
224 class idAudioBuffer {
225 public:
226 	virtual int		Play( dword dwPriority=0, dword dwFlags=0 ) = 0;
227 	virtual int			Stop( void ) = 0;
228 	virtual int			Reset( void ) = 0;
229 	virtual bool		IsSoundPlaying( void ) = 0;
230 	virtual void		SetVolume( float x ) = 0;
231 };
232 
233 
234 /*
235 ===================================================================================
236 
237 idSoundEmitterLocal
238 
239 ===================================================================================
240 */
241 
242 typedef enum {
243 	REMOVE_STATUS_INVALID				= -1,
244 	REMOVE_STATUS_ALIVE					=  0,
245 	REMOVE_STATUS_WAITSAMPLEFINISHED	=  1,
246 	REMOVE_STATUS_SAMPLEFINISHED		=  2
247 } removeStatus_t;
248 
249 class idSoundFade {
250 public:
251 	int					fadeStart44kHz;
252 	int					fadeEnd44kHz;
253 	float				fadeStartVolume;		// in dB
254 	float				fadeEndVolume;			// in dB
255 
256 	void				Clear();
257 	float				FadeDbAt44kHz( int current44kHz );
258 };
259 
260 class SoundFX {
261 protected:
262 	bool				initialized;
263 
264 	int					channel;
265 	int					maxlen;
266 
267 	float*				buffer;
268 	float				continuitySamples[4];
269 
270 	float				param;
271 
272 public:
SoundFX()273 						SoundFX()										{ channel = 0; buffer = NULL; initialized = false; maxlen = 0; memset( continuitySamples, 0, sizeof( float ) * 4 ); };
~SoundFX()274 	virtual				~SoundFX()										{ if ( buffer ) delete buffer; };
275 
Initialize()276 	virtual void		Initialize()									{ };
277 	virtual void		ProcessSample( float* in, float* out ) = 0;
278 
SetChannel(int chan)279 	void				SetChannel( int chan )							{ channel = chan; };
GetChannel()280 	int					GetChannel()									{ return channel; };
281 
SetContinuitySamples(float in1,float in2,float out1,float out2)282 	void				SetContinuitySamples( float in1, float in2, float out1, float out2 )		{ continuitySamples[0] = in1; continuitySamples[1] = in2; continuitySamples[2] = out1; continuitySamples[3] = out2; };		// FIXME?
GetContinuitySamples(float & in1,float & in2,float & out1,float & out2)283 	void				GetContinuitySamples( float& in1, float& in2, float& out1, float& out2 )	{ in1 = continuitySamples[0]; in2 = continuitySamples[1]; out1 = continuitySamples[2]; out2 = continuitySamples[3]; };
284 
SetParameter(float val)285 	void				SetParameter( float val )						{ param = val; };
286 };
287 
288 class SoundFX_Lowpass : public SoundFX {
289 public:
290 	virtual void		ProcessSample( float* in, float* out );
291 };
292 
293 class SoundFX_LowpassFast : public SoundFX {
294 	float				freq;
295 	float				res;
296 	float				a1, a2, a3;
297 	float				b1, b2;
298 
299 public:
300 	virtual void		ProcessSample( float* in, float* out );
301 	void				SetParms( float p1 = 0, float p2 = 0, float p3 = 0 );
302 };
303 
304 class SoundFX_Comb : public SoundFX {
305 	int					currentTime;
306 
307 public:
308 	virtual void		Initialize();
309 	virtual void		ProcessSample( float* in, float* out );
310 };
311 
312 class FracTime {
313 public:
314 	int			time;
315 	float		frac;
316 
Set(int val)317 	void		Set( int val )					{ time = val; frac = 0; };
Increment(float val)318 	void		Increment( float val )			{ frac += val; while ( frac >= 1.f ) { time++; frac--; } };
319 };
320 
321 enum {
322 	PLAYBACK_RESET,
323 	PLAYBACK_ADVANCING
324 };
325 
326 class idSoundChannel;
327 
328 class idSlowChannel {
329 	bool					active;
330 	const idSoundChannel*	chan;
331 
332 	int						playbackState;
333 	int						triggerOffset;
334 
335 	FracTime				newPosition;
336 	int						newSampleOffset;
337 
338 	FracTime				curPosition;
339 	int						curSampleOffset;
340 
341 	SoundFX_LowpassFast		lowpass;
342 
343 	// functions
344 	void					GenerateSlowChannel( FracTime& playPos, int sampleCount44k, float* finalBuffer );
345 
346 	float					GetSlowmoSpeed();
347 
348 public:
349 
350 	void					AttachSoundChannel( const idSoundChannel *chan );
351 	void					Reset();
352 
353 	void					GatherChannelSamples( int sampleOffset44k, int sampleCount44k, float *dest );
354 
IsActive()355 	bool					IsActive()				{ return active; };
GetCurrentPosition()356 	FracTime				GetCurrentPosition()	{ return curPosition; };
357 };
358 
359 class idSoundChannel {
360 public:
361 						idSoundChannel( void );
362 						~idSoundChannel( void );
363 
364 	void				Clear( void );
365 	void				Start( void );
366 	void				Stop( void );
367 	void				GatherChannelSamples( int sampleOffset44k, int sampleCount44k, float *dest ) const;
368 	void				ALStop( void );			// free OpenAL resources if any
369 
370 	bool				triggerState;
371 	int					trigger44kHzTime;		// hardware time sample the channel started
372 	int					triggerGame44kHzTime;	// game time sample time the channel started
373 	soundShaderParms_t	parms;					// combines the shader parms and the per-channel overrides
374 	idSoundSample *		leadinSample;			// if not looped, this is the only sample
375 	s_channelType		triggerChannel;
376 	const idSoundShader *soundShader;
377 	idSampleDecoder *	decoder;
378 	float				diversity;
379 	float				lastVolume;				// last calculated volume based on distance
380 	float				lastV[6];				// last calculated volume for each speaker, so we can smoothly fade
381 	idSoundFade			channelFade;
382 	bool				triggered;
383 	ALuint				openalSource;
384 	ALuint				openalStreamingOffset;
385 	ALuint				openalStreamingBuffer[3];
386 	ALuint				lastopenalStreamingBuffer[3];
387 	bool				stopped;
388 
389 	bool				disallowSlow;
390 
391 };
392 
393 class idSoundEmitterLocal : public idSoundEmitter {
394 public:
395 
396 						idSoundEmitterLocal( void );
397 	virtual				~idSoundEmitterLocal( void );
398 
399 	//----------------------------------------------
400 
401 	// the "time" parameters should be game time in msec, which is used to make queries
402 	// return deterministic values regardless of async buffer scheduling
403 
404 	// a non-immediate free will let all currently playing sounds complete
405 	virtual void		Free( bool immediate );
406 
407 	// the parms specified will be the default overrides for all sounds started on this emitter.
408 	// NULL is acceptable for parms
409 	virtual void		UpdateEmitter( const idVec3 &origin, int listenerId, const soundShaderParms_t *parms );
410 
411 	// returns the length of the started sound in msec
412 	virtual int			StartSound( const idSoundShader *shader, const s_channelType channel, float diversity = 0, int shaderFlags = 0, bool allowSlow = true /* D3XP */ );
413 
414 	// can pass SCHANNEL_ANY
415 	virtual void		ModifySound( const s_channelType channel, const soundShaderParms_t *parms );
416 	virtual void		StopSound( const s_channelType channel );
417 	virtual void		FadeSound( const s_channelType channel, float to, float over );
418 
419 	virtual bool		CurrentlyPlaying( void ) const;
420 
421 	// can pass SCHANNEL_ANY
422 	virtual	float		CurrentAmplitude( void );
423 
424 	// used for save games
425 	virtual	int			Index( void ) const;
426 
427 	//----------------------------------------------
428 
429 	void				Clear( void );
430 
431 	void				OverrideParms( const soundShaderParms_t *base, const soundShaderParms_t *over, soundShaderParms_t *out );
432 	void				CheckForCompletion( int current44kHzTime );
433 	void				Spatialize( idVec3 listenerPos, int listenerArea, idRenderWorld *rw );
434 
435 	idSoundWorldLocal *	soundWorld;				// the world that holds this emitter
436 
437 	int					index;						// in world emitter list
438 	removeStatus_t		removeStatus;
439 
440 	idVec3				origin;
441 	int					listenerId;
442 	soundShaderParms_t	parms;						// default overrides for all channels
443 
444 
445 	// the following are calculated in UpdateEmitter, and don't need to be archived
446 	float				maxDistance;				// greatest of all playing channel distances
447 	int					lastValidPortalArea;		// so an emitter that slides out of the world continues playing
448 	bool				playing;					// if false, no channel is active
449 	bool				hasShakes;
450 	idVec3				spatializedOrigin;			// the virtual sound origin, either the real sound origin,
451 													// or a point through a portal chain
452 	float				realDistance;				// in meters
453 	float				distance;					// in meters, this may be the straight-line distance, or
454 													// it may go through a chain of portals.  If there
455 													// is not an open-portal path, distance will be > maxDistance
456 
457 	// a single soundEmitter can have many channels playing from the same point
458 	idSoundChannel		channels[SOUND_MAX_CHANNELS];
459 
460 	idSlowChannel		slowChannels[SOUND_MAX_CHANNELS];
461 
462 	idSlowChannel		GetSlowChannel( const idSoundChannel *chan );
463 	void				SetSlowChannel( const idSoundChannel *chan, idSlowChannel slow );
464 	void				ResetSlowChannel( const idSoundChannel *chan );
465 
466 	// this is just used for feedback to the game or rendering system:
467 	// flashing lights and screen shakes.  Because the material expression
468 	// evaluation doesn't do common subexpression removal, we cache the
469 	// last generated value
470 	int					ampTime;
471 	float				amplitude;
472 };
473 
474 
475 /*
476 ===================================================================================
477 
478 idSoundWorldLocal
479 
480 ===================================================================================
481 */
482 
483 class s_stats {
484 public:
s_stats(void)485 	s_stats( void ) {
486 		rinuse = 0;
487 		runs = 1;
488 		timeinprocess = 0;
489 		missedWindow = 0;
490 		missedUpdateWindow = 0;
491 		activeSounds = 0;
492 	}
493 	int		rinuse;
494 	int		runs;
495 	int		timeinprocess;
496 	int		missedWindow;
497 	int		missedUpdateWindow;
498 	int		activeSounds;
499 };
500 
501 typedef struct soundPortalTrace_s {
502 	int		portalArea;
503 	const struct soundPortalTrace_s	*prevStack;
504 } soundPortalTrace_t;
505 
506 class idSoundWorldLocal : public idSoundWorld {
507 public:
508 	virtual					~idSoundWorldLocal( void );
509 
510 	// call at each map start
511 	virtual void			ClearAllSoundEmitters( void );
512 	virtual void			StopAllSounds( void );
513 
514 	// get a new emitter that can play sounds in this world
515 	virtual idSoundEmitter *AllocSoundEmitter( void );
516 
517 	// for load games
518 	virtual idSoundEmitter *EmitterForIndex( int index );
519 
520 	// query data from all emitters in the world
521 	virtual float			CurrentShakeAmplitudeForPosition( const int time, const idVec3 &listererPosition );
522 
523 	// where is the camera/microphone
524 	// listenerId allows listener-private sounds to be added
525 	virtual void			PlaceListener( const idVec3 &origin, const idMat3 &axis, const int listenerId, const int gameTime, const idStr& areaName );
526 
527 	// fade all sounds in the world with a given shader soundClass
528 	// to is in Db (sigh), over is in seconds
529 	virtual void			FadeSoundClasses( const int soundClass, const float to, const float over );
530 
531 	// dumps the current state and begins archiving commands
532 	virtual void			StartWritingDemo( idDemoFile *demo );
533 	virtual void			StopWritingDemo( void );
534 
535 	// read a sound command from a demo file
536 	virtual void			ProcessDemoCommand( idDemoFile *readDemo );
537 
538 	// background music
539 	virtual void			PlayShaderDirectly( const char *name, int channel = -1 );
540 
541 	// pause and unpause the sound world
542 	virtual void			Pause( void );
543 	virtual void			UnPause( void );
544 	virtual bool			IsPaused( void );
545 
546 	// avidump
547 	virtual void			AVIOpen( const char *path, const char *name );
548 	virtual void			AVIClose( void );
549 
550 	// SaveGame Support
551 	virtual void			WriteToSaveGame( idFile *savefile );
552 	virtual void			ReadFromSaveGame( idFile *savefile );
553 
554 	virtual void			ReadFromSaveGameSoundChannel( idFile *saveGame, idSoundChannel *ch );
555 	virtual void			ReadFromSaveGameSoundShaderParams( idFile *saveGame, soundShaderParms_t *params );
556 	virtual void			WriteToSaveGameSoundChannel( idFile *saveGame, idSoundChannel *ch );
557 	virtual void			WriteToSaveGameSoundShaderParams( idFile *saveGame, soundShaderParms_t *params );
558 
559 	virtual void			SetSlowmo( bool active );
560 	virtual void			SetSlowmoSpeed( float speed );
561 	virtual void			SetEnviroSuit( bool active );
562 
563 	//=======================================
564 
565 							idSoundWorldLocal( void );
566 
567 	void					Shutdown( void );
568 	void					Init( idRenderWorld *rw );
569 
570 	// update
571 	void					ForegroundUpdate( int currentTime );
572 	void					OffsetSoundTime( int offset44kHz );
573 
574 	idSoundEmitterLocal *	AllocLocalSoundEmitter();
575 	void					CalcEars( int numSpeakers, idVec3 realOrigin, idVec3 listenerPos, idMat3 listenerAxis, float ears[6], float spatialize );
576 	void					AddChannelContribution( idSoundEmitterLocal *sound, idSoundChannel *chan,
577 												int current44kHz, int numSpeakers, float *finalMixBuffer );
578 	void					MixLoop( int current44kHz, int numSpeakers, float *finalMixBuffer );
579 	void					AVIUpdate( void );
580 	void					ResolveOrigin( const int stackDepth, const soundPortalTrace_t *prevStack, const int soundArea, const float dist, const idVec3& soundOrigin, idSoundEmitterLocal *def );
581 	float					FindAmplitude( idSoundEmitterLocal *sound, const int localTime, const idVec3 *listenerPosition, const s_channelType channel, bool shakesOnly );
582 
583 	//============================================
584 
585 	idRenderWorld *			rw;				// for portals and debug drawing
586 	idDemoFile *			writeDemo;			// if not NULL, archive commands here
587 
588 	idMat3					listenerAxis;
589 	idVec3					listenerPos;		// position in meters
590 	int						listenerPrivateId;
591 	idVec3					listenerQU;			// position in "quake units"
592 	int						listenerArea;
593 	idStr					listenerAreaName;
594 	ALuint					listenerEffect;
595 	ALuint					listenerSlot;
596 	bool					listenerAreFiltersInitialized;
597 	ALuint					listenerFilters[2]; // 0 - direct; 1 - send.
598 
599 	int						gameMsec;
600 	int						game44kHz;
601 	int						pause44kHz;
602 	int						lastAVI44kHz;		// determine when we need to mix and write another block
603 
604 	idList<idSoundEmitterLocal *>emitters;
605 
606 	idSoundFade				soundClassFade[SOUND_MAX_CLASSES];	// for global sound fading
607 
608 	// avi stuff
609 	idFile *				fpa[6];
610 	idStr					aviDemoPath;
611 	idStr					aviDemoName;
612 
613 	idSoundEmitterLocal *	localSound;		// just for playShaderDirectly()
614 
615 	bool					slowmoActive;
616 	float					slowmoSpeed;
617 	bool					enviroSuitActive;
618 };
619 
620 /*
621 ===================================================================================
622 
623 idSoundSystemLocal
624 
625 ===================================================================================
626 */
627 
628 typedef struct {
629 	ALuint			handle;
630 	int				startTime;
631 	idSoundChannel	*chan;
632 	bool			inUse;
633 	bool			looping;
634 	bool			stereo;
635 } openalSource_t;
636 
637 class idSoundSystemLocal : public idSoundSystem {
638 public:
idSoundSystemLocal()639 	idSoundSystemLocal( ) {
640 		isInitialized = false;
641 	}
642 
643 	// all non-hardware initialization
644 	virtual void			Init( void );
645 
646 	// shutdown routine
647 	virtual	void			Shutdown( void );
648 
649 	// sound is attached to the window, and must be recreated when the window is changed
650 	virtual bool			ShutdownHW( void );
651 	virtual bool			InitHW( void );
652 
653 	// async loop, called at 60Hz
654 	virtual int				AsyncUpdate( int time );
655 	// async loop, when the sound driver uses a write strategy
656 	virtual int				AsyncUpdateWrite( int time );
657 	// direct mixing called from the sound driver thread for OSes that support it
658 	virtual int				AsyncMix( int soundTime, float *mixBuffer );
659 
660 	virtual void			SetMute( bool mute );
661 
662 	virtual cinData_t		ImageForTime( const int milliseconds, const bool waveform );
663 
664 	int						GetSoundDecoderInfo( int index, soundDecoderInfo_t &decoderInfo );
665 
666 	// if rw == NULL, no portal occlusion or rendered debugging is available
667 	virtual idSoundWorld	*AllocSoundWorld( idRenderWorld *rw );
668 
669 	// specifying NULL will cause silence to be played
670 	virtual void			SetPlayingSoundWorld( idSoundWorld *soundWorld );
671 
672 	// some tools, like the sound dialog, may be used in both the game and the editor
673 	// This can return NULL, so check!
674 	virtual idSoundWorld	*GetPlayingSoundWorld( void );
675 
676 	virtual	void			BeginLevelLoad( void );
677 	virtual	void			EndLevelLoad( const char *mapString );
678 
679 	virtual void			PrintMemInfo( MemInfo_t *mi );
680 
681 	virtual int				IsEFXAvailable( void );
682 
683 	//-------------------------
684 
685 	int						GetCurrent44kHzTime( void ) const;
686 	float					dB2Scale( const float val ) const;
687 	int						SamplesToMilliseconds( int samples ) const;
688 	int						MillisecondsToSamples( int ms ) const;
689 
690 	void					DoEnviroSuit( float* samples, int numSamples, int numSpeakers );
691 
692 	ALuint					AllocOpenALSource( idSoundChannel *chan, bool looping, bool stereo );
693 	void					FreeOpenALSource( ALuint handle );
694 
695 	// returns true if openalDevice is still available,
696 	// otherwise it will try to recover the device and return false while it's gone
697 	// (display audio sound devices sometimes disappear for a few seconds when switching resolution)
698 	bool					CheckDeviceAndRecoverIfNeeded();
699 
700 	idSoundCache *			soundCache;
701 
702 	idSoundWorldLocal *		currentSoundWorld;	// the one to mix each async tic
703 
704 	int						olddwCurrentWritePos;	// statistics
705 	int						buffers;				// statistics
706 	int						CurrentSoundTime;		// set by the async thread and only used by the main thread
707 
708 	unsigned int			nextWriteBlock;
709 
710 	float					realAccum[6*MIXBUFFER_SAMPLES+16];
711 	float *					finalMixBuffer;			// points inside realAccum at a 16 byte aligned boundary
712 
713 	bool					isInitialized;
714 	bool					muted;
715 	bool					shutdown;
716 
717 	s_stats					soundStats;				// NOTE: updated throughout the code, not displayed anywhere
718 
719 	int						meterTops[256];
720 	int						meterTopsTime[256];
721 
722 	dword *					graph;
723 
724 	float					volumesDB[1200];		// dB to float volume conversion
725 
726 	idList<SoundFX*>		fxList;
727 
728 	ALCdevice				*openalDevice;
729 	ALCcontext				*openalContext;
730 	ALsizei					openalSourceCount;
731 	openalSource_t			openalSources[256];
732 
733 	LPALGENEFFECTS			alGenEffects;
734 	LPALDELETEEFFECTS		alDeleteEffects;
735 	LPALISEFFECT			alIsEffect;
736 	LPALEFFECTI				alEffecti;
737 	LPALEFFECTF				alEffectf;
738 	LPALEFFECTFV			alEffectfv;
739 	LPALGENFILTERS			alGenFilters;
740 	LPALDELETEFILTERS		alDeleteFilters;
741 	LPALISFILTER			alIsFilter;
742 	LPALFILTERI				alFilteri;
743 	LPALFILTERF				alFilterf;
744 	LPALGENAUXILIARYEFFECTSLOTS		alGenAuxiliaryEffectSlots;
745 	LPALDELETEAUXILIARYEFFECTSLOTS	alDeleteAuxiliaryEffectSlots;
746 	LPALISAUXILIARYEFFECTSLOT		alIsAuxiliaryEffectSlot;
747 	LPALAUXILIARYEFFECTSLOTI		alAuxiliaryEffectSloti;
748 
749 	idEFXFile				EFXDatabase;
750 	bool					efxloaded;
751 							// latches
752 	static bool				useEFXReverb;
753 							// mark available during initialization, or through an explicit test
754 	static int				EFXAvailable;
755 
756 	// DG: for CheckDeviceAndRecoverIfNeeded()
757 	LPALCRESETDEVICESOFT	alcResetDeviceSOFT; // needs ALC_SOFT_HRTF extension
758 	int						resetRetryCount;
759 	unsigned int			lastCheckTime;
760 
761 	static idCVar			s_noSound;
762 	static idCVar			s_device;
763 	static idCVar			s_quadraticFalloff;
764 	static idCVar			s_drawSounds;
765 	static idCVar			s_minVolume6;
766 	static idCVar			s_dotbias6;
767 	static idCVar			s_minVolume2;
768 	static idCVar			s_dotbias2;
769 	static idCVar			s_spatializationDecay;
770 	static idCVar			s_showStartSound;
771 	static idCVar			s_maxSoundsPerShader;
772 	static idCVar			s_reverse;
773 	static idCVar			s_showLevelMeter;
774 	static idCVar			s_meterTopTime;
775 	static idCVar			s_volume;
776 	static idCVar			s_constantAmplitude;
777 	static idCVar			s_playDefaultSound;
778 	static idCVar			s_useOcclusion;
779 	static idCVar			s_subFraction;
780 	static idCVar			s_globalFraction;
781 	static idCVar			s_doorDistanceAdd;
782 	static idCVar			s_singleEmitter;
783 	static idCVar			s_numberOfSpeakers;
784 	static idCVar			s_force22kHz;
785 	static idCVar			s_clipVolumes;
786 	static idCVar			s_realTimeDecoding;
787 	static idCVar			s_useEAXReverb;
788 	static idCVar			s_decompressionLimit;
789 
790 	static idCVar			s_slowAttenuate;
791 
792 	static idCVar			s_enviroSuitCutoffFreq;
793 	static idCVar			s_enviroSuitCutoffQ;
794 	static idCVar			s_enviroSuitSkipLowpass;
795 	static idCVar			s_enviroSuitSkipReverb;
796 
797 	static idCVar			s_reverbTime;
798 	static idCVar			s_reverbFeedback;
799 	static idCVar			s_enviroSuitVolumeScale;
800 	static idCVar			s_skipHelltimeFX;
801 };
802 
803 extern	idSoundSystemLocal	soundSystemLocal;
804 
805 
806 /*
807 ===================================================================================
808 
809   This class holds the actual wavefile bitmap, size, and info.
810 
811 ===================================================================================
812 */
813 
814 const int SCACHE_SIZE = MIXBUFFER_SAMPLES*20;	// 1/2 of a second (aroundabout)
815 
816 class idSoundSample {
817 public:
818 							idSoundSample();
819 							~idSoundSample();
820 
821 	idStr					name;						// name of the sample file
822 	ID_TIME_T					timestamp;					// the most recent of all images used in creation, for reloadImages command
823 
824 	waveformatex_t			objectInfo;					// what are we caching
825 	int						objectSize;					// size of waveform in samples, excludes the header
826 	int						objectMemSize;				// object size in memory
827 	byte *					nonCacheData;				// if it's not cached
828 	byte *					amplitudeData;				// precomputed min,max amplitude pairs
829 	ALuint					openalBuffer;				// openal buffer
830 	bool					hardwareBuffer;
831 	bool					defaultSound;
832 	bool					onDemand;
833 	bool					purged;
834 	bool					levelLoadReferenced;		// so we can tell which samples aren't needed any more
835 
836 	int						LengthIn44kHzSamples() const;
837 	ID_TIME_T					GetNewTimeStamp( void ) const;
838 	void					MakeDefault();				// turns it into a beep
839 	void					Load();						// loads the current sound based on name
840 	void					Reload( bool force );		// reloads if timestamp has changed, or always if force
841 	void					PurgeSoundSample();			// frees all data
842 	void					CheckForDownSample();		// down sample if required
843 	bool					FetchFromCache( int offset, const byte **output, int *position, int *size, const bool allowIO );
844 };
845 
846 
847 /*
848 ===================================================================================
849 
850   Sound sample decoder.
851 
852 ===================================================================================
853 */
854 
855 class idSampleDecoder {
856 public:
857 	static void				Init( void );
858 	static void				Shutdown( void );
859 	static idSampleDecoder *Alloc( void );
860 	static void				Free( idSampleDecoder *decoder );
861 	static int				GetNumUsedBlocks( void );
862 	static int				GetUsedBlockMemory( void );
863 
~idSampleDecoder(void)864 	virtual					~idSampleDecoder( void ) {}
865 	virtual void			Decode( idSoundSample *sample, int sampleOffset44k, int sampleCount44k, float *dest ) = 0;
866 	virtual void			ClearDecoder( void ) = 0;
867 	virtual idSoundSample *	GetSample( void ) const = 0;
868 	virtual int				GetLastDecodeTime( void ) const = 0;
869 };
870 
871 
872 /*
873 ===================================================================================
874 
875   The actual sound cache.
876 
877 ===================================================================================
878 */
879 
880 class idSoundCache {
881 public:
882 							idSoundCache();
883 							~idSoundCache();
884 
885 	idSoundSample *			FindSound( const idStr &fname, bool loadOnDemandOnly );
886 
GetNumObjects(void)887 	const int				GetNumObjects( void ) { return listCache.Num(); }
888 	const idSoundSample *	GetObject( const int index ) const;
889 
890 	void					ReloadSounds( bool force );
891 
892 	void					BeginLevelLoad();
893 	void					EndLevelLoad();
894 
895 	void					PrintMemInfo( MemInfo_t *mi );
896 
897 private:
898 	bool					insideLevelLoad;
899 	idList<idSoundSample*>	listCache;
900 };
901 
902 #endif /* !__SND_LOCAL_H__ */
903