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