Panda3D
fmodAudioManager.cxx
1 // Filename: fmodAudioManager.cxx
2 // Created by: cort (January 22, 2003)
3 // Prior system by: cary
4 // Rewrite [for new Version of FMOD-EX] by: Stan Rosenbaum "Staque" - Spring 2006
5 //
6 //
7 ////////////////////////////////////////////////////////////////////
8 //
9 // PANDA 3D SOFTWARE
10 // Copyright (c) Carnegie Mellon University. All rights reserved.
11 //
12 // All use of this software is subject to the terms of the revised BSD
13 // license. You should have received a copy of this license along
14 // with this source code in a file named "LICENSE."
15 //
16 ////////////////////////////////////////////////////////////////////
17 
18 #include "pandabase.h"
19 #include "config_audio.h"
20 #include "config_fmodAudio.h"
21 #include "dcast.h"
22 
23 //Panda headers.
24 #include "config_audio.h"
25 #include "config_util.h"
26 #include "fmodAudioManager.h"
27 #include "fmodAudioSound.h"
28 #include "filename.h"
29 #include "virtualFileSystem.h"
30 #include "reMutexHolder.h"
31 
32 //FMOD Headers.
33 #include <fmod.hpp>
34 #include <fmod_errors.h>
35 
36 #define USER_DSP_MAGIC ((void*)0x7012AB35)
37 
38 TypeHandle FmodAudioManager::_type_handle;
39 
40 ReMutex FmodAudioManager::_lock;
41 FMOD::System *FmodAudioManager::_system;
42 
43 pset<FmodAudioManager *> FmodAudioManager::_all_managers;
44 
45 bool FmodAudioManager::_system_is_valid = false;
46 
47 
48 // This sets the distance factor for 3D audio to use feet.
49 // FMOD uses meters by default.
50 // Since Panda use feet we need to compensate for that with a factor of 3.28
51 //
52 // This can be overwritten. You just need to call
53 // audio_3d_set_distance_factor(PN_stdfloat factor) and set your new factor.
54 
55 PN_stdfloat FmodAudioManager::_doppler_factor = 1;
56 PN_stdfloat FmodAudioManager::_distance_factor = 3.28;
57 PN_stdfloat FmodAudioManager::_drop_off_factor = 1;
58 
59 
60 ////////////////////////////////////////////////////////////////////
61 // Central dispatcher for audio errors.
62 ////////////////////////////////////////////////////////////////////
63 
64 void fmod_audio_errcheck(const char *context, FMOD_RESULT result) {
65  if (result != 0) {
66  audio_error(context << ": " << FMOD_ErrorString(result) );
67  }
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: Create_FmodAudioManager
72 // Access: Private
73 // Description: Factory Function
74 ////////////////////////////////////////////////////////////////////
75 AudioManager *Create_FmodAudioManager() {
76  audio_debug("Create_FmodAudioManager()");
77  return new FmodAudioManager;
78 }
79 
80 
81 ////////////////////////////////////////////////////////////////////
82 // Function: FmodAudioManager::Constructor
83 // Access: Public
84 // Description:
85 ////////////////////////////////////////////////////////////////////
86 FmodAudioManager::
87 FmodAudioManager() {
88  ReMutexHolder holder(_lock);
89  FMOD_RESULT result;
90 
91  //We need a varible temporary to check the FMOD Version.
92  unsigned int version;
93 
94  _all_managers.insert(this);
95 
96  //Init 3D attributes
97  _position.x = 0;
98  _position.y = 0;
99  _position.z = 0;
100 
101  _velocity.x = 0;
102  _velocity.y = 0;
103  _velocity.z = 0;
104 
105  _forward.x = 0;
106  _forward.y = 0;
107  _forward.z = 0;
108 
109  _up.x = 0;
110  _up.y = 0;
111  _up.z = 0;
112 
113  _saved_outputtype = FMOD_OUTPUTTYPE_AUTODETECT;
114 
115  if (_system == (FMOD::System *)NULL) {
116  // Create the global FMOD System object. This one object must be
117  // shared by all FmodAudioManagers (this is particularly true on
118  // OSX, but the FMOD documentation is unclear as to whether this
119  // is the intended design on all systems).
120 
121  result = FMOD::System_Create(&_system);
122  fmod_audio_errcheck("FMOD::System_Create()", result);
123 
124  // Let check the Version of FMOD to make sure the Headers and Libraries are correct.
125  result = _system->getVersion(&version);
126  fmod_audio_errcheck("_system->getVersion()", result);
127 
128  if (version < FMOD_VERSION){
129  audio_error("You are using an old version of FMOD. This program requires:" << FMOD_VERSION);
130  }
131 
132  // Set speaker mode.
133  if (fmod_speaker_mode.get_value() == FSM_unspecified) {
134  if (fmod_use_surround_sound) {
135  // fmod-use-surround-sound is the old variable, now replaced
136  // by fmod-speaker-mode. This is for backward compatibility.
137  result = _system->setSpeakerMode(FMOD_SPEAKERMODE_5POINT1);
138  fmod_audio_errcheck("_system->setSpeakerMode()", result);
139  }
140  } else {
141  FMOD_SPEAKERMODE speakerMode;
142  speakerMode = (FMOD_SPEAKERMODE) fmod_speaker_mode.get_value();
143  result = _system->setSpeakerMode(speakerMode);
144  fmod_audio_errcheck("_system->setSpeakerMode()", result);
145  }
146 
147  //Now we Initialize the System.
148  int nchan = fmod_number_of_sound_channels;
149  int flags = FMOD_INIT_NORMAL;
150 
151  result = _system->init(nchan, flags, 0);
152  if (result == FMOD_ERR_TOOMANYCHANNELS) {
153  fmodAudio_cat.error()
154  << "Value too large for fmod-number-of-sound-channels: " << nchan
155  << "\n";
156  } else {
157  fmod_audio_errcheck("_system->init()", result);
158  }
159 
160  _system_is_valid = (result == FMOD_OK);
161 
162  if (_system_is_valid) {
163  result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
164  fmod_audio_errcheck("_system->set3DSettings()", result);
165  }
166  }
167 
168  _is_valid = _system_is_valid;
169 
170  memset(&_midi_info, 0, sizeof(_midi_info));
171  _midi_info.cbsize = sizeof(_midi_info);
172 
173  Filename dls_pathname = get_dls_pathname();
174 
175 #ifdef IS_OSX
176  // Here's a big kludge. Don't ever let FMOD try to load this
177  // OSX-provided file; it crashes messily if you do.
178  if (dls_pathname == "/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls") {
179  dls_pathname = "";
180  }
181 #endif // IS_OSX
182 
183  if (!dls_pathname.empty()) {
184  _dlsname = dls_pathname.to_os_specific();
185  _midi_info.dlsname = _dlsname.c_str();
186  }
187 
188  if (_is_valid) {
189  result = _system->createChannelGroup("UserGroup", &_channelgroup);
190  fmod_audio_errcheck("_system->createChannelGroup()", result);
191  }
192 }
193 
194 ////////////////////////////////////////////////////////////////////
195 // Function: FmodAudioManager::Destructor
196 // Access: Public
197 // Description:
198 ////////////////////////////////////////////////////////////////////
199 FmodAudioManager::
200 ~FmodAudioManager() {
201  ReMutexHolder holder(_lock);
202  // Be sure to delete associated sounds before deleting the manager!
203  FMOD_RESULT result;
204 
205  //Release Sounds Next
206  _all_sounds.clear();
207 
208  // Remove me from the managers list.
209  _all_managers.erase(this);
210 
211  if (_all_managers.empty()) {
212  result = _system->release();
213  fmod_audio_errcheck("_system->release()", result);
214  _system = NULL;
215  _system_is_valid = false;
216  }
217 }
218 
219 ////////////////////////////////////////////////////////////////////
220 // Function: FmodAudioManager::is_valid
221 // Access: Public
222 // Description: This just check to make sure the FMOD System is
223 // up and running correctly.
224 ////////////////////////////////////////////////////////////////////
227  return _is_valid;
228 }
229 
230 ////////////////////////////////////////////////////////////////////
231 // Function: FmodAudioManager::make_dsp
232 // Access: Private
233 // Description: Converts a FilterConfig to an FMOD_DSP
234 ////////////////////////////////////////////////////////////////////
235 FMOD::DSP *FmodAudioManager::
236 make_dsp(const FilterProperties::FilterConfig &conf) {
237  ReMutexHolder holder(_lock);
238  FMOD_DSP_TYPE dsptype;
239  FMOD_RESULT result;
240  FMOD::DSP *dsp;
241  switch (conf._type) {
242  case FilterProperties::FT_lowpass: dsptype = FMOD_DSP_TYPE_LOWPASS; break;
243  case FilterProperties::FT_highpass: dsptype = FMOD_DSP_TYPE_HIGHPASS; break;
244  case FilterProperties::FT_echo: dsptype = FMOD_DSP_TYPE_ECHO; break;
245  case FilterProperties::FT_flange: dsptype = FMOD_DSP_TYPE_FLANGE; break;
246  case FilterProperties::FT_distort: dsptype = FMOD_DSP_TYPE_DISTORTION; break;
247  case FilterProperties::FT_normalize: dsptype = FMOD_DSP_TYPE_NORMALIZE; break;
248  case FilterProperties::FT_parameq: dsptype = FMOD_DSP_TYPE_PARAMEQ; break;
249  case FilterProperties::FT_pitchshift: dsptype = FMOD_DSP_TYPE_PITCHSHIFT; break;
250  case FilterProperties::FT_chorus: dsptype = FMOD_DSP_TYPE_CHORUS; break;
251  case FilterProperties::FT_sfxreverb: dsptype = FMOD_DSP_TYPE_SFXREVERB; break;
252  case FilterProperties::FT_compress: dsptype = FMOD_DSP_TYPE_COMPRESSOR; break;
253  default:
254  audio_error("Garbage in DSP configuration data");
255  return NULL;
256  }
257 
258  result = _system->createDSPByType( dsptype, &dsp);
259  if (result != 0) {
260  audio_error("Could not create DSP object");
261  return NULL;
262  }
263 
264  FMOD_RESULT res1 = FMOD_OK;
265  FMOD_RESULT res2 = FMOD_OK;
266  FMOD_RESULT res3 = FMOD_OK;
267  FMOD_RESULT res4 = FMOD_OK;
268  FMOD_RESULT res5 = FMOD_OK;
269  FMOD_RESULT res6 = FMOD_OK;
270  FMOD_RESULT res7 = FMOD_OK;
271  FMOD_RESULT res8 = FMOD_OK;
272  FMOD_RESULT res9 = FMOD_OK;
273  FMOD_RESULT res10 = FMOD_OK;
274  FMOD_RESULT res11 = FMOD_OK;
275  FMOD_RESULT res12 = FMOD_OK;
276  FMOD_RESULT res13 = FMOD_OK;
277  FMOD_RESULT res14 = FMOD_OK;
278 
279  switch (conf._type) {
280  case FilterProperties::FT_lowpass:
281  res1 = dsp->setParameter(FMOD_DSP_LOWPASS_CUTOFF, conf._a);
282  res2 = dsp->setParameter(FMOD_DSP_LOWPASS_RESONANCE, conf._b);
283  break;
284  case FilterProperties::FT_highpass:
285  res1 = dsp->setParameter(FMOD_DSP_HIGHPASS_CUTOFF, conf._a);
286  res2 = dsp->setParameter(FMOD_DSP_HIGHPASS_RESONANCE, conf._b);
287  break;
288  case FilterProperties::FT_echo:
289  res1 = dsp->setParameter(FMOD_DSP_ECHO_DRYMIX, conf._a);
290  res2 = dsp->setParameter(FMOD_DSP_ECHO_WETMIX, conf._b);
291  res3 = dsp->setParameter(FMOD_DSP_ECHO_DELAY, conf._c);
292  res4 = dsp->setParameter(FMOD_DSP_ECHO_DECAYRATIO, conf._d);
293  break;
294  case FilterProperties::FT_flange:
295  res1 = dsp->setParameter(FMOD_DSP_FLANGE_DRYMIX, conf._a);
296  res2 = dsp->setParameter(FMOD_DSP_FLANGE_WETMIX, conf._b);
297  res3 = dsp->setParameter(FMOD_DSP_FLANGE_DEPTH, conf._c);
298  res4 = dsp->setParameter(FMOD_DSP_FLANGE_RATE, conf._d);
299  break;
300  case FilterProperties::FT_distort:
301  res1 = dsp->setParameter(FMOD_DSP_DISTORTION_LEVEL, conf._a);
302  break;
303  case FilterProperties::FT_normalize:
304  res1 = dsp->setParameter(FMOD_DSP_NORMALIZE_FADETIME, conf._a);
305  res2 = dsp->setParameter(FMOD_DSP_NORMALIZE_THRESHHOLD,conf._b);
306  res3 = dsp->setParameter(FMOD_DSP_NORMALIZE_MAXAMP, conf._c);
307  break;
308  case FilterProperties::FT_parameq:
309  res1 = dsp->setParameter(FMOD_DSP_PARAMEQ_CENTER, conf._a);
310  res2 = dsp->setParameter(FMOD_DSP_PARAMEQ_BANDWIDTH, conf._b);
311  res3 = dsp->setParameter(FMOD_DSP_PARAMEQ_GAIN, conf._c);
312  break;
313  case FilterProperties::FT_pitchshift:
314  res1 = dsp->setParameter(FMOD_DSP_PITCHSHIFT_PITCH, conf._a);
315  res2 = dsp->setParameter(FMOD_DSP_PITCHSHIFT_FFTSIZE, conf._b);
316  res3 = dsp->setParameter(FMOD_DSP_PITCHSHIFT_OVERLAP, conf._c);
317  break;
318  case FilterProperties::FT_chorus:
319  res1 = dsp->setParameter(FMOD_DSP_CHORUS_DRYMIX, conf._a);
320  res2 = dsp->setParameter(FMOD_DSP_CHORUS_WETMIX1, conf._b);
321  res3 = dsp->setParameter(FMOD_DSP_CHORUS_WETMIX2, conf._c);
322  res4 = dsp->setParameter(FMOD_DSP_CHORUS_WETMIX3, conf._d);
323  res5 = dsp->setParameter(FMOD_DSP_CHORUS_DELAY, conf._e);
324  res6 = dsp->setParameter(FMOD_DSP_CHORUS_RATE, conf._f);
325  res7 = dsp->setParameter(FMOD_DSP_CHORUS_DEPTH, conf._g);
326  break;
327  case FilterProperties::FT_sfxreverb:
328  res1 = dsp->setParameter(FMOD_DSP_SFXREVERB_DRYLEVEL, conf._a);
329  res2 = dsp->setParameter(FMOD_DSP_SFXREVERB_ROOM, conf._b);
330  res3 = dsp->setParameter(FMOD_DSP_SFXREVERB_ROOMHF, conf._c);
331  res4 = dsp->setParameter(FMOD_DSP_SFXREVERB_DECAYTIME,conf._d);
332  res5 = dsp->setParameter(FMOD_DSP_SFXREVERB_DECAYHFRATIO, conf._e);
333  res6 = dsp->setParameter(FMOD_DSP_SFXREVERB_REFLECTIONSLEVEL,conf._f);
334  res7 = dsp->setParameter(FMOD_DSP_SFXREVERB_REFLECTIONSDELAY,conf._g);
335  res8 = dsp->setParameter(FMOD_DSP_SFXREVERB_REVERBLEVEL, conf._h);
336  res9 = dsp->setParameter(FMOD_DSP_SFXREVERB_REVERBDELAY, conf._i);
337  res10 = dsp->setParameter(FMOD_DSP_SFXREVERB_DIFFUSION, conf._j);
338  res11 = dsp->setParameter(FMOD_DSP_SFXREVERB_DENSITY, conf._k);
339  res12 = dsp->setParameter(FMOD_DSP_SFXREVERB_HFREFERENCE, conf._l);
340  res13 = dsp->setParameter(FMOD_DSP_SFXREVERB_ROOMLF, conf._m);
341  res14 = dsp->setParameter(FMOD_DSP_SFXREVERB_LFREFERENCE, conf._n);
342  break;
343  case FilterProperties::FT_compress:
344  res1 = dsp->setParameter(FMOD_DSP_COMPRESSOR_THRESHOLD, conf._a);
345  res2 = dsp->setParameter(FMOD_DSP_COMPRESSOR_ATTACK, conf._b);
346  res3 = dsp->setParameter(FMOD_DSP_COMPRESSOR_RELEASE, conf._c);
347  res4 = dsp->setParameter(FMOD_DSP_COMPRESSOR_GAINMAKEUP,conf._d);
348  break;
349  }
350 
351  if ((res1!=FMOD_OK)||(res2!=FMOD_OK)||(res3!=FMOD_OK)||(res4!=FMOD_OK)||
352  (res5!=FMOD_OK)||(res6!=FMOD_OK)||(res7!=FMOD_OK)||(res8!=FMOD_OK)||
353  (res9!=FMOD_OK)||(res10!=FMOD_OK)||(res11!=FMOD_OK)||(res12!=FMOD_OK)||
354  (res13!=FMOD_OK)||(res14!=FMOD_OK)) {
355  audio_error("Could not configure DSP");
356  dsp->release();
357  return NULL;
358  }
359 
360  dsp->setUserData(USER_DSP_MAGIC);
361 
362  return dsp;
363 }
364 
365 ////////////////////////////////////////////////////////////////////
366 // Function: FmodAudioManager::update_dsp_chain
367 // Access: Public
368 // Description: Alters a DSP chain to make it match the specified
369 // configuration.
370 //
371 // This is an inadequate implementation - it just
372 // clears the whole DSP chain and rebuilds it from
373 // scratch. A better implementation would compare
374 // the existing DSP chain to the desired one, and
375 // make incremental changes. This would prevent
376 // a "pop" sound when the changes are made.
377 ////////////////////////////////////////////////////////////////////
378 void FmodAudioManager::
379 update_dsp_chain(FMOD::DSP *head, FilterProperties *config) {
380  ReMutexHolder holder(_lock);
381  const FilterProperties::ConfigVector &conf = config->get_config();
382  FMOD_RESULT result;
383 
384  while (1) {
385  int numinputs;
386  result = head->getNumInputs(&numinputs);
387  fmod_audio_errcheck("head->getNumInputs()", result);
388  if (numinputs != 1) {
389  break;
390  }
391  FMOD::DSP *prev;
392  result = head->getInput(0, &prev, NULL);
393  fmod_audio_errcheck("head->getInput()", result);
394  void *userdata;
395  result = prev->getUserData(&userdata);
396  fmod_audio_errcheck("prev->getUserData()", result);
397  if (userdata != USER_DSP_MAGIC) {
398  break;
399  }
400  result = prev->remove();
401  fmod_audio_errcheck("prev->remove()", result);
402  result = prev->release();
403  fmod_audio_errcheck("prev->release()", result);
404  }
405 
406  for (int i=0; i<(int)(conf.size()); i++) {
407  FMOD::DSP *dsp = make_dsp(conf[i]);
408  result = _channelgroup->addDSP(dsp, NULL);
409  fmod_audio_errcheck("_channelgroup->addDSP()", result);
410  }
411 }
412 
413 ////////////////////////////////////////////////////////////////////
414 // Function: FmodAudioManager::configure_filters
415 // Access: Public
416 // Description: Configure the global DSP filter chain.
417 //
418 // FMOD has a relatively powerful DSP
419 // implementation. It is likely that most
420 // configurations will be supported.
421 ////////////////////////////////////////////////////////////////////
422 bool FmodAudioManager::
423 configure_filters(FilterProperties *config) {
424  ReMutexHolder holder(_lock);
425  FMOD_RESULT result;
426  FMOD::DSP *head;
427  result = _channelgroup->getDSPHead(&head);
428  if (result != 0) {
429  audio_error("Getting DSP head: " << FMOD_ErrorString(result) );
430  return false;
431  }
432  update_dsp_chain(head, config);
433  return true;
434 }
435 
436 ////////////////////////////////////////////////////////////////////
437 // Function: FmodAudioManager::get_sound
438 // Access: Public
439 // Description: This is what creates a sound instance.
440 ////////////////////////////////////////////////////////////////////
441 PT(AudioSound) FmodAudioManager::
442 get_sound(const string &file_name, bool positional, int) {
443  ReMutexHolder holder(_lock);
444  //Needed so People use Panda's Generic UNIX Style Paths for Filename.
445  //path.to_os_specific() converts it back to the proper OS version later on.
446 
447  Filename path = file_name;
448 
450  vfs->resolve_filename(path, get_model_path());
451 
452  // Build a new AudioSound from the audio data.
453  PT(AudioSound) audioSound;
454  PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, path, positional);
455 
456  _all_sounds.insert(fmodAudioSound);
457 
458  audioSound = fmodAudioSound;
459 
460  return audioSound;
461 }
462 
463 ////////////////////////////////////////////////////////////////////
464 // Function: FmodAudioManager::get_sound
465 // Access: Public
466 // Description: This is what creates a sound instance.
467 ////////////////////////////////////////////////////////////////////
468 PT(AudioSound) FmodAudioManager::
469 get_sound(MovieAudio *source, bool positional, int) {
470  nassert_raise("FMOD audio manager does not support MovieAudio sources");
471  return NULL;
472 }
473 
474 ////////////////////////////////////////////////////////////////////
475 // Function: FmodAudioManager::getSpeakerSetup()
476 // Access: Published
477 // Description: This is to query if you are using a MultiChannel Setup.
478 ////////////////////////////////////////////////////////////////////
481  ReMutexHolder holder(_lock);
482  FMOD_RESULT result;
483  FMOD_SPEAKERMODE speakerMode;
484  int returnMode;
485 
486  result = _system->getSpeakerMode( &speakerMode );
487  fmod_audio_errcheck("_system->getSpeakerMode()", result);
488 
489  switch (speakerMode) {
490  case FMOD_SPEAKERMODE_RAW:
491  returnMode = 0;
492  break;
493  case FMOD_SPEAKERMODE_MONO:
494  returnMode = 1;
495  break;
496  case FMOD_SPEAKERMODE_STEREO:
497  returnMode = 2;
498  break;
499  case FMOD_SPEAKERMODE_QUAD:
500  returnMode = 3;
501  break;
502  case FMOD_SPEAKERMODE_SURROUND:
503  returnMode = 4;
504  break;
505  case FMOD_SPEAKERMODE_5POINT1:
506  returnMode = 5;
507  break;
508  case FMOD_SPEAKERMODE_7POINT1:
509  returnMode = 6;
510  break;
511  case FMOD_SPEAKERMODE_MAX:
512  returnMode = 7;
513  break;
514  default:
515  returnMode = -1;
516  }
517 
518  return returnMode;
519 }
520 
521 ////////////////////////////////////////////////////////////////////
522 // Function: FmodAudioManager::setSpeakerSetup()
523 // Access: Published
524 // Description: This is to set up FMOD to use a MultiChannel Setup.
525 // This method is pretty much useless.
526 // To set a speaker setup in FMOD for Surround Sound,
527 // stereo, or whatever you have to set the SpeakerMode
528 // BEFORE you Initialize FMOD.
529 // Since Panda Inits the FmodAudioManager right when you
530 // Start it up, you are never given an oppertunity to call
531 // this function.
532 // That is why I stuck a BOOL in the CONFIG.PRC file, whichs
533 // lets you flag if you want to use a Multichannel or not.
534 // That will set the speaker setup when an instance of this
535 // class is constructed.
536 // Still I put this here as a measure of good faith, since you
537 // can query the speaker setup after everything in Init.
538 // Also, maybe someone will completely hack Panda someday, in which
539 // one can init or re-init the AudioManagers after Panda is running.
540 ////////////////////////////////////////////////////////////////////
542 setSpeakerSetup(AudioManager::SpeakerModeCategory cat) {
543  ReMutexHolder holder(_lock);
544  FMOD_RESULT result;
545  FMOD_SPEAKERMODE speakerModeType = (FMOD_SPEAKERMODE)cat;
546  result = _system->setSpeakerMode( speakerModeType);
547  fmod_audio_errcheck("_system->setSpeakerMode()", result);
548 }
549 
550 ////////////////////////////////////////////////////////////////////
551 // Function: FmodAudioManager::set_volume(PN_stdfloat volume)
552 // Access: Public
553 // Description: Sets the volume of the AudioManager.
554 // It is not an override, but a multiplier.
555 ////////////////////////////////////////////////////////////////////
557 set_volume(PN_stdfloat volume) {
558  ReMutexHolder holder(_lock);
559  FMOD_RESULT result;
560  result = _channelgroup->setVolume(volume);
561  fmod_audio_errcheck("_channelgroup->setVolume()", result);
562 }
563 
564 ////////////////////////////////////////////////////////////////////
565 // Function: FmodAudioManager::get_volume()
566 // Access: Public
567 // Description: Returns the AudioManager's volume.
568 ////////////////////////////////////////////////////////////////////
569 PN_stdfloat FmodAudioManager::
570 get_volume() const {
571  ReMutexHolder holder(_lock);
572  float volume;
573  FMOD_RESULT result;
574  result = _channelgroup->getVolume(&volume);
575  fmod_audio_errcheck("_channelgroup->getVolume()", result);
576  return (PN_stdfloat)volume;
577 }
578 
579 ////////////////////////////////////////////////////////////////////
580 // Function: FmodAudioManager::set_wavwriter()
581 // Access: Public
582 // Description: Changes output mode to write all audio to a wav file.
583 ////////////////////////////////////////////////////////////////////
585 set_wavwriter(bool outputwav) {
586  ReMutexHolder holder(_lock);
587  if (outputwav) {
588  _system->getOutput(&_saved_outputtype);
589  _system->setOutput(FMOD_OUTPUTTYPE_WAVWRITER);
590  }
591  else {
592  _system->setOutput(_saved_outputtype);
593  }
594 }
595 
596 
597 ////////////////////////////////////////////////////////////////////
598 // Function: FmodAudioManager::set_active(bool active)
599 // Access: Public
600 // Description: Turn on/off
601 // Warning: not implemented.
602 ////////////////////////////////////////////////////////////////////
604 set_active(bool active) {
605  ReMutexHolder holder(_lock);
606  if (_active != active) {
607  _active = active;
608 
609  // Tell our AudioSounds to adjust:
610  for (SoundSet::iterator i = _all_sounds.begin();
611  i != _all_sounds.end();
612  ++i) {
613  (*i)->set_active(_active);
614  }
615  }
616 }
617 
618 ////////////////////////////////////////////////////////////////////
619 // Function: FmodAudioManager::get_active()
620 // Access: Public
621 // Description:
622 ////////////////////////////////////////////////////////////////////
623 bool FmodAudioManager::
624 get_active() const {
625  return _active;
626 }
627 
628 ////////////////////////////////////////////////////////////////////
629 // Function: FmodAudioManager::stop_all_sounds()
630 // Access: Public
631 // Description: Stop playback on all sounds managed by this manager.
632 ////////////////////////////////////////////////////////////////////
635  ReMutexHolder holder(_lock);
636  // We have to walk through this list with some care, since stopping
637  // a sound may also remove it from the set (if there are no other
638  // references to the sound).
639  SoundSet::iterator i;
640  i = _all_sounds.begin();
641  while (i != _all_sounds.end()) {
642  SoundSet::iterator next = i;
643  ++next;
644 
645  (*i)->stop();
646  i = next;
647  }
648 }
649 
650 ////////////////////////////////////////////////////////////////////
651 // Function: FmodAudioManager::update
652 // Access: Public
653 // Description: Perform all per-frame update functions.
654 ////////////////////////////////////////////////////////////////////
657  ReMutexHolder holder(_lock);
658  _system->update();
659 }
660 
661 ////////////////////////////////////////////////////////////////////
662 // Function: FmodAudioManager::audio_3d_set_listener_attributes
663 // Access: Public
664 // Description: Set position of the "ear" that picks up 3d sounds
665 // NOW LISTEN UP!!! THIS IS IMPORTANT!
666 // Both Panda3D and FMOD use a left handed coordinate system.
667 // But there is a major difference!
668 // In Panda3D the Y-Axis is going into the Screen and the Z-Axis is going up.
669 // In FMOD the Y-Axis is going up and the Z-Axis is going into the screen.
670 // The solution is simple, we just flip the Y and Z axis, as we move coordinates
671 // from Panda to FMOD and back.
672 // What does did mean to average Panda user? Nothing, they shouldn't notice anyway.
673 // But if you decide to do any 3D audio work in here you have to keep it in mind.
674 // I told you, so you can't say I didn't.
675 ////////////////////////////////////////////////////////////////////
677 audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz) {
678  ReMutexHolder holder(_lock);
679  audio_debug("FmodAudioManager::audio_3d_set_listener_attributes()");
680 
681  FMOD_RESULT result;
682 
683  _position.x = px;
684  _position.y = pz;
685  _position.z = py;
686 
687  _velocity.x = vx;
688  _velocity.y = vz;
689  _velocity.z = vy;
690 
691  _forward.x = fx;
692  _forward.y = fz;
693  _forward.z = fy;
694 
695  _up.x = ux;
696  _up.y = uz;
697  _up.z = uy;
698 
699  result = _system->set3DListenerAttributes( 0, &_position, &_velocity, &_forward, &_up);
700  fmod_audio_errcheck("_system->set3DListenerAttributes()", result);
701 
702 }
703 
704 ////////////////////////////////////////////////////////////////////
705 // Function: FmodAudioManager::audio_3d_get_listener_attributes
706 // Access: Public
707 // Description: Get position of the "ear" that picks up 3d sounds
708 ////////////////////////////////////////////////////////////////////
710 audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz) {
711  audio_error("audio3dGetListenerAttributes: currently unimplemented. Get the attributes of the attached object");
712 
713 }
714 
715 
716 ////////////////////////////////////////////////////////////////////
717 // Function: FmodAudioManager::audio_3d_set_distance_factor
718 // Access: Public
719 // Description: Set units per meter (Fmod uses meters internally for
720 // its sound-spacialization calculations)
721 ////////////////////////////////////////////////////////////////////
723 audio_3d_set_distance_factor(PN_stdfloat factor) {
724  ReMutexHolder holder(_lock);
725  audio_debug( "FmodAudioManager::audio_3d_set_distance_factor( factor= " << factor << ")" );
726 
727  FMOD_RESULT result;
728 
729  _distance_factor = factor;
730 
731  result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
732  fmod_audio_errcheck("_system->set3DSettings()", result);
733 
734 
735 }
736 
737 ////////////////////////////////////////////////////////////////////
738 // Function: FmodAudioManager::audio_3d_get_distance_factor
739 // Access: Public
740 // Description: Gets units per meter (Fmod uses meters internally for
741 // its sound-spacialization calculations)
742 ////////////////////////////////////////////////////////////////////
743 PN_stdfloat FmodAudioManager::
745  audio_debug("FmodAudioManager::audio_3d_get_distance_factor()");
746 
747  return _distance_factor;
748 }
749 
750 ////////////////////////////////////////////////////////////////////
751 // Function: FmodAudioManager::audio_3d_set_doppler_factor
752 // Access: Public
753 // Description: Exaggerates or diminishes the Doppler effect.
754 // Defaults to 1.0
755 ////////////////////////////////////////////////////////////////////
757 audio_3d_set_doppler_factor(PN_stdfloat factor) {
758  ReMutexHolder holder(_lock);
759  audio_debug("FmodAudioManager::audio_3d_set_doppler_factor(factor="<<factor<<")");
760 
761  FMOD_RESULT result;
762 
763  _doppler_factor = factor;
764 
765  result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
766  fmod_audio_errcheck("_system->set3DSettings()", result);
767 
768 }
769 
770 ////////////////////////////////////////////////////////////////////
771 // Function: FmodAudioManager::audio_3d_get_doppler_factor
772 // Access: Public
773 // Description:
774 ////////////////////////////////////////////////////////////////////
775 PN_stdfloat FmodAudioManager::
776 audio_3d_get_doppler_factor() const {
777  audio_debug("FmodAudioManager::audio_3d_get_doppler_factor()");
778 
779  return _doppler_factor;
780 }
781 
782 ////////////////////////////////////////////////////////////////////
783 // Function: FmodAudioManager::audio_3d_set_drop_off_factor
784 // Access: Public
785 // Description: Control the effect distance has on audability.
786 // Defaults to 1.0
787 ////////////////////////////////////////////////////////////////////
789 audio_3d_set_drop_off_factor(PN_stdfloat factor) {
790  ReMutexHolder holder(_lock);
791  audio_debug("FmodAudioManager::audio_3d_set_drop_off_factor("<<factor<<")");
792 
793  FMOD_RESULT result;
794 
795  _drop_off_factor = factor;
796 
797  result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
798  fmod_audio_errcheck("_system->set3DSettings()", result);
799 
800 }
801 
802 ////////////////////////////////////////////////////////////////////
803 // Function: FmodAudioManager::audio_3d_get_drop_off_factor
804 // Access: Public
805 // Description:
806 ////////////////////////////////////////////////////////////////////
807 PN_stdfloat FmodAudioManager::
808 audio_3d_get_drop_off_factor() const {
809  ReMutexHolder holder(_lock);
810  audio_debug("FmodAudioManager::audio_3d_get_drop_off_factor()");
811 
812  return _drop_off_factor;
813 
814 }
815 
816 
817 
818 ////////////////////////////////////////////////////////////////////
819 // Function: FmodAudioManager::set_concurrent_sound_limit
820 // Access: Public
821 // Description: NOT USED FOR FMOD-EX!!!
822 ////////////////////////////////////////////////////////////////////
824 set_concurrent_sound_limit(unsigned int limit) {
825 
826 }
827 
828 ////////////////////////////////////////////////////////////////////
829 // Function: FmodAudioManager::get_concurrent_sound_limit
830 // Access: Public
831 // Description: NOT USED FOR FMOD-EX!!!
832 ////////////////////////////////////////////////////////////////////
833 unsigned int FmodAudioManager::
835  return 1000000;
836 }
837 
838 ////////////////////////////////////////////////////////////////////
839 // Function: FmodAudioManager::reduce_sounds_playing_to
840 // Access: Private
841 // Description: NOT USED FOR FMOD-EX!!!
842 ////////////////////////////////////////////////////////////////////
844 reduce_sounds_playing_to(unsigned int count) {
845 
846 }
847 
848 
849 ////////////////////////////////////////////////////////////////////
850 // Function: FmodAudioManager::uncache_sound
851 // Access: Public
852 // Description: NOT USED FOR FMOD-EX!!!
853 // Clears a sound out of the sound cache.
854 ////////////////////////////////////////////////////////////////////
856 uncache_sound(const string& file_name) {
857  audio_debug("FmodAudioManager::uncache_sound(\""<<file_name<<"\")");
858 
859 }
860 
861 
862 ////////////////////////////////////////////////////////////////////
863 // Function: FmodAudioManager::clear_cache
864 // Access: Public
865 // Description: NOT USED FOR FMOD-EX!!!
866 // Clear out the sound cache.
867 ////////////////////////////////////////////////////////////////////
870  audio_debug("FmodAudioManager::clear_cache()");
871 
872 }
873 
874 ////////////////////////////////////////////////////////////////////
875 // Function: FmodAudioManager::set_cache_limit
876 // Access: Public
877 // Description: NOT USED FOR FMOD-EX!!!
878 // Set the number of sounds that the cache can hold.
879 ////////////////////////////////////////////////////////////////////
881 set_cache_limit(unsigned int count) {
882  audio_debug("FmodAudioManager::set_cache_limit(count="<<count<<")");
883 
884 }
885 
886 ////////////////////////////////////////////////////////////////////
887 // Function: FmodAudioManager::get_cache_limit
888 // Access: Public
889 // Description: NOT USED FOR FMOD-EX!!!
890 // Gets the number of sounds that the cache can hold.
891 ////////////////////////////////////////////////////////////////////
892 unsigned int FmodAudioManager::
894  audio_debug("FmodAudioManager::get_cache_limit() returning ");
895  //return _cache_limit;
896  return 0;
897 }
virtual void audio_3d_set_doppler_factor(PN_stdfloat factor)
Exaggerates or diminishes the Doppler effect.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
virtual void audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat xy, PN_stdfloat xz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz)
Set position of the "ear" that picks up 3d sounds NOW LISTEN UP!!! THIS IS IMPORTANT! Both Panda3D an...
virtual void audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz)
Get position of the "ear" that picks up 3d sounds.
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS&#39;s file system.
virtual PN_stdfloat get_volume() const
Returns the AudioManager&#39;s volume.
static Filename get_dls_pathname()
Returns the full pathname to the DLS file, as specified by the Config.prc file, or the default for th...
virtual void set_volume(PN_stdfloat)
Sets the volume of the AudioManager.
virtual void set_cache_limit(unsigned int count)
NOT USED FOR FMOD-EX!!! Set the number of sounds that the cache can hold.
Stores a configuration for a set of audio DSP filters.
const ConfigVector & get_config()
Intended for use by AudioManager and AudioSound implementations: allows access to the config vector...
virtual void update()
Perform all per-frame update functions.
virtual void clear_cache()
NOT USED FOR FMOD-EX!!! Clear out the sound cache.
virtual void set_active(bool)
Turn on/off Warning: not implemented.
virtual PN_stdfloat audio_3d_get_distance_factor() const
Gets units per meter (Fmod uses meters internally for its sound-spacialization calculations) ...
virtual void uncache_sound(const string &)
NOT USED FOR FMOD-EX!!! Clears a sound out of the sound cache.
virtual void set_wavwriter(bool)
Changes output mode to write all audio to a wav file.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
virtual bool is_valid()
This just check to make sure the FMOD System is up and running correctly.
virtual void setSpeakerSetup(SpeakerModeCategory cat)
This is to set up FMOD to use a MultiChannel Setup.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
virtual void reduce_sounds_playing_to(unsigned int count)
NOT USED FOR FMOD-EX!!!
Similar to MutexHolder, but for a reentrant mutex.
Definition: reMutexHolder.h:27
virtual void set_concurrent_sound_limit(unsigned int limit=0)
NOT USED FOR FMOD-EX!!!
virtual unsigned int get_concurrent_sound_limit() const
NOT USED FOR FMOD-EX!!!
virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor)
Control the effect distance has on audability.
This is our own Panda specialization on the default STL set.
Definition: pset.h:52
virtual void audio_3d_set_distance_factor(PN_stdfloat factor)
Set units per meter (Fmod uses meters internally for its sound-spacialization calculations) ...
virtual unsigned int get_cache_limit() const
NOT USED FOR FMOD-EX!!! Gets the number of sounds that the cache can hold.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:48
virtual int getSpeakerSetup()
This is to query if you are using a MultiChannel Setup.
string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
Definition: filename.cxx:1196
virtual void stop_all_sounds()
Stop playback on all sounds managed by this manager.
A reentrant mutex.
Definition: reMutex.h:36