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