FS2_Open
Open source remastering of the Freespace 2 engine
audiostr.cpp
Go to the documentation of this file.
1 
2 
3 #ifdef _WIN32
4 #define VC_EXTRALEAN
5 #define STRICT
6 
7 #include <windows.h>
8 #include <mmsystem.h>
9 #endif
10 
11 #define NEED_STRHDL // for STRHTL struct in audiostr.h
12 
13 #include "cfile/cfile.h"
14 #include "globalincs/pstypes.h"
15 #include "io/timer.h"
16 #include "sound/acm.h"
17 #include "sound/audiostr.h"
18 #include "sound/ds.h"
19 #include "sound/ogg/ogg.h"
20 #include "sound/openal.h"
21 #include "sound/sound.h"
22 
23 #define THREADED
24 #include "osapi/osapi.h"
25 
26 
27 #define MAX_STREAM_BUFFERS 4
28 
29 // status
30 #define ASF_FREE 0
31 #define ASF_USED 1
32 
33 // constants
34 #define BIGBUF_SIZE 176400
35 ubyte *Wavedata_load_buffer = NULL; // buffer used for cueing audiostreams
36 ubyte *Wavedata_service_buffer = NULL; // buffer used for servicing audiostreams
37 
39 
40 typedef bool (*TIMERCALLBACK)(ptr_u);
41 
42 #define COMPRESSED_BUFFER_SIZE 176400
43 ubyte *Compressed_buffer = NULL; // Used to load in compressed data during a cueing interval
44 ubyte *Compressed_service_buffer = NULL; // Used to read in compressed data during a service interval
45 
46 #define AS_HIGHEST_MAX 999999999 // max uncompressed filesize supported is 999 meg
47 
48 // Globalize the list of audio extensions for use in several sound related files
49 const char *audio_ext_list[] = { ".ogg", ".wav" };
50 const int NUM_AUDIO_EXT = sizeof(audio_ext_list) / sizeof(char*);
51 
52 
54 
55 
56 static int dbg_print_ogg_error(const char *filename, int rc)
57 {
58  int fatal = 0;
59  char err_msg[100];
60  memset( &err_msg, 0, sizeof(err_msg) );
61 
62  Assert( filename != NULL );
63 
64  switch (rc) {
65  case OV_FALSE:
66  strncpy(err_msg, "A false status was returned", 99);
67  // should this be fatal?
68  break;
69  case OV_EOF:
70  strncpy(err_msg, "End-of-file reached", 99);
71  fatal = 1;
72  break;
73  case OV_HOLE:
74  strncpy(err_msg, "Data interruption (hole)", 99);
75  // special handling
76  break;
77  case OV_EREAD:
78  strncpy(err_msg, "Media read error", 99);
79  fatal = 1;
80  break;
81  case OV_EFAULT:
82  strncpy(err_msg, "Internal logic fault", 99);
83  fatal = 1;
84  break;
85  case OV_EIMPL:
86  strncpy(err_msg, "Attempted to use a feature that's not supported", 99);
87  fatal = 1;
88  break;
89  case OV_EINVAL:
90  strncpy(err_msg, "Invalid argument value", 99);
91  // doesn't appear to be fatal
92  break;
93  case OV_ENOTVORBIS:
94  strncpy(err_msg, "File contains non-Vorbis data, or is not a Vorbis file", 99);
95  fatal = 1;
96  break;
97  case OV_EBADHEADER:
98  strncpy(err_msg, "Invalid bitstream header", 99);
99  fatal = 1;
100  break;
101  case OV_EVERSION:
102  strncpy(err_msg, "Vorbis version mismatch", 99);
103  fatal = 1;
104  break;
105  case OV_ENOTAUDIO:
106  strncpy(err_msg, "Submitted data is not audio", 99);
107  fatal = 1;
108  break;
109  case OV_EBADPACKET:
110  strncpy(err_msg, "An invalid packet was submitted", 99);
111  // is this fatal?
112  break;
113  case OV_EBADLINK:
114  strncpy(err_msg, "Invalid stream section supplied, or corrupt link", 99);
115  fatal = 1; // is this really fatal or does the lib compensate?
116  break;
117  case OV_ENOSEEK:
118  strncpy(err_msg, "Bitstream is not seekable", 99);
119  fatal = 1;
120  break;
121  default:
122  strncpy(err_msg, "Unknown error occurred", 99);
123  fatal = 1; // assume fatal
124  break;
125  }
126 
127  // only dump fatal errors, everything else should be handled silently by default
128  if (fatal)
129  mprintf(("OGG ERROR: \"%s\" in %s\n", err_msg, filename));
130 // else
131 // nprintf(("OGGISH", "OGG ERROR: \"%s\" in %s\n", err_msg, filename));
132 
133  return fatal;
134 }
135 
136 static int audiostr_read_uint(HMMIO rw, uint *i)
137 {
138  int rc = mmioRead( rw, (char *)i, sizeof(uint) );
139 
140  if (rc != sizeof(uint))
141  return 0;
142 
143  *i = INTEL_INT(*i); //-V570
144 
145  return 1;
146 }
147 
148 static int audiostr_read_word(HMMIO rw, WORD *i)
149 {
150  int rc = mmioRead( rw, (char *)i, sizeof(WORD) );
151 
152  if (rc != sizeof(WORD))
153  return 0;
154 
155  *i = INTEL_SHORT(*i); //-V570
156 
157  return 1;
158 }
159 
160 static int audiostr_read_dword(HMMIO rw, DWORD *i)
161 {
162  int rc = mmioRead( rw, (char *)i, sizeof(DWORD) );
163 
164  if (rc != sizeof(DWORD))
165  return 0;
166 
167  *i = INTEL_INT(*i); //-V570
168 
169  return 1;
170 }
171 
172 class Timer
173 {
174 public:
175  void constructor(void);
176  void destructor(void);
177  bool Create (uint nPeriod, uint nRes, ptr_u dwUser, TIMERCALLBACK pfnCallback);
178 protected:
179 #ifndef SCP_UNIX
180  static void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
181 #else
182  static uint TimeProc(uint interval, void *param);
183 #endif
188 #ifndef SCP_UNIX
190 #else
191  SDL_TimerID m_nIDTimer;
192 #endif
193 };
194 
195 class WaveFile
196 {
197 public:
198  void Init(void);
199  void Close(void);
200  bool Open (char *pszFilename, bool keep_ext = true);
201  bool Cue (void);
202  int Read (ubyte *pbDest, uint cbSize, int service=1);
205  uint GetDataSize (void) { return (m_nDataSize); }
206  uint GetNumBytesPlayed (void) { return (m_nBytesPlayed); }
208  WAVEFORMATEX m_wfmt; // format of wave file used by Direct Sound
209  WAVEFORMATEX *m_pwfmt_original; // foramt of wave file from actual wave source
213 
214 protected:
215  uint m_data_offset; // number of bytes to actual wave data
217 
218  uint m_wave_format; // format of wave source (ie WAVE_FORMAT_PCM, WAVE_FORMAT_ADPCM)
219  uint m_nBlockAlign; // wave data block alignment spec
220  uint m_nUncompressedAvgDataRate; // average wave data rate
221  uint m_nDataSize; // size of data chunk
222  uint m_nBytesPlayed; // offset into data chunk
225 
226  STRHDL m_snd_info;
227 
228  void *m_hStream;
232 };
233 
235 {
236 public:
237  AudioStream (void);
238  ~AudioStream (void);
239  bool Create (char *pszFilename);
240  bool Destroy (void);
241  void Play (float volume, int looping);
242  bool Is_Playing(){ return m_fPlaying; }
243  bool Is_Paused(){ return m_bIsPaused; }
244  bool Is_Past_Limit() { return m_bPastLimit; }
245  void Stop (int paused = 0);
246  void Stop_and_Rewind (void);
247  void Fade_and_Destroy (void);
248  void Fade_and_Stop(void);
249  void Set_Volume(float vol);
250  float Get_Volume();
251  void Init_Data();
252  void Set_Sample_Cutoff(uint sample_cutoff);
253  void Set_Default_Volume(float vol) { m_lDefaultVolume = vol; }
256  int Is_looping() { return m_bLooping; }
257  int status;
258  int type;
261 
262 protected:
263  void Cue (void);
264  bool WriteWaveData (uint cbSize, uint *num_bytes_written, int service = 1);
265  uint GetMaxWriteSize (void);
266  bool ServiceBuffer (void);
267  static bool TimerCallback (ptr_u dwUser);
268  bool PlaybackDone(void);
269 
270  ALuint m_source_id; // name of openAL source
271  ALuint m_buffer_ids[MAX_STREAM_BUFFERS]; // names of buffers
272 
273  Timer m_timer; // ptr to Timer object
274  WaveFile *m_pwavefile; // ptr to WaveFile object
275  bool m_fCued; // semaphore (stream cued)
276  bool m_fPlaying; // semaphore (stream playing)
277  uint m_cbBufOffset; // last write position
278  uint m_cbBufSize; // size of sound buffer in bytes
279  uint m_nBufService; // service interval in msec
280  uint m_nTimeStarted; // time (in system time) playback started
281 
282  bool m_bLooping; // whether or not to loop playback
283  bool m_bFade; // fade out music
285  float m_lVolume; // volume of stream ( 0 -> 1 )
287  bool m_bIsPaused; // stream is stopped, but not rewinded
288  bool m_bReadingDone; // no more bytes to be read from disk, still have remaining buffer to play
289  uint m_fade_timer_id; // timestamp so we know when to start fade
290  uint m_finished_id; // timestamp so we know when we've played #bytes required
291  bool m_bPastLimit; // flag to show we've played past the number of bytes requred
293 
295 };
296 
297 
298 // Timer class implementation
299 //
301 
302 // constructor
304 {
305  m_nIDTimer = NULL;
306 }
307 
308 
309 // Destructor
311 {
312  if (m_nIDTimer) {
313 #ifndef SCP_UNIX
314  timeKillEvent (m_nIDTimer);
315 #else
316  SDL_RemoveTimer(m_nIDTimer);
317 #endif
318  m_nIDTimer = NULL;
319  }
320 }
321 
322 // Create
323 bool Timer::Create (uint nPeriod, uint nRes, ptr_u dwUser, TIMERCALLBACK pfnCallback)
324 {
325  bool bRtn = true; // assume success
326 
327  Assert(pfnCallback);
328  Assert(nPeriod > 10);
329  Assert(nPeriod >= nRes);
330 
331  m_nPeriod = nPeriod;
332  m_nRes = nRes;
333  m_dwUser = dwUser;
334  m_pfnCallback = pfnCallback;
335 
336 #ifndef SCP_UNIX
337  if ((m_nIDTimer = timeSetEvent ((UINT)m_nPeriod, (UINT)m_nRes, TimeProc, (DWORD)this, TIME_PERIODIC)) == NULL) {
338 #else
339  if ((m_nIDTimer = SDL_AddTimer(m_nPeriod, TimeProc, (void*)this)) == NULL) {
340 #endif
341  bRtn = false;
342  }
343 
344  return (bRtn);
345 }
346 
347 
348 // Timer proc for multimedia timer callback set with timeSetTime().
349 //
350 // Calls procedure specified when Timer object was created. The
351 // dwUser parameter contains "this" pointer for associated Timer object.
352 //
353 #ifndef SCP_UNIX
354 void CALLBACK Timer::TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
355 #else
356 uint Timer::TimeProc(uint interval, void *dwUser)
357 #endif
358 {
359  // dwUser contains ptr to Timer object
360  Timer * ptimer = (Timer *) dwUser;
361 
362  // Call user-specified callback and pass back user specified data
363  (ptimer->m_pfnCallback) (ptimer->m_dwUser);
364 
365 #ifdef SCP_UNIX
366  if (ptimer->m_nPeriod) {
367  return interval;
368  } else {
369  SDL_RemoveTimer(ptimer->m_nIDTimer);
370  ptimer->m_nIDTimer = NULL;
371  return 0;
372  }
373 #endif
374 }
375 
376 
377 // WaveFile class implementation
378 //
380 
381 // Constructor
382 void WaveFile::Init(void)
383 {
384  // Init data members
385  m_data_offset = 0;
386  m_snd_info.cfp = NULL;
387  m_snd_info.true_offset = 0;
388  m_snd_info.size = 0;
389  m_pwfmt_original = NULL;
390  m_nBlockAlign= 0;
391  m_nUncompressedAvgDataRate = 0;
392  m_nDataSize = 0;
393  m_nBytesPlayed = 0;
394  m_total_uncompressed_bytes_read = 0;
395  m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
396  m_al_format = AL_FORMAT_MONO8;
397 
398  memset(&m_wFilename, 0, MAX_FILENAME_LEN);
399 
400  m_hStream_open = 0;
401  m_abort_next_read = false;
402 }
403 
404 // Destructor
405 void WaveFile::Close(void)
406 {
407  // Free memory
408  if (m_pwfmt_original) {
409  vm_free(m_pwfmt_original);
410  m_pwfmt_original = NULL;
411  }
412 
413  if ( m_hStream_open ) {
414  ACM_stream_close((void*)m_hStream);
415  m_hStream_open = 0;
416  }
417 
418  // Close file
419  if (m_snd_info.cfp) {
420  if (m_wave_format == OGG_FORMAT_VORBIS)
421  ov_clear(&m_snd_info.vorbis_file);
422 
423  mmioClose( m_snd_info.cfp, 0 );
424  m_snd_info.cfp = NULL;
425  m_snd_info.true_offset = 0;
426  m_snd_info.size = 0;
427  }
428 }
429 
430 // -- from parselo.cpp --
431 extern const char *stristr(const char *str, const char *substr);
432 
433 // Open
434 bool WaveFile::Open(char *pszFilename, bool keep_ext)
435 {
436  int rc = -1;
437  WORD cbExtra = 0;
438  bool fRtn = true; // assume success
439  PCMWAVEFORMAT pcmwf;
440  int FileSize, FileOffset;
441  char fullpath[MAX_PATH];
443 
444  m_total_uncompressed_bytes_read = 0;
445  m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
446 
447  // NOTE: we assume that the extension has already been stripped off if it was supposed to be!!
448  strcpy_s( filename, pszFilename );
449 
450 
451  // if we are supposed to load the file as passed...
452  if (keep_ext) {
453  for (int i = 0; i < NUM_AUDIO_EXT; i++) {
454  if ( stristr(pszFilename, audio_ext_list[i]) ) {
455  rc = i;
456  break;
457  }
458  }
459 
460  // not a supported extension format ... somebody screwed up their tbls :)
461  if (rc < 0)
462  goto OPEN_ERROR;
463 
464  cf_find_file_location(pszFilename, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset);
465  }
466  // ... otherwise we just find the best match
467  else {
468  rc = cf_find_file_location_ext(filename, NUM_AUDIO_EXT, audio_ext_list, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset);
469 
470  if (rc < 0)
471  goto OPEN_ERROR;
472 
473  // set proper filename for later use (assumes that it doesn't already have an extension)
474  strcat_s( filename, audio_ext_list[rc] );
475  }
476 
477  m_snd_info.cfp = mmioOpen( fullpath, NULL, MMIO_ALLOCBUF | MMIO_READ );
478 
479  if (m_snd_info.cfp == NULL)
480  goto OPEN_ERROR;
481 
482  m_snd_info.true_offset = FileOffset;
483  m_snd_info.size = FileSize;
484 
485  // if in a VP then position the stream at the start of the file
486  if (FileOffset > 0)
487  mmioSeek( m_snd_info.cfp, FileOffset, SEEK_SET );
488 
489  // if Ogg Vorbis...
490  if (rc == 0) {
491  if ( ov_open_callbacks(&m_snd_info, &m_snd_info.vorbis_file, NULL, 0, mmio_callbacks) == 0 ) {
492  // got an Ogg Vorbis, so lets read the info in
493  ov_info(&m_snd_info.vorbis_file, -1);
494 
495  // we only support one logical bitstream
496  if ( ov_streams(&m_snd_info.vorbis_file) != 1 ) {
497  mprintf(("AUDIOSTR => OGG reading error: We don't handle bitstream changes!\n"));
498  goto OPEN_ERROR;
499  }
500 
501  m_wave_format = OGG_FORMAT_VORBIS;
502  m_wfmt.wFormatTag = WAVE_FORMAT_PCM;
503  m_wfmt.nChannels = (WORD) m_snd_info.vorbis_file.vi->channels;
504  m_wfmt.nSamplesPerSec = m_snd_info.vorbis_file.vi->rate;
505 
507  case DS_SQ_HIGH:
508  m_wfmt.wBitsPerSample = Ds_float_supported ? 32 : 16;
509  break;
510 
511  case DS_SQ_MEDIUM:
512  m_wfmt.wBitsPerSample = 16;
513  break;
514 
515  default:
516  m_wfmt.wBitsPerSample = 8;
517  break;
518  }
519 
520  m_wfmt.cbSize = 0;
521 
522  m_wfmt.nBlockAlign = (ushort)(( m_wfmt.nChannels * m_wfmt.wBitsPerSample ) / 8);
523  m_wfmt.nAvgBytesPerSec = m_wfmt.nSamplesPerSec * m_wfmt.nBlockAlign;
524 
525  m_nBlockAlign = m_wfmt.nBlockAlign;
526  m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec;
527 
528  // location of start of file in VP
529  m_data_offset = 0;
530  m_nDataSize = m_data_bytes_left = ((int)ov_pcm_total(&m_snd_info.vorbis_file, -1) * m_wfmt.nBlockAlign);
531  } else {
532  mprintf(("AUDIOSTR => OGG reading error: Not a valid Vorbis file!\n"));
533  }
534  }
535  // if Wave...
536  else if (rc == 1) {
537  bool done = false;
538 
539  // Skip the "RIFF" tag and file size (8 bytes)
540  // Skip the "WAVE" tag (4 bytes)
541  mmioSeek( m_snd_info.cfp, 12+FileOffset, SEEK_SET );
542 
543  // Now read RIFF tags until the end of file
544  uint tag, size, next_chunk;
545 
546  while ( !done ) {
547  if ( !audiostr_read_uint(m_snd_info.cfp, &tag) )
548  break;
549 
550  if ( !audiostr_read_uint(m_snd_info.cfp, &size) )
551  break;
552 
553  next_chunk = mmioSeek(m_snd_info.cfp, 0, SEEK_CUR );
554  next_chunk += size;
555 
556  switch (tag)
557  {
558  case 0x20746d66: // The 'fmt ' tag
559  {
560  audiostr_read_word(m_snd_info.cfp, &pcmwf.wf.wFormatTag);
561  audiostr_read_word(m_snd_info.cfp, &pcmwf.wf.nChannels);
562  audiostr_read_dword(m_snd_info.cfp, &pcmwf.wf.nSamplesPerSec);
563  audiostr_read_dword(m_snd_info.cfp, &pcmwf.wf.nAvgBytesPerSec);
564  audiostr_read_word(m_snd_info.cfp, &pcmwf.wf.nBlockAlign);
565  audiostr_read_word(m_snd_info.cfp, &pcmwf.wBitsPerSample);
566 
567  if (pcmwf.wf.wFormatTag == WAVE_FORMAT_ADPCM)
568  audiostr_read_word(m_snd_info.cfp, &cbExtra);
569 
570  // Allocate memory for WAVEFORMATEX structure + extra bytes
571  if ( (m_pwfmt_original = (WAVEFORMATEX *) vm_malloc(sizeof(WAVEFORMATEX)+cbExtra)) != NULL ) {
572  Assert(m_pwfmt_original != NULL);
573  // Copy bytes from temporary format structure
574  memcpy (m_pwfmt_original, &pcmwf, sizeof(pcmwf));
575  m_pwfmt_original->cbSize = cbExtra;
576 
577  // Read those extra bytes, append to WAVEFORMATEX structure
578  if (cbExtra != 0)
579  mmioRead( m_snd_info.cfp, ((char *)(m_pwfmt_original) + sizeof(WAVEFORMATEX)), cbExtra );
580  } else {
581  Int3(); // malloc failed
582  goto OPEN_ERROR;
583  }
584 
585  break;
586  }
587 
588  case 0x61746164: // the 'data' tag
589  {
590  m_nDataSize = size; // This is size of data chunk. Compressed if ADPCM.
591  m_data_bytes_left = size;
592  m_data_offset = mmioSeek( m_snd_info.cfp, 0, SEEK_CUR );
593  done = true;
594 
595  break;
596  }
597 
598  default: // unknown, skip it
599  break;
600  } // end switch
601 
602  mmioSeek( m_snd_info.cfp, next_chunk, SEEK_SET );
603  }
604 
605  // make sure that we did good
606  if ( !done || (m_pwfmt_original == NULL) )
607  goto OPEN_ERROR;
608 
609  // At this stage, examine source format, and set up WAVEFORATEX structure for DirectSound.
610  // Since DirectSound only supports PCM, force this structure to be PCM compliant. We will
611  // need to convert data on the fly later if our souce is not PCM
612  switch (m_pwfmt_original->wFormatTag) {
613  case WAVE_FORMAT_PCM:
614  m_wave_format = WAVE_FORMAT_PCM;
615  m_wfmt.wBitsPerSample = m_pwfmt_original->wBitsPerSample;
616  break;
617 
618  case WAVE_FORMAT_ADPCM:
619  m_wave_format = WAVE_FORMAT_ADPCM;
620  m_wfmt.wBitsPerSample = (Ds_sound_quality) ? 16: 8;
621  m_bits_per_sample_uncompressed = m_wfmt.wBitsPerSample;
622  break;
623 
624  case WAVE_FORMAT_IEEE_FLOAT: {
625  m_wave_format = WAVE_FORMAT_IEEE_FLOAT;
626 
627  switch (Ds_sound_quality) {
628  case DS_SQ_HIGH:
629  m_wfmt.wBitsPerSample = (Ds_float_supported) ? 32 : 16;
630  break;
631 
632  case DS_SQ_MEDIUM:
633  m_wfmt.wBitsPerSample = 16;
634  break;
635 
636  default:
637  m_wfmt.wBitsPerSample = 8;
638  break;
639  }
640 
641  break;
642  }
643 
644  default:
645  nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_pwfmt_original->wFormatTag));
646  goto OPEN_ERROR;
647  break;
648 
649  } // end switch
650 
651  // Set up the WAVEFORMATEX structure to have the right PCM characteristics
652  m_wfmt.wFormatTag = WAVE_FORMAT_PCM;
653  m_wfmt.nChannels = m_pwfmt_original->nChannels;
654  m_wfmt.nSamplesPerSec = m_pwfmt_original->nSamplesPerSec;
655  m_wfmt.cbSize = 0;
656  m_wfmt.nBlockAlign = (ushort)(( m_wfmt.nChannels * m_wfmt.wBitsPerSample ) / 8);
657  m_wfmt.nAvgBytesPerSec = m_wfmt.nBlockAlign * m_wfmt.nSamplesPerSec;
658 
659  // Init some member data from format chunk
660  m_nBlockAlign = m_pwfmt_original->nBlockAlign;
661  m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec;
662 
663  Assert( (m_wfmt.nChannels == 1) || (m_wfmt.nChannels == 2) );
664  }
665  // something unkown???
666  else {
667  Int3();
668  }
669 
670  m_al_format = openal_get_format(m_wfmt.wBitsPerSample, m_wfmt.nChannels);
671 
672  if (m_al_format != AL_INVALID_VALUE) {
673  // Cue for streaming
674  Cue();
675 
676  goto OPEN_DONE;
677  }
678 
679 OPEN_ERROR:
680  // Handle all errors here
681  nprintf(("SOUND","SOUND ==> Could not open wave file %s for streaming\n", filename));
682 
683  fRtn = false;
684 
685  if (m_snd_info.cfp != NULL) {
686  // Close file
687  mmioClose( m_snd_info.cfp, 0 );
688  m_snd_info.cfp = NULL;
689  m_snd_info.true_offset = 0;
690  m_snd_info.size = 0;
691  }
692 
693  if (m_pwfmt_original) {
694  vm_free(m_pwfmt_original);
695  m_pwfmt_original = NULL;
696  }
697 
698 OPEN_DONE:
699  strncpy(m_wFilename, filename, MAX_FILENAME_LEN-1);
700 
701  if (fRtn)
702  nprintf(("SOUND", "AUDIOSTR => Successfully opened: %s\n", filename));
703 
704  return (fRtn);
705 }
706 
707 
708 // Cue
709 //
710 // Set the file pointer to the start of wave data
711 //
712 bool WaveFile::Cue (void)
713 {
714  bool fRtn = true; // assume success
715  int rval;
716 
717  m_total_uncompressed_bytes_read = 0;
718  m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
719 
720  if (m_wave_format == OGG_FORMAT_VORBIS) {
721  rval = (int)ov_raw_seek(&m_snd_info.vorbis_file, m_data_offset);
722  } else {
723  rval = mmioSeek( m_snd_info.cfp, m_data_offset, SEEK_SET );
724  }
725 
726  if ( rval == -1 ) {
727  fRtn = false;
728  }
729 
730  m_data_bytes_left = m_nDataSize;
731  m_abort_next_read = false;
732 
733  return fRtn;
734 }
735 
736 
737 // Read
738 //
739 // Returns number of bytes actually read.
740 //
741 // Returns -1 if there is nothing more to be read. This function can return 0, since
742 // sometimes the amount of bytes requested is too small for the ACM decompression to
743 // locate a suitable block
744 int WaveFile::Read(ubyte *pbDest, uint cbSize, int service)
745 {
746  void *dest_buf=NULL, *uncompressed_wave_data;
747  int rc, uncompressed_bytes_written, section, last_section = -1, byte_order = 0;
748  uint src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read;
749 
750 // nprintf(("Alan","Reqeusted: %d\n", cbSize));
751 
752 #if BYTE_ORDER == BIG_ENDIAN
753  byte_order = 1;
754 #endif
755 
756  if ( service ) {
757  uncompressed_wave_data = Wavedata_service_buffer;
758  } else {
759  uncompressed_wave_data = Wavedata_load_buffer;
760  }
761 
762  switch ( m_wave_format ) {
763  case WAVE_FORMAT_PCM:
764  num_bytes_desired = cbSize;
765  dest_buf = pbDest;
766  break;
767 
768  case WAVE_FORMAT_ADPCM: {
769  if ( !m_hStream_open ) {
770  if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream, m_bits_per_sample_uncompressed) ) {
771  m_hStream_open = 1;
772  } else {
773  Int3();
774  }
775  }
776 
777  num_bytes_desired = cbSize;
778 
779  if ( service ) {
780  dest_buf = Compressed_service_buffer;
781  } else {
782  dest_buf = Compressed_buffer;
783  }
784 
785  if ( num_bytes_desired <= 0 ) {
786  num_bytes_desired = 0;
787 // nprintf(("Alan","No bytes required for ADPCM time interval\n"));
788  } else {
789  num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize);
790 // nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired));
791  }
792 
793  break;
794  }
795 
796  case OGG_FORMAT_VORBIS:
797  num_bytes_desired = cbSize;
798  dest_buf = pbDest;
799  break;
800 
801  case WAVE_FORMAT_IEEE_FLOAT: {
802  num_bytes_desired = cbSize;
803 
804  if (m_wfmt.wBitsPerSample == 32) {
805  dest_buf = pbDest;
806  } else {
807  if (service) {
808  dest_buf = Compressed_service_buffer;
809  } else {
810  dest_buf = Compressed_buffer;
811  }
812  }
813 
814  break;
815  }
816 
817  default:
818  nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_wave_format));
819  Int3();
820  break;
821 
822  } // end switch
823 
824  num_bytes_read = 0;
825  convert_len = 0;
826  src_bytes_used = 0;
827 
828  // read data from disk
829  if ( m_data_bytes_left <= 0 ) {
830  num_bytes_read = 0;
831  uncompressed_bytes_written = 0;
832  return -1;
833  }
834 
835  if ( (m_data_bytes_left > 0) && (num_bytes_desired > 0) ) {
836  int actual_read = 0;
837 
838  if ( num_bytes_desired <= (uint)m_data_bytes_left ) {
839  num_bytes_read = num_bytes_desired;
840  }
841  else {
842  num_bytes_read = m_data_bytes_left;
843  }
844 
845  // OGG reading is special
846  if ( m_wave_format == OGG_FORMAT_VORBIS ) {
847  int sign = (m_wfmt.wBitsPerSample == 8) ? 0 : 1;
848  int sample_size = sizeof(float) * m_wfmt.nChannels;
849 
850  while ( !m_abort_next_read && ((uint)actual_read < num_bytes_read)) {
851  float **pcm = NULL;
852 
853  if (m_wfmt.wBitsPerSample == 32) {
854  rc = ov_read_float(&m_snd_info.vorbis_file, &pcm, (num_bytes_read - actual_read) / sample_size, &section);
855  } else {
856  rc = ov_read(&m_snd_info.vorbis_file, (char *)dest_buf + actual_read, num_bytes_read - actual_read, byte_order, m_wfmt.wBitsPerSample / 8, sign, &section);
857  }
858 
859  // fail if the bitstream changes, shouldn't get this far if that's the case though
860  if ((last_section != -1) && (last_section != section)) {
861  mprintf(("AUDIOSTR => OGG reading error: We don't handle bitstream changes!\n"));
862  goto READ_ERROR;
863  }
864 
865  if ( rc > 0 ) {
866  if (m_wfmt.wBitsPerSample == 32) {
867  float *out_p = (float*)((ubyte*)dest_buf + actual_read);
868 
869  for (int i = 0; i < rc; i++) {
870  for (int j = 0; j < m_wfmt.nChannels; j++) {
871  *out_p++ = pcm[j][i];
872  }
873  }
874 
875  actual_read += (rc * m_wfmt.nBlockAlign);
876  } else {
877  actual_read += rc;
878  }
879 
880  last_section = section;
881  } else if ( rc == 0 ) {
882  break;
883  } else if ( rc < 0 ) {
884  if ( dbg_print_ogg_error(m_wFilename, rc) ) {
885  // must be a fatal error
886  goto READ_ERROR;
887  } else {
888  // not fatal, just continue on
889  break;
890  }
891  }
892  }
893  }
894  // IEEE FLOAT is special too, downsampling can give short buffers
895  else if (m_wave_format == WAVE_FORMAT_IEEE_FLOAT) {
896  while ( !m_abort_next_read && ((uint)actual_read < num_bytes_read) ) {
897  rc = mmioRead(m_snd_info.cfp, (char *)dest_buf, num_bytes_read);
898 
899  if (rc <= 0) {
900  break;
901  }
902 
903 #if BYTE_ORDER == BIG_ENDIAN
904  // need to byte-swap before any later conversions
905  float *swap_tmp;
906 
907  for (int i = 0; i < rc; i += sizeof(float)) {
908  swap_tmp = (float *)((ubyte*)dest_buf + i);
909  *swap_tmp = INTEL_FLOAT(swap_tmp);
910  }
911 #endif
912 
913  if (m_wfmt.wBitsPerSample == 32) {
914  actual_read = rc;
915  } else if (m_wfmt.wBitsPerSample == 16) {
916  float *in_p = (float*)dest_buf;
917  short *out_p = (short*)((ubyte*)uncompressed_wave_data + actual_read);
918 
919  int end = rc / sizeof(float);
920 
921  for (int i = 0; i < end; i++) {
922  int i_val = (int)(in_p[i] * 32767.0f + 0.5f);
923  CLAMP(i_val, -32768, 32767);
924 
925  *out_p++ = (short)i_val;
926  }
927 
928  actual_read += (rc >> 1);
929  } else {
930  Assert( m_wfmt.wBitsPerSample == 8 );
931 
932  float *in_p = (float*)dest_buf;
933  ubyte *out_p = (ubyte*)((ubyte*)uncompressed_wave_data + actual_read);
934 
935  int end = num_bytes_read / sizeof(float);
936 
937  for (int i = 0; i < end; i++) {
938  int i_val = (int)(in_p[i] * 127.0f + 0.5f) + 128;
939  CLAMP(i_val, 0, 255);
940 
941  *out_p++ = (ubyte)i_val;
942  }
943 
944  actual_read += (rc >> 2);
945  }
946  }
947  }
948  // standard WAVE reading
949  else {
950  actual_read = mmioRead( m_snd_info.cfp, (char *)dest_buf, num_bytes_read );
951  }
952 
953  if ( (actual_read <= 0) || (m_abort_next_read) ) {
954  num_bytes_read = 0;
955  uncompressed_bytes_written = 0;
956  return -1;
957  }
958 
959  if ( num_bytes_desired >= (uint)m_data_bytes_left ) {
960  m_abort_next_read = 1;
961  }
962 
963  num_bytes_read = actual_read;
964  }
965 
966  // convert data if necessary, to PCM
967  if ( m_wave_format == WAVE_FORMAT_ADPCM ) {
968  if ( num_bytes_read > 0 ) {
969  rc = ACM_convert((void*)m_hStream, (ubyte*)dest_buf, num_bytes_read, (ubyte*)uncompressed_wave_data, BIGBUF_SIZE, &convert_len, &src_bytes_used);
970 
971  if ( rc == -1 ) {
972  goto READ_ERROR;
973  } else if ( convert_len == 0 ) {
974  if (num_bytes_read < m_nBlockAlign) {
975  mprintf(("AUDIOSTR => Warning: Short read detected in ACM decode of '%s'!!\n", m_wFilename));
976  } else {
977  Int3();
978  }
979  }
980  }
981 
982  Assert(src_bytes_used <= num_bytes_read);
983  if ( src_bytes_used < num_bytes_read ) {
984  // seek back file pointer to reposition before unused source data
985  mmioSeek( m_snd_info.cfp, src_bytes_used - num_bytes_read, SEEK_CUR );
986  }
987 
988  // Adjust number of bytes left
989  m_data_bytes_left -= src_bytes_used;
990  m_nBytesPlayed += src_bytes_used;
991  uncompressed_bytes_written = convert_len;
992 
993  // Successful read, keep running total of number of data bytes read
994  goto READ_DONE;
995  }
996  else {
997  // Successful read, keep running total of number of data bytes read
998  // Adjust number of bytes left
999  m_data_bytes_left -= num_bytes_read;
1000  m_nBytesPlayed += num_bytes_read;
1001  uncompressed_bytes_written = num_bytes_read;
1002 
1003 #if BYTE_ORDER == BIG_ENDIAN
1004  if ( m_wave_format == WAVE_FORMAT_PCM ) {
1005  // swap 16-bit sound data
1006  if (m_wfmt.wBitsPerSample == 16) {
1007  ushort *swap_tmp;
1008 
1009  for (uint i=0; i<uncompressed_bytes_written; i=i+2) {
1010  swap_tmp = (ushort*)((ubyte*)dest_buf + i);
1011  *swap_tmp = INTEL_SHORT(*swap_tmp);
1012  }
1013  }
1014  }
1015 #endif
1016 
1017  goto READ_DONE;
1018  }
1019 
1020 READ_ERROR:
1021  num_bytes_read = 0;
1022  uncompressed_bytes_written = 0;
1023 
1024 READ_DONE:
1025  m_total_uncompressed_bytes_read += uncompressed_bytes_written;
1026 // nprintf(("Alan","Read: %d\n", uncompressed_bytes_written));
1027  return (uncompressed_bytes_written);
1028 }
1029 
1030 //
1031 // AudioStream class implementation
1032 //
1034 
1035 // The following constants are the defaults for our streaming buffer operation.
1036 const ushort DefBufferServiceInterval = 250; // default buffer service interval in msec
1037 
1038 // Constructor
1040 {
1041  INITIALIZE_CRITICAL_SECTION( write_lock );
1042 }
1043 
1044 // Destructor
1046 {
1047  DELETE_CRITICAL_SECTION( write_lock );
1048 }
1049 
1051 {
1052  m_bLooping = 0;
1053  m_bFade = false;
1054  m_fade_timer_id = 0;
1055  m_finished_id = 0;
1056  m_bPastLimit = false;
1057 
1058  m_bDestroy_when_faded = false;
1059  m_lVolume = 1.0f;
1060  m_lCutoffVolume = 0.0f;
1061  m_bIsPaused = false;
1062  m_bReadingDone = false;
1063 
1064  m_pwavefile = NULL;
1065  m_fPlaying = m_fCued = false;
1066  m_cbBufOffset = 0;
1067  m_cbBufSize = 0;
1068  m_nBufService = DefBufferServiceInterval;
1069  m_nTimeStarted = 0;
1070 
1071  memset(m_buffer_ids, 0, sizeof(m_buffer_ids));
1072  m_source_id = 0;
1073 }
1074 
1075 // Create
1076 bool AudioStream::Create (char *pszFilename)
1077 {
1078  bool fRtn = true; // assume success
1079 
1080  Assert(pszFilename);
1081 
1082  Init_Data();
1083 
1084  if (pszFilename) {
1085  // make 100% sure we got a good filename
1086  if ( !strlen(pszFilename) )
1087  return false;
1088 
1089  // Create a new WaveFile object
1090  m_pwavefile = (WaveFile *)vm_malloc(sizeof(WaveFile));
1091  Assert(m_pwavefile);
1092 
1093  if (m_pwavefile) {
1094  // Call constructor
1095  m_pwavefile->Init();
1096  // Open given file
1097  m_pwavefile->m_bits_per_sample_uncompressed = m_bits_per_sample_uncompressed;
1098 
1099  if ( m_pwavefile->Open(pszFilename, (type == ASF_EVENTMUSIC)) ) {
1100  m_cbBufSize = m_pwavefile->m_wfmt.nAvgBytesPerSec >> 2;
1101  // make sure that we are a multiple of the frame size
1102  m_cbBufSize -= (m_cbBufSize % m_pwavefile->m_wfmt.nBlockAlign);
1103  m_cbBufSize += (m_cbBufSize % 12) << 1;
1104  // if the requested buffer size is too big then cap it
1105  m_cbBufSize = (m_cbBufSize > BIGBUF_SIZE) ? BIGBUF_SIZE : m_cbBufSize;
1106 
1107 // nprintf(("SOUND", "SOUND => Stream buffer created using %d bytes\n", m_cbBufSize));
1108 
1109  OpenAL_ErrorCheck( alGenSources(1, &m_source_id), { fRtn = false; goto ErrorExit; } );
1110 
1111  OpenAL_ErrorCheck( alGenBuffers(MAX_STREAM_BUFFERS, m_buffer_ids), { fRtn = false; goto ErrorExit; } );
1112 
1113  OpenAL_ErrorPrint( alSourcef(m_source_id, AL_ROLLOFF_FACTOR, 1.0f) );
1114  OpenAL_ErrorPrint( alSourcei(m_source_id, AL_SOURCE_RELATIVE, AL_TRUE) );
1115 
1116  OpenAL_ErrorPrint( alSource3f(m_source_id, AL_POSITION, 0.0f, 0.0f, 0.0f) );
1117  OpenAL_ErrorPrint( alSource3f(m_source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f) );
1118 
1119  OpenAL_ErrorPrint( alSourcef(m_source_id, AL_GAIN, 1.0f) );
1120  OpenAL_ErrorPrint( alSourcef(m_source_id, AL_PITCH, 1.0f) );
1121 
1122  // maybe set EFX
1123  if ( (type == ASF_SOUNDFX) && ds_eax_is_inited() ) {
1124  extern ALuint AL_EFX_aux_id;
1125  OpenAL_ErrorPrint( alSource3i(m_source_id, AL_AUXILIARY_SEND_FILTER, AL_EFX_aux_id, 0, AL_FILTER_NULL) );
1126  }
1127 
1128  // Cue for playback
1129  Cue();
1130  Snd_sram += (m_cbBufSize * MAX_STREAM_BUFFERS);
1131  }
1132  else {
1133  // Error opening file
1134  nprintf(("SOUND", "SOUND => Failed to open wave file: %s\n\r", pszFilename));
1135  fRtn = false;
1136  }
1137  }
1138  else {
1139  // Error, unable to create WaveFile object
1140  nprintf(("Sound", "SOUND => Failed to create WaveFile object %s\n\r", pszFilename));
1141  fRtn = false;
1142  }
1143  }
1144  else {
1145  // Error, passed invalid parms
1146  fRtn = false;
1147  }
1148 
1149 ErrorExit:
1150  if ( (fRtn == false) && (m_pwavefile) ) {
1151  mprintf(("AUDIOSTR => ErrorExit for ::Create() on wave file: %s\n", pszFilename));
1152 
1153  if (m_source_id)
1154  OpenAL_ErrorPrint( alDeleteSources(1, &m_source_id) );
1155 
1156  m_pwavefile->Close();
1157  vm_free(m_pwavefile);
1158  m_pwavefile = NULL;
1159  }
1160 
1161  return (fRtn);
1162 }
1163 
1164 // Destroy
1166 {
1167  bool fRtn = true;
1168  ALint buffers_processed = 0;
1169 
1170  ENTER_CRITICAL_SECTION(write_lock);
1171 
1172  // Stop playback
1173  Stop ();
1174 
1175  OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &buffers_processed) );
1176 
1177  while (buffers_processed) {
1178  ALuint buffer_id = 0;
1179  OpenAL_ErrorPrint( alSourceUnqueueBuffers(m_source_id, 1, &buffer_id) );
1180  buffers_processed--;
1181  }
1182 
1183  // Release sound sources and buffers
1184  OpenAL_ErrorPrint( alDeleteSources(1, &m_source_id) );
1185  OpenAL_ErrorPrint( alDeleteBuffers(MAX_STREAM_BUFFERS, m_buffer_ids) );
1186 
1187  Snd_sram -= (m_cbBufSize * MAX_STREAM_BUFFERS);
1188 
1189  // Delete WaveFile object
1190  if (m_pwavefile) {
1191  m_pwavefile->Close();
1192  vm_free(m_pwavefile);
1193  m_pwavefile = NULL;
1194  }
1195 
1196  status = ASF_FREE;
1197 
1198  LEAVE_CRITICAL_SECTION(write_lock);
1199 
1200  return fRtn;
1201 }
1202 
1203 // WriteWaveData
1204 //
1205 // Writes wave data to sound buffer. This is a helper method used by Create and
1206 // ServiceBuffer; it's not exposed to users of the AudioStream class.
1207 bool AudioStream::WriteWaveData (uint size, uint *num_bytes_written, int service)
1208 {
1209  bool fRtn = true;
1210  ubyte *uncompressed_wave_data;
1211 
1212  *num_bytes_written = 0;
1213 
1214  if ( size == 0 || m_bReadingDone ) {
1215  return fRtn;
1216  }
1217 
1218  if ( (m_buffer_ids[0] == 0) || !m_pwavefile ) {
1219  return fRtn;
1220  }
1221 
1222  if ( service ) {
1224  }
1225 
1226  if ( service ) {
1227  uncompressed_wave_data = Wavedata_service_buffer;
1228  } else {
1229  uncompressed_wave_data = Wavedata_load_buffer;
1230  }
1231 
1232  int num_bytes_read = 0;
1233 
1234  if ( !service ) {
1235  for (int ib = 0; ib < MAX_STREAM_BUFFERS; ib++) {
1236  num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, m_cbBufSize, service);
1237 
1238  if (num_bytes_read < 0) {
1239  m_bReadingDone = 1;
1240  } else if (num_bytes_read > 0) {
1241  OpenAL_ErrorCheck( alBufferData(m_buffer_ids[ib], m_pwavefile->GetALFormat(), uncompressed_wave_data, num_bytes_read, m_pwavefile->m_wfmt.nSamplesPerSec), { fRtn = false; goto ErrorExit; } );
1242  OpenAL_ErrorCheck( alSourceQueueBuffers(m_source_id, 1, &m_buffer_ids[ib]), { fRtn = false; goto ErrorExit; } );
1243 
1244  *num_bytes_written += num_bytes_read;
1245  }
1246  }
1247  } else {
1248  ALint buffers_processed = 0;
1249  OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &buffers_processed) );
1250 
1251  while (buffers_processed) {
1252  ALuint buffer_id = 0;
1253  OpenAL_ErrorPrint( alSourceUnqueueBuffers(m_source_id, 1, &buffer_id) );
1254 
1255  num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, m_cbBufSize, service);
1256 
1257  if (num_bytes_read < 0) {
1258  m_bReadingDone = 1;
1259  } else if (num_bytes_read > 0) {
1260  OpenAL_ErrorPrint( alBufferData(buffer_id, m_pwavefile->GetALFormat(), uncompressed_wave_data, num_bytes_read, m_pwavefile->m_wfmt.nSamplesPerSec) );
1261  OpenAL_ErrorPrint( alSourceQueueBuffers(m_source_id, 1, &buffer_id) );
1262 
1263  *num_bytes_written += num_bytes_read;
1264  }
1265 
1266  buffers_processed--;
1267  }
1268  }
1269 
1270 ErrorExit:
1271 
1272  if ( service ) {
1274  }
1275 
1276  return (fRtn);
1277 }
1278 
1279 // GetMaxWriteSize
1280 //
1281 // Helper function to calculate max size of sound buffer write operation, i.e. how much
1282 // free space there is in buffer.
1284 {
1285  uint dwMaxSize = m_cbBufSize;
1286  ALint n, q;
1287 
1288  OpenAL_ErrorCheck( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &n), return 0 );
1289 
1290  OpenAL_ErrorCheck( alGetSourcei(m_source_id, AL_BUFFERS_QUEUED, &q), return 0 );
1291 
1292  if (!n && (q >= MAX_STREAM_BUFFERS)) //all buffers queued
1293  dwMaxSize = 0;
1294 
1295  // nprintf(("Alan","Max write size: %d\n", dwMaxSize));
1296  return (dwMaxSize);
1297 }
1298 
1299 #define VOLUME_ATTENUATION_BEFORE_CUTOFF 0.03f
1300 #define VOLUME_ATTENUATION 0.65f
1302 {
1303  float vol;
1304  bool fRtn = true;
1305 
1306  if ( status != ASF_USED )
1307  return false;
1308 
1309  ENTER_CRITICAL_SECTION( write_lock );
1310 
1311  // status may have changed, so lets check once again
1312  if ( status != ASF_USED ){
1313  LEAVE_CRITICAL_SECTION( write_lock );
1314 
1315  return false;
1316  }
1317 
1318  if ( m_bFade == true ) {
1319  if ( m_lCutoffVolume == 0.0f ) {
1320  vol = Get_Volume();
1321 // nprintf(("Alan","Volume is: %d\n",vol));
1322  m_lCutoffVolume = vol * VOLUME_ATTENUATION_BEFORE_CUTOFF;
1323  }
1324 
1325  vol = Get_Volume() * VOLUME_ATTENUATION;
1326 // nprintf(("Alan","Volume is now: %d\n",vol));
1327  Set_Volume(vol);
1328 
1329 // nprintf(("Sound","SOUND => Volume for stream sound is %d\n",vol));
1330 // nprintf(("Alan","Cuttoff Volume is: %d\n",m_lCutoffVolume));
1331  if ( vol < m_lCutoffVolume ) {
1332  m_bFade = false;
1333  m_lCutoffVolume = 0.0f;
1334 
1335  if ( m_bDestroy_when_faded == true ) {
1336  LEAVE_CRITICAL_SECTION( write_lock );
1337 
1338  Destroy();
1339  // Reset reentrancy semaphore
1340 
1341  return false;
1342  } else {
1343  Stop_and_Rewind();
1344  // Reset reentrancy semaphore
1345  LEAVE_CRITICAL_SECTION( write_lock );
1346 
1347  return true;
1348  }
1349  }
1350  }
1351 
1352  // All of sound not played yet, send more data to buffer
1353  uint dwFreeSpace = GetMaxWriteSize ();
1354 
1355  // Determine free space in sound buffer
1356  if (dwFreeSpace) {
1357 
1358  // Some wave data remains, but not enough to fill free space
1359  // Send wave data to buffer, fill remainder of free space with silence
1360  uint num_bytes_written;
1361 
1362  if (WriteWaveData (dwFreeSpace, &num_bytes_written) == true) {
1363 // nprintf(("Alan","Num bytes written: %d\n", num_bytes_written));
1364 
1365  if ( m_pwavefile->m_total_uncompressed_bytes_read >= m_pwavefile->m_max_uncompressed_bytes_to_read ) {
1366  m_fade_timer_id = timer_get_milliseconds() + 1700; // start fading 1.7 seconds from now
1367  m_finished_id = timer_get_milliseconds() + 2000; // 2 seconds left to play out buffer
1368  m_pwavefile->m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
1369  }
1370 
1371  if ( (m_fade_timer_id>0) && ((uint)timer_get_milliseconds() > m_fade_timer_id) ) {
1372  m_fade_timer_id = 0;
1373  Fade_and_Stop();
1374  }
1375 
1376  if ( (m_finished_id>0) && ((uint)timer_get_milliseconds() > m_finished_id) ) {
1377  m_finished_id = 0;
1378  m_bPastLimit = true;
1379  }
1380 
1381  if ( PlaybackDone() ) {
1382  if ( m_bDestroy_when_faded == true ) {
1383  LEAVE_CRITICAL_SECTION( write_lock );
1384 
1385  Destroy();
1386  // Reset reentrancy semaphore
1387 
1388  return false;
1389  }
1390  // All of sound has played, stop playback or loop again
1391  if ( m_bLooping && !m_bFade) {
1392  Play(m_lVolume, m_bLooping);
1393  } else {
1394  Stop_and_Rewind();
1395  }
1396  }
1397  }
1398  else {
1399  // Error writing wave data
1400  fRtn = false;
1401  Int3();
1402  }
1403  }
1404 
1405  LEAVE_CRITICAL_SECTION( write_lock );
1406 
1407  return (fRtn);
1408 }
1409 
1410 // Cue
1411 void AudioStream::Cue (void)
1412 {
1413  uint num_bytes_written;
1414 
1415  if (!m_fCued) {
1416  m_bFade = false;
1417  m_fade_timer_id = 0;
1418  m_finished_id = 0;
1419  m_bPastLimit = false;
1420  m_lVolume = 1.0f;
1421  m_lCutoffVolume = 0.0f;
1422 
1423  m_bDestroy_when_faded = false;
1424 
1425  // Reset buffer ptr
1426  m_cbBufOffset = 0;
1427 
1428  // Reset file ptr, etc
1429  m_pwavefile->Cue ();
1430 
1431  // Unqueue all buffers
1432  ALint buffers_processed = 0;
1433  OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &buffers_processed) );
1434 
1435  while (buffers_processed) {
1436  ALuint buffer_id = 0;
1437  OpenAL_ErrorPrint( alSourceUnqueueBuffers(m_source_id, 1, &buffer_id) );
1438  buffers_processed--;
1439  }
1440 
1441  // Fill buffer with wave data
1442  WriteWaveData (m_cbBufSize, &num_bytes_written, 0);
1443 
1444  m_fCued = true;
1445  }
1446 }
1447 
1448 // Play
1449 void AudioStream::Play (float volume, int looping)
1450 {
1451  if (m_buffer_ids[0] != 0) {
1452  // If playing, stop
1453  if (m_fPlaying) {
1454  if ( m_bIsPaused == false)
1455  Stop_and_Rewind();
1456  }
1457 
1458  // Cue for playback if necessary
1459  if ( !m_fCued )
1460  Cue ();
1461 
1462  if ( looping )
1463  m_bLooping = 1;
1464  else
1465  m_bLooping = 0;
1466 
1467  OpenAL_ErrorPrint( alSourcePlay(m_source_id) );
1468 
1469  m_nTimeStarted = timer_get_milliseconds();
1470  Set_Volume(volume);
1471 
1472  // Kick off timer to service buffer
1473  m_timer.constructor();
1474 
1475  m_timer.Create (m_nBufService, m_nBufService, ptr_u (this), TimerCallback);
1476 
1477  // Playback begun, no longer cued
1478  m_fPlaying = true;
1479  m_bIsPaused = false;
1480  }
1481 }
1482 
1483 // Timer callback for Timer object created by ::Play method.
1485 {
1486  // dwUser contains ptr to AudioStream object
1487  AudioStream * pas = (AudioStream *) dwUser;
1488 
1489  return (pas->ServiceBuffer ());
1490 }
1491 
1492 void AudioStream::Set_Sample_Cutoff(unsigned int sample_cutoff)
1493 {
1494  if ( m_pwavefile == NULL )
1495  return;
1496 
1497  m_pwavefile->m_max_uncompressed_bytes_to_read = ((sample_cutoff * m_pwavefile->m_wfmt.wBitsPerSample) / 8);
1498 }
1499 
1501 {
1502  if ( m_pwavefile == NULL )
1503  return 0;
1504 
1505  return ((m_pwavefile->m_total_uncompressed_bytes_read * 8) / m_pwavefile->m_wfmt.wBitsPerSample);
1506 }
1507 
1508 
1513 {
1514  if (!m_fPlaying || PlaybackDone())
1515  {
1516  Destroy();
1517  }
1518  else
1519  {
1520  m_bFade = true;
1521  m_bDestroy_when_faded = true;
1522  }
1523 }
1524 
1525 // Fade_and_Destroy
1527 {
1528  m_bFade = true;
1529  m_bDestroy_when_faded = false;
1530 }
1531 
1532 
1533 // Stop
1534 void AudioStream::Stop(int paused)
1535 {
1536  if (m_fPlaying) {
1537  if (paused) {
1538  OpenAL_ErrorPrint( alSourcePause(m_source_id) );
1539  } else {
1540  OpenAL_ErrorPrint( alSourceStop(m_source_id) );
1541  }
1542 
1543  m_fPlaying = false;
1544  m_bIsPaused = (paused != 0);
1545 
1546  // Delete Timer object
1547  m_timer.destructor();
1548  }
1549 }
1550 
1551 // Stop_and_Rewind
1553 {
1554  if (m_fPlaying) {
1555  // Stop playback
1556  OpenAL_ErrorPrint( alSourceStop(m_source_id) );
1557 
1558  // Delete Timer object
1559  m_timer.destructor();
1560 
1561  m_fPlaying = false;
1562  m_bIsPaused = false;
1563  }
1564 
1565  // Unqueue all buffers
1566  ALint buffers_processed = 0;
1567  OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &buffers_processed) );
1568 
1569  while (buffers_processed) {
1570  ALuint buffer_id = 0;
1571  OpenAL_ErrorPrint( alSourceUnqueueBuffers(m_source_id, 1, &buffer_id) );
1572  buffers_processed--;
1573  }
1574 
1575  m_fCued = false; // this will cause wave file to start from beginning
1576  m_bReadingDone = false;
1577 }
1578 
1579 // Set_Volume
1581 {
1582  CAP(vol, 0.0f, 1.0f);
1583 
1584  OpenAL_ErrorPrint( alSourcef(m_source_id, AL_GAIN, vol) );
1585 
1586  m_lVolume = vol;
1587 }
1588 
1589 
1590 // Set_Volume
1592 {
1593  return m_lVolume;
1594 }
1595 
1597 {
1598  ALint state = 0;
1599  OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_SOURCE_STATE, &state) );
1600 
1601  if (m_bReadingDone && (state != AL_PLAYING))
1602  return true;
1603  else
1604  return false;
1605 }
1606 
1607 
1609 
1610 
1612 {
1613  int i;
1614 
1615  if ( Audiostream_inited == 1 )
1616  return;
1617 
1618  // Allocate memory for the buffer which holds the uncompressed wave data that is streamed from the
1619  // disk during a load/cue
1620  if ( Wavedata_load_buffer == NULL ) {
1622  Assert(Wavedata_load_buffer != NULL);
1623  }
1624 
1625  // Allocate memory for the buffer which holds the uncompressed wave data that is streamed from the
1626  // disk during a service interval
1627  if ( Wavedata_service_buffer == NULL ) {
1630  }
1631 
1632  // Allocate memory for the buffer which holds the compressed wave data that is read from the hard disk
1633  if ( Compressed_buffer == NULL ) {
1635  Assert(Compressed_buffer != NULL);
1636  }
1637 
1638  if ( Compressed_service_buffer == NULL ) {
1641  }
1642 
1643  for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1644  Audio_streams[i].Init_Data();
1645  Audio_streams[i].status = ASF_FREE;
1646  Audio_streams[i].type = ASF_NONE;
1647  Audio_streams[i].paused_via_sexp_or_script = false;
1648  }
1649 
1650 #ifdef SCP_UNIX
1651  SDL_InitSubSystem(SDL_INIT_TIMER);
1652 #endif
1653 
1655 
1656  Audiostream_inited = 1;
1657 }
1658 
1659 // Close down the audiostream system. Must call audiostream_init() before any audiostream functions can
1660 // be used.
1662 {
1663  if ( Audiostream_inited == 0 )
1664  return;
1665 
1666  int i;
1667 
1668  for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1669  if ( Audio_streams[i].status == ASF_USED ) {
1670  Audio_streams[i].status = ASF_FREE;
1671  Audio_streams[i].Destroy();
1672  }
1673  }
1674 
1675  // free global buffers
1676  if ( Wavedata_load_buffer ) {
1678  Wavedata_load_buffer = NULL;
1679  }
1680 
1681  if ( Wavedata_service_buffer ) {
1683  Wavedata_service_buffer = NULL;
1684  }
1685 
1686  if ( Compressed_buffer ) {
1688  Compressed_buffer = NULL;
1689  }
1690 
1691  if ( Compressed_service_buffer ) {
1694  }
1695 
1697 
1698  Audiostream_inited = 0;
1699 
1700 }
1701 
1702 // Open a digital sound file for streaming
1703 //
1704 // input: filename => disk filename of sound file
1705 // type => what type of audio stream do we want to open:
1706 // ASF_SOUNDFX
1707 // ASF_EVENTMUSIC
1708 // ASF_MENUMUSIC
1709 // ASF_VOICE
1710 //
1711 // returns: success => handle to identify streaming sound
1712 // failure => -1
1713 int audiostream_open( const char *filename, int type )
1714 {
1715  int i, rc;
1716  char fname[MAX_FILENAME_LEN];
1717 
1718  if ( !Audiostream_inited || !snd_is_inited() )
1719  return -1;
1720 
1721  for (i = 0; i < MAX_AUDIO_STREAMS; i++) {
1722  if (Audio_streams[i].status == ASF_FREE) {
1723  Audio_streams[i].status = ASF_USED;
1724  Audio_streams[i].type = type;
1725  break;
1726  }
1727  }
1728 
1729  if (i == MAX_AUDIO_STREAMS) {
1730  nprintf(("Sound", "SOUND => No more audio streams available!\n"));
1731  return -1;
1732  }
1733 
1734  // copy filename, since we might modify it
1735  strcpy_s(fname, filename);
1736 
1737  // we always uncompress to 16 bits
1738  Audio_streams[i].m_bits_per_sample_uncompressed = 16;
1739 
1740  switch (type)
1741  {
1742  case ASF_VOICE:
1743  case ASF_SOUNDFX:
1744  case ASF_MENUMUSIC:
1745  {
1746  // go ahead and strip off file extension
1747  char *p = strrchr(fname, '.');
1748  if ( p && (strlen(p) > 2) )
1749  (*p) = 0;
1750 
1751  break;
1752  }
1753 
1754  case ASF_EVENTMUSIC:
1755  break;
1756 
1757  default:
1758  Int3();
1759  return -1;
1760  }
1761 
1762  rc = Audio_streams[i].Create(fname);
1763 
1764  if ( rc == 0 ) {
1765  Audio_streams[i].status = ASF_FREE;
1766  return -1;
1767  } else {
1768  return i;
1769  }
1770 }
1771 
1772 void audiostream_close_file(int i, int fade)
1773 {
1774  if (!Audiostream_inited)
1775  return;
1776 
1777  if ( i == -1 )
1778  return;
1779 
1780  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1781 
1782  if ( Audio_streams[i].status == ASF_USED ) {
1783  if ( fade )
1784  Audio_streams[i].Fade_and_Destroy();
1785  else
1786  Audio_streams[i].Destroy();
1787  }
1788 
1789 }
1790 
1792 {
1793  int i;
1794 
1795  for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1796  if ( Audio_streams[i].status == ASF_FREE )
1797  continue;
1798 
1799  audiostream_close_file(i, fade);
1800  }
1801 }
1802 
1803 void audiostream_play(int i, float volume, int looping)
1804 {
1805  if (!Audiostream_inited)
1806  return;
1807 
1808  if ( i == -1 )
1809  return;
1810 
1811  Assert(looping >= 0);
1812  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1813 
1814  if (volume == -1.0f) {
1815  volume = Audio_streams[i].Get_Default_Volume();
1816  }
1817 
1818  Assert(volume >= 0.0f && volume <= 1.0f );
1819  CAP(volume, 0.0f, 1.0f);
1820 
1821  Assert( Audio_streams[i].status == ASF_USED );
1822  Audio_streams[i].Set_Default_Volume(volume);
1823  Audio_streams[i].Play(volume, looping);
1824 }
1825 
1826 // use as buffer service function
1828 {
1829  if ( i == -1 )
1830  return 0;
1831 
1832  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1833 
1834  if ( Audio_streams[i].status != ASF_USED )
1835  return 0;
1836 
1837  return (int)Audio_streams[i].Is_Playing();
1838 }
1839 
1840 void audiostream_stop(int i, int rewind, int paused)
1841 {
1842  if (!Audiostream_inited)
1843  return;
1844 
1845  if ( i == -1 )
1846  return;
1847 
1848  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1849  Assert( Audio_streams[i].status == ASF_USED );
1850 
1851  if ( rewind )
1852  Audio_streams[i].Stop_and_Rewind();
1853  else
1854  Audio_streams[i].Stop(paused);
1855 }
1856 
1857 void audiostream_set_volume_all(float volume, int type)
1858 {
1859  int i;
1860 
1861  for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1862  if ( Audio_streams[i].status == ASF_FREE )
1863  continue;
1864 
1865  if ( (Audio_streams[i].type == type) || ((Audio_streams[i].type == ASF_MENUMUSIC) && (type == ASF_EVENTMUSIC)) ) {
1866  Audio_streams[i].Set_Volume(volume);
1867  }
1868  }
1869 }
1870 
1871 void audiostream_set_volume(int i, float volume)
1872 {
1873  if ( i == -1 )
1874  return;
1875 
1876  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1877  Assert( volume >= 0.0f && volume <= 1.0f);
1878 
1879  if ( Audio_streams[i].status == ASF_FREE )
1880  return;
1881 
1882  Audio_streams[i].Set_Volume(volume);
1883 }
1884 
1886 {
1887  if ( i == -1 )
1888  return 0;
1889 
1890  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1891 
1892  if ( Audio_streams[i].status == ASF_FREE )
1893  return -1;
1894 
1895  return (int) Audio_streams[i].Is_Paused();
1896 }
1897 
1899 {
1900  if ( i == -1 )
1901  return;
1902 
1903  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1904  Assert( cutoff > 0 );
1905 
1906  if ( Audio_streams[i].status == ASF_FREE )
1907  return;
1908 
1909  Audio_streams[i].Set_Sample_Cutoff(cutoff);
1910 }
1911 
1913 {
1914  if ( i == -1 )
1915  return 0;
1916 
1917  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1918 
1919  if ( Audio_streams[i].status == ASF_FREE )
1920  return 0;
1921 
1922  return Audio_streams[i].Get_Samples_Committed();
1923 }
1924 
1926 {
1927  if ( i == -1 )
1928  return 0;
1929 
1930  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1931 
1932  if ( Audio_streams[i].status == ASF_FREE )
1933  return 0;
1934 
1935  return Audio_streams[i].Is_Past_Limit();
1936 }
1937 
1939 {
1940  return Audiostream_inited;
1941 }
1942 
1943 void audiostream_pause(int i, bool via_sexp_or_script)
1944 {
1945  if ( i == -1 )
1946  return;
1947 
1948  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1949 
1950  if ( Audio_streams[i].status == ASF_FREE )
1951  return;
1952 
1953  if ( audiostream_is_playing(i) == (int)true )
1954  audiostream_stop(i, 0, 1);
1955 
1956  if (via_sexp_or_script)
1957  Audio_streams[i].paused_via_sexp_or_script = true;
1958 }
1959 
1960 void audiostream_unpause(int i, bool via_sexp_or_script)
1961 {
1962  if ( i == -1 )
1963  return;
1964 
1965  Assert( i >= 0 && i < MAX_AUDIO_STREAMS );
1966 
1967  if ( Audio_streams[i].status == ASF_FREE )
1968  return;
1969 
1970  if ( audiostream_is_paused(i) == (int)true ) {
1971  audiostream_play(i, Audio_streams[i].Get_Volume(), Audio_streams[i].Is_looping());
1972  }
1973 
1974  if (via_sexp_or_script)
1975  Audio_streams[i].paused_via_sexp_or_script = false;
1976 }
1977 
1978 void audiostream_pause_all(bool via_sexp_or_script)
1979 {
1980  int i;
1981 
1982  for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1983  if ( Audio_streams[i].status == ASF_FREE )
1984  continue;
1985 
1986  audiostream_pause(i, via_sexp_or_script);
1987  }
1988 }
1989 
1990 void audiostream_unpause_all(bool via_sexp_or_script)
1991 {
1992  int i;
1993 
1994  for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) {
1995  if ( Audio_streams[i].status == ASF_FREE )
1996  continue;
1997 
1998  // if we explicitly paused this and we are not explicitly unpausing, skip this stream
1999  if ( Audio_streams[i].paused_via_sexp_or_script && !via_sexp_or_script )
2000  continue;
2001 
2002  audiostream_unpause(i, via_sexp_or_script);
2003  }
2004 }
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
#define VOLUME_ATTENUATION_BEFORE_CUTOFF
Definition: audiostr.cpp:1299
void Stop(int paused=0)
Definition: audiostr.cpp:1534
void Close(void)
Definition: audiostr.cpp:405
uint m_cbBufOffset
Definition: audiostr.cpp:277
int i
Definition: multi_pxo.cpp:466
bool m_fPlaying
Definition: audiostr.cpp:276
#define vm_free(ptr)
Definition: pstypes.h:548
uint m_cbBufSize
Definition: audiostr.cpp:278
uint m_max_uncompressed_bytes_to_read
Definition: audiostr.cpp:211
void audiostream_set_volume_all(float volume, int type)
Definition: audiostr.cpp:1857
WaveFile * m_pwavefile
Definition: audiostr.cpp:274
#define OpenAL_ErrorCheck(x, y)
Definition: openal.h:24
#define ASF_SOUNDFX
Definition: audiostr.h:18
bool PlaybackDone(void)
Definition: audiostr.cpp:1596
#define ASF_MENUMUSIC
Definition: audiostr.h:20
uint m_data_offset
Definition: audiostr.cpp:215
int snd_is_inited()
Definition: sound.cpp:1073
#define WAVE_FORMAT_ADPCM
Definition: mmreg.h:1303
WAVEFORMAT wf
Definition: config.h:160
bool m_bReadingDone
Definition: audiostr.cpp:288
#define MAX_STREAM_BUFFERS
Definition: audiostr.cpp:27
const char * audio_ext_list[]
Definition: audiostr.cpp:49
#define DELETE_CRITICAL_SECTION(csc)
Definition: osapi.h:41
T sign(T t)
Definition: sexp.cpp:8941
#define ASF_EVENTMUSIC
Definition: audiostr.h:19
void audiostream_close_all(int fade)
Definition: audiostr.cpp:1791
void Play(float volume, int looping)
Definition: audiostr.cpp:1449
#define MAX_PATH
#define ASF_VOICE
Definition: audiostr.h:21
ALuint m_buffer_ids[MAX_STREAM_BUFFERS]
Definition: audiostr.cpp:271
float Get_Default_Volume()
Definition: audiostr.cpp:254
uint GetDataSize(void)
Definition: audiostr.cpp:205
#define AS_HIGHEST_MAX
Definition: audiostr.cpp:46
uint m_nTimeStarted
Definition: audiostr.cpp:280
Assert(pm!=NULL)
#define VOLUME_ATTENUATION
Definition: audiostr.cpp:1300
STRHDL m_snd_info
Definition: audiostr.cpp:226
#define mprintf(args)
Definition: pstypes.h:238
bool Create(uint nPeriod, uint nRes, ptr_u dwUser, TIMERCALLBACK pfnCallback)
Definition: audiostr.cpp:323
~AudioStream(void)
Definition: audiostr.cpp:1045
void Fade_and_Stop(void)
Definition: audiostr.cpp:1526
bool m_bFade
Definition: audiostr.cpp:283
bool ServiceBuffer(void)
Definition: audiostr.cpp:1301
SDL_RWops * HMMIO
Definition: config.h:93
GLclampf f
Definition: Glext.h:7097
#define INTEL_SHORT(x)
Definition: pstypes.h:389
bool Create(char *pszFilename)
Definition: audiostr.cpp:1076
SDL_mutex * CRITICAL_SECTION
Definition: config.h:213
WORD nChannels
Definition: config.h:153
#define OpenAL_ErrorPrint(x)
Definition: openal.h:34
#define AL_AUXILIARY_SEND_FILTER
Definition: openal.h:86
uint m_nIDTimer
Definition: audiostr.cpp:189
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out=0, char *pack_filename=NULL, int *size=NULL, int *offset=NULL, bool localize=false)
ALuint *typedef ALuint *typedef ALenum
Definition: ds.cpp:133
WORD wBitsPerSample
Definition: config.h:161
void destructor(void)
Definition: audiostr.cpp:310
int ACM_query_source_size(void *stream, int dest_len)
Definition: acm.cpp:605
uint m_bits_per_sample_uncompressed
Definition: audiostr.cpp:212
unsigned int UINT
Definition: config.h:82
void Set_Sample_Cutoff(uint sample_cutoff)
Definition: audiostr.cpp:1492
GLsizeiptr size
Definition: Glext.h:5496
#define Int3()
Definition: pstypes.h:292
#define WAVE_FORMAT_PCM
Definition: mmreg.h:1394
uint m_finished_id
Definition: audiostr.cpp:290
bool Is_Paused()
Definition: audiostr.cpp:243
MMRESULT mmioClose(HMMIO hmmio, uint wFlags)
uint GetNumBytesRemaining(void)
Definition: audiostr.cpp:203
uint GetUncompressedAvgDataRate(void)
Definition: audiostr.cpp:204
GLenum type
Definition: Gl.h:1492
#define CLAMP(x, min, max)
Definition: pstypes.h:488
ubyte * Wavedata_load_buffer
Definition: audiostr.cpp:35
float Get_Volume()
Definition: audiostr.cpp:1591
int audiostream_is_inited()
Definition: audiostr.cpp:1938
int audiostream_is_playing(int i)
Definition: audiostr.cpp:1827
ubyte * Compressed_buffer
Definition: audiostr.cpp:43
uint audiostream_get_samples_committed(int i)
Definition: audiostr.cpp:1912
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
bool Destroy(void)
Definition: audiostr.cpp:1165
bool m_bIsPaused
Definition: audiostr.cpp:287
bool Open(char *pszFilename, bool keep_ext=true)
Definition: audiostr.cpp:434
CRITICAL_SECTION write_lock
Definition: audiostr.cpp:294
int cf_find_file_location(const char *filespec, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize=false)
uint m_nRes
Definition: audiostr.cpp:187
unsigned int uint
Definition: pstypes.h:64
WAVEFORMATEX m_wfxDest
Definition: audiostr.cpp:230
void Cue(void)
Definition: audiostr.cpp:1411
ALuint *typedef ALuint *typedef ALint
Definition: ds.cpp:133
CRITICAL_SECTION Global_service_lock
Definition: audiostr.cpp:38
#define nprintf(args)
Definition: pstypes.h:239
ALuint m_source_id
Definition: audiostr.cpp:270
#define MMIO_READ
Definition: config.h:251
void audiostream_stop(int i, int rewind, int paused)
Definition: audiostr.cpp:1840
void audiostream_unpause_all(bool via_sexp_or_script)
Definition: audiostr.cpp:1990
void audiostream_pause_all(bool via_sexp_or_script)
Definition: audiostr.cpp:1978
switch(qd->index)
Definition: lua.cpp:3137
int ds_eax_is_inited()
Definition: ds.cpp:2598
float m_lCutoffVolume
Definition: audiostr.cpp:286
bool m_bDestroy_when_faded
Definition: audiostr.cpp:284
char * filename
bool WriteWaveData(uint cbSize, uint *num_bytes_written, int service=1)
Definition: audiostr.cpp:1207
bool Is_Playing()
Definition: audiostr.cpp:242
#define COMPRESSED_BUFFER_SIZE
Definition: audiostr.cpp:42
long mmioSeek(HMMIO hmmio, long lOffset, int iOrigin)
#define ASF_NONE
Definition: audiostr.h:22
ptr_u m_dwUser
Definition: audiostr.cpp:185
#define BIGBUF_SIZE
Definition: audiostr.cpp:34
uint Get_Samples_Committed(void)
Definition: audiostr.cpp:1500
int Is_looping()
Definition: audiostr.cpp:256
const int NUM_AUDIO_EXT
Definition: audiostr.cpp:50
int m_hStream_open
Definition: audiostr.cpp:229
WAVEFORMATEX m_wfmt
Definition: audiostr.cpp:208
void audiostream_close()
Definition: audiostr.cpp:1661
#define ENTER_CRITICAL_SECTION(csc)
Definition: osapi.h:42
Timer m_timer
Definition: audiostr.cpp:273
DWORD nAvgBytesPerSec
Definition: config.h:155
void audiostream_set_volume(int i, float volume)
Definition: audiostr.cpp:1871
bool m_bPastLimit
Definition: audiostr.cpp:291
int ACM_stream_close(void *stream)
Definition: acm.cpp:591
unsigned long DWORD
Definition: config.h:90
uint m_nUncompressedAvgDataRate
Definition: audiostr.cpp:220
void audiostream_unpause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1960
char m_wFilename[MAX_FILENAME_LEN]
Definition: audiostr.cpp:231
GLclampd n
Definition: Glext.h:7286
unsigned char ubyte
Definition: pstypes.h:62
int Read(ubyte *pbDest, uint cbSize, int service=1)
Definition: audiostr.cpp:744
void Fade_and_Destroy(void)
Definition: audiostr.cpp:1512
uint m_nBytesPlayed
Definition: audiostr.cpp:222
UINT uMsg
Definition: msacm.h:1064
bool Cue(void)
Definition: audiostr.cpp:712
#define CALLBACK
Definition: config.h:75
void constructor(void)
Definition: audiostr.cpp:303
AudioStream(void)
Definition: audiostr.cpp:1039
#define vm_malloc(size)
Definition: pstypes.h:547
int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream, int dest_bps)
Definition: acm.cpp:499
#define INTEL_INT(x)
Definition: pstypes.h:388
#define INTEL_FLOAT(x)
Definition: pstypes.h:391
uint GetMaxWriteSize(void)
Definition: audiostr.cpp:1283
WORD nBlockAlign
Definition: config.h:156
uint m_nBlockAlign
Definition: audiostr.cpp:219
ubyte * Compressed_service_buffer
Definition: audiostr.cpp:44
bool m_abort_next_read
Definition: audiostr.cpp:223
void audiostream_close_file(int i, int fade)
Definition: audiostr.cpp:1772
GLfloat param
Definition: Glext.h:5373
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
GLdouble GLdouble GLdouble GLdouble q
Definition: Glext.h:5345
bool(* TIMERCALLBACK)(ptr_u)
Definition: audiostr.cpp:40
ALuint AL_EFX_aux_id
Definition: ds.cpp:174
#define LEAVE_CRITICAL_SECTION(csc)
Definition: osapi.h:43
void CAP(T &v, T mn, T mx)
Definition: pstypes.h:478
unsigned short WORD
Definition: config.h:81
#define strcat_s(...)
Definition: safe_strings.h:68
uint m_nDataSize
Definition: audiostr.cpp:221
static bool TimerCallback(ptr_u dwUser)
Definition: audiostr.cpp:1484
void Init_Data()
Definition: audiostr.cpp:1050
ALenum openal_get_format(ALint bits, ALint n_channels)
Definition: openal.cpp:78
ushort m_bits_per_sample_uncompressed
Definition: audiostr.cpp:260
unsigned int ptr_u
Definition: pstypes.h:57
int Ds_float_supported
Definition: ds.cpp:62
#define AL_FILTER_NULL
Definition: openal.h:76
int audiostream_is_paused(int i)
Definition: audiostr.cpp:1885
#define DS_SQ_MEDIUM
Definition: ds.h:33
bool paused_via_sexp_or_script
Definition: audiostr.cpp:259
ALenum m_al_format
Definition: audiostr.cpp:224
#define INITIALIZE_CRITICAL_SECTION(csc)
Definition: osapi.h:40
#define MAX_AUDIO_STREAMS
Definition: audiostr.h:26
static void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
Definition: audiostr.cpp:354
unsigned short ushort
Definition: pstypes.h:63
void Init(void)
Definition: audiostr.cpp:382
TIMERCALLBACK m_pfnCallback
Definition: audiostr.cpp:184
uint GetNumBytesPlayed(void)
Definition: audiostr.cpp:206
bool Is_Past_Limit()
Definition: audiostr.cpp:244
GLfloat GLfloat p
Definition: Glext.h:8373
#define MMIO_ALLOCBUF
Definition: config.h:254
const ushort DefBufferServiceInterval
Definition: audiostr.cpp:1036
uint m_total_uncompressed_bytes_read
Definition: audiostr.cpp:210
WORD wFormatTag
Definition: config.h:152
void Set_Volume(float vol)
Definition: audiostr.cpp:1580
void * m_hStream
Definition: audiostr.cpp:228
void audiostream_play(int i, float volume, int looping)
Definition: audiostr.cpp:1803
#define ASF_FREE
Definition: audiostr.cpp:30
long mmioRead(HMMIO hmmio, HPSTR pch, long cch)
bool m_fCued
Definition: audiostr.cpp:275
int m_data_bytes_left
Definition: audiostr.cpp:216
ov_callbacks mmio_callbacks
Definition: ogg.cpp:18
void audiostream_set_sample_cutoff(int i, uint cutoff)
Definition: audiostr.cpp:1898
DWORD nSamplesPerSec
Definition: config.h:154
int audiostream_open(const char *filename, int type)
Definition: audiostr.cpp:1713
uint m_wave_format
Definition: audiostr.cpp:218
ubyte * Wavedata_service_buffer
Definition: audiostr.cpp:36
int Ds_sound_quality
Definition: ds.cpp:61
bool m_bLooping
Definition: audiostr.cpp:282
uint m_nBufService
Definition: audiostr.cpp:279
#define ASF_USED
Definition: audiostr.cpp:31
void Stop_and_Rewind(void)
Definition: audiostr.cpp:1552
WAVEFORMATEX * m_pwfmt_original
Definition: audiostr.cpp:209
void audiostream_pause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1943
int ACM_convert(void *stream, ubyte *src, int src_len, ubyte *dest, int max_dest_bytes, unsigned int *dest_len, unsigned int *src_bytes_used)
Definition: acm.cpp:635
int Snd_sram
Definition: sound.cpp:52
#define CF_TYPE_ANY
Definition: cfile.h:42
float m_lDefaultVolume
Definition: audiostr.cpp:292
void audiostream_init()
Definition: audiostr.cpp:1611
#define DS_SQ_HIGH
Definition: ds.h:34
int timer_get_milliseconds()
Definition: timer.cpp:150
uint m_fade_timer_id
Definition: audiostr.cpp:289
ALenum GetALFormat()
Definition: audiostr.cpp:207
const char * stristr(const char *str, const char *substr)
Definition: parselo.cpp:3680
int Audiostream_inited
Definition: audiostr.cpp:53
void Set_Default_Volume(float vol)
Definition: audiostr.cpp:253
uint m_nPeriod
Definition: audiostr.cpp:186
GLuint GLuint end
Definition: Gl.h:1502
float m_lVolume
Definition: audiostr.cpp:285
int audiostream_done_reading(int i)
Definition: audiostr.cpp:1925
AudioStream Audio_streams[MAX_AUDIO_STREAMS]
Definition: audiostr.cpp:1608
#define strcpy_s(...)
Definition: safe_strings.h:67
#define WAVE_FORMAT_IEEE_FLOAT
Definition: mmreg.h:1304
#define OGG_FORMAT_VORBIS
Definition: ogg.h:15
HMMIO mmioOpen(LPSTR szFilename, LPMMIOINFO lpmmioinfo, DWORD dwOpenFlags)