fix fmod for OSX; fix reference count leaks; use model-path as well as sound-path
This commit is contained in:
parent
53e190a77a
commit
694873dc37
|
|
@ -41,6 +41,14 @@ ConfigVariableString audio_library_name
|
|||
ConfigVariableDouble audio_volume
|
||||
("audio-volume", 1.0f);
|
||||
|
||||
ConfigVariableFilename audio_dls_file
|
||||
("audio-dls-file", Filename(),
|
||||
PRC_DESC("Specifies a DLS file that defines an instrument set to load "
|
||||
"for MIDI file playback. If this is not specified, the sound "
|
||||
"interface will try to use the system default DLS file, if "
|
||||
"one is available; the likely success of this depends on the "
|
||||
"operating system."));
|
||||
|
||||
// Config variables for Fmod:
|
||||
|
||||
//I should note this somewhere. The actual number of sound one could
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ NotifyCategoryDecl(audio, EXPCL_PANDA, EXPTP_PANDA);
|
|||
extern EXPCL_PANDA ConfigVariableBool audio_active;
|
||||
extern EXPCL_PANDA ConfigVariableInt audio_cache_limit;
|
||||
extern EXPCL_PANDA ConfigVariableDouble audio_volume;
|
||||
extern EXPCL_PANDA ConfigVariableFilename audio_dls_file;
|
||||
|
||||
//We Need This one.
|
||||
extern EXPCL_PANDA ConfigVariableString audio_library_name;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#begin lib_target
|
||||
#define TARGET fmod_audio
|
||||
#define BUILD_TARGET $[HAVE_FMODEX]
|
||||
#define USE_PACKAGES fmod
|
||||
#define USE_PACKAGES fmodex
|
||||
#define BUILDING_DLL BUILDING_FMOD_AUDIO
|
||||
#define LOCAL_LIBS audio event
|
||||
#define WIN_SYS_LIBS $[WIN_SYS_LIBS] user32.lib advapi32.lib winmm.lib
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ FmodAudioDSP(AudioManager *manager, AudioManager::DSP_category cat) {
|
|||
FMOD_DSP_TYPE dsptype = (FMOD_DSP_TYPE)cat;
|
||||
|
||||
result = _manager->_system->createDSPByType( dsptype, &_dsp);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_system->createDSPByType()", result);
|
||||
|
||||
set_in_chain(false);
|
||||
|
||||
|
|
@ -74,10 +74,10 @@ FmodAudioDSP::
|
|||
FMOD_RESULT result;
|
||||
|
||||
result = _dsp->remove();
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->remove()", result);
|
||||
|
||||
result = _dsp->release();
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->release()", result);
|
||||
|
||||
audio_debug("DSP GONE");
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ reset() {
|
|||
FMOD_RESULT result;
|
||||
|
||||
result = _dsp->reset();
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->reset()", result);
|
||||
|
||||
audio_debug("DSP Reset.");
|
||||
}
|
||||
|
|
@ -118,7 +118,7 @@ remove() {
|
|||
FMOD_RESULT result;
|
||||
|
||||
result = _dsp->remove();
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->remove()", result);
|
||||
|
||||
audio_debug("DSP Removed from relative effects chain.");
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ set_bypass(bool bypass) {
|
|||
FMOD_RESULT result;
|
||||
|
||||
result = _dsp->setBypass(bypass);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->setBypass()", result);
|
||||
|
||||
audio_debug("DSP Bypass set to:" << bypass );
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ get_bypass() {
|
|||
bool bypass;
|
||||
|
||||
result = _dsp->getBypass(&bypass);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->getBypass()", result);
|
||||
|
||||
return bypass;
|
||||
}
|
||||
|
|
@ -183,7 +183,7 @@ set_parameter(const string &name, float value) {
|
|||
FMOD_RESULT result;
|
||||
|
||||
result = _dsp->setParameter(parameterIndex, value);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->setParameter()", result);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -203,7 +203,7 @@ get_num_parameters() {
|
|||
int numOfParameters;
|
||||
|
||||
result = _dsp->getNumParameters(&numOfParameters);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->getNumParameters()", result);
|
||||
|
||||
return numOfParameters;
|
||||
}
|
||||
|
|
@ -231,7 +231,7 @@ get_parameter_name(int parameterIndex) {
|
|||
float parameterMax;
|
||||
|
||||
result = _dsp->getParameterInfo(parameterIndex, parameterName, parameterLabel, parameterDescription, parameterDescriptionLength, ¶meterMin, ¶meterMax);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->getParameterInfo()", result);
|
||||
|
||||
string returnInfo = (parameterName);
|
||||
|
||||
|
|
@ -275,7 +275,7 @@ get_parameter_description(int parameterIndex) {
|
|||
float parameterMax;
|
||||
|
||||
result = _dsp->getParameterInfo(parameterIndex, parameterName, parameterLabel, parameterDescription, parameterDescriptionLength, ¶meterMin, ¶meterMax);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->getParameterInfo()", result);
|
||||
|
||||
return parameterLabel;
|
||||
|
||||
|
|
@ -304,7 +304,7 @@ get_parameter_min(int parameterIndex) {
|
|||
float parameterMax;
|
||||
|
||||
result = _dsp->getParameterInfo(parameterIndex, parameterName, parameterLabel, parameterDescription, parameterDescriptionLength, ¶meterMin, ¶meterMax);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->getParameterInfo()", result);
|
||||
|
||||
return parameterMin;
|
||||
}
|
||||
|
|
@ -332,7 +332,7 @@ get_parameter_max(int parameterIndex) {
|
|||
float parameterMax;
|
||||
|
||||
result = _dsp->getParameterInfo(parameterIndex, parameterName, parameterLabel, parameterDescription, parameterDescriptionLength, ¶meterMin, ¶meterMax);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->getParameterInfo()", result);
|
||||
|
||||
return parameterMax;
|
||||
}
|
||||
|
|
@ -361,7 +361,7 @@ get_parameter_value(const string &name) {
|
|||
|
||||
|
||||
result = _dsp->getParameter(parameterIndex, ¶meterValue, valuestr, valuestrlen);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->getParameter()", result);
|
||||
|
||||
return parameterValue;
|
||||
}
|
||||
|
|
@ -404,7 +404,7 @@ get_dsp_name() {
|
|||
int configheight;
|
||||
|
||||
result = _dsp->getInfo(name, &version, &channels, &configwidth, &configheight);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_dsp->getInfo()", result);
|
||||
|
||||
string returnInfo = (name);
|
||||
//returnInfo.append(" Version: ");
|
||||
|
|
|
|||
|
|
@ -43,15 +43,31 @@
|
|||
|
||||
TypeHandle FmodAudioManager::_type_handle;
|
||||
|
||||
FMOD::System *FmodAudioManager::_system;
|
||||
pset<FmodAudioManager *> FmodAudioManager::_all_managers;
|
||||
|
||||
bool FmodAudioManager::_system_is_valid = false;
|
||||
|
||||
|
||||
// This sets the distance factor for 3D audio to use feet.
|
||||
// FMOD uses meters by default.
|
||||
// Since Panda use feet we need to compensate for that with a factor of 3.28
|
||||
//
|
||||
// This can be overwritten. You just need to call
|
||||
// audio_3d_set_distance_factor(float factor) and set your new factor.
|
||||
|
||||
float FmodAudioManager::_doppler_factor = 1;
|
||||
float FmodAudioManager::_distance_factor = 3.28;
|
||||
float FmodAudioManager::_drop_off_factor = 1;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Central dispatcher for audio errors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
void fmod_audio_errcheck(FMOD_RESULT result) {
|
||||
void fmod_audio_errcheck(const char *context, FMOD_RESULT result) {
|
||||
if (result != 0) {
|
||||
audio_error("FMOD Error: "<< FMOD_ErrorString(result) );
|
||||
audio_error(context << ": " << FMOD_ErrorString(result) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,48 +111,60 @@ FmodAudioManager() {
|
|||
_up.x = 0;
|
||||
_up.y = 0;
|
||||
_up.z = 0;
|
||||
|
||||
if (_system == (FMOD::System *)NULL) {
|
||||
// Create the global FMOD System object. This one object must be
|
||||
// shared by all FmodAudioManagers (this is particularly true on
|
||||
// OSX, but the FMOD documentation is unclear as to whether this
|
||||
// is the intended design on all systems).
|
||||
|
||||
result = FMOD::System_Create(&_system);
|
||||
fmod_audio_errcheck("FMOD::System_Create()", result);
|
||||
|
||||
// Let check the Version of FMOD to make sure the Headers and Libraries are correct.
|
||||
result = _system->getVersion(&version);
|
||||
fmod_audio_errcheck("_system->getVersion()", result);
|
||||
|
||||
if (version < FMOD_VERSION){
|
||||
audio_error("You are using an old version of FMOD. This program requires:" << FMOD_VERSION);
|
||||
}
|
||||
|
||||
//Stick Surround Sound 5.1 thing Here.
|
||||
if (fmod_use_surround_sound) {
|
||||
audio_debug("Setting FMOD to use 5.1 Surround Sound.");
|
||||
result = _system->setSpeakerMode( FMOD_SPEAKERMODE_5POINT1 );
|
||||
fmod_audio_errcheck("_system->setSpeakerMode()", result);
|
||||
}
|
||||
|
||||
//Now we Initialize the System.
|
||||
result = _system->init(fmod_number_of_sound_channels, FMOD_INIT_NORMAL, 0);
|
||||
fmod_audio_errcheck("_system->init()", result);
|
||||
|
||||
_system_is_valid = (result == FMOD_OK);
|
||||
|
||||
if (_system_is_valid) {
|
||||
result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
|
||||
fmod_audio_errcheck("_system->set3DSettings()", result);
|
||||
|
||||
result = _system->setFileSystem(open_callback, close_callback, read_callback, seek_callback, -1);
|
||||
fmod_audio_errcheck("_system->setFileSystem()", result);
|
||||
}
|
||||
}
|
||||
|
||||
_is_valid = _system_is_valid;
|
||||
|
||||
memset(&_midi_info, 0, sizeof(_midi_info));
|
||||
_midi_info.cbsize = sizeof(_midi_info);
|
||||
|
||||
Filename dls_filename = audio_dls_file;
|
||||
if (!dls_filename.empty()) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->resolve_filename(dls_filename, get_sound_path()) ||
|
||||
vfs->resolve_filename(dls_filename, get_model_path());
|
||||
|
||||
result = FMOD::System_Create(&_system);
|
||||
fmod_audio_errcheck(result);
|
||||
|
||||
// Let check the Version of FMOD to make sure the Headers and Libraries are correct.
|
||||
result = _system->getVersion(&version);
|
||||
fmod_audio_errcheck(result);
|
||||
|
||||
if (version < FMOD_VERSION){
|
||||
audio_error("You are using an old version of FMOD. This program requires:" << FMOD_VERSION);
|
||||
_dlsname = dls_filename.to_os_specific();
|
||||
_midi_info.dlsname = _dlsname.c_str();
|
||||
}
|
||||
|
||||
//Stick Surround Sound 5.1 thing Here.
|
||||
if (fmod_use_surround_sound) {
|
||||
audio_debug("Setting FMOD to use 5.1 Surround Sound.");
|
||||
result = _system->setSpeakerMode( FMOD_SPEAKERMODE_5POINT1 );
|
||||
fmod_audio_errcheck(result);
|
||||
}
|
||||
|
||||
//Now we Initialize the System.
|
||||
result = _system->init(fmod_number_of_sound_channels, FMOD_INIT_NORMAL, 0);
|
||||
fmod_audio_errcheck(result);
|
||||
|
||||
if (result == FMOD_OK){
|
||||
_is_valid = true;
|
||||
} else {
|
||||
_is_valid = false;
|
||||
}
|
||||
|
||||
// This sets the distance factor for 3D audio to use feet.
|
||||
// FMOD uses meters by default.
|
||||
// Since Panda use feet we need to compensate for that with a factor of 3.28
|
||||
//
|
||||
// This can be over written. You just need to call
|
||||
// audio_3d_set_distance_factor(float factor) and set you new factor.
|
||||
|
||||
_doppler_factor = 1;
|
||||
_distance_factor = 3.28;
|
||||
_drop_off_factor = 1;
|
||||
|
||||
result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
|
||||
fmod_audio_errcheck( result );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -158,8 +186,12 @@ FmodAudioManager::
|
|||
// Remove me from the managers list.
|
||||
_all_managers.erase(this);
|
||||
|
||||
if (_all_managers.empty()) {
|
||||
result = _system->release();
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_system->release()", result);
|
||||
_system = NULL;
|
||||
_system_is_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -186,7 +218,8 @@ get_sound(const string &file_name, bool positional) {
|
|||
Filename path = file_name;
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->resolve_filename(path, get_sound_path());
|
||||
vfs->resolve_filename(path, get_sound_path()) ||
|
||||
vfs->resolve_filename(path, get_model_path());
|
||||
|
||||
// Build a new AudioSound from the audio data.
|
||||
PT(AudioSound) audioSound = 0;
|
||||
|
|
@ -233,7 +266,7 @@ add_dsp( PT(AudioDSP) x) {
|
|||
return false;
|
||||
} else {
|
||||
result = _system->addDSP( fdsp->_dsp );
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_system->addDSP()", result);
|
||||
_system_dsp.insert(fdsp);
|
||||
fdsp->set_in_chain(true);
|
||||
return true;
|
||||
|
|
@ -256,7 +289,7 @@ remove_dsp(PT(AudioDSP) x) {
|
|||
|
||||
if ( fdsp->get_in_chain() ) {
|
||||
result = fdsp->_dsp->remove();
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_dsp->remove()", result);
|
||||
|
||||
_system_dsp.erase(fdsp);
|
||||
|
||||
|
|
@ -281,7 +314,7 @@ getSpeakerSetup() {
|
|||
int returnMode;
|
||||
|
||||
result = _system->getSpeakerMode( &speakerMode );
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_system->getSpeakerMode()", result);
|
||||
|
||||
switch (speakerMode) {
|
||||
case FMOD_SPEAKERMODE_RAW:
|
||||
|
|
@ -343,7 +376,7 @@ setSpeakerSetup(AudioManager::SpeakerModeCategory cat) {
|
|||
FMOD_RESULT result;
|
||||
FMOD_SPEAKERMODE speakerModeType = (FMOD_SPEAKERMODE)cat;
|
||||
result = _system->setSpeakerMode( speakerModeType);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_system->setSpeakerMode()", result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -378,7 +411,16 @@ get_volume() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void FmodAudioManager::
|
||||
set_active(bool active) {
|
||||
_active = active;
|
||||
if (_active != active) {
|
||||
_active = active;
|
||||
|
||||
// Tell our AudioSounds to adjust:
|
||||
for (SoundSet::iterator i = _all_sounds.begin();
|
||||
i != _all_sounds.end();
|
||||
++i) {
|
||||
(*i)->set_active(_active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -398,8 +440,17 @@ get_active() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void FmodAudioManager::
|
||||
stop_all_sounds() {
|
||||
for (SoundSet::iterator i = _all_sounds.begin(); i != _all_sounds.end(); ++i) {
|
||||
// We have to walk through this list with some care, since stopping
|
||||
// a sound may also remove it from the set (if there are no other
|
||||
// references to the sound).
|
||||
SoundSet::iterator i;
|
||||
i = _all_sounds.begin();
|
||||
while (i != _all_sounds.end()) {
|
||||
SoundSet::iterator next = i;
|
||||
++next;
|
||||
|
||||
(*i)->stop();
|
||||
i = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +502,7 @@ audio_3d_set_listener_attributes(float px, float py, float pz, float vx, float v
|
|||
_up.z = uy;
|
||||
|
||||
result = _system->set3DListenerAttributes( 0, &_position, &_velocity, &_forward, &_up);
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_system->set3DListenerAttributes()", result);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -482,7 +533,7 @@ audio_3d_set_distance_factor(float factor) {
|
|||
_distance_factor = factor;
|
||||
|
||||
result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_system->set3DSettings()", result);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -515,7 +566,7 @@ audio_3d_set_doppler_factor(float factor) {
|
|||
_doppler_factor = factor;
|
||||
|
||||
result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_system->set3DSettings()", result);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -546,7 +597,7 @@ audio_3d_set_drop_off_factor(float factor) {
|
|||
_drop_off_factor = factor;
|
||||
|
||||
result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_system->set3DSettings()", result);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -646,6 +697,92 @@ get_cache_limit() const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::open_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioManager::
|
||||
open_callback(const char *name, int, unsigned int *file_size,
|
||||
void **handle, void **user_data) {
|
||||
if (name == (const char *)NULL || name[0] == '\0') {
|
||||
// An invalid attempt to open an unnamed file.
|
||||
return FMOD_ERR_FILE_NOTFOUND;
|
||||
}
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
PT(VirtualFile) file = vfs->get_file(Filename(name));
|
||||
if (file == (VirtualFile *)NULL) {
|
||||
return FMOD_ERR_FILE_NOTFOUND;
|
||||
}
|
||||
istream *str = file->open_read_file(true);
|
||||
|
||||
(*file_size) = file->get_file_size(str);
|
||||
(*handle) = (void *)str;
|
||||
(*user_data) = NULL;
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::close_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioManager::
|
||||
close_callback(void *handle, void *user_data) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
istream *str = (istream *)handle;
|
||||
vfs->close_read_file(str);
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::read_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioManager::
|
||||
read_callback(void *handle, void *buffer, unsigned int size_bytes,
|
||||
unsigned int *bytes_read, void *user_data) {
|
||||
istream *str = (istream *)handle;
|
||||
str->read((char *)buffer, size_bytes);
|
||||
(*bytes_read) = str->gcount();
|
||||
|
||||
if (str->eof()) {
|
||||
if ((*bytes_read) == 0) {
|
||||
return FMOD_ERR_FILE_EOF;
|
||||
} else {
|
||||
// Report the EOF next time.
|
||||
return FMOD_OK;
|
||||
}
|
||||
} if (str->fail()) {
|
||||
return FMOD_ERR_FILE_BAD;
|
||||
} else {
|
||||
return FMOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::seek_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioManager::
|
||||
seek_callback(void *handle, unsigned int pos, void *user_data) {
|
||||
istream *str = (istream *)handle;
|
||||
str->clear();
|
||||
str->seekg(pos);
|
||||
|
||||
if (str->fail() && !str->eof()) {
|
||||
return FMOD_ERR_FILE_COULDNOTSEEK;
|
||||
} else {
|
||||
return FMOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //]
|
||||
|
|
|
|||
|
|
@ -23,43 +23,52 @@
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//Hello, all future Panda audio code people! This is my errata documentation to
|
||||
//help any future programmer maintain FMOD and PANDA.
|
||||
//Hello, all future Panda audio code people! This is my errata
|
||||
//documentation to help any future programmer maintain FMOD and PANDA.
|
||||
//
|
||||
//This documentation more then that is needed, but I wanted to go all out, with
|
||||
//the documentation. Because I was a totally newbie at programming [especially
|
||||
//with C/C++] this semester I want to make sure future code maintainers have that
|
||||
//insight I did not when starting on the PANDA project here at the ETC/CMU.
|
||||
//This documentation more then that is needed, but I wanted to go all
|
||||
//out, with the documentation. Because I was a totally newbie at
|
||||
//programming [especially with C/C++] this semester I want to make
|
||||
//sure future code maintainers have that insight I did not when
|
||||
//starting on the PANDA project here at the ETC/CMU.
|
||||
//
|
||||
//As of Spring 2006, Panda's FMOD audio support has been pretty much completely
|
||||
//rewritten. This has been done so PANDA can use FMOD-EX [or AKA FMOD 4] and some
|
||||
//of its new features.
|
||||
//As of Spring 2006, Panda's FMOD audio support has been pretty much
|
||||
//completely rewritten. This has been done so PANDA can use FMOD-EX
|
||||
//[or AKA FMOD 4] and some of its new features.
|
||||
//
|
||||
//First, the FMOD-EX API itself has been completely rewritten compared to previous
|
||||
//versions. FMOD now handles any type of audio files, wave audio [WAV, AIF, MP3,
|
||||
//OGG, etc...] or musical file [MID, TRACKERS] as the same type of an object. The
|
||||
//API has also been structured more like a sound studio, with 'sounds' and
|
||||
//'channels'. This will be covered more in the FmodAudioSound.h/.cxx sources.
|
||||
//First, the FMOD-EX API itself has been completely rewritten compared
|
||||
//to previous versions. FMOD now handles any type of audio files, wave
|
||||
//audio [WAV, AIF, MP3, OGG, etc...] or musical file [MID, TRACKERS]
|
||||
//as the same type of an object. The API has also been structured more
|
||||
//like a sound studio, with 'sounds' and 'channels'. This will be
|
||||
//covered more in the FmodAudioSound.h/.cxx sources.
|
||||
//
|
||||
//Second, FMOD now offers virtually unlimited sounds to be played at once via
|
||||
//their virtual channels system. Actually the theoretical limit is around 4000,
|
||||
//but that is still a lot. What you need to know about this, is that even thought
|
||||
//you might only hear 32 sound being played at once, FMOD will keep playing any
|
||||
//additional sounds, and swap those on virtual channels in and out with those on real channels
|
||||
//depending on priority, or distance [if you are dealing with 3D audio].
|
||||
//Second, FMOD now offers virtually unlimited sounds to be played at
|
||||
//once via their virtual channels system. Actually the theoretical
|
||||
//limit is around 4000, but that is still a lot. What you need to know
|
||||
//about this, is that even thought you might only hear 32 sound being
|
||||
//played at once, FMOD will keep playing any additional sounds, and
|
||||
//swap those on virtual channels in and out with those on real
|
||||
//channels depending on priority, or distance [if you are dealing with
|
||||
//3D audio].
|
||||
//
|
||||
//Third, FMOD's DSP support has been added. So you can now add GLOBAL or SOUND
|
||||
//specific DSP effects. Right not you can only use FMOD's built in DSP effects.
|
||||
//But adding support for FMOD's support of VST effects shouldn't be that hard.
|
||||
//Third, FMOD's DSP support has been added. So you can now add GLOBAL
|
||||
//or SOUND specific DSP effects. Right not you can only use FMOD's
|
||||
//built in DSP effects. But adding support for FMOD's support of VST
|
||||
//effects shouldn't be that hard.
|
||||
//
|
||||
//As for the FmodManager itself, it is pretty straight forward, I hope. As a
|
||||
//manager class, it will create the FMOD system with the ‘_system’ variable which
|
||||
//is an instance of FMOD::SYSTEM. This class is also the one responsible for
|
||||
//creation of Sounds, DSP, and maintaining the GLOBAL DSP chains [The GLOBAL DSP
|
||||
//chain is the DSP Chain which affects ALL the sounds].
|
||||
//As for the FmodManager itself, it is pretty straight forward, I
|
||||
//hope. As a manager class, it will create the FMOD system with the
|
||||
//"_system" variable which is an instance of FMOD::SYSTEM. (Actually,
|
||||
//we create only one global _system variable now, and share it with
|
||||
//all outstanding FmodManager objects--this appears to be the way FMOD
|
||||
//wants to work.) The FmodManager class is also the one responsible
|
||||
//for creation of Sounds, DSP, and maintaining the GLOBAL DSP chains
|
||||
//[The GLOBAL DSP chain is the DSP Chain which affects ALL the
|
||||
//sounds].
|
||||
//
|
||||
//Any way that is it for an intro, lets move on to looking at the rest of the
|
||||
//code.
|
||||
//Any way that is it for an intro, lets move on to looking at the rest
|
||||
//of the code.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -82,7 +91,7 @@
|
|||
class FmodAudioSound;
|
||||
class FmodAudioDSP;
|
||||
|
||||
extern void fmod_audio_errcheck(FMOD_RESULT n);
|
||||
extern void fmod_audio_errcheck(const char *context, FMOD_RESULT n);
|
||||
|
||||
class EXPCL_FMOD_AUDIO FmodAudioManager : public AudioManager {
|
||||
friend class FmodAudioSound;
|
||||
|
|
@ -163,24 +172,44 @@ class EXPCL_FMOD_AUDIO FmodAudioManager : public AudioManager {
|
|||
virtual unsigned int get_cache_limit() const;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
open_callback(const char *name, int unicode, unsigned int *file_size,
|
||||
void **handle, void **user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
close_callback(void *handle, void *user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
read_callback(void *handle, void *buffer, unsigned int size_bytes,
|
||||
unsigned int *bytes_read, void *user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
seek_callback(void *handle, unsigned int pos, void *user_data);
|
||||
|
||||
private:
|
||||
|
||||
FMOD::System *_system;
|
||||
|
||||
static FMOD::System *_system;
|
||||
static pset<FmodAudioManager *> _all_managers;
|
||||
|
||||
static bool _system_is_valid;
|
||||
|
||||
static float _distance_factor;
|
||||
static float _doppler_factor;
|
||||
static float _drop_off_factor;
|
||||
|
||||
FMOD_VECTOR _position;
|
||||
FMOD_VECTOR _velocity;
|
||||
FMOD_VECTOR _forward;
|
||||
FMOD_VECTOR _up;
|
||||
|
||||
// DLS info for MIDI files
|
||||
string _dlsname;
|
||||
FMOD_CREATESOUNDEXINFO _midi_info;
|
||||
|
||||
bool _is_valid;
|
||||
bool _active;
|
||||
|
||||
float _distance_factor;
|
||||
float _doppler_factor;
|
||||
float _drop_off_factor;
|
||||
|
||||
// The set of all sounds. Needed only to implement stop_all_sounds.
|
||||
typedef pset<FmodAudioSound *> SoundSet;
|
||||
SoundSet _all_sounds;
|
||||
|
|
@ -189,8 +218,6 @@ class EXPCL_FMOD_AUDIO FmodAudioManager : public AudioManager {
|
|||
typedef pset<PT (FmodAudioDSP) > DSPSet;
|
||||
DSPSet _system_dsp;
|
||||
|
||||
friend class FmodAudioSound;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//These are needed for Panda's Pointer System. DO NOT ERASE!
|
||||
////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ FmodAudioSound::
|
|||
FmodAudioSound(AudioManager *manager, Filename file_name, bool positional) {
|
||||
audio_debug("FmodAudioSound::FmodAudioSound() Creating new sound, filename: " << file_name );
|
||||
|
||||
_active = manager->get_active();
|
||||
|
||||
//Local Variables that are needed.
|
||||
FMOD_RESULT result;
|
||||
|
||||
|
|
@ -73,9 +75,11 @@ FmodAudioSound(AudioManager *manager, Filename file_name, bool positional) {
|
|||
_channel = 0;
|
||||
_file_name = file_name;
|
||||
|
||||
FMOD_CREATESOUNDEXINFO *sound_info = NULL;
|
||||
|
||||
//Get the Speaker Mode [Important for later on.]
|
||||
result = _manager->_system->getSpeakerMode( &_speakermode );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_system->getSpeakerMode()", result);
|
||||
|
||||
// Calculate the approximate uncompressed size of the sound.
|
||||
int size = file_name.get_file_size();
|
||||
|
|
@ -84,12 +88,20 @@ FmodAudioSound(AudioManager *manager, Filename file_name, bool positional) {
|
|||
|
||||
int flag = positional ? FMOD_3D : FMOD_2D;
|
||||
int streamflag = (size > 250000) ? FMOD_CREATESTREAM : FMOD_CREATESAMPLE;
|
||||
|
||||
result = _manager->_system->createSound( file_name.to_os_specific().c_str(), FMOD_SOFTWARE | streamflag | flag , 0, &_sound);
|
||||
if (ext == "mid") {
|
||||
streamflag = FMOD_CREATESTREAM;
|
||||
sound_info = &_manager->_midi_info;
|
||||
}
|
||||
|
||||
result = _manager->_system->createSound( file_name.c_str(), FMOD_SOFTWARE | streamflag | flag ,
|
||||
sound_info, &_sound);
|
||||
if (result != FMOD_OK) {
|
||||
audio_error("createSound(" << file_name << "): " << FMOD_ErrorString(result));
|
||||
|
||||
// We couldn't load the sound file. Create a blank sound record
|
||||
// instead.
|
||||
char blank_data[100];
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
audio_error("CreateSound " << file_name << ": " << FMOD_ErrorString(result));
|
||||
memset(&exinfo, 0, sizeof(exinfo));
|
||||
memset(blank_data, 0, sizeof(blank_data));
|
||||
exinfo.cbsize = sizeof(exinfo);
|
||||
|
|
@ -98,7 +110,7 @@ FmodAudioSound(AudioManager *manager, Filename file_name, bool positional) {
|
|||
exinfo.defaultfrequency = 8000;
|
||||
exinfo.format = FMOD_SOUND_FORMAT_PCM16;
|
||||
result = _manager->_system->createSound( blank_data, FMOD_SOFTWARE | flag | FMOD_OPENMEMORY | FMOD_OPENRAW, &exinfo, &_sound);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("createSound (blank)", result);
|
||||
}
|
||||
|
||||
//This is just to collect the defaults of the sound, so we don't
|
||||
|
|
@ -107,7 +119,7 @@ FmodAudioSound(AudioManager *manager, Filename file_name, bool positional) {
|
|||
//'set_play_rate()' and 'get_play_rate()' methods later;
|
||||
|
||||
result = _sound->getDefaults( &_sampleFrequency, &_volume , &_balance, &_priority);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->getDefaults()", result);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -128,7 +140,7 @@ FmodAudioSound::
|
|||
|
||||
//The Release Sound
|
||||
result = _sound->release();
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->release()", result);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -154,7 +166,7 @@ FMOD_RESULT F_CALLBACK sound_end_callback(FMOD_CHANNEL * channel,
|
|||
unsigned int commanddata1,
|
||||
unsigned int commanddata2) {
|
||||
FmodAudioSound *fsound = (FmodAudioSound*)command;
|
||||
fsound->unref();
|
||||
fsound->_self_ref = fsound;
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
|
@ -170,9 +182,9 @@ stop() {
|
|||
if (_channel != 0) {
|
||||
result =_channel->stop();
|
||||
if (result == FMOD_OK) {
|
||||
unref();
|
||||
_self_ref.clear();
|
||||
}
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->stop()", result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,11 +199,10 @@ set_loop(bool loop) {
|
|||
FMOD_RESULT result;
|
||||
if ( loop ) {
|
||||
result = _sound->setMode(FMOD_LOOP_NORMAL);
|
||||
fmod_audio_errcheck(result);
|
||||
} else {
|
||||
result = _sound->setMode(FMOD_LOOP_OFF);
|
||||
fmod_audio_errcheck(result);
|
||||
}
|
||||
fmod_audio_errcheck("_sound->setMode()", result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -210,7 +221,7 @@ get_loop() const {
|
|||
bool loopState;
|
||||
|
||||
result = _sound->getMode( &loopMode );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->getMode()", result);
|
||||
|
||||
if ( (loopMode & FMOD_LOOP_NORMAL) != 0 ) {
|
||||
loopState = true;
|
||||
|
|
@ -244,11 +255,10 @@ set_loop_count(unsigned long loop_count) {
|
|||
|
||||
if (numberOfLoops == 0) {
|
||||
result = _sound->setLoopCount( -1 );
|
||||
fmod_audio_errcheck(result);
|
||||
} else {
|
||||
result = _sound->setLoopCount( numberOfLoops );
|
||||
fmod_audio_errcheck(result);
|
||||
}
|
||||
fmod_audio_errcheck("_sound->setLoopCount()", result);
|
||||
|
||||
audio_debug("FmodAudioSound::set_loop_count() Sound's loop count should be set to: " << loop_count);
|
||||
}
|
||||
|
|
@ -268,7 +278,7 @@ get_loop_count() const {
|
|||
unsigned long returnedNumber;
|
||||
|
||||
result = _sound->getLoopCount( &loop_count );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->getLoopCount()", result);
|
||||
|
||||
audio_debug("FmodAudioSound::get_loop_count() returning "<< loop_count);
|
||||
|
||||
|
|
@ -285,34 +295,36 @@ get_loop_count() const {
|
|||
void FmodAudioSound::
|
||||
set_time(float start_time) {
|
||||
FMOD_RESULT result;
|
||||
bool playing;
|
||||
|
||||
int startTime = (int)(start_time * 1000);
|
||||
|
||||
if (_channel != 0) {
|
||||
// try backing up current sound.
|
||||
result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
|
||||
if (result == FMOD_ERR_INVALID_HANDLE) {
|
||||
if (result == FMOD_ERR_INVALID_HANDLE ||
|
||||
result == FMOD_ERR_CHANNEL_STOLEN) {
|
||||
_channel = 0;
|
||||
|
||||
} else {
|
||||
fmod_audio_errcheck(result);
|
||||
}
|
||||
result = _channel->isPlaying(&playing);
|
||||
if ((result == FMOD_ERR_INVALID_HANDLE) || (playing == false)) {
|
||||
_channel = 0;
|
||||
} else {
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->setPosition()", result);
|
||||
|
||||
bool playing;
|
||||
result = _channel->isPlaying(&playing);
|
||||
fmod_audio_errcheck("_channel->isPlaying()", result);
|
||||
if (result != FMOD_OK || !playing) {
|
||||
_channel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_channel == 0) {
|
||||
|
||||
result = _manager->_system->playSound(FMOD_CHANNEL_FREE, _sound, true, &_channel);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_system->playSound()", result);
|
||||
result = _channel->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, sound_end_callback, (int)this);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->setCallback()", result);
|
||||
result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->setPosition()", result);
|
||||
|
||||
set_volume_on_channel();
|
||||
set_play_rate_on_channel();
|
||||
|
|
@ -320,13 +332,13 @@ set_time(float start_time) {
|
|||
add_dsp_on_channel();
|
||||
set_3d_attributes_on_channel();
|
||||
|
||||
result = _channel->setPaused(false);
|
||||
fmod_audio_errcheck(result);
|
||||
if (_active) {
|
||||
result = _channel->setPaused(false);
|
||||
fmod_audio_errcheck("_channel->setPaused()", result);
|
||||
}
|
||||
|
||||
this->ref();
|
||||
_self_ref = this;
|
||||
}
|
||||
|
||||
fmod_audio_errcheck(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -347,7 +359,7 @@ get_time() const {
|
|||
if (result == FMOD_ERR_INVALID_HANDLE) {
|
||||
return 0.0f;
|
||||
}
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->getPosition()", result);
|
||||
|
||||
current_time = current_time / 1000;
|
||||
|
||||
|
|
@ -390,7 +402,7 @@ set_volume_on_channel() {
|
|||
if (result == FMOD_ERR_INVALID_HANDLE) {
|
||||
_channel = 0;
|
||||
} else {
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->setVolume()", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -459,7 +471,7 @@ set_play_rate_on_channel() {
|
|||
if (result == FMOD_ERR_INVALID_HANDLE) {
|
||||
_channel = 0;
|
||||
} else {
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->setFrequency()", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -486,7 +498,7 @@ length() const {
|
|||
unsigned int length;
|
||||
|
||||
result = _sound->getLength( &length, FMOD_TIMEUNIT_MS );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->getLength()", result);
|
||||
|
||||
length = length / 1000;
|
||||
|
||||
|
|
@ -532,14 +544,14 @@ set_3d_attributes_on_channel() {
|
|||
FMOD_MODE soundMode;
|
||||
|
||||
result = _sound->getMode(&soundMode);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->getMode()", result);
|
||||
|
||||
if ((_channel != 0) && (soundMode & FMOD_3D)) {
|
||||
result = _channel->set3DAttributes( &_location, &_velocity );
|
||||
if (result == FMOD_ERR_INVALID_HANDLE) {
|
||||
_channel = 0;
|
||||
} else {
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->set3DAttributes()", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -568,7 +580,7 @@ set_3d_min_distance(float dist) {
|
|||
_min_dist = dist;
|
||||
|
||||
result = _sound->set3DMinMaxDistance( dist, _max_dist );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->set3DMinMaxDistance()", result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -593,7 +605,7 @@ set_3d_max_distance(float dist) {
|
|||
_max_dist = dist;
|
||||
|
||||
result = _sound->set3DMinMaxDistance( _min_dist, dist );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->set3DMinMaxDistance()", result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -636,10 +648,10 @@ add_dsp( PT(AudioDSP) x) {
|
|||
|
||||
if ( _channel != 0 ) {
|
||||
result = _channel->isPlaying( &playingState );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->isPlaying()", result);
|
||||
if ( playingState ) {
|
||||
result = _channel->addDSP( fdsp->_dsp );
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_channel->addDSP()", result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -665,7 +677,7 @@ add_dsp_on_channel() {
|
|||
if (result == FMOD_ERR_INVALID_HANDLE) {
|
||||
_channel = 0;
|
||||
} else {
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_channel->addDSP()", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -689,7 +701,7 @@ remove_dsp(PT(AudioDSP) x) {
|
|||
if ( fdsp->get_in_chain() ) {
|
||||
|
||||
result = fdsp->_dsp->remove();
|
||||
fmod_audio_errcheck( result );
|
||||
fmod_audio_errcheck("_dsp->remove()", result);
|
||||
|
||||
_sound_dsp.erase(fdsp);
|
||||
|
||||
|
|
@ -736,7 +748,7 @@ get_speaker_mix(AudioManager::SpeakerId speaker) {
|
|||
float sideright;
|
||||
|
||||
result = _channel->getSpeakerMix( &frontleft, &frontright, ¢er, &sub, &backleft, &backright, &sideleft, &sideright );
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->getSpeakerMix()", result);
|
||||
|
||||
switch(speaker) {
|
||||
case AudioManager::SPK_frontleft: return frontleft;
|
||||
|
|
@ -798,7 +810,7 @@ set_speaker_mix_or_balance_on_channel() {
|
|||
FMOD_MODE soundMode;
|
||||
|
||||
result = _sound->getMode(&soundMode);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->getMode()", result);
|
||||
|
||||
if ((_channel != 0) && (( soundMode & FMOD_3D ) == 0)) {
|
||||
if ( _speakermode == FMOD_SPEAKERMODE_STEREO ) {
|
||||
|
|
@ -817,7 +829,7 @@ set_speaker_mix_or_balance_on_channel() {
|
|||
if (result == FMOD_ERR_INVALID_HANDLE) {
|
||||
_channel = 0;
|
||||
} else {
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_channel->setSpeakerMix()/setPan()", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -852,7 +864,7 @@ set_priority(int priority) {
|
|||
_priority = priority;
|
||||
|
||||
result = _sound->setDefaults( _sampleFrequency, _volume , _balance, _priority);
|
||||
fmod_audio_errcheck(result);
|
||||
fmod_audio_errcheck("_sound->setDefaults()", result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -880,31 +892,32 @@ status() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioSound::set_active
|
||||
// Access: public
|
||||
// Description: NOT USED ANYMORE!!!
|
||||
//
|
||||
//
|
||||
// Description: Sets whether the sound is marked "active". By
|
||||
// default, the active flag true for all sounds. If the
|
||||
// active flag is set to false for any particular sound,
|
||||
// the sound will not be heard.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FmodAudioSound::
|
||||
set_active(bool active) {
|
||||
audio_debug("NOT USED ANYMORE in FMOD-EX version of PANDA.");
|
||||
_active = active;
|
||||
|
||||
if (status() == PLAYING) {
|
||||
// If the sound is (or should be) playing, then pause or unpause
|
||||
// it in the system.
|
||||
FMOD_RESULT result = _channel->setPaused(!_active);
|
||||
fmod_audio_errcheck("_channel->setPaused()", result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioSound::get_active
|
||||
// Access: public
|
||||
// Description: NOT 'REALLY' USED ANYMORE!!!
|
||||
// This is actually an layover from the old version of the FMOD code.
|
||||
// The old version used a weird cache system to keep track of the sounds' states.
|
||||
// I just converted this method, to return if a sound is 'Playing' or not.
|
||||
// This is not exactly how the orignal use of this function btu I figured I might
|
||||
// as well get some use out of it.
|
||||
// Description: Returns whether the sound has been marked "active".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool FmodAudioSound::
|
||||
get_active() const {
|
||||
audio_debug("FmodAudioSound::get_active() Going to get a sound's activity.");
|
||||
audio_debug("NOT USED ANYMORE in FMOD-EX version of PANDA.");
|
||||
return false;
|
||||
return _active;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -23,44 +23,50 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//[FIRST READ FmodAudioManager for an Introduction if you haven't already].
|
||||
//[FIRST READ FmodAudioManager for an Introduction if you haven't
|
||||
//already].
|
||||
//
|
||||
//Hello, all future Panda audio code people! This is my errata documentation to
|
||||
//Help any future programmer maintain FMOD and PANDA.
|
||||
//Hello, all future Panda audio code people! This is my errata
|
||||
//documentation to Help any future programmer maintain FMOD and PANDA.
|
||||
//
|
||||
//Well, if you reading this you probably want to know how PANDA deals with sounds
|
||||
//directly using FMOD-EX. Well I am going to tell you.
|
||||
//Well, if you reading this you probably want to know how PANDA deals
|
||||
//with sounds directly using FMOD-EX. Well I am going to tell you.
|
||||
//
|
||||
//The first thing, you as the programmer have to understand, especially if you
|
||||
//never have done sound programming before, is how the FMOD-EX API works.
|
||||
//The first thing, you as the programmer have to understand,
|
||||
//especially if you never have done sound programming before, is how
|
||||
//the FMOD-EX API works.
|
||||
//
|
||||
//With FMOD-EX the guys at Firelight, adopted a model of managing sounds with FMOD
|
||||
//similar to how a Sound Designer creates sound in a sound studio using SOUNDS
|
||||
//and CHANNELS. Although this may seem strange at first, if you are not familiar
|
||||
//with sound programming, there is a very good metaphor you are probably already
|
||||
//familiar with to explain how FMOD-EX works.
|
||||
//With FMOD-EX the guys at Firelight, adopted a model of managing
|
||||
//sounds with FMOD similar to how a Sound Designer creates sound in a
|
||||
//sound studio using SOUNDS and CHANNELS. Although this may seem
|
||||
//strange at first, if you are not familiar with sound programming,
|
||||
//there is a very good metaphor you are probably already familiar with
|
||||
//to explain how FMOD-EX works.
|
||||
//
|
||||
//Think of you standard GUI API. Usually a GUI API is made up of two things:
|
||||
//Windows and Widgets. These correspond to CHANNELS and SOUNDS, where a
|
||||
//Channel is a Window and a Sound is Widget. Sounds are played within channels,
|
||||
//and channels don’t exist unless they have something to display.
|
||||
//Think of you standard GUI API. Usually a GUI API is made up of two
|
||||
//things: Windows and Widgets. These correspond to CHANNELS and
|
||||
//SOUNDS, where a Channel is a Window and a Sound is Widget. Sounds
|
||||
//are played within channels, and channels don't exist unless they
|
||||
//have something to display.
|
||||
//
|
||||
//Now why am I explaining all of this? When PANDA was created they set up the
|
||||
//basic audio classes to handle only the idea of a SOUND. The idea of a
|
||||
//Channel really wasn't prevalent as in more modern Audio APIs. With this rewrite
|
||||
//of PANDA to use the FMOD-EX API, the PANDA FmodAudioSound Class, now has to
|
||||
//handle two different parts of the FMOD-EX API in order to play a sound.
|
||||
//Now why am I explaining all of this? When PANDA was created they set
|
||||
//up the basic audio classes to handle only the idea of a SOUND. The
|
||||
//idea of a Channel really wasn't prevalent as in more modern Audio
|
||||
//APIs. With this rewrite of PANDA to use the FMOD-EX API, the PANDA
|
||||
//FmodAudioSound Class, now has to handle two different parts of the
|
||||
//FMOD-EX API in order to play a sound.
|
||||
//
|
||||
//SOUND: The object the handles the audio data in form of WAV, AIF, OGG, MID, IT,
|
||||
//MP3, etc... And CHANNEL: The object that actually plays the sound and
|
||||
//manipulates it in real time.
|
||||
//SOUND: The object the handles the audio data in form of WAV, AIF,
|
||||
//OGG, MID, IT, MP3, etc... And CHANNEL: The object that actually
|
||||
//plays the sound and manipulates it in real time.
|
||||
//
|
||||
//Ultimately this isn’t a problem expect for a couple situations when you go to
|
||||
//play a sound, which I will explain in more detail in that part of the code. All
|
||||
//that you have to know right now is that Channels in FMOD do not exist
|
||||
//unless they are playing a sound. And in the PANDA FmodAudioSound API class there
|
||||
//is only ONE dedicated channel per sound.
|
||||
//Otherwise there is really nothing to worry about.
|
||||
//Ultimately this isn't a problem expect for a couple situations when
|
||||
//you go to play a sound, which I will explain in more detail in that
|
||||
//part of the code. All that you have to know right now is that
|
||||
//Channels in FMOD do not exist unless they are playing a sound. And
|
||||
//in the PANDA FmodAudioSound API class there is only ONE dedicated
|
||||
//channel per sound. Otherwise there is really nothing to worry
|
||||
//about.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -126,7 +132,7 @@ class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound {
|
|||
void set_play_rate(float play_rate=1.0f);
|
||||
float get_play_rate() const;
|
||||
|
||||
const string& get_name() const;
|
||||
const string &get_name() const;
|
||||
|
||||
// return: playing time in seconds.
|
||||
float length() const;
|
||||
|
|
@ -151,13 +157,13 @@ class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound {
|
|||
virtual float get_speaker_mix(AudioManager::SpeakerId speaker);
|
||||
virtual void set_speaker_mix(float frontleft, float frontright, float center, float sub, float backleft, float backright, float sideleft, float sideright);
|
||||
|
||||
void set_active(bool active=true);
|
||||
bool get_active() const;
|
||||
|
||||
//THESE ARE NOT USED ANYMORE.
|
||||
//THEY ARE ONLY HERE BECAUSE THEY are still needed by Miles.
|
||||
//THESE are stubs in FMOD-EX version
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void set_active(bool active=true);
|
||||
bool get_active() const;
|
||||
|
||||
void finished();
|
||||
void set_finished_event(const string& event);
|
||||
const string& get_finished_event() const;
|
||||
|
|
@ -204,6 +210,16 @@ class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound {
|
|||
typedef pset<PT (FmodAudioDSP) > DSPSet;
|
||||
DSPSet _sound_dsp;
|
||||
|
||||
bool _active;
|
||||
|
||||
// This reference-counting pointer is set to this while the sound is
|
||||
// playing, and cleared when we get an indication that the sound has
|
||||
// stopped. This prevents a sound from destructing while it is
|
||||
// playing. We use a PT instead of managing the reference counts by
|
||||
// hand to help guard against accidental reference count leaks or
|
||||
// other mismanagement.
|
||||
PT(FmodAudioSound) _self_ref;
|
||||
|
||||
//THESE AREN'T USED ANYMORE.
|
||||
//THEY ARE ONLY HERE BECAUSE THEY are still need by Miles.
|
||||
//THESE are stubs in FMOD-EX version
|
||||
|
|
|
|||
|
|
@ -333,7 +333,8 @@ get_sound(const string& file_name, bool) {
|
|||
Filename path = file_name;
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->resolve_filename(path, get_sound_path());
|
||||
vfs->resolve_filename(path, get_sound_path()) ||
|
||||
vfs->resolve_filename(path, get_model_path());
|
||||
audio_debug(" resolved file_name is '"<<path<<"'");
|
||||
|
||||
PT(SoundData) sd;
|
||||
|
|
@ -402,7 +403,8 @@ uncache_sound(const string& file_name) {
|
|||
Filename path = file_name;
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->resolve_filename(path, get_sound_path());
|
||||
vfs->resolve_filename(path, get_sound_path()) ||
|
||||
vfs->resolve_filename(path, get_model_path());
|
||||
|
||||
audio_debug(" path=\""<<path<<"\"");
|
||||
SoundMap::iterator i=_sounds.find(path);
|
||||
|
|
@ -737,6 +739,12 @@ get_registry_entry(HKEY base, const char* subKeyName,
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioManager::
|
||||
get_gm_file_path(string& result) {
|
||||
Filename dls_filename = audio_dls_file;
|
||||
if (!dls_filename.empty()) {
|
||||
result = dls_filename.to_os_specific();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if(!get_registry_entry(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\DirectMusic", "GMFilePath", result)) {
|
||||
char sysdir[MAX_PATH+1];
|
||||
|
|
|
|||
Loading…
Reference in New Issue