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  */
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  */
528 PN_stdfloat FmodAudioManager::
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  */
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  */
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  */
681 PN_stdfloat FmodAudioManager::
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  */
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::
804  audio_debug("FmodAudioManager::get_cache_limit() returning ");
805  // return _cache_limit;
806  return 0;
807 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void audio_3d_set_doppler_factor(PN_stdfloat factor)
Exaggerates or diminishes the Doppler effect.
virtual void set_speaker_setup(SpeakerModeCategory cat)
This is to set up FMOD to use a MultiChannel Setup.
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 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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void uncache_sound(const Filename &)
NOT USED FOR FMOD-EX!!! Clears a sound out of the sound cache.
A hierarchy of directories and files that appears to be one continuous file system,...
virtual PN_stdfloat get_volume() const
Returns the AudioManager's volume.
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void set_volume(PN_stdfloat)
Sets the volume of the AudioManager.
AudioManager * Create_FmodAudioManager()
Factory Function.
virtual void set_cache_limit(unsigned int count)
NOT USED FOR FMOD-EX!!! Set the number of sounds that the cache can hold.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Stores a configuration for a set of audio DSP filters.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
const ConfigVector & get_config()
Intended for use by AudioManager and AudioSound implementations: allows access to the config vector.
The abstract base class for a file or directory within the VirtualFileSystem.
Definition: virtualFile.h:35
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void update()
Perform all per-frame update functions.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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:176
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 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:39
virtual bool is_valid()
This just check to make sure the FMOD System is up and running correctly.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
virtual void reduce_sounds_playing_to(unsigned int count)
NOT USED FOR FMOD-EX!!!
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
Similar to MutexHolder, but for a reentrant mutex.
Definition: reMutexHolder.h:25
virtual void set_concurrent_sound_limit(unsigned int limit=0)
NOT USED FOR FMOD-EX!!!
virtual int get_speaker_setup()
This is to query if you are using a MultiChannel Setup.
virtual unsigned int get_concurrent_sound_limit() const
NOT USED FOR FMOD-EX!!!
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(AudioSound) FmodAudioManager
This is what creates a sound instance.
virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor)
Control the effect distance has on audability.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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:81
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:44
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
virtual void stop_all_sounds()
Stop playback on all sounds managed by this manager.
A reentrant mutex.
Definition: reMutex.h:32
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.