]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/audiostr.cpp
this should return true; handled earlier/later
[taylor/freespace2.git] / src / sound / audiostr.cpp
1 /*
2  * $Logfile: $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * OpenAL based audio streaming
8  *
9  * $Log$
10  * Revision 1.4  2005/10/01 21:53:06  taylor
11  * include file cleanup
12  * byte-swap streaming PCM to avoid the endless, loud, static
13  *
14  * Revision 1.3  2005/08/13 16:59:23  taylor
15  * type check
16  *
17  * Revision 1.2  2005/08/12 20:21:06  taylor
18  * woorps!
19  *
20  * Revision 1.1  2005/08/12 08:44:39  taylor
21  * import of FS2_Open audio code which is now *nix only, does not include windows or ogg support that FS2_Open has
22  *
23  * Revision 1.12  2005/06/24 19:36:49  taylor
24  * we only want to have m_data_offset be 0 for oggs since the seeking callback will account for the true offset
25  * only extern the one int we need for the -nosound speech fix rather than including the entire header
26  *
27  * Revision 1.11  2005/06/19 02:45:55  taylor
28  * OGG streaming fixes to get data reading right and avoid skipping
29  * properly handle seeking in OGG streams
30  * compiler warning fix in OpenAL builds
31  *
32  * Revision 1.10  2005/06/01 09:41:14  taylor
33  * bit of cleanup for audiostr-openal and fix a Windows-only enum error
34  * bunch of OGG related fixes for Linux and Windows (DirectSound and OpenAL), fixes audio related TBP 3.2 crashes
35  * gracefully handle OGG logical bitstream changes, shouldn't even load if there is more than 1
36  *
37  * Revision 1.9  2005/05/28 19:43:28  taylor
38  * debug message fixing
39  * a little bit of code clarity
40  *
41  * Revision 1.8  2005/05/24 03:11:38  taylor
42  * an extra bounds check in sound.cpp
43  * fix audiostr error when filename is !NULL but 0 in len might hit on SDL debug code
44  *
45  * Revision 1.7  2005/05/15 06:47:57  taylor
46  * don't let the ogg callbacks close the file handle on us, let us do it ourselves to keep things straight
47  *
48  * Revision 1.6  2005/05/13 23:09:28  taylor
49  * Ooops!  Added the wrong version of the streaming patch from Jens
50  *
51  * Revision 1.5  2005/05/12 17:47:57  taylor
52  * use vm_malloc(), vm_free(), vm_realloc(), vm_strdup() rather than system named macros
53  *   fixes various problems and is past time to make the switch
54  * fix a few streaming errors in OpenAL code (Jens Granseuer)
55  * temporary change to help deal with missing music in OpenAL Windows builds
56  * don't assert when si->data is NULL unless we really need to check (OpenAL only)
57  *
58  * Revision 1.4  2005/04/05 11:48:22  taylor
59  * remove acm-unix.cpp, replaced by acm-openal.cpp since it's properly cross-platform now
60  * better error handling for OpenAL functions
61  * Windows can now build properly with OpenAL
62  * extra check to make sure we don't try and use too many hardware bases sources
63  * fix memory error from OpenAL extension list in certain instances
64  *
65  * Revision 1.3  2005/04/01 07:33:08  taylor
66  * fix hanging on exit with OpenAL
67  * some better error handling on OpenAL init and make it more Windows friendly too
68  * basic 3d sound stuff for OpenAL, not working right yet
69  *
70  * Revision 1.2  2005/03/27 08:51:24  taylor
71  * this is what coding on an empty stomach will get you
72  *
73  * Revision 1.1  2005/03/27 05:48:58  taylor
74  * initial import of OpenAL streaming (many thanks to Pierre Willenbrock for the missing parts)
75  *
76  *
77  * $NoKeywords: $
78  */
79
80
81 #include <vector>
82
83 #include "pstypes.h"
84 #include "audiostr.h"
85 #include "oal.h"
86 #include "acm.h"
87 #include "cfile.h"
88 #include "sound.h"
89 #include "timer.h"
90
91
92 #define MAX_STREAM_BUFFERS 4
93
94 // Constants
95 #define BIGBUF_SIZE                                     180000                  // This can be reduced to 88200 once we don't use any stereo
96 //#define BIGBUF_SIZE                                   88300                   // This can be reduced to 88200 once we don't use any stereo
97 static ubyte *Wavedata_load_buffer = NULL;              // buffer used for cueing audiostreams
98 static ubyte *Wavedata_service_buffer = NULL;   // buffer used for servicing audiostreams
99
100 SDL_mutex *Global_service_lock;
101
102 typedef bool (*TIMERCALLBACK)(ptr_u);
103
104 #define COMPRESSED_BUFFER_SIZE  88300
105 static ubyte *Compressed_buffer = NULL;                         // Used to load in compressed data during a cueing interval
106 static ubyte *Compressed_service_buffer = NULL; // Used to read in compressed data during a service interval
107
108 #define AS_HIGHEST_MAX  999999999       // max uncompressed filesize supported is 999 meg
109
110 // status
111 #define ASF_FREE        0
112 #define ASF_USED        1
113
114 static int Audiostream_inited = 0;
115
116
117 class Timer
118 {
119 public:
120     void constructor();
121     void destructor();
122
123     bool Create(uint nPeriod, ptr_u dwUser, TIMERCALLBACK pfnCallback);
124
125 protected:
126         static Uint32 TimeProc(Uint32 interval, void *dwUser);
127
128         TIMERCALLBACK m_pfnCallback;
129     ptr_u m_dwUser;
130     uint m_nPeriod;
131     SDL_TimerID m_nIDTimer;
132 };
133
134 class WaveFile
135 {
136 public:
137         void Init();
138         void Close();
139         bool Open(const char *pszFilename);
140         bool Cue();
141         int     Read(ubyte *pbDest, uint cbSize, int service = 1);
142         ubyte GetSilenceData();
143
144         uint GetNumBytesRemaining()
145         {
146                 return (m_nDataSize - m_nBytesPlayed);
147         }
148
149         uint GetUncompressedAvgDataRate()
150         {
151                 return m_nUncompressedAvgDataRate;
152         }
153
154         uint GetDataSize()
155         {
156                 return m_nDataSize;
157         }
158
159         uint GetNumBytesPlayed()
160         {
161                 return m_nBytesPlayed;
162         }
163
164         ALenum GetOALFormat()
165         {
166                 return m_oal_format;
167         }
168
169         WAVE_chunk m_wfmt;                                      // format of wave file
170         WAVE_chunk *m_pwfmt_original;   // foramt of wave file from actual wave source
171         uint m_total_uncompressed_bytes_read;
172         uint m_max_uncompressed_bytes_to_read;
173         uint m_bits_per_sample_uncompressed;
174
175 protected:
176         uint m_data_offset;                                             // number of bytes to actual wave data
177         int  m_data_bytes_left;
178         CFILE *cfp;
179
180         ALenum m_oal_format;
181         uint m_wave_format;                                             // format of wave source (ie WAVE_FORMAT_PCM, WAVE_FORMAT_ADPCM)
182         uint m_nBlockAlign;                                             // wave data block alignment spec
183         uint m_nUncompressedAvgDataRate;                // average wave data rate
184         uint m_nDataSize;                                                       // size of data chunk
185         uint m_nBytesPlayed;                                            // offset into data chunk
186         bool m_abort_next_read;
187
188         void *m_hStream;
189         int m_hStream_open;
190         WAVE_chunk m_wfxDest;
191 };
192
193 class AudioStream
194 {
195 public:
196         AudioStream();
197         ~AudioStream();
198
199         bool Create(const char *pszFilename);
200         bool Destroy();
201         void Play(float volume, int looping);
202         void Stop(int paused = 0);
203         void Stop_and_Rewind();
204         void Fade_and_Destroy();
205         void Fade_and_Stop();
206         void Set_Volume(float vol);
207         float Get_Volume();
208         void Init_Data();
209         void Set_Byte_Cutoff(uint num_bytes_cutoff);
210         uint Get_Bytes_Committed();
211
212         int Is_Playing()
213         {
214                 return m_fPlaying;
215         }
216
217         int Is_Paused()
218         {
219                 return m_bIsPaused;
220         }
221
222         int Is_Past_Limit()
223         {
224                 return m_bPastLimit;
225         }
226
227         void Set_Default_Volume(float _volume)
228         {
229                 m_lDefaultVolume = _volume;
230         }
231
232         float Get_Default_Volume()
233         {
234                 return m_lDefaultVolume;
235         }
236
237         int     Is_looping()
238         {
239                 return m_bLooping;
240         }
241
242         int status;
243         int     type;
244         ushort m_bits_per_sample_uncompressed;
245
246 protected:
247         void Cue();
248         bool WriteWaveData(uint cbSize, uint* num_bytes_written,int service=1);
249         uint GetMaxWriteSize();
250         bool ServiceBuffer();
251         static bool TimerCallback(ptr_u dwUser);
252
253         ALuint m_source_id;   // name of openAL source
254         ALuint m_buffer_ids[MAX_STREAM_BUFFERS]; //names of buffers
255         int m_play_buffer_id;
256
257         Timer m_timer;              // ptr to Timer object
258         WaveFile *m_pwavefile;        // ptr to WaveFile object
259         bool m_fCued;                  // semaphore (stream cued)
260         bool m_fPlaying;               // semaphore (stream playing)
261         long m_lInService;             // reentrancy semaphore
262         uint m_cbBufOffset;            // last write position
263         uint m_nBufLength;             // length of sound buffer in msec
264         uint m_cbBufSize;              // size of sound buffer in bytes
265         uint m_nBufService;            // service interval in msec
266         uint m_nTimeStarted;           // time (in system time) playback started
267
268         bool    m_bLooping;                                             // whether or not to loop playback
269         bool    m_bFade;                                                        // fade out music
270         bool    m_bDestroy_when_faded;
271         float   m_lVolume;                                              // volume of stream ( 0 -> -10 000 )
272         float   m_lCutoffVolume;
273         bool    m_bIsPaused;                                    // stream is stopped, but not rewinded
274         ushort  m_silence_written;                      // number of bytes of silence written to buffer
275         ushort  m_bReadingDone;                         // no more bytes to be read from disk, still have remaining buffer to play
276         uint    m_fade_timer_id;                                // timestamp so we know when to start fade
277         uint    m_finished_id;                                  // timestamp so we know when we've played #bytes required
278         bool    m_bPastLimit;                                   // flag to show we've played past the number of bytes requred
279         float   m_lDefaultVolume;
280 };
281
282
283 // Timer class implementation
284 //
285 ////////////////////////////////////////////////////////////
286
287 void Timer::constructor()
288 {
289         m_nIDTimer = 0;
290 }
291
292 void Timer::destructor()
293 {
294         if (m_nIDTimer) {
295                 SDL_RemoveTimer(m_nIDTimer);
296                 m_nIDTimer = 0;
297         }
298 }
299
300 bool Timer::Create(uint nPeriod, ptr_u dwUser, TIMERCALLBACK pfnCallback)
301 {
302         SDL_assert( pfnCallback != NULL );
303         SDL_assert( nPeriod > 10 );
304
305         m_nPeriod = nPeriod;
306         m_dwUser = dwUser;
307         m_pfnCallback = pfnCallback;
308
309         m_nIDTimer = SDL_AddTimer(m_nPeriod, TimeProc, (void*)this);
310
311         if ( !m_nIDTimer ) {
312                 nprintf(("SOUND", "SOUND ==> Error, unable to create timer\n"));
313                 return false;
314         }
315
316         return true;
317 }
318
319 // Calls procedure specified when Timer object was created. The 
320 // dwUser parameter contains "this" pointer for associated Timer object.
321 // 
322 Uint32 Timer::TimeProc(Uint32 interval, void *dwUser)
323 {
324     // dwUser contains ptr to Timer object
325         Timer *ptimer = (Timer *)dwUser;
326
327     // Call user-specified callback and pass back user specified data
328     (ptimer->m_pfnCallback)(ptimer->m_dwUser);
329
330     if (ptimer->m_nPeriod) {
331                 return interval;
332     } else {
333                 SDL_RemoveTimer(ptimer->m_nIDTimer);
334                 ptimer->m_nIDTimer = 0;
335
336                 return 0;
337     }
338 }
339
340
341 // WaveFile class implementation
342 //
343 ////////////////////////////////////////////////////////////
344
345 void WaveFile::Init()
346 {
347         // Init data members
348         m_data_offset = 0;
349         cfp = NULL;
350         m_pwfmt_original = NULL;
351         m_nBlockAlign= 0;
352         m_nUncompressedAvgDataRate = 0;
353         m_nDataSize = 0;
354         m_nBytesPlayed = 0;
355         m_total_uncompressed_bytes_read = 0;
356         m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
357
358         m_hStream_open = 0;
359         m_abort_next_read = false;
360 }
361
362 void WaveFile::Close()
363 {
364         // Free memory
365         if (m_pwfmt_original) {
366                 free(m_pwfmt_original);
367                 m_pwfmt_original = NULL;
368         }
369
370         if (m_hStream_open) {
371                 ACM_stream_close((void*)m_hStream);
372                 m_hStream_open = 0;
373         }
374
375         // Close file
376         if (cfp) {
377                 cfclose(cfp);
378                 cfp = NULL;
379         }
380 }
381
382 bool WaveFile::Open(const char *pszFilename)
383 {
384         int done = false;
385         bool fRtn = true;    // assume success
386         int id = 0;
387         uint tag = 0, size = 0, next_chunk;
388
389         m_total_uncompressed_bytes_read = 0;
390         m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
391
392         m_pwfmt_original = (WAVE_chunk*) malloc (sizeof(WAVE_chunk));
393
394         if (m_pwfmt_original == NULL) {
395                 goto OPEN_ERROR;
396         }
397
398         cfp = cfopen(pszFilename, "rb");
399
400         if (cfp == NULL) {
401                 goto OPEN_ERROR;
402         }
403
404         // check for valid file type
405         id = cfread_int(cfp);
406
407         // 'RIFF'
408         if (id != 0x46464952) {
409                 nprintf(("Error", "Not a WAVE file '%s'\n", pszFilename));
410                 goto OPEN_ERROR;
411         }
412
413         // skip RIFF size
414         cfread_int(cfp);
415
416         // check for valid RIFF type
417         id = cfread_int(cfp);
418
419         // 'WAVE'
420         if (id != 0x45564157) {
421                 nprintf(("Error", "Not a WAVE file '%s'\n", pszFilename));
422                 goto OPEN_ERROR;
423         }
424
425         while ( !done ) {
426                 tag = cfread_uint(cfp);
427                 size = cfread_uint(cfp);
428
429                 next_chunk = cftell(cfp) + size;
430
431                 switch (tag) {
432                         // 'fmt '
433                         case 0x20746d66: {
434                                 m_pwfmt_original->code = cfread_short(cfp);
435                                 m_pwfmt_original->num_channels = cfread_ushort(cfp);
436                                 m_pwfmt_original->sample_rate = cfread_uint(cfp);
437                                 m_pwfmt_original->bytes_per_second = cfread_uint(cfp);
438                                 m_pwfmt_original->block_align = cfread_ushort(cfp);
439                                 m_pwfmt_original->bits_per_sample = cfread_ushort(cfp);
440
441                                 if (m_pwfmt_original->code != 1) {
442                                         m_pwfmt_original->extra_size = cfread_ushort(cfp);
443                                 }
444
445                                 if (m_pwfmt_original->extra_size) {
446                                         m_pwfmt_original->extra_data = (ubyte*) malloc (m_pwfmt_original->extra_size);
447                                         SDL_assert( m_pwfmt_original->extra_data != NULL );
448
449                                         if (m_pwfmt_original->extra_data == NULL) {
450                                                 goto OPEN_ERROR;
451                                         }
452
453                                         cfread(m_pwfmt_original->extra_data, m_pwfmt_original->extra_size, 1, cfp);
454                                 }
455
456                                 break;
457                         }
458
459                         // 'data'
460                         case 0x61746164: {
461                                 m_nDataSize = size;     // size of data, compressed size if ADPCM
462                                 m_data_bytes_left = size;
463                                 m_data_offset = cftell(cfp);
464
465                                 done = true;
466
467                                 break;
468                         }
469
470                         // drop everything else
471                         default:
472                                 break;
473                 }
474
475                 cfseek(cfp, next_chunk, CF_SEEK_SET);
476         }
477
478         // we force PCM format, so keep track of original format for later
479         switch (m_pwfmt_original->code) {
480                 case WAVE_FORMAT_PCM:
481                         m_wave_format = WAVE_FORMAT_PCM;
482                         m_wfmt.bits_per_sample = m_pwfmt_original->bits_per_sample;
483                         break;
484
485                 case WAVE_FORMAT_ADPCM:
486                         m_wave_format = WAVE_FORMAT_ADPCM;
487                         m_wfmt.bits_per_sample = 16;
488                         m_bits_per_sample_uncompressed = 16;
489                         break;
490
491                 default:
492                         nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_pwfmt_original->code));
493                         //Int3();
494                         goto OPEN_ERROR;
495                         break;
496
497         }
498             
499         m_wfmt.code = WAVE_FORMAT_PCM;
500         m_wfmt.num_channels = m_pwfmt_original->num_channels;
501         m_wfmt.sample_rate = m_pwfmt_original->sample_rate;
502         m_wfmt.extra_size = 0;
503         m_wfmt.block_align = (ushort)(( m_wfmt.num_channels * m_wfmt.bits_per_sample ) / 8);
504         m_wfmt.bytes_per_second = m_wfmt.block_align * m_wfmt.sample_rate;
505
506         // set OpenAL format
507         m_oal_format = AL_FORMAT_MONO8;
508
509         if (m_wfmt.num_channels == 1) {
510                 if (m_wfmt.bits_per_sample == 8) {
511                         m_oal_format = AL_FORMAT_MONO8;
512                 } else if (m_wfmt.bits_per_sample == 16) {
513                         m_oal_format = AL_FORMAT_MONO16;
514                 }
515         } else if (m_wfmt.num_channels == 2) {
516                 if (m_wfmt.bits_per_sample == 8) {
517                         m_oal_format = AL_FORMAT_STEREO8;
518                 } else if (m_wfmt.bits_per_sample == 16) {
519                         m_oal_format = AL_FORMAT_STEREO16;
520                 }
521         }
522
523         // Init some member data from format chunk
524         m_nBlockAlign = m_pwfmt_original->block_align;
525         m_nUncompressedAvgDataRate = m_wfmt.bytes_per_second;
526
527         // Successful open
528         goto OPEN_DONE;
529
530 OPEN_ERROR:
531         // Handle all errors here
532         nprintf(("SOUND","SOUND ==> Could not open wave file %s for streaming\n", pszFilename));
533
534         fRtn = false;
535
536         if (m_pwfmt_original) {
537                 free(m_pwfmt_original);
538                 m_pwfmt_original = NULL;
539         }
540
541         if (cfp != NULL) {
542                 cfclose(cfp);
543                 cfp = NULL;
544         }
545
546 OPEN_DONE:
547         return (fRtn);
548 }
549
550 // Cue
551 //
552 // Set the file pointer to the start of wave data
553 //
554 bool WaveFile::Cue()
555 {
556         bool fRtn = true;    // assume success
557         int rval = -1;
558
559         m_total_uncompressed_bytes_read = 0;
560         m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
561
562         rval = cfseek(cfp, m_data_offset, CF_SEEK_SET);
563
564         if (rval) {
565                 fRtn = false;
566         }
567
568         m_data_bytes_left = m_nDataSize;
569         m_abort_next_read = false;
570
571         return fRtn;
572 }
573
574 // Read
575 //
576 // Returns number of bytes actually read.
577 // 
578 //      Returns -1 if there is nothing more to be read.  This function can return 0, since
579 // sometimes the amount of bytes requested is too small for the ACM decompression to 
580 // locate a suitable block
581 int WaveFile::Read(ubyte *pbDest, uint cbSize, int service)
582 {
583         void *dest_buf = NULL, *uncompressed_wave_data;
584         int rc, uncompressed_bytes_written;
585         uint src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read;
586
587 //      nprintf(("Alan","Reqeusted: %d\n", cbSize));
588
589         if ( service ) {
590                 uncompressed_wave_data = Wavedata_service_buffer;
591         } else {
592                 uncompressed_wave_data = Wavedata_load_buffer;
593         }
594
595         switch (m_wave_format) {
596                 case WAVE_FORMAT_PCM: {
597                         num_bytes_desired = cbSize;
598                         dest_buf = pbDest;
599
600                         break;
601                 }
602
603                 case WAVE_FORMAT_ADPCM: {
604                         if ( !m_hStream_open ) {
605                                 if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream, m_bits_per_sample_uncompressed) ) {
606                                         m_hStream_open = 1;
607                                 } else {
608                                         Int3();
609                                 }
610                         }
611
612                         num_bytes_desired = cbSize;
613         
614                         if (service) {
615                                 dest_buf = Compressed_service_buffer;
616                         } else {
617                                 dest_buf = Compressed_buffer;
618                         }
619
620                         if (num_bytes_desired <= 0) {
621                                 num_bytes_desired = 0;
622 //                              nprintf(("Alan","No bytes required for ADPCM time interval\n"));
623                         } else {
624                                 num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize);
625 //                              nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired));
626                         }
627
628                         break;
629                 }
630
631                 default:
632                         nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n"));
633                         Int3();
634                         break;
635
636         } // end switch
637
638         num_bytes_read = 0;
639         convert_len = 0;
640         src_bytes_used = 0;
641
642         // read data from disk
643         if (m_data_bytes_left <= 0) {
644                 num_bytes_read = 0;
645                 uncompressed_bytes_written = 0;
646
647                 return -1;
648         }
649
650         if ( (m_data_bytes_left > 0) && (num_bytes_desired > 0) ) {
651                 int actual_read = 0;
652
653                 if (num_bytes_desired <= (uint)m_data_bytes_left) {
654                         num_bytes_read = num_bytes_desired;
655                 } else {
656                         num_bytes_read = m_data_bytes_left;
657                 }
658
659                 actual_read = cfread(dest_buf, 1, num_bytes_read, cfp);
660
661                 if ( (actual_read <= 0) || (m_abort_next_read) ) {
662                         num_bytes_read = 0;
663                         uncompressed_bytes_written = 0;
664
665                         return -1;
666                 }
667
668                 if (num_bytes_desired >= (uint)m_data_bytes_left) {
669                         m_abort_next_read = 1;                  
670                 }
671
672                 num_bytes_read = actual_read;
673         }
674
675         // convert data if necessary, to PCM
676         if (m_wave_format == WAVE_FORMAT_ADPCM) {
677                 if ( num_bytes_read > 0 ) {
678                         rc = ACM_convert((void*)m_hStream, (ubyte*)dest_buf, num_bytes_read, (ubyte*)uncompressed_wave_data, BIGBUF_SIZE, &convert_len, &src_bytes_used);
679
680                         if (rc == -1) {
681                                 goto READ_ERROR;
682                         }
683
684                         if (convert_len == 0) {
685                                 Int3();
686                         }
687                 }
688
689                 SDL_assert( src_bytes_used <= num_bytes_read );
690
691                 if (src_bytes_used < num_bytes_read) {
692                         // seek back file pointer to reposition before unused source data
693                         cfseek(cfp, src_bytes_used - num_bytes_read, CF_SEEK_CUR);
694                 }
695
696                 // Adjust number of bytes left
697                 m_data_bytes_left -= src_bytes_used;
698                 m_nBytesPlayed += src_bytes_used;
699                 uncompressed_bytes_written = convert_len;
700
701                 // Successful read, keep running total of number of data bytes read
702                 goto READ_DONE;
703         } else {
704                 // Successful read, keep running total of number of data bytes read
705                 // Adjust number of bytes left
706                 m_data_bytes_left -= num_bytes_read;
707                 m_nBytesPlayed += num_bytes_read;
708                 uncompressed_bytes_written = num_bytes_read;
709
710 #if BYTE_ORDER == BIG_ENDIAN
711                 if (m_wave_format == WAVE_FORMAT_PCM) {
712                         // swap 16-bit sound data
713                         if (m_wfmt.bits_per_sample == 16) {
714                                 ushort *swap_tmp;
715                                 
716                                 for (int i = 0; i < uncompressed_bytes_written; i = (i+2)) {
717                                         swap_tmp = (ushort*)((ubyte*)dest_buf + i);
718                                         *swap_tmp = INTEL_SHORT(*swap_tmp);
719                                 }
720                         }
721                 }
722 #endif
723
724                 goto READ_DONE;
725         }
726     
727 READ_ERROR:
728         num_bytes_read = 0;
729         uncompressed_bytes_written = 0;
730
731 READ_DONE:
732         m_total_uncompressed_bytes_read += uncompressed_bytes_written;
733 //      nprintf(("Alan","Read: %d\n", uncompressed_bytes_written));
734
735         return uncompressed_bytes_written;
736 }
737
738 // GetSilenceData
739 //
740 // Returns 8 bits of data representing silence for the Wave file format.
741 //
742 // Since we are dealing only with PCM format, we can fudge a bit and take
743 // advantage of the fact that for all PCM formats, silence can be represented
744 // by a single byte, repeated to make up the proper word size. The actual size
745 // of a word of wave data depends on the format:
746 //
747 // PCM Format       Word Size       Silence Data
748 // 8-bit mono       1 byte          0x80
749 // 8-bit stereo     2 bytes         0x8080
750 // 16-bit mono      2 bytes         0x0000
751 // 16-bit stereo    4 bytes         0x00000000
752 //
753 ubyte WaveFile::GetSilenceData()
754 {
755         ubyte bSilenceData = 0;
756
757         // Silence data depends on format of Wave file
758         if (m_pwfmt_original) {
759                 if (m_wfmt.bits_per_sample == 8) {
760                         // For 8-bit formats (unsigned, 0 to 255)
761                         // Packed DWORD = 0x80808080;
762                         bSilenceData = 0x80;
763                 } else if (m_wfmt.bits_per_sample == 16) {
764                         // For 16-bit formats (signed, -32768 to 32767)
765                         // Packed DWORD = 0x00000000;
766                         bSilenceData = 0x00;
767                 } else {
768                         Int3();
769                 }
770         } else {
771                 Int3();
772         }
773
774         return bSilenceData;
775 }
776
777 //
778 // AudioStream class implementation
779 //
780 ////////////////////////////////////////////////////////////
781
782 // The following constants are the defaults for our streaming buffer operation.
783 static const ushort DefBufferLength          = 2000; // default buffer length in msec
784 static const ushort DefBufferServiceInterval = 250;  // default buffer service interval in msec
785
786 // Constructor
787 AudioStream::AudioStream()
788 {
789 }
790
791 // Destructor
792 AudioStream::~AudioStream()
793 {
794 }
795
796 void AudioStream::Init_Data()
797 {
798         m_bLooping = false;
799         m_bFade = false;
800         m_fade_timer_id = 0;
801         m_finished_id = 0;
802         m_bPastLimit = false;
803
804         m_bDestroy_when_faded = false;
805         m_lDefaultVolume = 1.0f;
806         m_lVolume = 1.0f;
807         m_lCutoffVolume = 0.0f;
808         m_bIsPaused = false;
809         m_silence_written = 0;
810         m_bReadingDone = false;
811
812         m_pwavefile = NULL;
813
814         m_fPlaying = m_fCued = false;
815         m_lInService = false;
816         m_cbBufOffset = 0;
817         m_nBufLength = DefBufferLength;
818         m_cbBufSize = 0;
819         m_nBufService = DefBufferServiceInterval;
820         m_nTimeStarted = 0;
821
822         memset(m_buffer_ids, 0, sizeof(m_buffer_ids));
823         m_source_id = 0;
824         m_play_buffer_id = 0;
825 }
826
827 // Create
828 bool AudioStream::Create(const char *pszFilename)
829 {
830         SDL_assert( pszFilename != NULL );
831
832         Init_Data();
833
834         if (pszFilename == NULL) {
835                 return false;
836         }
837
838         // make 100% sure we got a good filename
839         if ( !strlen(pszFilename) ) {
840                 return false;
841         }
842
843         // Create a new WaveFile object
844         m_pwavefile = (WaveFile *)malloc(sizeof(WaveFile));
845         SDL_assert( m_pwavefile != NULL );
846
847         if (m_pwavefile == NULL) {
848                 nprintf(("Sound", "SOUND => Failed to create WaveFile object %s\n\r", pszFilename));
849                 return false;
850         }
851
852         // Call constructor
853         m_pwavefile->Init();
854
855         m_pwavefile->m_bits_per_sample_uncompressed = m_bits_per_sample_uncompressed;
856
857         // Open given file
858         if ( m_pwavefile->Open(pszFilename) ) {
859                 // Calculate sound buffer size in bytes
860                 // Buffer size is average data rate times length of buffer
861                 // No need for buffer to be larger than wave data though
862                 m_cbBufSize = (m_nBufLength/1000) * (m_pwavefile->m_wfmt.bits_per_sample/8) * m_pwavefile->m_wfmt.num_channels * m_pwavefile->m_wfmt.sample_rate;
863                 m_cbBufSize /= MAX_STREAM_BUFFERS;
864                 // if the requested buffer size is too big then cap it
865                 m_cbBufSize = (m_cbBufSize > BIGBUF_SIZE) ? BIGBUF_SIZE : m_cbBufSize;
866
867 //              nprintf(("SOUND", "SOUND => Stream buffer created using %d bytes\n", m_cbBufSize));
868
869                 // Create sound buffer
870                 alGenBuffers(MAX_STREAM_BUFFERS, m_buffer_ids);
871
872                 Snd_sram += m_cbBufSize * MAX_STREAM_BUFFERS;
873         } else {
874                 // Error opening file
875                 nprintf(("SOUND", "SOUND => Failed to open wave file: %s\n\r", pszFilename));
876
877                 m_pwavefile->Close();
878
879                 free(m_pwavefile);
880                 m_pwavefile = NULL;
881
882                 return false;
883         }
884
885         return true;
886 }
887
888 // Destroy
889 bool AudioStream::Destroy()
890 {
891         // Stop playback
892         Stop();
893
894         // Release sound buffer
895         alDeleteBuffers(MAX_STREAM_BUFFERS, m_buffer_ids);
896
897         Snd_sram -= m_cbBufSize;
898
899         // Delete WaveFile object
900         if (m_pwavefile) {
901                 m_pwavefile->Close();
902
903                 free(m_pwavefile);
904                 m_pwavefile = NULL;
905         }
906
907         status = ASF_FREE;
908
909         return true;
910 }
911
912 // WriteWaveData
913 //
914 // Writes wave data to sound buffer. This is a helper method used by Create and
915 // ServiceBuffer; it's not exposed to users of the AudioStream class.
916 bool AudioStream::WriteWaveData(uint size, uint *num_bytes_written, int service)
917 {
918         ubyte *uncompressed_wave_data;
919
920         *num_bytes_written = 0;
921
922         if ( (size == 0) || m_bReadingDone ) {
923                 return true;
924         }
925
926         if ( (m_buffer_ids[0] == 0) || !m_pwavefile ) {
927                 return true;
928         }
929
930         if ( service ) {
931                 SDL_LockMutex(Global_service_lock);
932         }
933                     
934         if ( service ) {
935                 uncompressed_wave_data = Wavedata_service_buffer;
936         } else {
937                 uncompressed_wave_data = Wavedata_load_buffer;
938         }
939
940         int num_bytes_read = 0;
941
942         oal_check_for_errors("AudioStream::WriteWaveData() begin");
943
944         if ( !service ) {
945                 for (int ib = 0; ib < MAX_STREAM_BUFFERS; ib++) {
946                         num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, m_cbBufSize, service);
947
948                         if (num_bytes_read < 0) {
949                                 m_bReadingDone = 1;
950                         } else if (num_bytes_read > 0) {
951                                 alBufferData(m_buffer_ids[ib], m_pwavefile->GetOALFormat(), uncompressed_wave_data, num_bytes_read, m_pwavefile->m_wfmt.sample_rate);
952                                 alSourceQueueBuffers(m_source_id, 1, &m_buffer_ids[ib]);
953                                 *num_bytes_written += num_bytes_read;
954                         }
955                 }
956         } else {
957                 ALint buffers_processed = 0;
958                 ALuint buffer_id = 0;
959
960                 alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &buffers_processed);
961
962                 while (buffers_processed) {
963                         alSourceUnqueueBuffers(m_source_id, 1, &buffer_id);
964
965                         num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, m_cbBufSize, service);
966
967                         if (num_bytes_read < 0) {
968                                 m_bReadingDone = 1;
969                         } else if (num_bytes_read > 0) {
970                                 alBufferData(buffer_id, m_pwavefile->GetOALFormat(), uncompressed_wave_data, num_bytes_read, m_pwavefile->m_wfmt.sample_rate);
971                                 alSourceQueueBuffers(m_source_id, 1, &buffer_id);
972                                 *num_bytes_written += num_bytes_read;
973                         }
974
975                         buffers_processed--;
976                 }
977         }
978
979         oal_check_for_errors("AudioStream::WriteWaveData() end");
980
981         if ( service ) {
982                 SDL_UnlockMutex(Global_service_lock);
983         }
984     
985         return true;
986 }
987
988 // GetMaxWriteSize
989 //
990 // Helper function to calculate max size of sound buffer write operation, i.e. how much
991 // free space there is in buffer.
992 uint AudioStream::GetMaxWriteSize()
993 {
994         uint dwMaxSize = m_cbBufSize;
995         ALint n = 0, q = 0;
996
997         oal_check_for_errors("AudioStream::GetMaxWriteSize() begin");
998
999         alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &n);
1000
1001         alGetSourcei(m_source_id, AL_BUFFERS_QUEUED, &q);
1002
1003         if ( !n && (q >= MAX_STREAM_BUFFERS) ) {
1004                 //all buffers queued
1005                 dwMaxSize = 0;
1006         }
1007
1008         oal_check_for_errors("AudioStream::GetMaxWriteSize() end");
1009
1010         //      nprintf(("Alan","Max write size: %d\n", dwMaxSize));
1011         return dwMaxSize;
1012 }
1013
1014 #define VOLUME_ATTENUATION_BEFORE_CUTOFF        0.03f           //  12db
1015 #define VOLUME_ATTENUATION                                      0.65f
1016
1017 bool AudioStream::ServiceBuffer()
1018 {
1019         float vol;
1020         int     fRtn = true;
1021
1022         if (type == ASF_FREE) {
1023                 return false;
1024         }
1025
1026         if (m_bFade) {
1027                 if (m_lCutoffVolume == 0.0f) {
1028                         vol = Get_Volume();
1029 //                      nprintf(("Alan","Volume is: %d\n",vol));
1030                         m_lCutoffVolume = vol * VOLUME_ATTENUATION_BEFORE_CUTOFF;
1031                 }
1032
1033                 vol = Get_Volume() * VOLUME_ATTENUATION;
1034 //              nprintf(("Alan","Volume is now: %d\n",vol));
1035                 Set_Volume(vol);
1036
1037 //              nprintf(("Sound","SOUND => Volume for stream sound is %d\n",vol));
1038 //              nprintf(("Alan","Cuttoff Volume is: %d\n",m_lCutoffVolume));
1039                 if (vol < m_lCutoffVolume) {
1040                         m_bFade = false;
1041                         m_lCutoffVolume = 0.0f;
1042
1043                         if (m_bDestroy_when_faded) {
1044                                 Destroy();      
1045
1046                                 return false;
1047                         }
1048                         else {
1049                                 Stop_and_Rewind();
1050
1051                                 return true;
1052                         }
1053                 }
1054         }
1055
1056         // All of sound not played yet, send more data to buffer
1057         uint dwFreeSpace = GetMaxWriteSize();
1058
1059         // Determine free space in sound buffer
1060         if (dwFreeSpace) {
1061                 // Some wave data remains, but not enough to fill free space
1062                 // Send wave data to buffer, fill remainder of free space with silence
1063                 uint num_bytes_written;
1064
1065                 if ( WriteWaveData(dwFreeSpace, &num_bytes_written) ) {
1066 //                      nprintf(("Alan","Num bytes written: %d\n", num_bytes_written));
1067
1068                         if (m_pwavefile->m_total_uncompressed_bytes_read >= m_pwavefile->m_max_uncompressed_bytes_to_read) {
1069                                 m_fade_timer_id = timer_get_milliseconds() + 1700;              // start fading 1.7 seconds from now
1070                                 m_finished_id = timer_get_milliseconds() + 2000;                // 2 seconds left to play out buffer
1071                                 m_pwavefile->m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
1072                         }
1073
1074                         if ( (m_fade_timer_id > 0) && ((uint)timer_get_milliseconds() > m_fade_timer_id) ) {
1075                                 m_fade_timer_id = 0;
1076                                 Fade_and_Stop();
1077                         }
1078
1079                         if ( (m_finished_id > 0) && ((uint)timer_get_milliseconds() > m_finished_id) ) {
1080                                 m_finished_id = 0;
1081                                 m_bPastLimit = true;
1082                         }
1083
1084                         // see if we're done
1085                         ALint state = 0;
1086
1087                         alGetSourcei(m_source_id, AL_SOURCE_STATE, &state);
1088
1089                         if ( m_bReadingDone && (state != AL_PLAYING) ) {
1090                                 if ( m_bDestroy_when_faded == true ) {
1091                                         Destroy();
1092                                         // Reset reentrancy semaphore
1093
1094                                         return false;
1095                                 }
1096
1097                                 // All of sound has played, stop playback or loop again
1098                                 if ( m_bLooping && !m_bFade) {
1099                                         Play(m_lVolume, m_bLooping);
1100                                 } else {
1101                                         Stop_and_Rewind();
1102                                 }
1103                         }
1104                 } else {
1105                         // Error writing wave data
1106                         fRtn = false;
1107                         Int3(); 
1108                 }
1109         }
1110
1111         return (fRtn);
1112 }
1113
1114 // Cue
1115 void AudioStream::Cue()
1116 {
1117         uint num_bytes_written;
1118
1119         if ( !m_fCued ) {
1120                 m_bFade = false;
1121                 m_fade_timer_id = 0;
1122                 m_finished_id = 0;
1123                 m_bPastLimit = false;
1124                 m_lVolume = 1.0f;
1125                 m_lCutoffVolume = 0.0f;
1126
1127                 m_bDestroy_when_faded = false;
1128
1129                 // Reset buffer ptr
1130                 m_cbBufOffset = 0;
1131
1132                 // Reset file ptr, etc
1133                 m_pwavefile->Cue();
1134
1135                 // Unqueue all buffers
1136                 ALint buffers_processed = 0;
1137                 ALuint buffer_id = 0;
1138
1139                 alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &buffers_processed);
1140
1141                 while (buffers_processed) {
1142                         alSourceUnqueueBuffers(m_source_id, 1, &buffer_id);
1143
1144                         buffers_processed--;
1145                 }
1146
1147                 // Fill buffer with wave data
1148                 WriteWaveData(m_cbBufSize, &num_bytes_written, 0);
1149
1150                 m_fCued = true;
1151         }
1152 }
1153
1154 // Play
1155 void AudioStream::Play(float volume, int looping)
1156 {
1157         if ( m_buffer_ids[0] ) {
1158                 oal_check_for_errors("AudioStream::Play() begin");
1159
1160                 // If playing, stop
1161                 if (m_fPlaying) {
1162                         if ( m_bIsPaused == false)
1163                                 Stop_and_Rewind();
1164                 }
1165
1166                 // get source id if we don't have one
1167                 if ( !m_source_id ) {
1168                         sound_channel *chan = oal_get_free_channel(1.0f, -1, SND_PRIORITY_MUST_PLAY);
1169                         m_source_id = chan->source_id;
1170                 }
1171
1172                 // Cue for playback if necessary
1173                 if (!m_fCued) {
1174                         Cue ();
1175                 }
1176
1177                 if (looping == 1) {
1178                         m_bLooping = true;
1179                 } else {
1180                         m_bLooping = false;
1181                 }
1182
1183                 m_nTimeStarted = timer_get_milliseconds();
1184                 Set_Volume(volume);
1185
1186                 // Kick off timer to service buffer
1187                 m_timer.constructor();
1188
1189                 m_timer.Create(m_nBufService, (ptr_u)this, TimerCallback);
1190
1191                 alSourcef(m_source_id, AL_GAIN, m_lVolume);
1192                 alSource3f(m_source_id, AL_POSITION, 0.0f, 0.0f, 0.0f);
1193                 alSource3f(m_source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1194                 alSource3f(m_source_id, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
1195                 alSourcef(m_source_id, AL_ROLLOFF_FACTOR, 0.0f);
1196                 alSourcei(m_source_id, AL_SOURCE_RELATIVE, AL_TRUE);
1197
1198                 alSourcePlay(m_source_id);
1199
1200                 // Playback begun, no longer cued
1201                 m_fPlaying = true;
1202                 m_bIsPaused = false;
1203
1204                 oal_check_for_errors("AudioStream::Play() end");
1205         }
1206 }
1207
1208 // Timer callback for Timer object created by ::Play method.
1209 bool AudioStream::TimerCallback(ptr_u dwUser)
1210 {
1211     // dwUser contains ptr to AudioStream object
1212     AudioStream * pas = (AudioStream *) dwUser;
1213
1214     return (pas->ServiceBuffer ());
1215 }
1216
1217 void AudioStream::Set_Byte_Cutoff(unsigned int byte_cutoff)
1218 {
1219         if ( m_pwavefile == NULL )
1220                 return;
1221
1222         m_pwavefile->m_max_uncompressed_bytes_to_read = byte_cutoff;
1223 }
1224
1225 uint AudioStream::Get_Bytes_Committed(void)
1226 {
1227         if (m_pwavefile == NULL) {
1228                 return 0;
1229         }
1230
1231         return m_pwavefile->m_total_uncompressed_bytes_read;
1232 }
1233
1234 // Fade_and_Destroy
1235 void AudioStream::Fade_and_Destroy()
1236 {
1237         m_bFade = true;
1238         m_bDestroy_when_faded = true;
1239 }
1240
1241 // Fade_and_Destroy
1242 void AudioStream::Fade_and_Stop()
1243 {
1244         m_bFade = true;
1245         m_bDestroy_when_faded = false;
1246 }
1247
1248 // Stop
1249 void AudioStream::Stop(int paused)
1250 {
1251         if (m_fPlaying) {
1252                 if (paused) {
1253                         alSourcePause(m_source_id);
1254                 } else {
1255                         alSourceStop(m_source_id);
1256                         alSourcei(m_source_id, AL_BUFFER, 0);
1257                         m_source_id = 0;
1258                 }
1259
1260                 m_fPlaying = false;
1261                 m_bIsPaused = paused;
1262
1263                 // Delete Timer object
1264                 m_timer.destructor();
1265         }
1266 }
1267
1268 // Stop_and_Rewind
1269 void AudioStream::Stop_and_Rewind()
1270 {
1271         if (m_fPlaying) {
1272                 // Stop playback
1273                 alSourceStop(m_source_id);
1274                 alSourcei(m_source_id, AL_BUFFER, 0);
1275                 m_source_id = 0;
1276
1277                 // Delete Timer object
1278                 m_timer.destructor();
1279
1280                 m_fPlaying = false;
1281         }
1282
1283         m_fCued = false;        // this will cause wave file to start from beginning
1284         m_bReadingDone = false;
1285 }
1286
1287 // Set_Volume
1288 void AudioStream::Set_Volume(float vol)
1289 {
1290         if (m_fPlaying) {
1291                 alSourcef(m_source_id, AL_GAIN, vol);
1292         }
1293
1294         m_lVolume = vol;
1295 }
1296
1297
1298 // Set_Volume
1299 float AudioStream::Get_Volume()
1300 {
1301         return m_lVolume;
1302 }
1303
1304
1305 #define MAX_AUDIO_STREAMS       30
1306 static AudioStream *Audio_streams = NULL;
1307
1308
1309 void audiostream_init()
1310 {
1311         if (Audiostream_inited) {
1312                 return;
1313         }
1314
1315         // Allocate memory for the buffer which holds the uncompressed wave data that is streamed from the
1316         // disk during a load/cue
1317         if (Wavedata_load_buffer == NULL) {
1318                 Wavedata_load_buffer = (ubyte*)malloc(BIGBUF_SIZE);
1319
1320                 if (Wavedata_load_buffer == NULL) {
1321                         goto INIT_ERROR;
1322                 }
1323         }
1324
1325         // Allocate memory for the buffer which holds the uncompressed wave data that is streamed from the
1326         // disk during a service interval
1327         if (Wavedata_service_buffer == NULL) {
1328                 Wavedata_service_buffer = (ubyte*)malloc(BIGBUF_SIZE);
1329
1330                 if (Wavedata_service_buffer == NULL) {
1331                         goto INIT_ERROR;
1332                 }
1333         }
1334
1335         // Allocate memory for the buffer which holds the compressed wave data that is read from the hard disk
1336         if (Compressed_buffer == NULL) {
1337                 Compressed_buffer = (ubyte*)malloc(COMPRESSED_BUFFER_SIZE);
1338
1339                 if (Compressed_buffer == NULL) {
1340                         goto INIT_ERROR;
1341                 }
1342         }
1343
1344         if (Compressed_service_buffer == NULL) {
1345                 Compressed_service_buffer = (ubyte*)malloc(COMPRESSED_BUFFER_SIZE);
1346
1347                 if (Compressed_service_buffer == NULL) {
1348                         goto INIT_ERROR;
1349                 }
1350         }
1351
1352         if (Audio_streams == NULL) {
1353                 Audio_streams = (AudioStream*)malloc(sizeof(AudioStream) * MAX_AUDIO_STREAMS);
1354
1355                 if (Audio_streams == NULL) {
1356                         goto INIT_ERROR;
1357                 }
1358         }
1359
1360         for (int i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1361                 Audio_streams[i].Init_Data();
1362                 Audio_streams[i].status = ASF_FREE;
1363                 Audio_streams[i].type = ASF_NONE;
1364         }
1365
1366         Global_service_lock = SDL_CreateMutex();
1367
1368         Audiostream_inited = 1;
1369
1370         return;
1371
1372 INIT_ERROR:
1373         if (Wavedata_service_buffer) {
1374                 free(Wavedata_service_buffer);
1375                 Wavedata_service_buffer = NULL;
1376         }
1377
1378         if (Compressed_buffer) {
1379                 free(Compressed_buffer);
1380                 Compressed_buffer = NULL;
1381         }
1382
1383         if (Compressed_service_buffer) {
1384                 free(Compressed_service_buffer);
1385                 Compressed_service_buffer = NULL;
1386         }
1387
1388         if (Audio_streams) {
1389                 free(Audio_streams);
1390                 Audio_streams = NULL;
1391         }
1392
1393         Audiostream_inited = 0;
1394 }
1395
1396 // Close down the audiostream system.  Must call audiostream_init() before any audiostream functions can
1397 // be used.
1398 void audiostream_close()
1399 {
1400         if ( !Audiostream_inited ) {
1401                 return;
1402         }
1403
1404         SDL_assert( Audio_streams != NULL );
1405
1406         for (int i = 0; i < MAX_AUDIO_STREAMS; i++) {
1407                 if ( Audio_streams[i].status == ASF_USED ) {
1408                         Audio_streams[i].status = ASF_FREE;
1409                         Audio_streams[i].Destroy();
1410                 }
1411         }
1412
1413         free(Audio_streams);
1414         Audio_streams = NULL;
1415
1416         // free global buffers
1417         if (Wavedata_load_buffer) {
1418                 free(Wavedata_load_buffer);
1419                 Wavedata_load_buffer = NULL;
1420         }
1421
1422         if (Wavedata_service_buffer) {
1423                 free(Wavedata_service_buffer);
1424                 Wavedata_service_buffer = NULL;
1425         }
1426
1427         if (Compressed_buffer) {
1428                 free(Compressed_buffer);
1429                 Compressed_buffer = NULL;
1430         }
1431
1432         if (Compressed_service_buffer) {
1433                 free(Compressed_service_buffer);
1434                 Compressed_service_buffer = NULL;
1435         }
1436
1437         SDL_DestroyMutex( Global_service_lock );
1438
1439         Audiostream_inited = 0;
1440
1441 }
1442
1443 // Open a digital sound file for streaming
1444 //
1445 // input:       filename        =>      disk filename of sound file
1446 //                              type            => what type of audio stream do we want to open:
1447 //                                                                      ASF_SOUNDFX
1448 //                                                                      ASF_EVENTMUSIC
1449 //                                                                      ASF_VOICE
1450 //      
1451 // returns:     success => handle to identify streaming sound
1452 //                              failure => -1
1453 int audiostream_open( const char *filename, int type )
1454 {
1455         int i;
1456
1457         if ( !Audiostream_inited ) {
1458                 return -1;
1459         }
1460
1461         for (i = 0; i < MAX_AUDIO_STREAMS; i++) {
1462                 if (Audio_streams[i].status == ASF_FREE) {
1463                         Audio_streams[i].status = ASF_USED;
1464                         Audio_streams[i].type = type;
1465                         break;
1466                 }
1467         }
1468
1469         if (i == MAX_AUDIO_STREAMS) {
1470                 nprintf(("Sound", "SOUND => No more audio streams available!\n"));
1471                 return -1;
1472         }
1473
1474         switch (type) {
1475                 case ASF_VOICE:
1476                 case ASF_SOUNDFX:
1477                         Audio_streams[i].m_bits_per_sample_uncompressed = 8;
1478                         break;
1479
1480                 case ASF_EVENTMUSIC:
1481                         Audio_streams[i].m_bits_per_sample_uncompressed = 16;
1482                         break;
1483
1484                 default:
1485                         Int3();
1486                         return -1;
1487         }
1488
1489         if ( !Audio_streams[i].Create(filename) ) {
1490                 Audio_streams[i].status = ASF_FREE;
1491                 return -1;
1492         }
1493
1494         return i;
1495 }
1496
1497 void audiostream_close_file(int i, int fade)
1498 {
1499         if ( !Audiostream_inited ) {
1500                 return;
1501         }
1502
1503         if (i < 0) {
1504                 return;
1505         }
1506
1507         SDL_assert( i < MAX_AUDIO_STREAMS );
1508
1509         if (Audio_streams[i].status == ASF_FREE) {
1510                 return;
1511         }
1512
1513         if (fade) {
1514                 Audio_streams[i].Fade_and_Destroy();
1515         } else {
1516                 Audio_streams[i].Destroy();
1517         }
1518 }
1519
1520 void audiostream_close_all(int fade)
1521 {
1522         int i;
1523
1524         if ( !Audiostream_inited ) {
1525                 return;
1526         }
1527
1528         for (i = 0; i < MAX_AUDIO_STREAMS; i++) {
1529                 if (Audio_streams[i].status == ASF_FREE) {
1530                         continue;
1531                 }
1532
1533                 audiostream_close_file(i, fade);
1534         }
1535 }
1536
1537 void audiostream_play(int i, float volume, int looping)
1538 {
1539         if ( !Audiostream_inited ) {
1540                 return;
1541         }
1542
1543         if (i < 0) {
1544                 return;
1545         }
1546
1547         SDL_assert( i < MAX_AUDIO_STREAMS );
1548
1549         if (Audio_streams[i].status == ASF_FREE) {
1550                 return;
1551         }
1552
1553         if (volume < 0.0f) {
1554                 volume = Audio_streams[i].Get_Default_Volume();
1555         }
1556
1557         Audio_streams[i].Set_Default_Volume(volume);
1558         Audio_streams[i].Play(volume, looping);
1559 }
1560
1561 // use as buffer service function
1562 bool audiostream_is_playing(int i)
1563 {
1564         if ( !Audiostream_inited ) {
1565                 return false;
1566         }
1567
1568         if (i < 0) {
1569                 return false;
1570         }
1571
1572         SDL_assert( i < MAX_AUDIO_STREAMS );
1573
1574         if (Audio_streams[i].status == ASF_FREE) {
1575                 return false;
1576         }
1577
1578         return Audio_streams[i].Is_Playing();
1579 }
1580
1581 void audiostream_stop(int i, int rewind, int paused)
1582 {
1583         if ( !Audiostream_inited ) {
1584                 return;
1585         }
1586
1587         if (i < 0) {
1588                 return;
1589         }
1590
1591         SDL_assert( i < MAX_AUDIO_STREAMS );
1592
1593         if (Audio_streams[i].status == ASF_FREE) {
1594                 return;
1595         }
1596
1597         if (rewind) {
1598                 Audio_streams[i].Stop_and_Rewind();
1599         } else {
1600                 Audio_streams[i].Stop(paused);
1601         }
1602 }
1603
1604 void audiostream_set_volume_all(float volume, int type)
1605 {
1606         int i;
1607
1608         if ( !Audiostream_inited ) {
1609                 return;
1610         }
1611
1612         for (i = 0; i < MAX_AUDIO_STREAMS; i++) {
1613                 if (Audio_streams[i].status == ASF_FREE) {
1614                         continue;
1615                 }
1616
1617                 if (Audio_streams[i].type == type) {
1618                         Audio_streams[i].Set_Volume(volume);
1619                 }
1620         }
1621 }
1622
1623 void audiostream_set_volume(int i, float volume)
1624 {
1625         if ( !Audiostream_inited ) {
1626                 return;
1627         }
1628
1629         if (i < 0) {
1630                 return;
1631         }
1632
1633         SDL_assert( i < MAX_AUDIO_STREAMS );
1634
1635         if (Audio_streams[i].status == ASF_FREE) {
1636                 return;
1637         }
1638
1639         Audio_streams[i].Set_Volume(volume);
1640 }
1641
1642 bool audiostream_is_paused(int i)
1643 {
1644         if ( !Audiostream_inited ) {
1645                 return false;
1646         }
1647
1648         if (i < 0) {
1649                 return false;
1650         }
1651
1652         SDL_assert( i < MAX_AUDIO_STREAMS );
1653
1654         if (Audio_streams[i].status == ASF_FREE) {
1655                 return false;
1656         }
1657
1658         return Audio_streams[i].Is_Paused();
1659 }
1660
1661 void audiostream_set_byte_cutoff(int i, uint cutoff)
1662 {
1663         if ( !Audiostream_inited ) {
1664                 return;
1665         }
1666
1667         if (i < 0) {
1668                 return;
1669         }
1670
1671         SDL_assert( i < MAX_AUDIO_STREAMS );
1672
1673         if (Audio_streams[i].status == ASF_FREE) {
1674                 return;
1675         }
1676
1677         Audio_streams[i].Set_Byte_Cutoff(cutoff);
1678 }
1679
1680 uint audiostream_get_bytes_committed(int i)
1681 {
1682         if ( !Audiostream_inited ) {
1683                 return 0;
1684         }
1685
1686         if (i < 0) {
1687                 return 0;
1688         }
1689
1690         SDL_assert( i < MAX_AUDIO_STREAMS );
1691
1692         if (Audio_streams[i].status == ASF_FREE) {
1693                 return 0;
1694         }
1695
1696         return Audio_streams[i].Get_Bytes_Committed();
1697 }
1698
1699 bool audiostream_done_reading(int i)
1700 {
1701         if ( !Audiostream_inited ) {
1702                 return true;
1703         }
1704
1705         if (i < 0) {
1706                 return true;
1707         }
1708
1709         SDL_assert( i < MAX_AUDIO_STREAMS );
1710
1711         if (Audio_streams[i].status == ASF_FREE) {
1712                 return true;
1713         }
1714
1715         return Audio_streams[i].Is_Past_Limit();
1716 }
1717
1718 int audiostream_is_inited()
1719 {
1720         return Audiostream_inited;
1721 }
1722
1723 void audiostream_pause(int i)
1724 {
1725         if ( !Audiostream_inited ) {
1726                 return;
1727         }
1728
1729         if (i < 0) {
1730                 return;
1731         }
1732
1733         SDL_assert( i < MAX_AUDIO_STREAMS );
1734
1735         if (Audio_streams[i].status == ASF_FREE) {
1736                 return;
1737         }
1738
1739         if ( audiostream_is_playing(i) ) {
1740                 audiostream_stop(i, 0, 1);
1741         }
1742 }
1743
1744 void audiostream_pause_all()
1745 {
1746         int i;
1747
1748         if ( !Audiostream_inited ) {
1749                 return;
1750         }
1751
1752         for (i = 0; i < MAX_AUDIO_STREAMS; i++) {
1753                 if (Audio_streams[i].status == ASF_FREE) {
1754                         continue;
1755                 }
1756
1757                 audiostream_pause(i);
1758         }
1759 }
1760
1761 void audiostream_unpause(int i)
1762 {
1763         int is_looping;
1764
1765         if ( !Audiostream_inited ) {
1766                 return;
1767         }
1768
1769         if (i < 0) {
1770                 return;
1771         }
1772
1773         SDL_assert( i < MAX_AUDIO_STREAMS );
1774
1775         if (Audio_streams[i].status == ASF_FREE) {
1776                 return;
1777         }
1778
1779         if ( audiostream_is_paused(i) ) {
1780                 is_looping = Audio_streams[i].Is_looping();
1781                 audiostream_play(i, -1.0f, is_looping);
1782         }
1783 }
1784
1785 void audiostream_unpause_all()
1786 {
1787         int i;
1788
1789         if ( !Audiostream_inited ) {
1790                 return;
1791         }
1792
1793         for (i = 0; i < MAX_AUDIO_STREAMS; i++) {
1794                 if (Audio_streams[i].status == ASF_FREE) {
1795                         continue;
1796                 }
1797
1798                 audiostream_unpause(i);
1799         }
1800 }