32 #include <fmod_errors.h>
34 #define USER_DSP_MAGIC ((void*)0x7012AB35)
38 ReMutex FmodAudioManager::_lock;
39 FMOD::System *FmodAudioManager::_system;
43 bool FmodAudioManager::_system_is_valid =
false;
45 PN_stdfloat FmodAudioManager::_doppler_factor = 1;
46 PN_stdfloat FmodAudioManager::_distance_factor = 1;
47 PN_stdfloat FmodAudioManager::_drop_off_factor = 1;
52 void fmod_audio_errcheck(
const char *context, FMOD_RESULT result) {
54 audio_error(context <<
": " << FMOD_ErrorString(result) );
62 audio_debug(
"Create_FmodAudioManager()");
78 _all_managers.insert(
this);
99 _saved_outputtype = FMOD_OUTPUTTYPE_AUTODETECT;
101 if (_system ==
nullptr) {
107 result = FMOD::System_Create(&_system);
108 fmod_audio_errcheck(
"FMOD::System_Create()", result);
112 result = _system->getVersion(&version);
113 fmod_audio_errcheck(
"_system->getVersion()", result);
115 if (version < FMOD_VERSION){
116 audio_error(
"You are using an old version of FMOD. This program requires:" << FMOD_VERSION);
120 if (fmod_speaker_mode.get_value() == FSM_unspecified) {
121 if (fmod_use_surround_sound) {
124 result = _system->setSpeakerMode(FMOD_SPEAKERMODE_5POINT1);
125 fmod_audio_errcheck(
"_system->setSpeakerMode()", result);
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);
135 int nchan = fmod_number_of_sound_channels;
136 int flags = FMOD_INIT_NORMAL;
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
144 fmod_audio_errcheck(
"_system->init()", result);
147 _system_is_valid = (result == FMOD_OK);
149 if (_system_is_valid) {
150 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
151 fmod_audio_errcheck(
"_system->set3DSettings()", result);
155 _is_valid = _system_is_valid;
157 memset(&_midi_info, 0,
sizeof(_midi_info));
158 _midi_info.cbsize =
sizeof(_midi_info);
165 if (dls_pathname ==
"/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls") {
170 if (!dls_pathname.empty()) {
172 _midi_info.dlsname = _dlsname.c_str();
176 result = _system->createChannelGroup(
"UserGroup", &_channelgroup);
177 fmod_audio_errcheck(
"_system->createChannelGroup()", result);
185 ~FmodAudioManager() {
194 _all_managers.erase(
this);
196 if (_all_managers.empty()) {
197 result = _system->release();
198 fmod_audio_errcheck(
"_system->release()", result);
200 _system_is_valid =
false;
215 FMOD::DSP *FmodAudioManager::
218 FMOD_DSP_TYPE dsptype;
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;
234 audio_error(
"Garbage in DSP configuration data");
238 result = _system->createDSPByType( dsptype, &dsp);
240 audio_error(
"Could not create DSP object");
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;
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);
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);
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);
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);
280 case FilterProperties::FT_distort:
281 res1 = dsp->setParameter(FMOD_DSP_DISTORTION_LEVEL, conf._a);
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);
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);
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);
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);
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);
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);
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");
340 dsp->setUserData(USER_DSP_MAGIC);
353 void FmodAudioManager::
361 result = head->getNumInputs(&numinputs);
362 fmod_audio_errcheck(
"head->getNumInputs()", result);
363 if (numinputs != 1) {
367 result = head->getInput(0, &prev,
nullptr);
368 fmod_audio_errcheck(
"head->getInput()", result);
370 result = prev->getUserData(&userdata);
371 fmod_audio_errcheck(
"prev->getUserData()", result);
372 if (userdata != USER_DSP_MAGIC) {
375 result = prev->remove();
376 fmod_audio_errcheck(
"prev->remove()", result);
377 result = prev->release();
378 fmod_audio_errcheck(
"prev->release()", result);
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);
394 bool FmodAudioManager::
399 result = _channelgroup->getDSPHead(&head);
401 audio_error(
"Getting DSP head: " << FMOD_ErrorString(result) );
404 update_dsp_chain(head, config);
412 get_sound(
const Filename &file_name,
bool positional,
int) {
425 if (file !=
nullptr) {
429 _all_sounds.insert(sound);
432 audio_error(
"createSound(" << path <<
"): File not found.");
433 return get_null_sound();
441 get_sound(
MovieAudio *source,
bool positional,
int) {
442 nassert_raise(
"FMOD audio manager does not support MovieAudio sources");
453 FMOD_SPEAKERMODE speakerMode;
456 result = _system->getSpeakerMode( &speakerMode );
457 fmod_audio_errcheck(
"_system->getSpeakerMode()", result);
459 switch (speakerMode) {
460 case FMOD_SPEAKERMODE_RAW:
463 case FMOD_SPEAKERMODE_MONO:
466 case FMOD_SPEAKERMODE_STEREO:
469 case FMOD_SPEAKERMODE_QUAD:
472 case FMOD_SPEAKERMODE_SURROUND:
475 case FMOD_SPEAKERMODE_5POINT1:
478 case FMOD_SPEAKERMODE_7POINT1:
481 case FMOD_SPEAKERMODE_MAX:
508 FMOD_SPEAKERMODE speakerModeType = (FMOD_SPEAKERMODE)cat;
509 result = _system->setSpeakerMode( speakerModeType);
510 fmod_audio_errcheck(
"_system->setSpeakerMode()", result);
521 result = _channelgroup->setVolume(volume);
522 fmod_audio_errcheck(
"_channelgroup->setVolume()", result);
533 result = _channelgroup->getVolume(&volume);
534 fmod_audio_errcheck(
"_channelgroup->getVolume()", result);
535 return (PN_stdfloat)volume;
545 _system->getOutput(&_saved_outputtype);
546 _system->setOutput(FMOD_OUTPUTTYPE_WAVWRITER);
549 _system->setOutput(_saved_outputtype);
560 if (_active != active) {
564 for (SoundSet::iterator i = _all_sounds.begin();
565 i != _all_sounds.end();
567 (*i)->set_active(_active);
575 bool FmodAudioManager::
589 SoundSet::iterator i;
590 i = _all_sounds.begin();
591 while (i != _all_sounds.end()) {
592 SoundSet::iterator next = i;
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) {
623 audio_debug(
"FmodAudioManager::audio_3d_set_listener_attributes()");
643 result = _system->set3DListenerAttributes( 0, &_position, &_velocity, &_forward, &_up);
644 fmod_audio_errcheck(
"_system->set3DListenerAttributes()", result);
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");
665 audio_debug(
"FmodAudioManager::audio_3d_set_distance_factor( factor= " << factor <<
")" );
669 _distance_factor = factor;
671 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
672 fmod_audio_errcheck(
"_system->set3DSettings()", result);
683 audio_debug(
"FmodAudioManager::audio_3d_get_distance_factor()");
685 return _distance_factor;
694 audio_debug(
"FmodAudioManager::audio_3d_set_doppler_factor(factor="<<factor<<
")");
698 _doppler_factor = factor;
700 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
701 fmod_audio_errcheck(
"_system->set3DSettings()", result);
708 PN_stdfloat FmodAudioManager::
709 audio_3d_get_doppler_factor()
const {
710 audio_debug(
"FmodAudioManager::audio_3d_get_doppler_factor()");
712 return _doppler_factor;
721 audio_debug(
"FmodAudioManager::audio_3d_set_drop_off_factor("<<factor<<
")");
725 _drop_off_factor = factor;
727 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
728 fmod_audio_errcheck(
"_system->set3DSettings()", result);
735 PN_stdfloat FmodAudioManager::
736 audio_3d_get_drop_off_factor()
const {
738 audio_debug(
"FmodAudioManager::audio_3d_get_drop_off_factor()");
740 return _drop_off_factor;
776 audio_debug(
"FmodAudioManager::uncache_sound(\""<<file_name<<
"\")");
786 audio_debug(
"FmodAudioManager::clear_cache()");
795 audio_debug(
"FmodAudioManager::set_cache_limit(count="<<count<<
")");
804 audio_debug(
"FmodAudioManager::get_cache_limit() returning ");
get_dls_pathname
Returns the full pathname to the DLS file, as specified by the Config.prc file, or the default for th...
The name of a file, such as a texture file or an Egg file.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
void set_binary()
Indicates that the filename represents a binary file.
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.
Similar to MutexHolder, but for a reentrant mutex.
TypeHandle is the identifier used to differentiate C++ class types.
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.
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.