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