FS2_Open
Open source remastering of the Freespace 2 engine
sound.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include "cfile/cfile.h"
13 #include "cmdline/cmdline.h"
14 #include "debugconsole/console.h"
15 #include "gamesnd/eventmusic.h"
16 #include "gamesnd/gamesnd.h"
17 #include "globalincs/alphacolors.h"
18 #include "globalincs/pstypes.h"
19 #include "globalincs/vmallocator.h"
20 #include "osapi/osapi.h"
21 #include "render/3d.h"
22 #include "sound/acm.h"
23 #include "sound/audiostr.h"
24 #include "sound/ds.h"
25 #include "sound/ds3d.h"
26 #include "sound/dscap.h"
27 #include "sound/ogg/ogg.h"
28 #include "sound/sound.h"
29 
30 #ifdef _WIN32
31 #include <windows.h>
32 #endif
33 #include <limits.h>
34 
35 const unsigned int SND_ENHANCED_MAX_LIMIT = 15; // seems like a good max limit
36 
37 #define SND_F_USED (1<<0) // Sounds[] element is used
38 
39 typedef struct sound {
40  int sid; // software id
42  int sig;
43  int flags;
45  int uncompressed_size; // size (in bytes) of sound (uncompressed)
46  int duration;
47 } sound;
48 
50 
51 int Sound_enabled = FALSE; // global flag to turn sound on/off
52 int Snd_sram; // mem (in bytes) used up by storing sounds in system memory
53 float Master_sound_volume = 1.0f; // range is 0 -> 1, used for non-music sound fx
54 float Master_voice_volume = 0.7f; // range is 0 -> 1, used for all voice playback
55 
56 unsigned int SND_ENV_DEFAULT = 0;
57 
62 
63  LoopingSoundInfo(int dsHandle, float defaultVolume, float dynamicVolume):
64  m_dsHandle(dsHandle),
65  m_defaultVolume(defaultVolume),
66  m_dynamicVolume(dynamicVolume)
67  {
68  }
69 
70  LoopingSoundInfo() : m_dsHandle(-1), m_defaultVolume(0.0f), m_dynamicVolume(0.0f)
71  {
72  }
73 };
74 
76 
77 //For the adjust-audio-volume sexp
78 float aav_voice_volume = 1.0f;
79 float aav_music_volume = 1.0f;
80 float aav_effect_volume = 1.0f;
81 
82 struct aav {
83  float start_volume;
84  float delta;
85  float start_time;
87 };
88 
90 
91 // min volume to play a sound after all volume processing (range is 0.0 -> 1.0)
92 #define MIN_SOUND_VOLUME 0.05f
93 
94 static int snd_next_sig = 1;
95 
96 // convert the game level sound priorities to the DirectSound priority descriptions
97 int ds_priority(int priority)
98 {
99  switch(priority){
101  return DS_MUST_PLAY;
103  return DS_LIMIT_ONE;
105  return DS_LIMIT_TWO;
107  return DS_LIMIT_THREE;
108  default:
109  Int3();
110  return DS_MUST_PLAY;
111  };
112 }
113 
114 void snd_clear()
115 {
116  Sounds.clear();
117 
118  // reset how much storage sounds are taking up in memory
119  Snd_sram = 0;
120 }
121 
122 // ---------------------------------------------------------------------------------------
123 // Initialize the game sound system
124 //
125 // Initialize the game sound system. Depending on what sound library is being used,
126 // call the appropriate low-level initiailizations
127 //
128 // returns: 1 => init success
129 // 0 => init failed
130 //
131 int snd_init()
132 {
133  int rval;
134 
136  return 0;
137 
138  if (ds_initialized) {
139  nprintf(( "Sound", "SOUND => Audio is already initialized!\n" ));
140  return 1;
141  }
142 
143  snd_clear();
144 
145  rval = ds_init();
146 
147  if ( rval != 0 ) {
148  nprintf(( "Sound", "SOUND ==> Fatal error initializing audio device, turn sound off.\n" ));
150  goto Failure;
151  }
152 
153  if ( OGG_init() == -1 ) {
154  mprintf(("Could not initialize the OGG vorbis converter.\n"));
155  }
156 
157  snd_aav_init();
158 
159  // Init the audio streaming stuff
161 
162  ds_initialized = 1;
164  return 1;
165 
166 Failure:
167 // Warning(LOCATION, "Sound system was unable to be initialized. If you continue, sound will be disabled.\n");
168  nprintf(( "Sound", "SOUND => Audio init unsuccessful, continuing without sound.\n" ));
169  return 0;
170 }
171 
172 
174 {
175  size_t idx;
176  char txt[512] = "";
177  CFILE *out = cfopen("sounds.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
178  if(out == NULL){
179  return;
180  }
181 
182  cfwrite_string("Sounds loaded :\n", out);
183 
184  // spew info for all sounds
185  for (idx = 0; idx < Sounds.size(); idx++) {
186  if(!(Sounds[idx].flags & SND_F_USED)){
187  continue;
188  }
189 
190  sprintf(txt, "%s (%ds)\n", Sounds[idx].filename, Sounds[idx].info.duration);
191  cfwrite_string(txt, out);
192  }
193 
194  // close the outfile
195  if(out != NULL){
196  cfclose(out);
197  out = NULL;
198  }
199 }
200 
201 int Sound_spew = 0;
202 DCF(show_sounds, "Toggles display of sound debug info")
203 {
204  if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
205  dc_printf("Sound debug info is %s", (Sound_spew ? "ON" : "OFF"));
206  return;
207  }
208 
210  dc_printf("Sound debug info is %s", (Sound_spew ? "ON" : "OFF"));
211 }
213 {
214  int game_sounds = 0;
215  int message_sounds = 0;
216  int interface_sounds = 0;
217  int done = 0;
218 
219  if(!Sound_spew){
220  return;
221  }
222 
223  // count up game, interface and message sounds
224  for (size_t idx = 0; idx < Sounds.size(); idx++) {
225  if(!(Sounds[idx].flags & SND_F_USED)){
226  continue;
227  }
228 
229  done = 0;
230 
231  // what kind of sound is this
232  for(SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs){
233  if(!stricmp(gs->filename, Sounds[idx].filename)){
234  game_sounds++;
235  done = 1;
236  }
237  }
238 
239  if(!done){
240  for(SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs){
241  if(!stricmp(gs->filename, Sounds[idx].filename)){
242  interface_sounds++;
243  done = 1;
244  }
245  }
246  }
247 
248  if(!done){
249  message_sounds++;
250  }
251  }
252 
253  // spew info
254  int line_height = gr_get_font_height() + 1;
255  int sx = gr_screen.center_offset_x + 30;
256  int sy = gr_screen.center_offset_y + 100;
258  gr_printf_no_resize(sx, sy, "Game sounds : %d\n", game_sounds);
259  sy += line_height;
260  gr_printf_no_resize(sx, sy, "Interface sounds : %d\n", interface_sounds);
261  sy += line_height;
262  gr_printf_no_resize(sx, sy, "Message sounds : %d\n", message_sounds);
263  sy += line_height;
264  gr_printf_no_resize(sx, sy, "Total sounds : %d\n", game_sounds + interface_sounds + message_sounds);
265 }
266 
267 // ---------------------------------------------------------------------------------------
268 // snd_load()
269 //
270 // Load a sound into memory and prepare it for playback. The sound will reside in memory as
271 // a single instance, and can be played multiple times simultaneously. Through the magic of
272 // DirectSound, only 1 copy of the sound is used.
273 //
274 // parameters: gs => file of sound to load
275 // allow_hardware_load => whether to try to allocate in hardware
276 //
277 // returns: success => index of sound in Sounds[] array
278 // failure => -1
279 //
280 //int snd_load( char *filename, int hardware, int use_ds3d, int *sig)
281 int snd_load( game_snd *gs, int allow_hardware_load )
282 {
283  int type;
284  sound_info *si;
285  sound *snd;
286  WAVEFORMATEX *header = NULL;
287  int rc, FileSize, FileOffset;
288  char fullpath[MAX_PATH];
290  size_t n;
291 
292 
293  if ( !ds_initialized )
294  return -1;
295 
296  if ( !VALID_FNAME(gs->filename) )
297  return -1;
298 
299  for (n = 0; n < Sounds.size(); n++) {
300  if ( !(Sounds[n].flags & SND_F_USED) ) {
301  break;
302  } else if ( !stricmp( Sounds[n].filename, gs->filename) ) {
303  // extra check: make sure the sound is actually loaded in a compatible way (2D vs. 3D)
304  //
305  // NOTE: this will allow a duplicate 3D entry if 2D stereo entry exists,
306  // but will not load a duplicate 2D entry to get stereo if 3D
307  // version already loaded
308  if ( (Sounds[n].info.n_channels == 1) || !(gs->flags & GAME_SND_USE_DS3D) ) {
309  return (int)n;
310  }
311  }
312  }
313 
314  if ( n == Sounds.size() ) {
315  sound new_sound;
316  new_sound.sid = -1;
317  new_sound.flags = 0;
318 
319  Sounds.push_back( new_sound );
320  }
321 
322  snd = &Sounds[n];
323 
324  si = &snd->info;
325 
326  si->data = NULL;
327  si->size = 0;
328 
329  // strip the extension from the filename and try to open any extension
330  strcpy_s( filename, gs->filename );
331  char *p = strrchr(filename, '.');
332  if ( p ) *p = 0;
333 
334  rc = cf_find_file_location_ext(filename, NUM_AUDIO_EXT, audio_ext_list, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset);
335 
336  if (rc < 0)
337  return -1;
338 
339  // open the file
340  CFILE *fp = cfopen_special(fullpath, "rb", FileSize, FileOffset);
341 
342  // ok, we got it, so set the proper filename for logging purposes
343  strcat_s(filename, audio_ext_list[rc]);
344 
345  nprintf(("Sound", "SOUND => Loading '%s'\n", filename));
346 
347  // ds_parse_sound() will do a NULL check on fp for us
348  if ( ds_parse_sound(fp, &si->data, &si->size, &header, (rc == 0), &si->ogg_info) == -1 ) {
349  nprintf(("Sound", "SOUND ==> Could not read sound file!\n"));
350 
351  if (fp != NULL) {
352  cfclose(fp);
353  }
354 
355  return -1;
356  }
357 
358  // Load was a success, should be some sort of WAV or an OGG
359  si->format = header->wFormatTag; // 16-bit flag (wFormatTag)
360  si->n_channels = header->nChannels; // 16-bit channel count (nChannels)
361  si->sample_rate = header->nSamplesPerSec; // 32-bit sample rate (nSamplesPerSec)
362  si->avg_bytes_per_sec = header->nAvgBytesPerSec; // 32-bit average bytes per second (nAvgBytesPerSec)
363  si->n_block_align = header->nBlockAlign; // 16-bit block alignment (nBlockAlign)
364  si->bits = header->wBitsPerSample; // Read 16-bit bits per sample
365 
366  type = 0;
367 
368  if (gs->flags & GAME_SND_USE_DS3D) {
369  type |= DS_3D;
370  }
371 
372  rc = ds_load_buffer(&snd->sid, &snd->uncompressed_size, header, si, type);
373 
374  // NOTE: "si" values can change once loaded in the buffer
375  snd->duration = fl2i(1000.0f * ((si->size / (si->bits/8.0f)) / si->sample_rate / si->n_channels));
376 
377  // free the header if needed
378  if (header != NULL)
379  vm_free(header);
380 
381  // we don't need to keep si->data around anymore, this should be NULL for OGG files
382  if (si->data != NULL) {
383  vm_free(si->data);
384  si->data = NULL;
385  }
386 
387  // make sure the file handle is closed
388  if (fp != NULL)
389  cfclose(fp);
390 
391  if ( rc == -1 ) {
392  nprintf(("Sound", "SOUND ==> Failed to load '%s'\n", filename));
393  return -1;
394  }
395 
396  strncpy( snd->filename, gs->filename, MAX_FILENAME_LEN );
397  snd->flags = SND_F_USED;
398 
399  snd->sig = snd_next_sig++;
400  if (snd_next_sig < 0 ) snd_next_sig = 1;
401  gs->id_sig = snd->sig;
402  gs->id = (int)n;
403 
404 // nprintf(("Sound", "SOUND ==> Finished loading '%s'\n", filename));
405 
406  return (int)n;
407 }
408 
409 // ---------------------------------------------------------------------------------------
410 // snd_unload()
411 //
412 // Unload a sound from memory. This will release the storage, and the sound must be re-loaded via
413 // sound_load() before it can be played again.
414 //
415 int snd_unload( int n )
416 {
417  if (!ds_initialized)
418  return 0;
419 
420  if ( (n < 0) || ((size_t)n >= Sounds.size()) ) {
421  return 0;
422  }
423 
424  ds_unload_buffer(Sounds[n].sid);
425 
426  if (Sounds[n].sid != -1) {
427  Snd_sram -= Sounds[n].uncompressed_size;
428  }
429 
430  //If this sound is at the end of the array, we might as well get rid of it
431  if ( (size_t)n == Sounds.size()-1 ) {
432  Sounds.pop_back();
433  } else {
434  Sounds[n].sid = -1;
435  Sounds[n].flags &= ~SND_F_USED;
436  }
437 
438  return 1;
439 }
440 
441 // ---------------------------------------------------------------------------------------
442 // snd_unload_all()
443 //
444 // Unload all sounds from memory. If there's a problem unloading a file the array may not be fully cleared
445 // but future files will still use unused spots, so the array size shouldn't grow out of control.
446 //
448 {
449  while ( !Sounds.empty() ) {
450  snd_unload( Sounds.size()-1 );
451  }
452 }
453 
454 // ---------------------------------------------------------------------------------------
455 // snd_close()
456 //
457 // This is the companion function to snd_init()... it closes down the game sound system.
458 //
459 void snd_close(void)
460 {
461  snd_stop_all();
462  if (!ds_initialized) return;
463  snd_unload_all(); // free the sound data stored in DirectSound secondary buffers
464  dscap_close(); // Close DirectSoundCapture
465  ds_close(); // Close DirectSound off
466 }
467 
468 // ---------------------------------------------------------------------------------------
469 // snd_play_raw()
470 //
471 // Allow a sound to be played directly from the index in Sounds[]. This bypasses the
472 // normal game sound management system.
473 //
474 // returns: -1 => sound could not be played
475 // n => handle for instance of sound
476 //
477 int snd_play_raw( int soundnum, float pan, float vol_scale, int priority )
478 {
479  game_snd gs;
480  int rval;
481 
482  if ( (soundnum < 0) || ((size_t)soundnum >= Sounds.size() ) ) {
483  return -1;
484  }
485 
486  gs.id = soundnum;
487  gs.id_sig = Sounds[soundnum].sig;
488  gs.filename[0] = 0;
489  gs.default_volume = 1.0f;
490 // gs.flags = GAME_SND_VOICE | GAME_SND_USE_DS3D;
491  gs.flags = GAME_SND_VOICE;
492 
493  rval = snd_play(&gs, pan, vol_scale, priority, true);
494  return rval;
495 }
496 
497 MONITOR( NumSoundsStarted )
498 MONITOR( NumSoundsLoaded )
499 
500 // ---------------------------------------------------------------------------------------
501 // snd_play()
502 //
503 // NOTE: vol_scale parameter is the multiplicative scaling applied to the default volume
504 // (vol_scale is a default parameter with a default value of 1.0f)
505 //
506 // input: gs => game-level sound description
507 // pan => -1 (full left) to 1.0 (full right), this is a default parm
508 // vol_scale => factor to scale default volume by (applied before global sound volume applied)
509 // priority => SND_PRIORITY_MUST_PLAY
510 // SND_PRIORITY_SINGLE_INSTANCE (default value)
511 // SND_PRIORITY_DOUBLE_INSTANCE
512 // SND_PRIORITY_TRIPLE_INSTANCE
513 //
514 // returns: -1 => sound could not be played
515 // n => handle for instance of sound
516 //
517 int snd_play( game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg )
518 {
519  float volume;
520  sound *snd;
521 
522  int handle = -1;
523 
524  if (!Sound_enabled)
525  return -1;
526 
527  if (gs == NULL) {
528  Int3();
529  return -1;
530  }
531 
532  MONITOR_INC( NumSoundsStarted, 1 );
533 
534  if ( gs->id == -1 ) {
535  gs->id = snd_load(gs);
536  MONITOR_INC( NumSoundsLoaded, 1);
537  } else if ( gs->id_sig != Sounds[gs->id].sig ) {
538  gs->id = snd_load(gs);
539  }
540 
541  if ( gs->id == -1 )
542  return -1;
543 
544  volume = gs->default_volume * vol_scale;
545  if ( gs->flags&GAME_SND_VOICE ) {
547  } else {
549  }
550  if ( volume > 1.0f )
551  volume = 1.0f;
552 
553  snd = &Sounds[gs->id];
554 
555  if ( !(snd->flags & SND_F_USED) )
556  return -1;
557 
558  if (!ds_initialized)
559  return -1;
560 
561  if ( volume > MIN_SOUND_VOLUME ) {
562  handle = ds_play( snd->sid, gs->id_sig, ds_priority(priority), &gs->enhanced_sound_data, volume, pan, 0, is_voice_msg);
563  }
564 
565  return handle;
566 }
567 
568 MONITOR( Num3DSoundsStarted )
569 MONITOR( Num3DSoundsLoaded )
570 
571 // ---------------------------------------------------------------------------------------
572 // snd_play_3d()
573 //
574 // NOTE: vol_scale parameter is the multiplicative scaling applied to the default volume
575 // (vol_scale is a default parameter with a default value of 1.0f)
576 //
577 // input: gs => game-level sound description
578 // source_pos => global pos of where the sound is
579 // listen_pos => global pos of where listener is
580 // radius => optional parameter, this specifes distance at which to apply min/max distances
581 // source_vel => velocity of the source playing the sound (used for DirectSound3D only)
582 // looping => flag to indicate the sound should loop (default value 0)
583 // vol_scale => factor to scale the static volume by (applied before attenuation)
584 // priority => SND_PRIORITY_MUST_PLAY
585 // SND_PRIORITY_SINGLE_INSTANCE (default value)
586 // SND_PRIORITY_DOUBLE_INSTANCE
587 // SND_PRIORITY_TRIPLE_INSTANCE
588 // sound_fvec => forward vector of where sound is emitting from (RSX use only)
589 // range_factor => factor N, which increases distance sound is heard by N times (default value 1)
590 //
591 // returns: -1 => sound could not be played
592 // n => handle for instance of sound
593 //
594 int snd_play_3d(game_snd *gs, vec3d *source_pos, vec3d *listen_pos, float radius, vec3d *source_vel, int looping, float vol_scale, int priority, vec3d *sound_fvec, float range_factor, int force, bool is_ambient )
595 {
596  int handle;
597  vec3d vector_to_sound;
598  sound *snd;
599  float volume, distance, max_volume;
600  float min_range, max_range;
601  float pan;
602 
603  if ( !Sound_enabled )
604  return -1;
605 
606  if (gs == NULL) {
607  Int3();
608  return -1;
609  }
610 
611  MONITOR_INC( Num3DSoundsStarted, 1 );
612 
613  if ( gs->id < 0 ) {
614  gs->id = snd_load(gs);
615  MONITOR_INC( Num3DSoundsLoaded, 1 );
616  }else if ( gs->id_sig != Sounds[gs->id].sig ) {
617  gs->id = snd_load(gs);
618  }
619 
620  if ( gs->id == -1 )
621  return -1;
622 
623  snd = &Sounds[gs->id];
624 
625  if ( !(snd->flags & SND_F_USED) )
626  return -1;
627 
628  if (snd->sid < 0) {
629  return -1;
630  }
631 
632  handle = -1;
633 
634  min_range = (gs->min + radius) * range_factor;
635  max_range = (gs->max + radius) * range_factor;
636 
637  if (!ds_initialized)
638  return -1;
639 
640  // DirectSound3D will not cut off sounds, no matter how quite they become.. so manually
641  // prevent sounds from playing past the max distance.
642  //IMPORTANT THIS IS NOT WORKING RIGHT OMG WTF
643  distance = vm_vec_normalized_dir_quick( &vector_to_sound, source_pos, listen_pos );
644 
645  if ( (distance > max_range) && !force){
646  return -1;
647  }
648 
649  max_volume = gs->default_volume * vol_scale;
650 
651  if ( distance <= min_range ) {
652  volume = max_volume;
653  }
654  else {
655  volume = max_volume - max_volume*(distance/max_range);
656  }
657 
658  if ( volume > 1.0f ){
659  volume = 1.0f;
660  }
661 
662  if ( priority == SND_PRIORITY_MUST_PLAY ) {
663  if ( volume < 0.3 ) {
664  priority = SND_PRIORITY_DOUBLE_INSTANCE;
665  }
666  }
667 
669  if ( (volume < MIN_SOUND_VOLUME) && !force) {
670  return -1;
671  }
672 
673  // any stereo sounds will not play in proper 3D, but they should have
674  // been converted to mono already!
675  Assertion( snd->info.n_channels == 1, "Sound should be mono! Sound file: %s", snd->filename );
676 
677  if (Cmdline_no_3d_sound) {
678  if (distance <= 0.0f) {
679  pan = 0.0f;
680  } else {
681  pan = vm_vec_dot(&View_matrix.vec.rvec, &vector_to_sound);
682  }
683 
684  handle = ds_play(snd->sid, gs->id_sig, ds_priority(priority), &gs->enhanced_sound_data, volume / gs->default_volume, pan, looping);
685  } else {
686  handle = ds3d_play(snd->sid, gs->id_sig, source_pos, source_vel, min_range, max_range, looping, (max_volume*Master_sound_volume*aav_effect_volume), volume, &gs->enhanced_sound_data, ds_priority(priority));
687  }
688 
689  return handle;
690 }
691 
692 // update the given 3d sound with a new position
693 void snd_update_3d_pos(int soundnum, game_snd *gs, vec3d *new_pos, float radius, float range_factor)
694 {
695  if (Cmdline_no_3d_sound) {
696  float vol, pan;
697 
698  // get new volume and pan vals
699  snd_get_3d_vol_and_pan(gs, new_pos, &vol, &pan, radius, range_factor);
700 
701  // set volume
702  snd_set_volume(soundnum, vol);
703 
704  // set pan
705  snd_set_pan(soundnum, pan);
706  } else {
707  // MageKing17 - It's a 3D sound effect, we should use the function for setting the position of a 3D sound effect.
708  sound *snd;
709  int channel;
710 
711  if (!ds_initialized)
712  return;
713 
714  Assertion( gs != NULL, "*gs was NULL in snd_update_3d_pos(); get a coder!\n" );
715 
716  if ( gs->id == -1 ) {
717  gs->id = snd_load(gs);
718  }
719 
720  if (gs->id == -1)
721  return;
722 
723  snd = &Sounds[gs->id];
724  if ( !(snd->flags & SND_F_USED) )
725  return;
726 
727  channel = ds_get_channel(soundnum);
728  if (channel == -1) {
729  nprintf(( "Sound", "WARNING: Trying to set position for a non-playing sound.\n" ));
730  return;
731  }
732 
733  float min_range = (float) (fl2i( (gs->min) * range_factor));
734  float max_range = (float) (fl2i( (gs->max) * range_factor + 0.5f));
735 
736  ds3d_update_buffer(channel, min_range, max_range, new_pos, NULL);
737  }
738 }
739 
740 // ---------------------------------------------------------------------------------------
741 // snd_get_3d_vol_and_pan()
742 //
743 // Based on the 3D position the player and the object, calculate
744 // the correct volume and pan.
745 //
746 // parameters: gs => pointer to sound description
747 // pos => 3D position used to calc volume and pan
748 // vol => output parameter for the volume
749 // pan => output parameter for the pan
750 // radius => optional parameter (default value 0) which indicates sound attenuation
751 // should occur from this radius
752 //
753 // returns: -1 => could not determine vol or pan
754 // 0 => success
755 //
756 // NOTE: the volume is not scaled by the Master_sound_volume, since this always occurs
757 // when snd_play() or snd_play_looping() is called
758 //
759 int snd_get_3d_vol_and_pan(game_snd *gs, vec3d *pos, float* vol, float *pan, float radius, float range_factor)
760 {
761  vec3d vector_to_sound;
762  float distance, max_volume;
763  sound *snd;
764 
765  *vol = 0.0f;
766  *pan = 0.0f;
767 
768  if (!ds_initialized)
769  return -1;
770 
771  Assertion( gs != NULL, "*gs was NULL in snd_get_3d_vol_and_pan(); get a coder!\n" );
772 
773  if ( gs->id == -1 ) {
774  gs->id = snd_load(gs);
775  }
776 
777  if (gs->id == -1)
778  return -1;
779 
780  snd = &Sounds[gs->id];
781  if ( !(snd->flags & SND_F_USED) )
782  return -1;
783 
784  float min_range = (float) (fl2i( (gs->min) * range_factor));
785  float max_range = (float) (fl2i( (gs->max) * range_factor + 0.5f));
786 
787  distance = vm_vec_normalized_dir_quick( &vector_to_sound, pos, &View_position );
788  distance -= radius;
789 
790  max_volume = gs->default_volume;
791  if ( distance <= min_range ) {
792  *vol = max_volume;
793  }
794  else {
795  *vol = max_volume - (distance - min_range) * max_volume / (max_range - min_range);
796  }
797 
798  if ( *vol > 1.0f )
799  *vol = 1.0f;
800 
801  if ( *vol > MIN_SOUND_VOLUME ) {
802  if ( distance <= 0 )
803  *pan = 0.0f;
804  else
805  *pan = vm_vec_dot(&View_matrix.vec.rvec,&vector_to_sound);
806  }
807 
808  return 0;
809 }
810 
822 int snd_play_looping( game_snd *gs, float pan, int start_loop, int stop_loop, float vol_scale, int scriptingUpdateVolume)
823 {
824  float volume;
825  int handle = -1;
826  sound *snd;
827 
828  if (!Sound_enabled)
829  return -1;
830 
831  if (!ds_initialized)
832  return -1;
833 
834  if (gs == NULL) {
835  Int3();
836  return -1;
837  }
838 
839  if ( gs->id == -1 ) {
840  gs->id = snd_load(gs);
841  }
842  else if ( gs->id_sig != Sounds[gs->id].sig ) {
843  gs->id = snd_load(gs);
844  }
845 
846  if ( gs->id == -1 )
847  return -1;
848 
849  snd = &Sounds[gs->id];
850 
851  if ( !(snd->flags & SND_F_USED) )
852  return -1;
853 
854  volume = gs->default_volume * vol_scale;
856  if ( volume > 1.0f )
857  volume = 1.0f;
858 
859  if (volume > MIN_SOUND_VOLUME) {
860  handle = ds_play( snd->sid, gs->id_sig, DS_MUST_PLAY, &gs->enhanced_sound_data, volume, pan, 1);
861 
862  if(handle != -1 && scriptingUpdateVolume) {
863  currentlyLoopingSoundInfos.push_back(LoopingSoundInfo(handle, gs->default_volume, vol_scale));
864  }
865  }
866 
867  return handle;
868 }
869 
875 void snd_stop( int sig )
876 {
877  int channel;
878 
879  if (!ds_initialized) return;
880  if ( sig < 0 ) return;
881 
882  channel = ds_get_channel(sig);
883  if ( channel == -1 )
884  return;
885 
886  SCP_list<LoopingSoundInfo>::iterator iter = currentlyLoopingSoundInfos.begin();
887  while (iter != currentlyLoopingSoundInfos.end())
888  {
889  if(iter->m_dsHandle == sig) {
890  iter = currentlyLoopingSoundInfos.erase(iter);
891  } else {
892  ++iter;
893  }
894  }
895 
896  ds_stop_channel(channel);
897 }
898 
906 {
907  if (!ds_initialized)
908  return;
909 
910  currentlyLoopingSoundInfos.clear();
912 }
913 
920 void snd_set_volume( int sig, float volume )
921 {
922  int channel;
923  float new_volume;
924 
925  if (!ds_initialized)
926  return;
927 
928  if ( sig < 0 )
929  return;
930 
931  channel = ds_get_channel(sig);
932  if ( channel == -1 ) {
933  nprintf(( "Sound", "WARNING: Trying to set volume for a non-playing sound.\n" ));
934  return;
935  }
936 
937  bool isLoopingSound = false;
938 
940  for (iter = currentlyLoopingSoundInfos.begin(); iter != currentlyLoopingSoundInfos.end(); ++iter) {
941  if(iter->m_dsHandle == sig) {
942  iter->m_dynamicVolume = volume;
943 
944  isLoopingSound = true;
945  break;
946  }
947  }
948 
949  //looping sound volumes are updated in snd_do_frame
950  if(!isLoopingSound) {
951  new_volume = volume * (Master_sound_volume * aav_effect_volume);
952  ds_set_volume( channel, new_volume );
953  }
954 }
955 
956 // ---------------------------------------------------------------------------------------
957 // snd_set_pan()
958 //
959 // Set the pan of a currently playing sound
960 //
961 // parameters: sig => handle to sound, what is returned from snd_play()
962 // pan => pan of sound (range: -1.0 -> 1.0)
963 //
964 void snd_set_pan( int sig, float pan )
965 {
966  int channel;
967 
968  if (!ds_initialized)
969  return;
970 
971  if ( sig < 0 )
972  return;
973 
974  channel = ds_get_channel(sig);
975  if ( channel == -1 ) {
976  nprintf(( "Sound", "WARNING: Trying to set pan for a non-playing sound.\n" ));
977  return;
978  }
979 
980  ds_set_pan( channel, pan );
981 }
982 
983 // ---------------------------------------------------------------------------------------
984 // snd_get_pitch()
985 //
986 // Return the pitch of a currently playing sound
987 //
988 // returns: pitch of sound ( range: 100 to 100000)
989 //
990 // parameters: sig => handle to sound, what is returned from snd_play()
991 //
992 int snd_get_pitch(int sig)
993 {
994  int channel, pitch=10000;
995 
996  if (!ds_initialized)
997  return -1;
998 
999  if ( sig < 0 )
1000  return -1;
1001 
1002  channel = ds_get_channel(sig);
1003  if ( channel == -1 ) {
1004  nprintf(( "Sound", "WARNING: Trying to get pitch for a non-playing sound.\n" ));
1005  return -1;
1006  }
1007 
1008  pitch = ds_get_pitch(channel);
1009 
1010  return pitch;
1011 }
1012 
1013 // ---------------------------------------------------------------------------------------
1014 // snd_set_pitch()
1015 //
1016 // Set the pitch of a currently playing sound
1017 //
1018 // parameters: sig => handle to sound, what is returned from snd_play()
1019 // pan => pitch of sound (range: 100 to 100000)
1020 //
1021 void snd_set_pitch( int sig, int pitch )
1022 {
1023  int channel;
1024 
1025  if (!ds_initialized) return;
1026  if ( sig < 0 ) return;
1027 
1028  channel = ds_get_channel(sig);
1029  if ( channel == -1 ) {
1030  nprintf(( "Sound", "WARNING: Trying to set pitch for a non-playing sound.\n" ));
1031  return;
1032  }
1033 
1034  ds_set_pitch(channel, pitch);
1035 }
1036 
1037 // ---------------------------------------------------------------------------------------
1038 // snd_is_playing()
1039 //
1040 // Determine if a sound is playing
1041 //
1042 // returns: 1 => sound is currently playing
1043 // 0 => sound is not playing
1044 //
1045 // parameters: sig => signature of sound, what is returned from snd_play()
1046 //
1047 int snd_is_playing( int sig )
1048 {
1049  int channel, is_playing;
1050 
1051  if (!ds_initialized)
1052  return 0;
1053 
1054  if ( sig < 0 )
1055  return 0;
1056 
1057  channel = ds_get_channel(sig);
1058  if ( channel == -1 )
1059  return 0;
1060 
1061  is_playing = ds_is_channel_playing(channel);
1062  if ( is_playing == TRUE ) {
1063  return 1;
1064  }
1065 
1066  return 0;
1067 }
1068 
1069 // ---------------------------------------------------------------------------------------
1070 // snd_is_inited()
1071 //
1072 //
1074 {
1075  if ( !ds_initialized )
1076  return FALSE;
1077 
1078  return TRUE;
1079 }
1080 
1081 // return the time in ms for the duration of the sound
1082 int snd_get_duration(int snd_id)
1083 {
1084  if ( snd_id < 0 )
1085  return 0;
1086 
1087  Assertion( !Sounds.empty(), "Sounds vector is empty. Why are we trying to look up an index?\n" );
1088 
1089  if ( Sounds.empty() )
1090  return 0;
1091 
1092  Assertion(Sounds[snd_id].duration > 0, "Sound duration for sound %s is bogus (%d)\n", Sounds[snd_id].filename, Sounds[snd_id].duration);
1093 
1094  if (Sounds[snd_id].duration > 0)
1095  return Sounds[snd_id].duration;
1096  else
1097  return 0;
1098 }
1099 
1100 // return the time in ms for the duration of the sound
1101 const char *snd_get_filename(int snd_id)
1102 {
1103  Assertion(snd_id >= 0 && snd_id < (int) Sounds.size(), "Invalid sound id %d!", snd_id);
1104 
1105  return Sounds[snd_id].filename;
1106 }
1107 
1108 
1109 MONITOR( SoundChannels )
1110 
1111 // update the position of the listener for the specific 3D sound API we're
1112 // using
1114 {
1115  MONITOR_INC( SoundChannels, ds_get_number_channels() );
1116  ds3d_update_listener(pos, vel, orient);
1117 }
1118 
1119 // this could probably be optimized a bit
1120 void snd_rewind(int snd_handle, game_snd *gs, float seconds)
1121 {
1122  float current_time,desired_time;
1123  float bps;
1124  DWORD current_offset,desired_offset;
1125  sound_info *snd;
1126 
1127  if(!snd_is_playing(snd_handle))
1128  return;
1129 
1130  if (gs->id < 0)
1131  return;
1132 
1133  snd = &Sounds[gs->id].info;
1134 
1135  current_offset = ds_get_play_position(ds_get_channel(snd_handle)); // current offset into the sound
1136  bps = (float)snd->sample_rate * (float)snd->bits; // data rate
1137  current_time = (float)current_offset/bps; // how many seconds we're into the sound
1138 
1139  // don't rewind if it'll put us before the beginning of the sound
1140  if(current_time - seconds < 0.0f)
1141  return;
1142 
1143  desired_time = current_time - seconds; // where we want to be
1144  desired_offset = (DWORD)(desired_time * bps); // the target
1145 
1146  ds_set_position(ds_get_channel(snd_handle),desired_offset);
1147 }
1148 
1149 // this could probably be optimized a bit
1150 void snd_ffwd(int snd_handle, game_snd *gs, float seconds)
1151 {
1152  float current_time,desired_time;
1153  float bps;
1154  DWORD current_offset,desired_offset;
1155  sound_info *snd;
1156 
1157  if(!snd_is_playing(snd_handle))
1158  return;
1159 
1160  if (gs->id < 0)
1161  return;
1162 
1163  snd = &Sounds[gs->id].info;
1164 
1165  current_offset = ds_get_play_position(ds_get_channel(snd_handle)); // current offset into the sound
1166  bps = (float)snd->sample_rate * (float)snd->bits; // data rate
1167  current_time = (float)current_offset/bps; // how many seconds we're into the sound
1168 
1169  // don't rewind if it'll put us past the end of the sound
1170  if(current_time + seconds > (float)snd->duration)
1171  return;
1172 
1173  desired_time = current_time + seconds; // where we want to be
1174  desired_offset = (DWORD)(desired_time * bps); // the target
1175 
1176  ds_set_position(ds_get_channel(snd_handle),desired_offset);
1177 }
1178 
1179 // this could probably be optimized a bit
1180 void snd_set_pos(int snd_handle, game_snd *gs, float val,int as_pct)
1181 {
1182  sound_info *snd;
1183 
1184  if(!snd_is_playing(snd_handle))
1185  return;
1186 
1187  if (gs->id < 0)
1188  return;
1189 
1190  snd = &Sounds[gs->id].info;
1191 
1192  // set position as an absolute from 0 to 1
1193  if(as_pct){
1194  Assert((val >= 0.0) && (val <= 1.0));
1195  ds_set_position(ds_get_channel(snd_handle),(DWORD)((float)snd->size * val));
1196  }
1197  // set the position as an absolute # of seconds from the beginning of the sound
1198  else {
1199  float bps;
1200  Assert(val <= (float)snd->duration/1000.0f);
1201  bps = (float)snd->sample_rate * (float)snd->bits; // data rate
1202  ds_set_position(ds_get_channel(snd_handle),(DWORD)(bps * val));
1203  }
1204 }
1205 
1206 // Return the number of sounds currently playing
1208 {
1209  return ds_get_number_channels();
1210 }
1211 
1212 // Stop the first channel found that is playing a sound
1214 {
1215  int i;
1216 
1217  for ( i = 0; i < 16; i++ ) {
1218  if ( ds_is_channel_playing(i) ) {
1219  ds_stop_channel(i);
1220  break;
1221  }
1222  }
1223 }
1224 
1225 // Return the raw sound data for a loaded sound
1226 //
1227 // input: handle => index into Sounds[] array
1228 // data => allocated mem to hold sound
1229 //
1230 // exit: 0 => success
1231 // !0 => fail
1232 int snd_get_data(int handle, char *data)
1233 {
1234  Assert( (handle >= 0) && ((size_t)handle < Sounds.size()) );
1235 
1236  if ( ds_get_data(Sounds[handle].sid, data) ) {
1237  return -1;
1238  }
1239 
1240  return 0;
1241 }
1242 
1243 // return the size of the sound data associated with the sound handle
1244 int snd_size(int handle, int *size)
1245 {
1246  Assert( (handle >= 0) && ((size_t)handle < Sounds.size()) );
1247 
1248  if ( ds_get_size(Sounds[handle].sid, size) ) {
1249  return -1;
1250  }
1251 
1252  return 0;
1253 }
1254 
1255 // retrieve the bits per sample and frequency for a given sound
1256 void snd_get_format(int handle, int *bits_per_sample, int *frequency)
1257 {
1258  Assert( (handle >= 0) && ((size_t)handle < Sounds.size()) );
1259 
1260  if (bits_per_sample)
1261  *bits_per_sample = Sounds[handle].info.bits;
1262 
1263  if (frequency)
1264  *frequency = Sounds[handle].info.sample_rate;
1265 }
1266 
1267 // given a sound sig (handle) return the index in Sounds[] for that sound
1268 int snd_get_index(int sig)
1269 {
1270  int channel, channel_id;
1271  size_t i;
1272 
1273  channel = ds_get_channel(sig);
1274 
1275  if (channel < 0) {
1276  return -1;
1277  }
1278 
1279  channel_id = ds_get_sound_id(channel);
1280 
1281  for (i = 0; i < Sounds.size(); i++) {
1282  if ( (Sounds[i].flags & SND_F_USED) && (Sounds[i].sig == channel_id) ) {
1283  return (int)i;
1284  }
1285  }
1286 
1287  return -1;
1288 }
1289 
1290 // return the time for the sound to play in milliseconds
1291 int snd_time_remaining(int handle)
1292 {
1293  int channel, is_playing, time_remaining = 0;
1294 
1295  if (!ds_initialized)
1296  return 0;
1297 
1298  if ( handle < 0 )
1299  return 0;
1300 
1301  channel = ds_get_channel(handle);
1302  if ( channel == -1 )
1303  return 0;
1304 
1305  is_playing = ds_is_channel_playing(channel);
1306  if ( !is_playing ) {
1307  return 0;
1308  }
1309 
1310  int current_offset, max_offset, sdx;
1311  int bits_per_sample = 0, frequency = 0;
1312 
1313  sdx = snd_get_index(handle);
1314 
1315  if (sdx < 0) {
1316  Int3();
1317  return 0;
1318  }
1319 
1320  snd_get_format(sdx, &bits_per_sample, &frequency);
1321 
1322  if ( (bits_per_sample <= 0) || (frequency <= 0) )
1323  return 0;
1324 
1325  // handle ADPCM properly. It's always 16bit for OpenAL but should be 8 or 16
1326  // for Windows. We can't leave it as 4 here (the ADPCM rate) because that is the
1327  // compressed bps and the math is against the uncompressed bps.
1328  if ( bits_per_sample == 4 ) {
1329  bits_per_sample = 16;
1330  }
1331 
1332  Assert( bits_per_sample >= 8 );
1333 
1334  current_offset = ds_get_play_position(channel);
1335  max_offset = ds_get_channel_size(channel);
1336 
1337  if ( current_offset < max_offset ) {
1338  int bytes_remaining = max_offset - current_offset;
1339  int samples_remaining = bytes_remaining / (bits_per_sample/8);
1340  time_remaining = fl2i(1000.0f * samples_remaining/frequency + 0.5f);
1341  }
1342 
1343 // mprintf(("time_remaining: %d\n", time_remaining));
1344  return time_remaining;
1345 }
1346 
1347 
1348 // snd_env_ interface
1349 
1350 static int Sound_env_id;
1351 static float Sound_env_volume;
1352 static float Sound_env_damping;
1353 static float Sound_env_decay;
1354 
1355 // Set the sound environment
1356 //
1358 {
1359  if (ds_eax_set_all(se->id, se->volume, se->damping, se->decay) == 0) {
1360  Sound_env_id = se->id;
1361  Sound_env_volume = se->volume;
1362  Sound_env_damping = se->damping;
1363  Sound_env_decay = se->decay;
1364  return 0;
1365  } else {
1366  return -1;
1367  }
1368 }
1369 
1370 // Get the sound environment
1371 //
1372 int sound_env_get(sound_env *se, int preset)
1373 {
1375 
1376  if (ds_eax_get_all(&er, preset) == 0) {
1377  se->id = (int)er.environment;
1378  se->volume = er.fVolume;
1379  se->decay = er.fDecayTime_sec;
1380  se->damping = er.fDamping;
1381  return 0;
1382  } else {
1383  return -1;
1384  }
1385 }
1386 
1387 // Turn off the sound environment
1388 //
1390 {
1391  sound_env se;
1393  se.volume = 0.0f;
1394  se.damping = 0.0f;
1395  se.decay = 0.0f;
1396  sound_env_set(&se);
1397  return 0;
1398 }
1399 
1400 // Return 1 if EAX can used to set the sound environment, otherwise return 0
1401 //
1403 {
1404  return ds_eax_is_inited();
1405 }
1406 
1407 // Called once per game frame
1408 //
1409 
1410 void adjust_volume_on_frame(float* volume_now, aav* data);
1412 {
1416 
1418  for (iter = currentlyLoopingSoundInfos.begin(); iter != currentlyLoopingSoundInfos.end(); ++iter) {
1419 
1420  float new_volume = iter->m_defaultVolume * iter->m_dynamicVolume * (Master_sound_volume * aav_effect_volume);
1421  ds_set_volume(ds_get_channel(iter->m_dsHandle), new_volume);
1422  }
1423 
1424  ds_do_frame();
1425 }
1426 
1427 // return the number of samples per pre-defined measure in a piece of audio
1428 int snd_get_samples_per_measure(char *filename, float num_measures)
1429 {
1430  sound_info si;
1431  uint total_bytes = 0;
1432  int bytes_per_measure = 0;
1433 
1434  // although this function doesn't require sound to work, if sound is disabled then this is useless
1435  if ( !Sound_enabled )
1436  return -1;
1437 
1438  if ( !VALID_FNAME(filename) )
1439  return -1;
1440 
1441  if (num_measures <= 0.0f)
1442  return -1;
1443 
1444 
1445  if ( ds_parse_sound_info(filename, &si) ) {
1446  nprintf(("Sound", "Could not read sould file '%s' for SPM check!\n", filename));
1447  return -1;
1448  }
1449 
1450  total_bytes = (uint)si.size;
1451 
1452  // if it's ADPCM then we have to account for the uncompressed size
1453  if (si.format == WAVE_FORMAT_ADPCM) {
1454  total_bytes *= 16; // we always decode APDCM to 16-bit (for OpenAL at least)
1455  total_bytes /= si.bits;
1456  total_bytes *= 2; // this part isn't at all accurate though
1457  }
1458 
1459  bytes_per_measure = fl2i(total_bytes / num_measures);
1460 
1461  // ok, now return the samples per measure (which is half of bytes_per_measure)
1462  return (bytes_per_measure / 2);
1463 }
1464 
1465 void snd_adjust_audio_volume(int type, float percent, int time)
1466 {
1467  Assert( type >= 0 && type < 3 );
1468 
1469  if ( type >= 0 && type < 3 ) {
1470  switch (type) {
1471  case AAV_MUSIC:
1472  aav_data[type].start_volume = aav_music_volume;
1473  if (percent < aav_music_volume)
1474  aav_data[type].delta = (aav_music_volume - percent) * -1.0f;
1475  else
1476  aav_data[type].delta = percent - aav_music_volume;
1477  break;
1478  case AAV_VOICE:
1479  aav_data[type].start_volume = aav_voice_volume;
1480  if (percent < aav_voice_volume)
1481  aav_data[type].delta = (aav_voice_volume - percent) * -1.0f;
1482  else
1483  aav_data[type].delta = percent - aav_voice_volume;
1484  break;
1485  case AAV_EFFECTS:
1486  aav_data[type].start_volume = aav_effect_volume;
1487  if (percent < aav_effect_volume)
1488  aav_data[type].delta = (aav_effect_volume - percent) * -1.0f;
1489  else
1490  aav_data[type].delta = percent - aav_effect_volume;
1491  break;
1492  default:
1493  Int3();
1494  }
1495 
1496  aav_data[type].delta_time = time;
1497  aav_data[type].start_time = (f2fl(Missiontime) * 1000);
1498  }
1499 }
1500 
1501 void adjust_volume_on_frame(float* volume_now, aav* data)
1502 {
1503  if (Missiontime == 0){
1504  return;
1505  }
1506 
1507  if (*volume_now == (data->start_volume + data->delta))
1508  return;
1509 
1510  float msMissiontime = (f2fl(Missiontime) * 1000);
1511 
1512  if ( msMissiontime > ( data->start_time + data->delta_time) ) {
1513  *volume_now = data->start_volume + data->delta;
1514  return;
1515  }
1516 
1517  float done = 0.0f;
1518  //How much change do we need?
1519  if (data->delta_time == 0)
1520  done = 1.0f;
1521  else
1522  done =(float) (msMissiontime - data->start_time)/data->delta_time;
1523 
1524  //apply change
1525  *volume_now = data->start_volume + (data->delta * done);
1526  CLAMP(*volume_now, 0.0f, 1.0f);
1527 
1528  // if setting music volume, trigger volume change in playing tracks
1529  // done here in order to avoid setting music volume in every frame regardless if it changed or not
1530  if (&aav_music_volume == volume_now) {
1532  }
1533 }
1534 
1536 {
1537  aav_music_volume = 1.0f;
1538  aav_voice_volume = 1.0f;
1539  aav_effect_volume = 1.0f;
1540 
1541  for (int i = 0; i < 3; i++) {
1542  aav_data[i].delta = 0.0f;
1543  aav_data[i].start_volume = 1.0f;
1544  aav_data[i].delta_time = 0;
1545  aav_data[i].start_time = 0.0f;
1546  }
1547 }
1548 
1550 
1552  : name ( "" ), signature( nextSignature++ ), default_volume( 0 ), preload( false ), id( -1 ), id_sig( -1 ), flags( 0 )
1553 {
1554  filename[0] = 0;
1555  min = 0;
1556  max = 0;
1557 }
void snd_spew_info()
Definition: sound.cpp:173
int ds_priority(int priority)
Definition: sound.cpp:97
Definition: sound.cpp:39
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
int ds_init()
Definition: ds.cpp:1060
SCP_vector< sound > Sounds
Definition: sound.cpp:49
void snd_stop_all()
Definition: sound.cpp:905
#define CFILE_NORMAL
Definition: cfile.h:89
int i
Definition: multi_pxo.cpp:466
fix Missiontime
Definition: systemvars.cpp:19
#define vm_free(ptr)
Definition: pstypes.h:548
#define DS_MUST_PLAY
Definition: ds.h:40
void audiostream_set_volume_all(float volume, int type)
Definition: audiostr.cpp:1857
void snd_update_listener(vec3d *pos, vec3d *vel, matrix *orient)
Definition: sound.cpp:1113
#define AAV_VOICE
Definition: sound.h:66
int Cmdline_freespace_no_music
Definition: cmdline.cpp:271
vec3d View_position
Definition: 3dsetup.cpp:20
int snd_is_inited()
Definition: sound.cpp:1073
#define WAVE_FORMAT_ADPCM
Definition: mmreg.h:1303
char filename[MAX_FILENAME_LEN]
Definition: sound.cpp:41
unsigned int ds_get_play_position(int channel_id)
Definition: ds.cpp:2127
#define AAV_MUSIC
Definition: sound.h:65
aav aav_data[3]
Definition: sound.cpp:89
LOCAL state_stack gs[GS_STACK_SIZE]
const char * audio_ext_list[]
Definition: audiostr.cpp:49
int ds_play(int sid, int snd_id, int priority, const EnhancedSoundData *enhanced_sound_data, float volume, float pan, int looping, bool is_voice_msg)
Definition: ds.cpp:1794
int sound_env_set(sound_env *se)
Definition: sound.cpp:1357
#define ASF_EVENTMUSIC
Definition: audiostr.h:19
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
#define DS_LIMIT_ONE
Definition: ds.h:41
int snd_load(game_snd *gs, int allow_hardware_load)
Definition: sound.cpp:281
float m_defaultVolume
The default volume of this sound (from game_snd)
Definition: sound.cpp:60
#define MAX_PATH
int ds_initialized
Definition: ds.cpp:229
float delta
Definition: sound.cpp:84
void ds_set_pan(int channel_id, float pan)
Definition: ds.cpp:1946
int min
distance at which sound will stop getting louder
Definition: sound.h:79
Assert(pm!=NULL)
Definition: pstypes.h:88
WORD nChannels
Definition: config.h:166
#define mprintf(args)
Definition: pstypes.h:238
DWORD nAvgBytesPerSec
Definition: config.h:168
WORD nBlockAlign
Definition: config.h:169
int Snd_sram
Definition: sound.cpp:52
void ds_set_pitch(int channel_id, int pitch)
Definition: ds.cpp:1990
void ds_stop_channel_all()
Definition: ds.cpp:1914
int ds_load_buffer(int *sid, int *final_size, void *header, sound_info *si, int flags)
Load a secondary buffer with sound data.
Definition: ds.cpp:676
int sound_env_supported()
Definition: sound.cpp:1402
GLclampf f
Definition: Glext.h:7097
int snd_init()
Definition: sound.cpp:131
#define TRUE
Definition: pstypes.h:399
int bits
Definition: ds.h:56
int snd_is_playing(int sig)
Definition: sound.cpp:1047
int ds_eax_get_all(EAX_REVERBPROPERTIES *er, int id)
Definition: ds.cpp:2468
Definition: cfile.h:28
int sid
Definition: sound.cpp:40
#define GAME_SND_VOICE
Definition: sound.h:22
int center_offset_y
Definition: 2d.h:364
#define Assertion(expr, msg,...)
Definition: clang.h:41
#define f2fl(fx)
Definition: floating.h:37
#define DS_LIMIT_TWO
Definition: ds.h:42
int uncompressed_size
Definition: sound.cpp:45
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)
int n_block_align
Definition: ds.h:55
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
#define DS_LIMIT_THREE
Definition: ds.h:43
hull_check orient
Definition: lua.cpp:5049
int flags
Definition: sound.h:84
void adjust_volume_on_frame(float *volume_now, aav *data)
Definition: sound.cpp:1501
GLsizeiptr size
Definition: Glext.h:5496
#define Int3()
Definition: pstypes.h:292
struct channel channel
void snd_close(void)
Definition: sound.cpp:459
void snd_update_3d_pos(int soundnum, game_snd *gs, vec3d *new_pos, float radius, float range_factor)
Definition: sound.cpp:693
#define cfopen_special(...)
Definition: cfile.h:140
int Sound_spew
Definition: sound.cpp:201
float volume
Definition: sound.h:93
GLenum type
Definition: Gl.h:1492
char filename[MAX_FILENAME_LEN]
Definition: sound.h:76
SCP_list< LoopingSoundInfo > currentlyLoopingSoundInfos
Definition: sound.cpp:75
#define CLAMP(x, min, max)
Definition: pstypes.h:488
float start_volume
Definition: sound.cpp:83
void snd_get_format(int handle, int *bits_per_sample, int *frequency)
Definition: sound.cpp:1256
#define SND_PRIORITY_DOUBLE_INSTANCE
Definition: sound.h:28
int ds3d_update_buffer(int channel_id, float min, float max, vec3d *pos, vec3d *vel)
Definition: ds3d.cpp:35
void snd_rewind(int snd_handle, game_snd *gs, float seconds)
Definition: sound.cpp:1120
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
int sig
Definition: sound.cpp:42
int ds_get_channel(int sig)
Definition: ds.cpp:1870
struct matrix::@228::@230 vec
unsigned int uint
Definition: pstypes.h:64
#define cfopen(...)
Definition: cfile.h:134
#define nprintf(args)
Definition: pstypes.h:239
int snd_get_pitch(int sig)
Definition: sound.cpp:992
int sample_rate
Definition: ds.h:53
float Master_sound_volume
Definition: sound.cpp:53
int snd_num_playing()
Definition: sound.cpp:1207
int ds3d_update_listener(vec3d *pos, vec3d *vel, matrix *orient)
Definition: ds3d.cpp:88
int snd_get_data(int handle, char *data)
Definition: sound.cpp:1232
int ds_eax_is_inited()
Definition: ds.cpp:2598
void snd_stop_any_sound()
Definition: sound.cpp:1213
char * filename
int id
index into Sounds[], where sound data is stored
Definition: sound.h:82
int snd_play_3d(game_snd *gs, vec3d *source_pos, vec3d *listen_pos, float radius, vec3d *source_vel, int looping, float vol_scale, int priority, vec3d *sound_fvec, float range_factor, int force, bool is_ambient)
Definition: sound.cpp:594
int delta_time
Definition: sound.cpp:86
int cfwrite_string(const char *buf, CFILE *file)
Definition: cfile.cpp:1366
#define AAV_EFFECTS
Definition: sound.h:67
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
void snd_unload_all()
Definition: sound.cpp:447
int format
Definition: ds.h:50
int flags
Definition: sound.cpp:43
const int NUM_AUDIO_EXT
Definition: audiostr.cpp:50
#define SND_F_USED
Definition: sound.cpp:37
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
uint size
Definition: ds.h:52
void snd_set_pitch(int sig, int pitch)
Definition: sound.cpp:1021
int duration
Definition: ds.h:58
WORD wFormatTag
Definition: config.h:165
EnhancedSoundData enhanced_sound_data
Definition: sound.h:85
LoopingSoundInfo(int dsHandle, float defaultVolume, float dynamicVolume)
Definition: sound.cpp:63
DCF(show_sounds,"Toggles display of sound debug info")
Definition: sound.cpp:202
bool dc_optional_string_either(const char *str1, const char *str2)
Searches for an optional string and it's alias.
#define MONITOR(function_name)
Definition: pstypes.h:454
int snd_size(int handle, int *size)
Definition: sound.cpp:1244
uint nextSignature
Definition: sound.cpp:1549
int duration
Definition: sound.cpp:46
float start_time
Definition: sound.cpp:85
GLenum GLuint id
Definition: Glext.h:5156
int ds_get_size(int sid, int *size)
Definition: ds.cpp:2233
unsigned long DWORD
Definition: config.h:90
int idx
Definition: multiui.cpp:761
int ds_get_data(int sid, char *data)
Definition: ds.cpp:2225
cfbp fp
Definition: cfile.cpp:1065
int Sound_enabled
Definition: sound.cpp:51
void ds_close()
Definition: ds.cpp:1344
Definition: ds.h:49
int OGG_init()
Definition: ogg.cpp:108
int snd_get_duration(int snd_id)
Definition: sound.cpp:1082
GLclampd n
Definition: Glext.h:7286
#define MONITOR_INC(function_name, inc)
Definition: pstypes.h:457
int ds_get_pitch(int channel_id)
Definition: ds.cpp:1965
void ds_do_frame()
Definition: ds.cpp:2606
unsigned int environment
Definition: ds.h:174
#define SND_PRIORITY_MUST_PLAY
Definition: sound.h:26
int ds_get_channel_size(int channel_id)
Definition: ds.cpp:2177
int snd_get_3d_vol_and_pan(game_snd *gs, vec3d *pos, float *vol, float *pan, float radius, float range_factor)
Definition: sound.cpp:759
int max
distance at which sound is inaudible
Definition: sound.h:80
float decay
Definition: sound.h:95
GLbitfield flags
Definition: Glext.h:6722
int sound_env_get(sound_env *se, int preset)
Definition: sound.cpp:1372
typedef void(APIENTRY *PFNGLARRAYELEMENTEXTPROC)(GLint i)
unsigned int SND_ENV_DEFAULT
Definition: sound.cpp:56
int ds_get_number_channels()
Definition: ds.cpp:2202
const char * snd_get_filename(int snd_id)
Definition: sound.cpp:1101
GLuint const GLchar * name
Definition: Glext.h:5608
void snd_aav_init()
Definition: sound.cpp:1535
#define MIN_SOUND_VOLUME
Definition: sound.cpp:92
GLuint GLfloat * val
Definition: Glext.h:6741
#define CF_TYPE_DATA
Definition: cfile.h:46
DWORD nSamplesPerSec
Definition: config.h:167
float vm_vec_normalized_dir_quick(vec3d *dest, const vec3d *end, const vec3d *start)
Definition: vecmat.cpp:604
float fDecayTime_sec
Definition: ds.h:176
if(aifft_max_checks<=0)
Definition: aiturret.cpp:1581
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
#define strcat_s(...)
Definition: safe_strings.h:68
struct sound sound
WORD wBitsPerSample
Definition: config.h:170
ubyte * data
Definition: ds.h:59
int Cmdline_freespace_no_sound
Definition: cmdline.cpp:272
const unsigned int SND_ENHANCED_MAX_LIMIT
Definition: sound.cpp:35
int snd_time_remaining(int handle)
Definition: sound.cpp:1291
#define GAME_SND_USE_DS3D
Definition: sound.h:21
#define fl2i(fl)
Definition: floating.h:33
float m_dynamicVolume
The dynamic volume before scripted volume adjustment is applied (is updated via snd_set_volume) ...
Definition: sound.cpp:61
Definition: multi.h:385
screen gr_screen
Definition: 2d.cpp:46
int snd_play_looping(game_snd *gs, float pan, int start_loop, int stop_loop, float vol_scale, int scriptingUpdateVolume)
Definition: sound.cpp:822
float damping
Definition: sound.h:94
void snd_ffwd(int snd_handle, game_snd *gs, float seconds)
Definition: sound.cpp:1150
int gr_get_font_height()
Definition: font.cpp:187
int center_offset_x
Definition: 2d.h:364
GLfloat GLfloat p
Definition: Glext.h:8373
An overhauled/updated debug console to allow monitoring, testing, and general debugging of new featur...
void snd_set_volume(int sig, float volume)
Definition: sound.cpp:920
int n_channels
Definition: ds.h:57
float Master_event_music_volume
Definition: eventmusic.cpp:40
void snd_set_pos(int snd_handle, game_snd *gs, float val, int as_pct)
Definition: sound.cpp:1180
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
int ds_eax_set_all(unsigned long id, float vol, float damping, float decay)
Definition: ds.cpp:2348
game_snd()
Definition: sound.cpp:1551
int snd_get_index(int sig)
Definition: sound.cpp:1268
OggVorbis_File ogg_info
Definition: ds.h:51
#define SND_PRIORITY_SINGLE_INSTANCE
Definition: sound.h:27
int ds_parse_sound_info(char *real_filename, sound_info *s_info)
Definition: ds.cpp:457
int snd_get_samples_per_measure(char *filename, float num_measures)
Definition: sound.cpp:1428
hull_check pos
Definition: lua.cpp:5050
void snd_clear()
Definition: sound.cpp:114
int snd_unload(int n)
Definition: sound.cpp:415
#define VALID_FNAME(x)
Definition: pstypes.h:418
color Color_normal
Definition: alphacolors.cpp:28
#define SND_PRIORITY_TRIPLE_INSTANCE
Definition: sound.h:29
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
float fDamping
Definition: ds.h:177
int ds_get_sound_id(int channel_id)
Definition: ds.cpp:2639
void ds_stop_channel(int channel_id)
Definition: ds.cpp:1904
matrix View_matrix
Definition: 3dsetup.cpp:19
int ds3d_play(int sid, int snd_id, vec3d *pos, vec3d *vel, float min, float max, int looping, float max_volume, float estimated_vol, const EnhancedSoundData *enhanced_sound_data, int priority, bool is_ambient)
Definition: ds.cpp:2044
int ds_parse_sound(CFILE *fp, ubyte **dest, uint *dest_size, WAVEFORMATEX **header, bool ogg, OggVorbis_File *ovf)
Parse a wave file.
Definition: ds.cpp:246
float aav_voice_volume
Definition: sound.cpp:78
void dc_printf(const char *format,...)
Prints the given char string to the debug console.
Definition: console.cpp:358
float fVolume
Definition: ds.h:175
void dscap_close()
Definition: dscap.cpp:172
float aav_effect_volume
Definition: sound.cpp:80
#define DS_3D
Definition: ds.h:47
int avg_bytes_per_sec
Definition: ds.h:54
int id_sig
signature of Sounds[] element
Definition: sound.h:83
sound_info info
Definition: sound.cpp:44
void snd_spew_debug_info()
Definition: sound.cpp:212
false
Definition: lua.cpp:6789
void snd_do_frame()
Definition: sound.cpp:1411
void snd_stop(int sig)
Definition: sound.cpp:875
void _cdecl gr_printf_no_resize(int x, int y, const char *format,...)
Definition: font.cpp:342
int Cmdline_no_3d_sound
Definition: cmdline.cpp:446
void ds_unload_buffer(int sid)
Definition: ds.cpp:1307
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
void snd_adjust_audio_volume(int type, float percent, int time)
Definition: sound.cpp:1465
void ds_set_volume(int channel_id, float vol)
Set the volume for a channel. The volume is expected to be in linear scale.
Definition: ds.cpp:1929
#define CF_TYPE_ANY
Definition: cfile.h:42
void audiostream_init()
Definition: audiostr.cpp:1611
float default_volume
range: 0.0 -> 1.0
Definition: sound.h:78
#define FALSE
Definition: pstypes.h:400
int sound_env_disable()
Definition: sound.cpp:1389
float aav_music_volume
Definition: sound.cpp:79
#define stricmp(s1, s2)
Definition: config.h:271
int ds_is_channel_playing(int channel_id)
Definition: ds.cpp:1888
int id
Definition: sound.h:92
void ds_set_position(int channel_id, unsigned int offset)
Definition: ds.cpp:2115
Definition: sound.cpp:82
float Master_voice_volume
Definition: sound.cpp:54
void snd_set_pan(int sig, float pan)
Definition: sound.cpp:964
#define strcpy_s(...)
Definition: safe_strings.h:67
Definition: sound.h:72
int snd_play_raw(int soundnum, float pan, float vol_scale, int priority)
Definition: sound.cpp:477