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 ");
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.
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.
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...
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.
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.
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.
A MovieAudio is actually any source that provides a sequence of audio samples.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
virtual void stop_all_sounds()
Stop playback on all sounds managed by this manager.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.