]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/audiostr.cpp
cleanup; compile warning fixes
[taylor/freespace2.git] / src / sound / audiostr.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Sound/AudioStr.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Routines to stream large WAV files from disk
16  *
17  * $Log$
18  * Revision 1.6  2003/08/03 16:10:30  taylor
19  * cleanup; compile warning fixes
20  *
21  * Revision 1.5  2002/06/09 04:41:26  relnev
22  * added copyright header
23  *
24  * Revision 1.4  2002/06/05 04:03:33  relnev
25  * finished cfilesystem.
26  *
27  * removed some old code.
28  *
29  * fixed mouse save off-by-one.
30  *
31  * sound cleanups.
32  *
33  * Revision 1.3  2002/05/27 18:42:50  theoddone33
34  * Fix missing audiostr_* symbols
35  *
36  * Revision 1.2  2002/05/07 03:16:52  theoddone33
37  * The Great Newline Fix
38  *
39  * Revision 1.1.1.1  2002/05/03 03:28:10  root
40  * Initial import.
41  *
42  * 
43  * 5     9/14/99 1:32a Jimb
44  * Commented out Int3() that was hanging Jim's machine.  Happens before
45  * sm2-07 command brief.
46  * 
47  * 4     7/14/99 12:09p Jefff
48  * Make sure we're not servicing a bogus audiostream. Check for "used"
49  * after the critical section lock.
50  * 
51  * 3     12/17/98 4:01p Andsager
52  * up wavedata buffer size to 180000 to allow stereo 16b/22KHz streaming
53  * 
54  * 2     10/07/98 10:53a Dave
55  * Initial checkin.
56  * 
57  * 1     10/07/98 10:51a Dave
58  * 
59  * 53    6/28/98 6:35p Lawrance
60  * move re-entrancy semaphore into audiostream class
61  * 
62  * 52    5/24/98 4:42p Dan
63  * AL: Fix several bugs related to pausing and enabling/disabling event
64  * music
65  * 
66  * 51    5/21/98 11:57a Lawrance
67  * fix potential bug with transitions for music when in packfiles
68  * 
69  * 50    5/15/98 9:09p Lawrance
70  * The last of the multi-threading fixes
71  * 
72  * 49    5/15/98 7:57p Duncan
73  * AL: Fix race condition with music streaming
74  * 
75  * 48    5/15/98 10:13a Lawrance
76  * remove unused audiostream member
77  * 
78  * 47    5/14/98 5:45p Lawrance2
79  * Put critical section around audiostream destroying
80  * 
81  * 46    5/12/98 5:40p Lawrance
82  * Add critical section code to the service buffer call.. since it is
83  * possible to release buffers while in this call
84  * 
85  * 45    5/10/98 3:49p Sandeep
86  * Fix problem with having the audio streaming while trying to close down
87  * sound
88  * 
89  * 44    4/30/98 4:53p John
90  * Restructured and cleaned up cfile code.  Added capability to read off
91  * of CD-ROM drive and out of multiple pack files.
92  * 
93  * 43    4/26/98 3:30a Lawrance
94  * Fix a couple of potential bugs
95  * 
96  * 42    4/21/98 10:18a Dan
97  * 
98  * 41    4/17/98 6:59a John
99  * Changed code the used 'new' and 'delete' to use 'malloc' and 'free'
100  * instead.  Had to manually can constructors/destructors.
101  * 
102  * 40    4/13/98 10:18a John
103  * fixed warnings
104  * 
105  * 39    4/13/98 10:16a John
106  * Switched gettime back to timer_get_milliseconds, which is now thread
107  * safe.
108  * 
109  * 38    4/12/98 11:08p Lawrance
110  * switch back to using gettime() in separate threads
111  * 
112  * 37    4/12/98 5:31p Lawrance
113  * use timer_get_milliseconds() instead of gettime()
114  * 
115  * 36    4/06/98 12:36a Lawrance
116  * Ensure all non-music ADPCM files get decompressed to 8 bit.
117  * 
118  * 35    4/03/98 4:56p Lawrance
119  * Upu the max audio streams to 30
120  * 
121  * 34    3/31/98 4:50p Dan
122  * AL: Clean up all audio streams if necessary in
123  * event_music_level_close()
124  * 
125  * 33    3/23/98 4:12p Lawrance
126  * Fix subtle bug with looping and fading out songs
127  * 
128  * 32    2/18/98 5:49p Lawrance
129  * Even if the ADPCM codec is unavailable, allow game to continue.
130  * 
131  * 31    2/15/98 4:43p Lawrance
132  * work on real-time voice
133  * 
134  * 30    1/19/98 11:37p Lawrance
135  * Fixing Optimization build warnings
136  * 
137  * 29    1/17/98 4:41p Lawrance
138  * Fix problem with multiple audio streams using the same buffers
139  * 
140  * 28    1/16/98 11:49a Lawrance
141  * Use own internal timer for fading.
142  * 
143  * 27    12/28/97 12:43p John
144  * Put in support for reading archive files; Made missionload use the
145  * cf_get_file_list function.   Moved demos directory out of data tree.
146  * 
147  * 26    12/27/97 8:08p Lawrance
148  * If an audiostream doesn't exists, it can't be playing
149  * 
150  * 25    12/18/97 3:30p Lawrance
151  * Fix bug that sometimes caused music with no volume to not get stopped
152  * properly.
153  * 
154  * 24    12/17/97 10:17p Allender
155  * redid streadming code to use mmio* functions instead of cf* functions.
156  * Our functions are not reentrant!
157  * 
158  * 23    12/10/97 10:04p Lawrance
159  * modify what happens in Audio_stream constructor
160  * 
161  * 22    12/09/97 6:14p Lawrance
162  * add -nomusic flag
163  * 
164  * 21    12/08/97 6:21p Lawrance
165  * fix problems with signaling that end-of-file has been reached
166  * 
167  * 20    12/05/97 10:50a Lawrance
168  * improve how silence bytes are written on transitions
169  * 
170  * 19    12/04/97 5:35p Lawrance
171  * fix bug that may have caused errors when writing silence
172  * 
173  * 18    11/28/97 2:09p Lawrance
174  * Overhaul how ADPCM conversion works... use much less memory... safer
175  * too.
176  * 
177  * 17    10/03/97 8:24a Lawrance
178  * When unpausing, be sure to retain looping status
179  * 
180  * 16    9/24/97 5:30p Lawrance
181  * fix bug that was messing up streaming of 8 bit audio
182  * 
183  * 15    9/18/97 10:31p Lawrance
184  * add functions to pause and unpause all audio streams
185  * 
186  * 14    9/09/97 3:39p Sandeep
187  * warning level 4 bugs
188  * 
189  * $NoKeywords: $
190  */
191
192 #define VC_EXTRALEAN
193 #define STRICT
194
195 #include "pstypes.h"
196
197 #ifndef PLAT_UNIX
198 #include <windows.h>
199 #include <mmsystem.h>
200 #include <mmreg.h>
201 #include <msacm.h>
202 #include "vdsound.h"
203 #endif
204 #include "audiostr.h"
205 #include "cfile.h"              // needed for cf_get_path
206 #include "timer.h"
207 #include "sound.h"              /* for Snd_sram */
208 #include "acm.h"
209 #include "ds.h"
210
211 // Constants
212 #ifndef SUCCESS
213 #define SUCCESS TRUE        // Error returns for all member functions
214 #define FAILURE FALSE
215 #endif // SUCCESS
216
217 #ifndef PLAT_UNIX 
218
219 typedef BOOL (*TIMERCALLBACK)(DWORD);
220
221 #define BIGBUF_SIZE                                     180000                  // This can be reduced to 88200 once we don't use any stereo
222 //#define BIGBUF_SIZE                                   88300                   // This can be reduced to 88200 once we don't use any stereo
223 unsigned char *Wavedata_load_buffer = NULL;             // buffer used for cueing audiostreams
224 unsigned char *Wavedata_service_buffer = NULL;  // buffer used for servicing audiostreams
225
226 CRITICAL_SECTION Global_service_lock;
227
228 #define COMPRESSED_BUFFER_SIZE  88300
229 unsigned char *Compressed_buffer = NULL;                                // Used to load in compressed data during a cueing interval
230 unsigned char *Compressed_service_buffer = NULL;        // Used to read in compressed data during a service interval
231
232 #define AS_HIGHEST_MAX                          999999999       // max uncompressed filesize supported is 999 meg
233
234 // Classes
235
236 // Timer
237 //
238 // Wrapper class for Windows multimedia timer services. Provides
239 // both periodic and one-shot events. User must supply callback
240 // for periodic events.
241 // 
242
243 class Timer
244 {
245 public:
246     void constructor(void);
247     void destructor(void);
248     BOOL Create (UINT nPeriod, UINT nRes, DWORD dwUser,  TIMERCALLBACK pfnCallback);
249 protected:
250     static void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
251     TIMERCALLBACK m_pfnCallback;
252     DWORD m_dwUser;
253     UINT m_nPeriod;
254     UINT m_nRes;
255     UINT m_nIDTimer;
256 };
257
258
259 // Class
260
261 // WaveFile
262 //
263 // WAV file class (read-only).
264 //
265 // Public Methods:
266 //
267 // Public Data:
268 //   
269 //
270
271 class WaveFile
272 {
273 public:
274         void Init(void);
275         void Close(void);
276         BOOL Open (LPSTR pszFilename);
277         BOOL Cue (void);
278         int     Read (BYTE * pbDest, UINT cbSize, int service=1);
279         UINT GetNumBytesRemaining (void) { return (m_nDataSize - m_nBytesPlayed); }
280         UINT GetUncompressedAvgDataRate (void) { return (m_nUncompressedAvgDataRate); }
281         UINT GetDataSize (void) { return (m_nDataSize); }
282         UINT GetNumBytesPlayed (void) { return (m_nBytesPlayed); }
283         BYTE GetSilenceData (void);
284         WAVEFORMATEX m_wfmt;                                    // format of wave file used by Direct Sound
285         WAVEFORMATEX * m_pwfmt_original;        // foramt of wave file from actual wave source
286         UINT m_total_uncompressed_bytes_read;
287         UINT m_max_uncompressed_bytes_to_read;
288         UINT    m_bits_per_sample_uncompressed;
289
290 protected:
291         UINT m_data_offset;                                             // number of bytes to actual wave data
292         int  m_data_bytes_left;
293         HMMIO   cfp;
294
295         UINT m_wave_format;                                             // format of wave source (ie WAVE_FORMAT_PCM, WAVE_FORMAT_ADPCM)
296         UINT m_nBlockAlign;                                             // wave data block alignment spec
297         UINT m_nUncompressedAvgDataRate;                // average wave data rate
298         UINT m_nDataSize;                                                       // size of data chunk
299         UINT m_nBytesPlayed;                                            // offset into data chunk
300         BOOL m_abort_next_read;
301
302         HACMSTREAM              m_hStream;
303         int                             m_hStream_open;
304         WAVEFORMATEX    m_wfxDest;
305 };
306
307 // Classes
308
309 // AudioStreamServices
310 //
311 // DirectSound apportions services on a per-window basis to allow
312 // sound from background windows to be muted. The AudioStreamServices
313 // class encapsulates the initialization of DirectSound services.
314 //
315 // Each window that wants to create AudioStream objects must
316 // first create and initialize an AudioStreamServices object. 
317 // All AudioStream objects must be destroyed before the associated 
318 // AudioStreamServices object is destroyed.
319 class AudioStreamServices
320 {
321 public:
322     void Constructor(void);
323     BOOL Initialize ();
324     LPDIRECTSOUND GetPDS (void) { return m_pds; }
325 protected:
326     LPDIRECTSOUND m_pds;
327 };
328
329
330 // AudioStream
331 //
332 // Audio stream interface class for playing WAV files using DirectSound.
333 // Users of this class must create AudioStreamServices object before
334 // creating an AudioStream object.
335 //
336 // Public Methods:
337 //
338 // Public Data:
339 //
340
341 // status
342 #define ASF_FREE        0
343 #define ASF_USED        1
344
345 class AudioStream
346 {
347 public:
348         AudioStream (void);
349         ~AudioStream (void);
350         BOOL Create (LPSTR pszFilename, AudioStreamServices * pass);
351         BOOL Destroy (void);
352         void Play (long volume, int looping);
353         int Is_Playing(){ return(m_fPlaying); }
354         int Is_Paused(){ return(m_bIsPaused); }
355         int Is_Past_Limit() { return m_bPastLimit; }
356         void Stop (int paused=0);
357         void Stop_and_Rewind (void);
358         void Fade_and_Destroy (void);
359         void Fade_and_Stop(void);
360         void    Set_Volume(long vol);
361         long    Get_Volume();
362         void    Init_Data();
363         void    Set_Byte_Cutoff(unsigned int num_bytes_cutoff);
364         void  Set_Default_Volume(long converted_volume) { m_lDefaultVolume = converted_volume; }
365         long    Get_Default_Volume() { return m_lDefaultVolume; }
366         unsigned int Get_Bytes_Committed(void);
367         int     Is_looping() { return m_bLooping; }
368         int     status;
369         int     type;
370         UINT m_bits_per_sample_uncompressed;
371
372 protected:
373         void Cue (void);
374         BOOL WriteWaveData (UINT cbSize, UINT* num_bytes_written,int service=1);
375         BOOL WriteSilence (UINT cbSize);
376         DWORD GetMaxWriteSize (void);
377         BOOL ServiceBuffer (void);
378         static BOOL TimerCallback (DWORD dwUser);
379
380         AudioStreamServices * m_pass;  // ptr to AudioStreamServices object
381         LPDIRECTSOUNDBUFFER m_pdsb;    // ptr to Direct Sound buffer
382         WaveFile * m_pwavefile;        // ptr to WaveFile object
383         Timer m_timer;              // ptr to Timer object
384         BOOL m_fCued;                  // semaphore (stream cued)
385         BOOL m_fPlaying;               // semaphore (stream playing)
386         DSBUFFERDESC m_dsbd;           // Direct Sound buffer description
387         LONG m_lInService;             // reentrancy semaphore
388         UINT m_cbBufOffset;            // last write position
389         UINT m_nBufLength;             // length of sound buffer in msec
390         UINT m_cbBufSize;              // size of sound buffer in bytes
391         UINT m_nBufService;            // service interval in msec
392         UINT m_nTimeStarted;           // time (in system time) playback started
393
394         BOOL    m_bLooping;                                             // whether or not to loop playback
395         BOOL    m_bFade;                                                        // fade out music 
396         BOOL    m_bDestroy_when_faded;
397         LONG  m_lVolume;                                                // volume of stream ( 0 -> -10 000 )
398         LONG    m_lCutoffVolume;
399         BOOL  m_bIsPaused;                                      // stream is stopped, but not rewinded
400         UINT    m_silence_written;                      // number of bytes of silence written to buffer
401         UINT  m_bReadingDone;                           // no more bytes to be read from disk, still have remaining buffer to play
402         DWORD   m_fade_timer_id;                                // timestamp so we know when to start fade
403         DWORD   m_finished_id;                                  // timestamp so we know when we've played #bytes required
404         BOOL    m_bPastLimit;                                   // flag to show we've played past the number of bytes requred
405         LONG    m_lDefaultVolume;
406         HRESULT h_result;
407
408         CRITICAL_SECTION write_lock;
409 };
410
411
412 // AudioStreamServices class implementation
413 //
414 ////////////////////////////////////////////////////////////
415
416 // Constructor
417 void AudioStreamServices::Constructor(void)
418 {
419     // Initialize member data
420     m_pds = NULL;
421
422     // It would seem to make sense to initialize DirectSound here,
423     // but because there could be an error, it's best done in a
424     // separate member function, ::Initialize.
425 }
426
427
428 extern LPDIRECTSOUND pDirectSound;              // From Sound.cpp
429
430
431 // Initialize
432 BOOL AudioStreamServices::Initialize ()
433 {
434     
435     BOOL fRtn = SUCCESS;    // assume success
436
437     if (m_pds == NULL)  {
438                 m_pds = pDirectSound;
439     }
440
441     return (fRtn);
442 }
443
444
445
446 //
447 // AudioStream class implementation
448 //
449 ////////////////////////////////////////////////////////////
450
451 // The following constants are the defaults for our streaming buffer operation.
452 const UINT DefBufferLength          = 2000; // default buffer length in msec
453 const UINT DefBufferServiceInterval = 250;  // default buffer service interval in msec
454
455 // Constructor
456 AudioStream::AudioStream (void)
457 {
458         InitializeCriticalSection( &write_lock );
459 }
460
461
462 // Destructor
463 AudioStream::~AudioStream (void)
464 {
465         DeleteCriticalSection( &write_lock );
466 }
467
468
469 void AudioStream::Init_Data ()
470 {
471         m_bLooping = 0;
472         m_bFade = FALSE;
473         m_fade_timer_id = 0;
474         m_finished_id = 0;
475         m_bPastLimit = FALSE;
476         
477         m_bDestroy_when_faded = FALSE;
478         m_lVolume = 0;
479         m_lCutoffVolume = -10000;
480         m_bIsPaused = FALSE;
481         m_silence_written = 0;
482         m_bReadingDone = FALSE;
483
484         m_pwavefile = NULL;
485         m_pdsb = NULL;
486         m_fPlaying = m_fCued = FALSE;
487         m_lInService = FALSE;
488         m_cbBufOffset = 0;
489         m_nBufLength = DefBufferLength;
490         m_cbBufSize = 0;
491         m_nBufService = DefBufferServiceInterval;
492         m_nTimeStarted = 0;
493 }
494
495 // Create
496 BOOL AudioStream::Create (LPSTR pszFilename, AudioStreamServices * pass)
497 {
498         BOOL fRtn = SUCCESS;    // assume success
499
500         Assert(pszFilename);
501         Assert(pass);
502
503         m_pass = pass;
504         Init_Data();
505
506         if (pszFilename && m_pass) {
507                 // Create a new WaveFile object
508         
509                 m_pwavefile = (WaveFile *)malloc(sizeof(WaveFile));
510                 Assert(m_pwavefile);
511
512                 if (m_pwavefile) {
513                         // Call constructor
514                         m_pwavefile->Init();
515                         // Open given file
516                         m_pwavefile->m_bits_per_sample_uncompressed = m_bits_per_sample_uncompressed;
517                         if (m_pwavefile->Open (pszFilename)) {
518                                 // Calculate sound buffer size in bytes
519                                 // Buffer size is average data rate times length of buffer
520                                 // No need for buffer to be larger than wave data though
521                                 m_cbBufSize = (m_pwavefile->GetUncompressedAvgDataRate () * m_nBufLength) / 1000;
522                                 nprintf(("SOUND", "SOUND => Stream buffer created using %d bytes\n", m_cbBufSize));
523                                 // m_cbBufSize = (m_cbBufSize > m_pwavefile->GetDataSize ()) ? m_pwavefile->GetDataSize () : m_cbBufSize;
524
525                                 //nprintf(("Sound", "SOUND => average data rate = %d\n\r", m_pwavefile->GetUncompressedAvgDataRate ()));
526                                 //nprintf(("Sound", "SOUND => m_cbBufSize = %d\n\r", m_cbBufSize));
527
528                                 // Create sound buffer
529                                 HRESULT hr;
530                                 memset (&m_dsbd, 0, sizeof (DSBUFFERDESC));
531                                 m_dsbd.dwSize = sizeof (DSBUFFERDESC);
532                                 m_dsbd.dwBufferBytes = m_cbBufSize;
533                                 m_dsbd.lpwfxFormat = &m_pwavefile->m_wfmt;
534                                 m_dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_LOCSOFTWARE;
535
536                                 hr = (m_pass->GetPDS ())->CreateSoundBuffer (&m_dsbd, &m_pdsb, NULL);
537                                 if (hr == DS_OK) {
538                                         // Cue for playback
539                                         Cue ();
540                                         Snd_sram += m_cbBufSize;
541                                 }
542                                 else {
543                                         // Error, unable to create DirectSound buffer
544                                         nprintf(("Sound", "SOUND => Error, unable to create DirectSound buffer\n\r"));
545                                         if (hr == DSERR_BADFORMAT) {
546                                                 nprintf(("Sound", "SOUND => Bad format (probably ADPCM)\n\r"));
547                                         }
548
549                                         fRtn = FAILURE;
550                                 }
551                         }
552                         else {
553                                 // Error opening file
554                                 nprintf(("SOUND", "SOUND => Failed to open wave file: %s\n\r", pszFilename));
555                                 m_pwavefile->Close();
556                                 free(m_pwavefile);
557                                 m_pwavefile = NULL;
558                                 fRtn = FAILURE;
559                         }   
560                 }
561                 else {
562                         // Error, unable to create WaveFile object
563                         nprintf(("Sound", "SOUND => Failed to create WaveFile object %s\n\r", pszFilename));
564                         fRtn = FAILURE;
565                 }
566         }
567         else {
568                 // Error, passed invalid parms
569                 fRtn = FAILURE;
570         }
571
572         return (fRtn);
573 }
574
575
576 // Destroy
577 BOOL AudioStream::Destroy (void)
578 {
579         BOOL fRtn = SUCCESS;
580
581         EnterCriticalSection(&write_lock);
582         
583         // Stop playback
584         Stop ();
585
586         // Release DirectSound buffer
587         if (m_pdsb) {
588                 m_pdsb->Release ();
589                 m_pdsb = NULL;
590                 Snd_sram -= m_cbBufSize;
591         }
592
593         // Delete WaveFile object
594         if (m_pwavefile) {
595                 m_pwavefile->Close();
596                 free(m_pwavefile);
597                 m_pwavefile = NULL;
598         }
599
600         status = ASF_FREE;
601
602         LeaveCriticalSection(&write_lock);
603
604         return fRtn;
605 }
606
607 // WriteWaveData
608 //
609 // Writes wave data to sound buffer. This is a helper method used by Create and
610 // ServiceBuffer; it's not exposed to users of the AudioStream class.
611 BOOL AudioStream::WriteWaveData (UINT size, UINT *num_bytes_written, int service)
612 {
613         HRESULT hr;
614         LPBYTE lpbuf1 = NULL;
615         LPBYTE lpbuf2 = NULL;
616         DWORD dwsize1 = 0;
617         DWORD dwsize2 = 0;
618         DWORD dwbyteswritten1 = 0;
619         DWORD dwbyteswritten2 = 0;
620         BOOL fRtn = SUCCESS;
621         unsigned char   *uncompressed_wave_data;
622
623         *num_bytes_written = 0;
624
625         if ( size == 0 || m_bReadingDone ) {
626                 return fRtn;
627         }
628
629         if ( !m_pdsb || !m_pwavefile ) {
630                 return fRtn;
631         }
632
633         if ( service ) {
634                 EnterCriticalSection(&Global_service_lock);
635         }
636                     
637         if ( service ) {
638                 uncompressed_wave_data = Wavedata_service_buffer;
639         } else {
640                 uncompressed_wave_data = Wavedata_load_buffer;
641         }
642
643         int num_bytes_read = 0;
644
645     // Lock the sound buffer
646         hr = m_pdsb->Lock (m_cbBufOffset, size, (void**)(&lpbuf1), &dwsize1, (void**)(&lpbuf2), &dwsize2, 0);
647         if (hr == DS_OK) {
648                 // Write data to sound buffer. Because the sound buffer is circular, we may have to
649                 // do two write operations if locked portion of buffer wraps around to start of buffer.
650                 Assert(lpbuf1);
651                 
652                 num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, dwsize1+dwsize2,service);
653                 if ( num_bytes_read == -1 ) {
654                         // means nothing left to read!
655                         num_bytes_read = 0;
656                         m_bReadingDone = 1;
657                 }
658
659                 if ( num_bytes_read > 0 ) {
660                         if ( (unsigned int)num_bytes_read > dwsize1 ) {
661                                 dwbyteswritten1 = dwsize1;
662                                 dwbyteswritten2 = num_bytes_read - dwsize1;
663
664                                 memcpy(lpbuf1, uncompressed_wave_data, dwsize1);
665                                 Assert(lpbuf2);
666                                 memcpy(lpbuf2, uncompressed_wave_data+dwsize1, num_bytes_read-dwsize1);
667                         } else {
668                                 dwbyteswritten1 = num_bytes_read;
669                                 dwbyteswritten2 = 0;
670                                 memcpy(lpbuf1, uncompressed_wave_data, num_bytes_read);
671                         }
672                 }
673                         
674                 // Update our buffer offset and unlock sound buffer
675                 m_cbBufOffset = (m_cbBufOffset + dwbyteswritten1 + dwbyteswritten2) % m_cbBufSize;
676                 *num_bytes_written = dwbyteswritten1 + dwbyteswritten2;
677                 m_pdsb->Unlock (lpbuf1, dwsize1, lpbuf2, dwsize2);
678     }
679         else {
680                 // Error locking sound buffer
681                 nprintf(("SOUND", "SOUND ==> Error, unable to lock sound buffer in AudioStr\n"));
682                 fRtn = FAILURE;
683         }
684
685         if ( service ) {
686                 LeaveCriticalSection(&Global_service_lock);
687         }
688     
689         return (fRtn);
690 }
691
692
693 // WriteSilence
694 //
695 // Writes silence to sound buffer. This is a helper method used by
696 // ServiceBuffer; it's not exposed to users of the AudioStream class.
697 BOOL AudioStream::WriteSilence (UINT size)
698 {
699         HRESULT hr;
700         LPBYTE lpbuf1 = NULL;
701         LPBYTE lpbuf2 = NULL;
702         DWORD dwsize1 = 0;
703         DWORD dwsize2 = 0;
704         DWORD dwbyteswritten1 = 0;
705         DWORD dwbyteswritten2 = 0;
706         BOOL fRtn = SUCCESS;
707
708         // Lock the sound buffer
709         hr = m_pdsb->Lock (m_cbBufOffset, size, (void**)(&lpbuf1), &dwsize1, (void**)(&lpbuf2), &dwsize2, 0);
710         if (hr == DS_OK) {
711
712                 // Get silence data for this file format. Although word sizes vary for different
713                 // wave file formats, ::Lock will always return pointers on word boundaries.
714                 // Because silence data for 16-bit PCM formats is 0x0000 or 0x00000000, we can
715                 // get away with writing bytes and ignoring word size here.
716                 BYTE bSilence = m_pwavefile->GetSilenceData ();
717         
718                 // Write silence to sound buffer. Because the sound buffer is circular, we may have to
719                 // do two write operations if locked portion of buffer wraps around to start of buffer.
720                 memset (lpbuf1, bSilence, dwsize1);
721                 dwbyteswritten1 = dwsize1;
722             
723      // Second write required?
724                 if (lpbuf2) {
725                         memset (lpbuf2, bSilence, dwsize2);
726                         dwbyteswritten2 = dwsize2;
727                 }
728             
729                 // Update our buffer offset and unlock sound buffer
730                 m_cbBufOffset = (m_cbBufOffset + dwbyteswritten1 + dwbyteswritten2) % m_cbBufSize;
731 //              m_pdsb->Unlock (lpbuf1, dwbyteswritten1, lpbuf2, dwbyteswritten2);
732                 m_pdsb->Unlock (lpbuf1, dwsize1, lpbuf2, dwsize2);
733         }
734         else {
735                 // Error locking sound buffer
736                 nprintf(("SOUND", "SOUND ==> Error, unable to lock sound buffer in AudioStr\n"));
737                 fRtn = FAILURE;
738         }
739
740         return (fRtn);
741 }
742
743
744 // GetMaxWriteSize
745 //
746 // Helper function to calculate max size of sound buffer write operation, i.e. how much
747 // free space there is in buffer.
748 DWORD AudioStream::GetMaxWriteSize (void)
749 {
750         DWORD dwWriteCursor, dwPlayCursor, dwMaxSize;
751
752         // Get current play position
753         if (m_pdsb->GetCurrentPosition (&dwPlayCursor, &dwWriteCursor) == DS_OK) {
754                 if (m_cbBufOffset <= dwPlayCursor) {
755                         // Our write position trails play cursor
756                         dwMaxSize = dwPlayCursor - m_cbBufOffset;
757                 }
758
759                 else  {// (m_cbBufOffset > dw7Cursor)
760                         // Play cursor has wrapped
761                         dwMaxSize = m_cbBufSize - m_cbBufOffset + dwPlayCursor;
762                 }
763         }
764         else {
765                 // GetCurrentPosition call failed
766                 Int3();
767                 dwMaxSize = 0;
768         }
769
770 //      nprintf(("Alan","Max write size: %d\n", dwMaxSize));
771         return (dwMaxSize);
772 }
773
774
775 // ServiceBuffer
776 //
777 // Routine to service buffer requests initiated by periodic timer.
778 //
779 // Returns TRUE if buffer serviced normally; otherwise returns FALSE.
780 #define FADE_VOLUME_INTERVAL                                                    400             // 100 == 1db
781 #define VOLUME_ATTENUATION_BEFORE_CUTOFF                        3000            //  12db 
782 BOOL AudioStream::ServiceBuffer (void)
783 {
784         long    vol;
785         int     fRtn = TRUE;
786
787         if ( status != ASF_USED )
788                 return FALSE;
789
790         EnterCriticalSection(&write_lock);
791
792         // status may have changed, so lets check once again
793         if ( status != ASF_USED ){
794                 LeaveCriticalSection(&write_lock);
795                 return FALSE;
796         }
797
798         // Check for reentrance
799         if (InterlockedExchange (&m_lInService, TRUE) == FALSE) {
800                 if ( m_bFade == TRUE ) {
801                         if ( m_lCutoffVolume == -10000 ) {
802                                 vol = Get_Volume();
803 //                              nprintf(("Alan","Volume is: %d\n",vol));
804                                 m_lCutoffVolume = max(vol - VOLUME_ATTENUATION_BEFORE_CUTOFF, -10000);
805                         }
806
807                         vol = Get_Volume();
808                         vol = vol - FADE_VOLUME_INTERVAL;       // decrease by 1db
809 //                      nprintf(("Alan","Volume is now: %d\n",vol));
810                         Set_Volume(vol);
811
812 //                      nprintf(("Sound","SOUND => Volume for stream sound is %d\n",vol));
813 //                      nprintf(("Alan","Cuttoff Volume is: %d\n",m_lCutoffVolume));
814                         if ( vol < m_lCutoffVolume ) {
815                                 m_bFade = 0;
816                                 m_lCutoffVolume = -10000;
817                                 if ( m_bDestroy_when_faded == TRUE ) {
818                                         LeaveCriticalSection(&write_lock);
819                                         Destroy();      
820                                         // Reset reentrancy semaphore
821                                         InterlockedExchange (&m_lInService, FALSE);
822                                         return FALSE;
823                                 }
824                                 else {
825                                         Stop_and_Rewind();
826                                         // Reset reentrancy semaphore
827                                         LeaveCriticalSection(&write_lock);
828                                         InterlockedExchange (&m_lInService, FALSE);
829                                         return TRUE;
830                                 }
831                         }
832                 }
833
834                 // All of sound not played yet, send more data to buffer
835                 DWORD dwFreeSpace = GetMaxWriteSize ();
836
837                 // Determine free space in sound buffer
838                 if (dwFreeSpace) {
839
840                         // Some wave data remains, but not enough to fill free space
841                         // Send wave data to buffer, fill remainder of free space with silence
842                         uint num_bytes_written;
843
844                         if (WriteWaveData (dwFreeSpace, &num_bytes_written) == SUCCESS) {
845 //                              nprintf(("Alan","Num bytes written: %d\n", num_bytes_written));
846
847                                 if ( m_pwavefile->m_total_uncompressed_bytes_read >= m_pwavefile->m_max_uncompressed_bytes_to_read ) {
848                                         m_fade_timer_id = timer_get_milliseconds() + 1700;              // start fading 1.7 seconds from now
849                                         m_finished_id = timer_get_milliseconds() + 2000;                // 2 seconds left to play out buffer
850                                         m_pwavefile->m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
851                                 }
852
853                                 if ( (m_fade_timer_id>0) && ((uint)timer_get_milliseconds() > m_fade_timer_id) ) {
854                                         m_fade_timer_id = 0;
855                                         Fade_and_Stop();
856                                 }
857
858                                 if ( (m_finished_id>0) && ((uint)timer_get_milliseconds() > m_finished_id) ) {
859                                         m_finished_id = 0;
860                                         m_bPastLimit = TRUE;
861                                 }
862
863                                 if ( (num_bytes_written < dwFreeSpace) && m_bReadingDone ) {
864                                         int num_bytes_silence;
865                                         num_bytes_silence = dwFreeSpace - num_bytes_written;
866
867                                         if ( num_bytes_silence > 0 ) {
868
869                                                 m_silence_written += num_bytes_silence;
870                                                 if (WriteSilence (num_bytes_silence) == FAILURE)        {
871                                                         fRtn = FALSE;
872                                                         Int3();
873                                                 }
874
875                                                 if ( m_silence_written >= m_cbBufSize ) {
876                                                         m_silence_written = 0;
877
878                                                         if ( m_bDestroy_when_faded == TRUE ) {
879                                                                 LeaveCriticalSection(&write_lock);
880                                                                 Destroy();
881                                                                 // Reset reentrancy semaphore
882                                                                 InterlockedExchange (&m_lInService, FALSE);
883                                                                 return FALSE;
884                                                         }
885
886                                                         // All of sound has played, stop playback or loop again
887                                                         if ( m_bLooping && !m_bFade) {
888                                                                 Play(m_lVolume, m_bLooping);
889                                                         }
890                                                         else {
891                                                                 Stop_and_Rewind();
892                                                         }
893                                                 }
894                                         }
895                                 }
896                         }
897                         else {
898                                 // Error writing wave data
899                                 fRtn = FALSE;
900                                 Int3(); 
901                         }
902                 }
903
904         // Reset reentrancy semaphore
905         InterlockedExchange (&m_lInService, FALSE);
906     } else {
907                 // Service routine reentered. Do nothing, just return
908                 fRtn = FALSE;
909     }
910
911         LeaveCriticalSection(&write_lock);
912         return (fRtn);
913 }
914
915 // Cue
916 void AudioStream::Cue (void)
917 {
918         UINT num_bytes_written;
919
920         if (!m_fCued) {
921                 m_bFade = FALSE;
922                 m_fade_timer_id = 0;
923                 m_finished_id = 0;
924                 m_bPastLimit = FALSE;
925                 m_lVolume = 0;
926                 m_lCutoffVolume = -10000;
927
928                 m_bDestroy_when_faded = FALSE;
929
930                 // Reset buffer ptr
931                 m_cbBufOffset = 0;
932
933                 // Reset file ptr, etc
934                 m_pwavefile->Cue ();
935
936                 // Reset DirectSound buffer
937                 m_pdsb->SetCurrentPosition (0);
938
939                 // Fill buffer with wave data
940                 WriteWaveData (m_cbBufSize, &num_bytes_written,0);
941
942                 m_fCued = TRUE;
943         }
944 }
945
946
947 // Play
948 void AudioStream::Play (long volume, int looping)
949 {
950         if (m_pdsb) {
951                 // If playing, stop
952                 if (m_fPlaying) {
953                         if ( m_bIsPaused == FALSE)
954                         Stop_and_Rewind();
955                 }
956
957                 // Cue for playback if necessary
958                 if (!m_fCued) {
959                         Cue ();
960                 }
961
962                 if ( looping )
963                         m_bLooping = 1;
964                 else
965                         m_bLooping = 0;
966
967                 // Begin DirectSound playback
968                 HRESULT hr = m_pdsb->Play (0, 0, DSBPLAY_LOOPING);
969                 if (hr == DS_OK) {
970                         m_nTimeStarted = timer_get_milliseconds();
971                         Set_Volume(volume);
972                         // Kick off timer to service buffer
973                         m_timer.constructor();
974
975                         m_timer.Create (m_nBufService, m_nBufService, DWORD (this), TimerCallback);
976
977                         // Playback begun, no longer cued
978                         m_fPlaying = TRUE;
979                         m_bIsPaused = FALSE;
980                 }
981                 else {
982                         // If the buffer was lost, try to restore it
983                         if ( hr == DSERR_BUFFERLOST ) {
984                                 hr = m_pdsb->Restore();
985                                 if ( hr == DS_OK ) {
986                                         hr = m_pdsb->Play (0, 0, DSBPLAY_LOOPING);
987                                 }
988                                 else {
989                                         nprintf(("Sound", "Sound => Lost a buffer, tried restoring but got %s\n", get_DSERR_text(hr) ));
990                                         Int3(); // get Alan, he wants to see this
991                                 }
992                         }
993
994                         if ( hr != DS_OK ) {
995                                 nprintf(("Sound", "Sound => Play failed with return value %s\n", get_DSERR_text(hr) ));
996                         }
997                 }
998         }
999 }
1000
1001 // Timer callback for Timer object created by ::Play method.
1002 BOOL AudioStream::TimerCallback (DWORD dwUser)
1003 {
1004     // dwUser contains ptr to AudioStream object
1005     AudioStream * pas = (AudioStream *) dwUser;
1006
1007     return (pas->ServiceBuffer ());
1008 }
1009
1010 void AudioStream::Set_Byte_Cutoff(unsigned int byte_cutoff)
1011 {
1012         if ( m_pwavefile == NULL )
1013                 return;
1014
1015         m_pwavefile->m_max_uncompressed_bytes_to_read = byte_cutoff;
1016 }
1017
1018 unsigned int AudioStream::Get_Bytes_Committed(void)
1019 {
1020         if ( m_pwavefile == NULL )
1021                 return 0;
1022
1023         return m_pwavefile->m_total_uncompressed_bytes_read;
1024 }
1025
1026
1027 // Fade_and_Destroy
1028 void AudioStream::Fade_and_Destroy (void)
1029 {
1030         m_bFade = TRUE;
1031         m_bDestroy_when_faded = TRUE;
1032 }
1033
1034 // Fade_and_Destroy
1035 void AudioStream::Fade_and_Stop (void)
1036 {
1037         m_bFade = TRUE;
1038         m_bDestroy_when_faded = FALSE;
1039 }
1040
1041
1042 // Stop
1043 void AudioStream::Stop(int paused)
1044 {
1045         if (m_fPlaying) {
1046                 // Stop DirectSound playback
1047                 m_pdsb->Stop ();
1048                 m_fPlaying = FALSE;
1049                 m_bIsPaused = paused;
1050
1051                 // Delete Timer object
1052                 m_timer.destructor();
1053         }
1054 }
1055
1056 // Stop_and_Rewind
1057 void AudioStream::Stop_and_Rewind (void)
1058 {
1059         if (m_fPlaying) {
1060                 // Stop DirectSound playback
1061                 m_pdsb->Stop ();
1062
1063                 // Delete Timer object
1064                 m_timer.destructor();
1065
1066                 m_fPlaying = FALSE;
1067         }
1068
1069         m_fCued = FALSE;        // this will cause wave file to start from beginning
1070         m_bReadingDone = FALSE;
1071 }
1072
1073 // Set_Volume
1074 void AudioStream::Set_Volume(long vol)
1075 {
1076         if ( vol < -10000 )
1077                 vol = -10000;
1078         
1079         if ( vol > 0 )
1080                 vol = 0;
1081
1082         Assert( vol >= -10000 && vol <= 0 );
1083         h_result = m_pdsb->SetVolume(vol);
1084         m_lVolume = vol;
1085         if ( h_result != DS_OK )
1086                 nprintf(("Sound","SOUND => SetVolume() failed with code '%s'\n", get_DSERR_text(h_result) ));
1087 }
1088
1089
1090 // Set_Volume
1091 long AudioStream::Get_Volume()
1092 {
1093         return m_lVolume;
1094 }
1095
1096 // constructor
1097 void Timer::constructor(void)
1098 {
1099         m_nIDTimer = NULL;
1100 }
1101
1102
1103 // Destructor
1104 void Timer::destructor(void)
1105 {
1106         if (m_nIDTimer) {
1107                 timeKillEvent (m_nIDTimer);
1108                 m_nIDTimer = NULL;
1109         }
1110 }
1111
1112
1113 // Create
1114 BOOL Timer::Create (UINT nPeriod, UINT nRes, DWORD dwUser, TIMERCALLBACK pfnCallback)
1115 {
1116         BOOL bRtn = SUCCESS;    // assume success
1117
1118         Assert(pfnCallback);
1119         Assert(nPeriod > 10);
1120         Assert(nPeriod >= nRes);
1121
1122         m_nPeriod = nPeriod;
1123         m_nRes = nRes;
1124         m_dwUser = dwUser;
1125         m_pfnCallback = pfnCallback;
1126
1127         if ((m_nIDTimer = timeSetEvent (m_nPeriod, m_nRes, TimeProc, (DWORD) this, TIME_PERIODIC)) == NULL) {
1128           bRtn = FAILURE;
1129         }
1130
1131         return (bRtn);
1132 }
1133
1134
1135 // Timer proc for multimedia timer callback set with timeSetTime().
1136 //
1137 // Calls procedure specified when Timer object was created. The 
1138 // dwUser parameter contains "this" pointer for associated Timer object.
1139 // 
1140 void CALLBACK Timer::TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
1141 {
1142     // dwUser contains ptr to Timer object
1143     Timer * ptimer = (Timer *) dwUser;
1144
1145     // Call user-specified callback and pass back user specified data
1146     (ptimer->m_pfnCallback) (ptimer->m_dwUser);
1147 }
1148
1149
1150 // WaveFile class implementation
1151 //
1152 ////////////////////////////////////////////////////////////
1153
1154 // Constructor
1155 void WaveFile::Init(void)
1156 {
1157         // Init data members
1158         m_data_offset = 0;
1159         cfp = NULL;
1160         m_pwfmt_original = NULL;
1161         m_nBlockAlign= 0;
1162         m_nUncompressedAvgDataRate = 0;
1163         m_nDataSize = 0;
1164         m_nBytesPlayed = 0;
1165         m_total_uncompressed_bytes_read = 0;
1166         m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
1167
1168         m_hStream_open = 0;
1169         m_abort_next_read = FALSE;
1170 }
1171
1172 // Destructor
1173 void WaveFile::Close(void)
1174 {
1175         // Free memory
1176         if (m_pwfmt_original) {
1177                 free(m_pwfmt_original);
1178                 m_pwfmt_original = NULL;
1179         }
1180
1181         if ( m_hStream_open ) {
1182                 ACM_stream_close((void*)m_hStream);
1183                 m_hStream_open = 0;
1184         }
1185
1186         // Close file
1187         if (cfp) {
1188                 //cfclose(cfp);
1189                 mmioClose( cfp, 0 );
1190                 cfp = NULL;
1191         }
1192 }
1193
1194
1195 // Open
1196 BOOL WaveFile::Open (LPSTR pszFilename)
1197 {
1198         int done = FALSE;
1199         WORD cbExtra = 0;
1200         BOOL fRtn = SUCCESS;    // assume success
1201         PCMWAVEFORMAT pcmwf;
1202         char fullpath[_MAX_PATH];
1203
1204         m_total_uncompressed_bytes_read = 0;
1205         m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
1206
1207         int FileSize, FileOffset;
1208
1209         if ( !cf_find_file_location(pszFilename, CF_TYPE_ANY, fullpath, &FileSize, &FileOffset ))       {
1210                 goto OPEN_ERROR;
1211         }
1212
1213         cfp = mmioOpen(fullpath, NULL, MMIO_ALLOCBUF | MMIO_READ);
1214         if ( cfp == NULL ) {
1215                 goto OPEN_ERROR;
1216         }
1217
1218         // Skip the "RIFF" tag and file size (8 bytes)
1219         // Skip the "WAVE" tag (4 bytes)
1220         mmioSeek( cfp, 12+FileOffset, SEEK_SET );
1221
1222         // Now read RIFF tags until the end of file
1223         uint tag, size, next_chunk;
1224
1225         while(done == FALSE)    {
1226                 if ( mmioRead(cfp, (char *)&tag, sizeof(uint)) != sizeof(uint) )
1227                         break;
1228
1229                 if ( mmioRead(cfp, (char *)&size, sizeof(uint)) != sizeof(uint) )
1230                         break;
1231
1232                 next_chunk = mmioSeek( cfp, 0, SEEK_CUR );
1233                 next_chunk += size;
1234
1235                 switch( tag )   {
1236                 case 0x20746d66:                // The 'fmt ' tag
1237                         mmioRead( cfp, (char *)&pcmwf, sizeof(PCMWAVEFORMAT) );
1238                         if ( pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM ) {
1239                                 mmioRead( cfp, (char *)&cbExtra, sizeof(short) );
1240                         }
1241
1242                         // Allocate memory for WAVEFORMATEX structure + extra bytes
1243                         if ( (m_pwfmt_original = (WAVEFORMATEX *) malloc ( sizeof(WAVEFORMATEX)+cbExtra )) != NULL ){
1244                                 Assert(m_pwfmt_original != NULL);
1245                                 // Copy bytes from temporary format structure
1246                                 memcpy (m_pwfmt_original, &pcmwf, sizeof(pcmwf));
1247                                 m_pwfmt_original->cbSize = cbExtra;
1248
1249                                 // Read those extra bytes, append to WAVEFORMATEX structure
1250                                 if (cbExtra != 0) {
1251                                         mmioRead( cfp, (char *)((ubyte *)(m_pwfmt_original) + sizeof(WAVEFORMATEX)), cbExtra );
1252                                 }
1253                         }
1254                         else {
1255                                 Int3();         // malloc failed
1256                                 goto OPEN_ERROR;
1257                         }       
1258                         break;
1259
1260                 case 0x61746164:                // the 'data' tag
1261                         m_nDataSize = size;     // This is size of data chunk.  Compressed if ADPCM.
1262                         m_data_bytes_left = size;
1263                         m_data_offset = mmioSeek( cfp, 0, SEEK_CUR);
1264                         done = TRUE;
1265                         break;
1266
1267                 default:        // unknown, skip it
1268                         break;
1269                 }       // end switch
1270
1271                 mmioSeek( cfp, next_chunk, SEEK_SET );
1272         }
1273
1274         // At this stage, examine source format, and set up WAVEFORATEX structure for DirectSound.
1275         // Since DirectSound only supports PCM, force this structure to be PCM compliant.  We will
1276         // need to convert data on the fly later if our souce is not PCM
1277         switch ( m_pwfmt_original->wFormatTag ) {
1278                 case WAVE_FORMAT_PCM:
1279                         m_wave_format = WAVE_FORMAT_PCM;
1280                         m_wfmt.wBitsPerSample = m_pwfmt_original->wBitsPerSample;
1281                         break;
1282
1283                 case WAVE_FORMAT_ADPCM:
1284                         m_wave_format = WAVE_FORMAT_ADPCM;
1285                         m_wfmt.wBitsPerSample = 16;
1286                         break;
1287
1288                 default:
1289                         nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n"));
1290                         //Int3();
1291                         goto OPEN_ERROR;
1292                         break;
1293
1294         } // end switch
1295             
1296         // Set up the WAVEFORMATEX structure to have the right PCM characteristics
1297         m_wfmt.wFormatTag = WAVE_FORMAT_PCM;
1298         m_wfmt.nChannels = m_pwfmt_original->nChannels;
1299         m_wfmt.nSamplesPerSec = m_pwfmt_original->nSamplesPerSec;
1300         m_wfmt.cbSize = 0;
1301         m_wfmt.nBlockAlign = (unsigned short)(( m_wfmt.nChannels * m_wfmt.wBitsPerSample ) / 8);
1302         m_wfmt.nAvgBytesPerSec = m_wfmt.nBlockAlign * m_wfmt.nSamplesPerSec;
1303
1304         // Init some member data from format chunk
1305         m_nBlockAlign = m_pwfmt_original->nBlockAlign;
1306         m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec;
1307
1308         // Cue for streaming
1309         Cue ();
1310  
1311         // Successful open
1312         goto OPEN_DONE;
1313     
1314 OPEN_ERROR:
1315         // Handle all errors here
1316         nprintf(("SOUND","SOUND ==> Could not open wave file %s for streaming\n",pszFilename));
1317
1318         fRtn = FAILURE;
1319         if (cfp != NULL) {
1320                 // Close file
1321                 mmioClose( cfp, 0 );
1322                 cfp = NULL;
1323         }
1324         if (m_pwfmt_original)
1325         {
1326                 free(m_pwfmt_original);
1327                 m_pwfmt_original = NULL;
1328         }
1329
1330 OPEN_DONE:
1331         return (fRtn);
1332 }
1333
1334
1335 // Cue
1336 //
1337 // Set the file pointer to the start of wave data
1338 //
1339 BOOL WaveFile::Cue (void)
1340 {
1341         BOOL fRtn = SUCCESS;    // assume success
1342         int rval;
1343
1344         m_total_uncompressed_bytes_read = 0;
1345         m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
1346
1347         rval = mmioSeek( cfp, m_data_offset, SEEK_SET );
1348         if ( rval == -1 ) {
1349                 fRtn = FAILURE;
1350         }
1351
1352         m_data_bytes_left = m_nDataSize;
1353         m_abort_next_read = FALSE;
1354
1355         return fRtn;
1356 }
1357
1358
1359 // Read
1360 //
1361 // Returns number of bytes actually read.
1362 // 
1363 //      Returns -1 if there is nothing more to be read.  This function can return 0, since
1364 // sometimes the amount of bytes requested is too small for the ACM decompression to 
1365 // locate a suitable block
1366 int WaveFile::Read(BYTE *pbDest, UINT cbSize, int service)
1367 {
1368         unsigned char   *dest_buf=NULL, *uncompressed_wave_data;
1369         int                             rc, uncompressed_bytes_written;
1370         unsigned int    src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read;
1371
1372 //      nprintf(("Alan","Reqeusted: %d\n", cbSize));
1373
1374
1375         if ( service ) {
1376                 uncompressed_wave_data = Wavedata_service_buffer;
1377         } else {
1378                 uncompressed_wave_data = Wavedata_load_buffer;
1379         }
1380
1381         switch ( m_wave_format ) {
1382                 case WAVE_FORMAT_PCM:
1383                         num_bytes_desired = cbSize;
1384                         dest_buf = pbDest;
1385                         break;
1386
1387                 case WAVE_FORMAT_ADPCM:
1388                         if ( !m_hStream_open ) {
1389                                 if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream), m_bits_per_sample_uncompressed  ) {
1390                                         m_hStream_open = 1;
1391                                 } else {
1392                                         Int3();
1393                                 }
1394                         }
1395
1396                         num_bytes_desired = cbSize;
1397         
1398                         if ( service ) {
1399                                 dest_buf = Compressed_service_buffer;
1400                         } else {
1401                                 dest_buf = Compressed_buffer;
1402                         }
1403
1404                         if ( num_bytes_desired <= 0 ) {
1405                                 num_bytes_desired = 0;
1406 //                              nprintf(("Alan","No bytes required for ADPCM time interval\n"));
1407                         } else {
1408                                 num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize);
1409 //                              nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired));
1410                         }
1411                         break;
1412
1413                 default:
1414                         nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n"));
1415                         Int3();
1416                         break;
1417
1418         } // end switch
1419                 
1420         num_bytes_read = 0;
1421         convert_len = 0;
1422         src_bytes_used = 0;
1423
1424         // read data from disk
1425         if ( m_data_bytes_left <= 0 ) {
1426                 num_bytes_read = 0;
1427                 uncompressed_bytes_written = 0;
1428                 return -1;
1429         }
1430
1431         if ( m_data_bytes_left > 0 && num_bytes_desired > 0 ) {
1432                 int actual_read;
1433
1434                 if ( num_bytes_desired <= (unsigned int)m_data_bytes_left ) {
1435                         num_bytes_read = num_bytes_desired;
1436                 }
1437                 else {
1438                         num_bytes_read = m_data_bytes_left;
1439                 }
1440
1441                 actual_read = mmioRead( cfp, (char *)dest_buf, num_bytes_read );
1442                 if ( (actual_read <= 0) || (m_abort_next_read) ) {
1443                         num_bytes_read = 0;
1444                         uncompressed_bytes_written = 0;
1445                         return -1;
1446                 }
1447
1448                 if ( num_bytes_desired >= (unsigned int)m_data_bytes_left ) {
1449                         m_abort_next_read = 1;                  
1450                 }
1451
1452                 num_bytes_read = actual_read;
1453         }
1454
1455         // convert data if necessary, to PCM
1456         if ( m_wave_format == WAVE_FORMAT_ADPCM ) {
1457                 if ( num_bytes_read > 0 ) {
1458                                 rc = ACM_convert((void*)m_hStream, dest_buf, num_bytes_read, uncompressed_wave_data, BIGBUF_SIZE, &convert_len, &src_bytes_used);
1459                                 if ( rc == -1 ) {
1460                                         goto READ_ERROR;
1461                                 }
1462                                 if ( convert_len == 0 ) {
1463                                         Int3();
1464                                 }
1465                 }
1466
1467                 Assert(src_bytes_used <= num_bytes_read);
1468                 if ( src_bytes_used < num_bytes_read ) {
1469                         // seek back file pointer to reposition before unused source data
1470                         mmioSeek(cfp, src_bytes_used - num_bytes_read, SEEK_CUR);
1471                 }
1472
1473                 // Adjust number of bytes left
1474                 m_data_bytes_left -= src_bytes_used;
1475                 m_nBytesPlayed += src_bytes_used;
1476                 uncompressed_bytes_written = convert_len;
1477
1478                 // Successful read, keep running total of number of data bytes read
1479                 goto READ_DONE;
1480         }
1481         else {
1482                 // Successful read, keep running total of number of data bytes read
1483                 // Adjust number of bytes left
1484                 m_data_bytes_left -= num_bytes_read;
1485                 m_nBytesPlayed += num_bytes_read;
1486                 uncompressed_bytes_written = num_bytes_read;
1487                 goto READ_DONE;
1488         }
1489     
1490 READ_ERROR:
1491         num_bytes_read = 0;
1492         uncompressed_bytes_written = 0;
1493
1494 READ_DONE:
1495         m_total_uncompressed_bytes_read += uncompressed_bytes_written;
1496 //      nprintf(("Alan","Read: %d\n", uncompressed_bytes_written));
1497         return (uncompressed_bytes_written);
1498 }
1499
1500
1501 // GetSilenceData
1502 //
1503 // Returns 8 bits of data representing silence for the Wave file format.
1504 //
1505 // Since we are dealing only with PCM format, we can fudge a bit and take
1506 // advantage of the fact that for all PCM formats, silence can be represented
1507 // by a single byte, repeated to make up the proper word size. The actual size
1508 // of a word of wave data depends on the format:
1509 //
1510 // PCM Format       Word Size       Silence Data
1511 // 8-bit mono       1 byte          0x80
1512 // 8-bit stereo     2 bytes         0x8080
1513 // 16-bit mono      2 bytes         0x0000
1514 // 16-bit stereo    4 bytes         0x00000000
1515 //
1516 BYTE WaveFile::GetSilenceData (void)
1517 {
1518         BYTE bSilenceData = 0;
1519
1520         // Silence data depends on format of Wave file
1521         if (m_pwfmt_original) {
1522                 if (m_wfmt.wBitsPerSample == 8) {
1523                         // For 8-bit formats (unsigned, 0 to 255)
1524                         // Packed DWORD = 0x80808080;
1525                         bSilenceData = 0x80;
1526                 }
1527                 else if (m_wfmt.wBitsPerSample == 16) {
1528                         // For 16-bit formats (signed, -32768 to 32767)
1529                         // Packed DWORD = 0x00000000;
1530                         bSilenceData = 0x00;
1531                 }
1532                 else {
1533                         Int3();
1534                 }
1535         }
1536         else {
1537                 Int3();
1538         }
1539
1540         return (bSilenceData);
1541 }
1542
1543 AudioStreamServices * m_pass = NULL;   // ptr to AudioStreamServices object
1544
1545 #define MAX_AUDIO_STREAMS       30
1546 AudioStream Audio_streams[MAX_AUDIO_STREAMS];
1547 #endif // !PLAT_UNIX
1548
1549 int Audiostream_inited = 0;
1550
1551 void audiostream_init()
1552 {
1553         if ( Audiostream_inited == 1 )
1554                 return;
1555                 
1556 #ifdef PLAT_UNIX
1557         STUB_FUNCTION;
1558 #else
1559         int i;
1560
1561         if ( !ACM_is_inited() ) {
1562                 return;
1563         }
1564
1565         // Create and initialize AudioStreamServices object.
1566         // This must be done once and only once for each window that uses
1567         // streaming services.
1568         m_pass = (AudioStreamServices *)malloc(sizeof(AudioStreamServices));
1569
1570         if (m_pass)     {
1571                 m_pass->Constructor();
1572                 m_pass->Initialize();
1573         
1574                 if ( !pDirectSound ) {
1575                         return;
1576                 }
1577         }
1578
1579         // Allocate memory for the buffer which holds the uncompressed wave data that is streamed from the
1580         // disk during a load/cue
1581         if ( Wavedata_load_buffer == NULL ) {
1582                 Wavedata_load_buffer = (unsigned char*)malloc(BIGBUF_SIZE);
1583                 Assert(Wavedata_load_buffer != NULL);
1584         }
1585
1586         // Allocate memory for the buffer which holds the uncompressed wave data that is streamed from the
1587         // disk during a service interval
1588         if ( Wavedata_service_buffer == NULL ) {
1589                 Wavedata_service_buffer = (unsigned char*)malloc(BIGBUF_SIZE);
1590                 Assert(Wavedata_service_buffer != NULL);
1591         }
1592
1593         // Allocate memory for the buffer which holds the compressed wave data that is read from the hard disk
1594         if ( Compressed_buffer == NULL ) {
1595                 Compressed_buffer = (unsigned char*)malloc(COMPRESSED_BUFFER_SIZE);
1596                 Assert(Compressed_buffer != NULL);
1597         }
1598
1599         if ( Compressed_service_buffer == NULL ) {
1600                 Compressed_service_buffer = (unsigned char*)malloc(COMPRESSED_BUFFER_SIZE);
1601                 Assert(Compressed_service_buffer != NULL);
1602         }
1603
1604         for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1605                 Audio_streams[i].Init_Data();
1606                 Audio_streams[i].status = ASF_FREE;
1607                 Audio_streams[i].type = ASF_NONE;
1608         }
1609
1610         InitializeCriticalSection( &Global_service_lock );
1611 #endif
1612
1613         Audiostream_inited = 1;
1614 }
1615
1616 // Close down the audiostream system.  Must call audiostream_init() before any audiostream functions can
1617 // be used.
1618 void audiostream_close()
1619 {
1620         if ( Audiostream_inited == 0 )
1621                 return;
1622
1623 #ifdef PLAT_UNIX
1624         STUB_FUNCTION;
1625 #else
1626         int i;
1627
1628         for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1629                 if ( Audio_streams[i].status == ASF_USED ) {
1630                         Audio_streams[i].status = ASF_FREE;
1631                         Audio_streams[i].Destroy();
1632                 }
1633         }
1634
1635         // Destroy AudioStreamServices object
1636         if (m_pass)     {
1637                 free(m_pass);
1638                 m_pass = NULL;
1639         }
1640
1641         // free global buffers
1642         if ( Wavedata_load_buffer ) {
1643                 free(Wavedata_load_buffer);
1644                 Wavedata_load_buffer = NULL;
1645         }
1646
1647         if ( Wavedata_service_buffer ) {
1648                 free(Wavedata_service_buffer);
1649                 Wavedata_service_buffer = NULL;
1650         }
1651
1652         if ( Compressed_buffer ) {
1653                 free(Compressed_buffer);
1654                 Compressed_buffer = NULL;
1655         }
1656
1657         if ( Compressed_service_buffer ) {
1658                 free(Compressed_service_buffer);
1659                 Compressed_service_buffer = NULL;
1660         }
1661
1662         DeleteCriticalSection( &Global_service_lock );
1663 #endif
1664         Audiostream_inited = 0;
1665 }
1666
1667 // Open a digital sound file for streaming
1668 //
1669 // input:       filename        =>      disk filename of sound file
1670 //                              type            => what type of audio stream do we want to open:
1671 //                                                                      ASF_SOUNDFX
1672 //                                                                      ASF_EVENTMUSIC
1673 //                                                                      ASF_VOICE
1674 //      
1675 // returns:     success => handle to identify streaming sound
1676 //                              failure => -1
1677 int audiostream_open( char * filename, int type )
1678 {
1679 #ifdef PLAT_UNIX
1680         STUB_FUNCTION;
1681         return -1;
1682 #else
1683         int i, rc;
1684         if (!Audiostream_inited || !snd_is_inited())
1685                 return -1;
1686
1687         for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1688                 if ( Audio_streams[i].status == ASF_FREE ) {
1689                         Audio_streams[i].status = ASF_USED;
1690                         Audio_streams[i].type = type;
1691                         break;
1692                 }
1693         }
1694
1695         if ( i == MAX_AUDIO_STREAMS ) {
1696                 nprintf(("Sound", "SOUND => No more audio streams available!\n"));
1697                 return -1;
1698         }
1699
1700         switch(type) {
1701         case ASF_VOICE:
1702         case ASF_SOUNDFX:
1703                 Audio_streams[i].m_bits_per_sample_uncompressed = 8;
1704                 break;
1705         case ASF_EVENTMUSIC:
1706                 Audio_streams[i].m_bits_per_sample_uncompressed = 16;
1707                 break;
1708         default:
1709                 Int3();
1710                 return -1;
1711         }
1712         
1713         rc = Audio_streams[i].Create(filename, m_pass);
1714         if ( rc == 0 ) {
1715                 Audio_streams[i].status = ASF_FREE;
1716                 return -1;
1717         }
1718         else
1719                 return i;
1720 #endif
1721 }
1722
1723
1724 void audiostream_close_file(int i, int fade)
1725 {
1726         if (!Audiostream_inited)
1727                 return;
1728
1729         if ( i == -1 )
1730                 return;
1731 #ifdef PLAT_UNIX
1732         STUB_FUNCTION;
1733 #else
1734
1735         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1736
1737         if ( Audio_streams[i].status == ASF_USED ) {
1738                 if ( fade == TRUE ) {
1739                         Audio_streams[i].Fade_and_Destroy();
1740                 }
1741                 else {
1742                         Audio_streams[i].Destroy();
1743                 }
1744         }
1745 #endif
1746 }
1747
1748 void audiostream_close_all(int fade)
1749 {
1750 #ifdef PLAT_UNIX
1751         STUB_FUNCTION;
1752 #else
1753         int i;
1754
1755         for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1756                 if ( Audio_streams[i].status == ASF_FREE )
1757                         continue;
1758
1759                 audiostream_close_file(i, fade);
1760         }
1761 #endif
1762 }
1763
1764 extern int ds_convert_volume(float volume);
1765
1766 void audiostream_play(int i, float volume, int looping)
1767 {
1768         if (!Audiostream_inited)
1769                 return;
1770
1771         if ( i == -1 )
1772                 return;
1773
1774 #ifdef PLAT_UNIX
1775         STUB_FUNCTION;
1776 #else
1777         Assert(looping >= 0);
1778         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1779
1780         // convert from 0->1 to -10000->0 for volume
1781         int converted_volume;
1782         if ( volume == -1 ) {
1783                 converted_volume = Audio_streams[i].Get_Default_Volume();
1784         }
1785         else {
1786                 Assert(volume >= 0.0f && volume <= 1.0f );
1787                 converted_volume = ds_convert_volume(volume);
1788         }
1789
1790         Assert( Audio_streams[i].status == ASF_USED );
1791         Audio_streams[i].Set_Default_Volume(converted_volume);
1792         Audio_streams[i].Play(converted_volume, looping);
1793 #endif
1794 }
1795
1796 void audiostream_stop(int i, int rewind, int paused)
1797 {
1798         if (!Audiostream_inited) return;
1799
1800         if ( i == -1 )
1801                 return;
1802
1803 #ifdef PLAT_UNIX
1804         STUB_FUNCTION;
1805 #else
1806         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1807         Assert( Audio_streams[i].status == ASF_USED );
1808
1809         if ( rewind )
1810                 Audio_streams[i].Stop_and_Rewind();
1811         else
1812                 Audio_streams[i].Stop(paused);
1813 #endif
1814 }
1815
1816 int audiostream_is_playing(int i)
1817 {
1818         if ( i == -1 )
1819                 return 0;
1820
1821 #ifdef PLAT_UNIX
1822         STUB_FUNCTION;
1823         return 0;
1824 #else
1825         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1826         if ( Audio_streams[i].status != ASF_USED )
1827                 return 0;
1828
1829         return Audio_streams[i].Is_Playing();
1830 #endif
1831 }
1832
1833
1834 void audiostream_set_volume_all(float volume, int type)
1835 {
1836 #ifdef PLAT_UNIX
1837         STUB_FUNCTION;
1838 #else
1839         int i;
1840
1841         for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1842                 if ( Audio_streams[i].status == ASF_FREE )
1843                         continue;
1844
1845                 if ( Audio_streams[i].type == type ) {
1846                         int converted_volume;
1847                         converted_volume = ds_convert_volume(volume);
1848                         Audio_streams[i].Set_Volume(converted_volume);
1849                 }
1850         }
1851 #endif
1852 }
1853
1854
1855 void audiostream_set_volume(int i, float volume)
1856 {
1857         if ( i == -1 )
1858                 return;
1859
1860 #ifdef PLAT_UNIX
1861         STUB_FUNCTION;
1862 #else
1863         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1864         Assert( volume >= 0 && volume <= 1);
1865
1866         if ( Audio_streams[i].status == ASF_FREE )
1867                 return;
1868
1869         int converted_volume;
1870         converted_volume = ds_convert_volume(volume);
1871         Audio_streams[i].Set_Volume(converted_volume);
1872 #endif
1873 }
1874
1875
1876 int audiostream_is_paused(int i)
1877 {
1878         if ( i == -1 )
1879                 return 0;
1880
1881 #ifdef PLAT_UNIX
1882         STUB_FUNCTION;
1883         return 0;
1884 #else
1885         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1886         if ( Audio_streams[i].status == ASF_FREE )
1887                 return -1;
1888
1889         BOOL is_paused;
1890         is_paused = Audio_streams[i].Is_Paused();
1891         return is_paused;
1892 #endif
1893 }
1894
1895
1896 void audiostream_set_byte_cutoff(int i, unsigned int cutoff)
1897 {
1898         if ( i == -1 )
1899                 return;
1900
1901 #ifdef PLAT_UNIX
1902         STUB_FUNCTION;
1903 #else
1904         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1905         Assert( cutoff > 0 );
1906
1907         if ( Audio_streams[i].status == ASF_FREE )
1908                 return;
1909
1910         Audio_streams[i].Set_Byte_Cutoff(cutoff);
1911 #endif
1912 }
1913
1914
1915 unsigned int audiostream_get_bytes_committed(int i)
1916 {
1917         if ( i == -1 )
1918                 return 0;
1919
1920 #ifdef PLAT_UNIX
1921         STUB_FUNCTION;
1922         return 0;
1923 #else
1924         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1925
1926         if ( Audio_streams[i].status == ASF_FREE )
1927                 return 0;
1928
1929         unsigned int num_bytes_committed;
1930         num_bytes_committed = Audio_streams[i].Get_Bytes_Committed();
1931         return num_bytes_committed;
1932 #endif
1933 }
1934
1935 int audiostream_done_reading(int i)
1936 {
1937         if ( i == -1 )
1938                 return 0;
1939
1940 #ifdef PLAT_UNIX
1941         STUB_FUNCTION;
1942         return 0;
1943 #else
1944         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1945
1946         if ( Audio_streams[i].status == ASF_FREE )
1947                 return 0;
1948
1949         int done_reading;
1950         done_reading = Audio_streams[i].Is_Past_Limit();
1951         return done_reading;
1952 #endif
1953 }
1954
1955
1956 int audiostream_is_inited()
1957 {
1958         return Audiostream_inited;
1959 }
1960
1961 // pause a single audio stream, indentified by handle i.
1962 void audiostream_pause(int i)
1963 {
1964         if ( i == -1 )
1965                 return;
1966
1967 #ifdef PLAT_UNIX
1968         STUB_FUNCTION;
1969 #else
1970         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1971         if ( Audio_streams[i].status == ASF_FREE )
1972                 return;
1973
1974         if ( audiostream_is_playing(i) == TRUE ) {
1975                 audiostream_stop(i, 0, 1);
1976         }
1977 #endif
1978 }
1979
1980 // pause all audio streams that are currently playing.
1981 void audiostream_pause_all()
1982 {
1983 #ifdef PLAT_UNIX
1984         STUB_FUNCTION;
1985 #else
1986         int i;
1987
1988         for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1989                 if ( Audio_streams[i].status == ASF_FREE )
1990                         continue;
1991
1992                 audiostream_pause(i);
1993         }
1994 #endif
1995 }
1996
1997 // unpause the audio stream identified by handle i.
1998 void audiostream_unpause(int i)
1999 {
2000         if ( i == -1 )
2001                 return;
2002
2003 #ifdef PLAT_UNIX
2004         STUB_FUNCTION;
2005 #else
2006         int is_looping;
2007
2008         Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
2009         if ( Audio_streams[i].status == ASF_FREE )
2010                 return;
2011
2012         if ( audiostream_is_paused(i) == TRUE ) {
2013                 is_looping = Audio_streams[i].Is_looping();
2014                 audiostream_play(i, -1.0f, is_looping);
2015         }
2016 #endif
2017 }
2018
2019 // unpause all audio streams that are currently paused
2020 void audiostream_unpause_all()
2021 {
2022 #ifdef PLAT_UNIX
2023         STUB_FUNCTION;
2024 #else
2025         int i;
2026
2027         for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
2028                 if ( Audio_streams[i].status == ASF_FREE )
2029                         continue;
2030
2031                 audiostream_unpause(i);
2032         }
2033 #endif
2034 }
2035