18 #include "pandabase.h"
19 #include "config_audio.h"
20 #include "config_fmodAudio.h"
24 #include "config_audio.h"
25 #include "config_util.h"
26 #include "fmodAudioManager.h"
27 #include "fmodAudioSound.h"
29 #include "virtualFileSystem.h"
30 #include "reMutexHolder.h"
34 #include <fmod_errors.h>
36 #define USER_DSP_MAGIC ((void*)0x7012AB35)
40 ReMutex FmodAudioManager::_lock;
41 FMOD::System *FmodAudioManager::_system;
45 bool FmodAudioManager::_system_is_valid =
false;
55 PN_stdfloat FmodAudioManager::_doppler_factor = 1;
56 PN_stdfloat FmodAudioManager::_distance_factor = 3.28;
57 PN_stdfloat FmodAudioManager::_drop_off_factor = 1;
64 void fmod_audio_errcheck(
const char *context, FMOD_RESULT result) {
66 audio_error(context <<
": " << FMOD_ErrorString(result) );
76 audio_debug(
"Create_FmodAudioManager()");
94 _all_managers.insert(
this);
113 _saved_outputtype = FMOD_OUTPUTTYPE_AUTODETECT;
115 if (_system == (FMOD::System *)NULL) {
121 result = FMOD::System_Create(&_system);
122 fmod_audio_errcheck(
"FMOD::System_Create()", result);
125 result = _system->getVersion(&version);
126 fmod_audio_errcheck(
"_system->getVersion()", result);
128 if (version < FMOD_VERSION){
129 audio_error(
"You are using an old version of FMOD. This program requires:" << FMOD_VERSION);
133 if (fmod_speaker_mode.get_value() == FSM_unspecified) {
134 if (fmod_use_surround_sound) {
137 result = _system->setSpeakerMode(FMOD_SPEAKERMODE_5POINT1);
138 fmod_audio_errcheck(
"_system->setSpeakerMode()", result);
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);
148 int nchan = fmod_number_of_sound_channels;
149 int flags = FMOD_INIT_NORMAL;
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
157 fmod_audio_errcheck(
"_system->init()", result);
160 _system_is_valid = (result == FMOD_OK);
162 if (_system_is_valid) {
163 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
164 fmod_audio_errcheck(
"_system->set3DSettings()", result);
168 _is_valid = _system_is_valid;
170 memset(&_midi_info, 0,
sizeof(_midi_info));
171 _midi_info.cbsize =
sizeof(_midi_info);
178 if (dls_pathname ==
"/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls") {
183 if (!dls_pathname.empty()) {
185 _midi_info.dlsname = _dlsname.c_str();
189 result = _system->createChannelGroup(
"UserGroup", &_channelgroup);
190 fmod_audio_errcheck(
"_system->createChannelGroup()", result);
200 ~FmodAudioManager() {
209 _all_managers.erase(
this);
211 if (_all_managers.empty()) {
212 result = _system->release();
213 fmod_audio_errcheck(
"_system->release()", result);
215 _system_is_valid =
false;
235 FMOD::DSP *FmodAudioManager::
238 FMOD_DSP_TYPE dsptype;
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;
254 audio_error(
"Garbage in DSP configuration data");
258 result = _system->createDSPByType( dsptype, &dsp);
260 audio_error(
"Could not create DSP object");
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;
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);
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);
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);
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);
300 case FilterProperties::FT_distort:
301 res1 = dsp->setParameter(FMOD_DSP_DISTORTION_LEVEL, conf._a);
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);
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);
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);
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);
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);
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);
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");
360 dsp->setUserData(USER_DSP_MAGIC);
378 void FmodAudioManager::
386 result = head->getNumInputs(&numinputs);
387 fmod_audio_errcheck(
"head->getNumInputs()", result);
388 if (numinputs != 1) {
392 result = head->getInput(0, &prev, NULL);
393 fmod_audio_errcheck(
"head->getInput()", result);
395 result = prev->getUserData(&userdata);
396 fmod_audio_errcheck(
"prev->getUserData()", result);
397 if (userdata != USER_DSP_MAGIC) {
400 result = prev->remove();
401 fmod_audio_errcheck(
"prev->remove()", result);
402 result = prev->release();
403 fmod_audio_errcheck(
"prev->release()", result);
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);
422 bool FmodAudioManager::
427 result = _channelgroup->getDSPHead(&head);
429 audio_error(
"Getting DSP head: " << FMOD_ErrorString(result) );
432 update_dsp_chain(head, config);
442 get_sound(const
string &file_name,
bool positional,
int) {
456 _all_sounds.insert(fmodAudioSound);
458 audioSound = fmodAudioSound;
469 get_sound(
MovieAudio *source,
bool positional,
int) {
470 nassert_raise(
"FMOD audio manager does not support MovieAudio sources");
483 FMOD_SPEAKERMODE speakerMode;
486 result = _system->getSpeakerMode( &speakerMode );
487 fmod_audio_errcheck(
"_system->getSpeakerMode()", result);
489 switch (speakerMode) {
490 case FMOD_SPEAKERMODE_RAW:
493 case FMOD_SPEAKERMODE_MONO:
496 case FMOD_SPEAKERMODE_STEREO:
499 case FMOD_SPEAKERMODE_QUAD:
502 case FMOD_SPEAKERMODE_SURROUND:
505 case FMOD_SPEAKERMODE_5POINT1:
508 case FMOD_SPEAKERMODE_7POINT1:
511 case FMOD_SPEAKERMODE_MAX:
545 FMOD_SPEAKERMODE speakerModeType = (FMOD_SPEAKERMODE)cat;
546 result = _system->setSpeakerMode( speakerModeType);
547 fmod_audio_errcheck(
"_system->setSpeakerMode()", result);
560 result = _channelgroup->setVolume(volume);
561 fmod_audio_errcheck(
"_channelgroup->setVolume()", result);
574 result = _channelgroup->getVolume(&volume);
575 fmod_audio_errcheck(
"_channelgroup->getVolume()", result);
576 return (PN_stdfloat)volume;
588 _system->getOutput(&_saved_outputtype);
589 _system->setOutput(FMOD_OUTPUTTYPE_WAVWRITER);
592 _system->setOutput(_saved_outputtype);
606 if (_active != active) {
610 for (SoundSet::iterator i = _all_sounds.begin();
611 i != _all_sounds.end();
613 (*i)->set_active(_active);
623 bool FmodAudioManager::
639 SoundSet::iterator i;
640 i = _all_sounds.begin();
641 while (i != _all_sounds.end()) {
642 SoundSet::iterator next = i;
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) {
679 audio_debug(
"FmodAudioManager::audio_3d_set_listener_attributes()");
699 result = _system->set3DListenerAttributes( 0, &_position, &_velocity, &_forward, &_up);
700 fmod_audio_errcheck(
"_system->set3DListenerAttributes()", result);
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");
725 audio_debug(
"FmodAudioManager::audio_3d_set_distance_factor( factor= " << factor <<
")" );
729 _distance_factor = factor;
731 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
732 fmod_audio_errcheck(
"_system->set3DSettings()", result);
745 audio_debug(
"FmodAudioManager::audio_3d_get_distance_factor()");
747 return _distance_factor;
759 audio_debug(
"FmodAudioManager::audio_3d_set_doppler_factor(factor="<<factor<<
")");
763 _doppler_factor = factor;
765 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
766 fmod_audio_errcheck(
"_system->set3DSettings()", result);
775 PN_stdfloat FmodAudioManager::
776 audio_3d_get_doppler_factor()
const {
777 audio_debug(
"FmodAudioManager::audio_3d_get_doppler_factor()");
779 return _doppler_factor;
791 audio_debug(
"FmodAudioManager::audio_3d_set_drop_off_factor("<<factor<<
")");
795 _drop_off_factor = factor;
797 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
798 fmod_audio_errcheck(
"_system->set3DSettings()", result);
807 PN_stdfloat FmodAudioManager::
808 audio_3d_get_drop_off_factor()
const {
810 audio_debug(
"FmodAudioManager::audio_3d_get_drop_off_factor()");
812 return _drop_off_factor;
857 audio_debug(
"FmodAudioManager::uncache_sound(\""<<file_name<<
"\")");
870 audio_debug(
"FmodAudioManager::clear_cache()");
882 audio_debug(
"FmodAudioManager::set_cache_limit(count="<<count<<
")");
894 audio_debug(
"FmodAudioManager::get_cache_limit() returning ");
virtual void audio_3d_set_doppler_factor(PN_stdfloat factor)
Exaggerates or diminishes the Doppler effect.
virtual PN_stdfloat get_volume() const
Returns the AudioManager's volume.
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.
virtual PN_stdfloat audio_3d_get_distance_factor() const
Gets units per meter (Fmod uses meters internally for its sound-spacialization calculations) ...
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's file system.
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.
virtual unsigned int get_cache_limit() const
NOT USED FOR FMOD-EX!!! Gets 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 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.
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!!!
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
Similar to MutexHolder, but for a reentrant mutex.
string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
virtual void set_concurrent_sound_limit(unsigned int limit=0)
NOT USED FOR FMOD-EX!!!
virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor)
Control the effect distance has on audability.
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_concurrent_sound_limit() const
NOT USED FOR FMOD-EX!!!
TypeHandle is the identifier used to differentiate C++ class types.
A MovieAudio is actually any source that provides a sequence of audio samples.
virtual int getSpeakerSetup()
This is to query if you are using a MultiChannel Setup.
virtual void stop_all_sounds()
Stop playback on all sounds managed by this manager.