//
// C++-ified by Curtis Olson, started March 2001.
//
-// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org
+// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
-#include <iostream>
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#include <simgear/compiler.h>
#if defined(__APPLE__)
# include <OpenAL/al.h>
-# include <OpenAL/alut.h>
# include <OpenAL/alc.h>
#else
# include <AL/al.h>
-# include <AL/alut.h>
# include <AL/alc.h>
#endif
+#if defined (__APPLE__)
+# ifdef __GNUC__
+# if ( __GNUC__ >= 3 ) && ( __GNUC_MINOR__ >= 3 )
+// # include <math.h>
+inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
+# else
+ // any C++ header file undefines isinf and isnan
+ // so this should be included before <iostream>
+ // the functions are STILL in libm (libSystem on mac os x)
+extern "C" int isnan (double);
+extern "C" int isinf (double);
+# endif
+# else
+// inline int (isinf)(double r) { return isinf(r); }
+// inline int (isnan)(double r) { return isnan(r); }
+# endif
+#endif
+
+#if defined (__FreeBSD__)
+# if __FreeBSD_version < 500000
+ extern "C" {
+ inline int isnan(double r) { return !(r <= 0 || r >= 0); }
+ }
+# endif
+#endif
+
+#if defined (__CYGWIN__)
+#include <ieeefp.h>
+#endif
+
+
+#include <iostream>
+
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include "soundmgr_openal.hxx"
+#if defined(__MINGW32__)
+#define isnan(x) _isnan(x)
+#endif
//
// Sound Manager
// constructor
SGSoundMgr::SGSoundMgr() {
- SG_LOG( SG_GENERAL, SG_ALERT, "Initializing OpenAL sound manager" );
+ SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" );
// initialize OpenAL
- alutInit( 0, NULL );
- alGetError();
- if ( alGetError() == AL_NO_ERROR) {
+#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
+ if (!alutInit(NULL, NULL))
+ {
+ ALenum error = alutGetError ();
+ SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
+ SG_LOG( SG_GENERAL, SG_ALERT, " "+string(alutGetErrorString(error)));
+ working = false;
+ context = 0;
+ return;
+ }
+ else
+ {
working = true;
+ context = alcGetCurrentContext();
+ }
+#else
+ if ( (dev = alcOpenDevice( NULL )) != NULL
+ && ( context = alcCreateContext( dev, NULL )) != NULL ) {
+ working = true;
+ alcMakeContextCurrent( context );
} else {
working = false;
- SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
+ context = 0;
+ SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
+ return;
}
+#endif
listener_pos[0] = 0.0;
listener_pos[1] = 0.0;
listener_ori[4] = 1.0;
listener_ori[5] = 0.0;
+ alListenerf( AL_GAIN, 0.0f );
alListenerfv( AL_POSITION, listener_pos );
alListenerfv( AL_VELOCITY, listener_vel );
alListenerfv( AL_ORIENTATION, listener_ori );
alGetError();
if ( alGetError() != AL_NO_ERROR) {
- SG_LOG( SG_GENERAL, SG_ALERT,
+ SG_LOG( SG_GENERAL, SG_ALERT,
"Oops AL error after audio initialization!" );
}
+
+ // exaggerate the ear candy?
+ alDopplerFactor(1.0);
+ alDopplerVelocity(340.0); // speed of sound in meters per second.
}
// destructor
SGSoundMgr::~SGSoundMgr() {
- //
- // Remove the samples from the sample manager.
- //
- sample_map_iterator sample_current = samples.begin();
- sample_map_iterator sample_end = samples.end();
- for ( ; sample_current != sample_end; ++sample_current ) {
- SGSoundSample *sample = sample_current->second;
- delete sample;
- }
-
- alutExit();
+#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
+ alutExit ();
+#else
+ if (context)
+ alcDestroyContext( context );
+#endif
}
//
// Remove the samples from the sample manager.
//
- sample_map_iterator sample_current = samples.begin();
- sample_map_iterator sample_end = samples.end();
- for ( ; sample_current != sample_end; ++sample_current ) {
- SGSoundSample *sample = sample_current->second;
- delete sample;
- }
samples.clear();
}
void
SGSoundMgr::pause ()
{
- ALCcontext *pCurContext = alcGetCurrentContext();
- alcSuspendContext( pCurContext );
- if ( alGetError() != AL_NO_ERROR) {
- SG_LOG( SG_GENERAL, SG_ALERT,
- "Oops AL error after soundmgr pause()!" );
+ if (context) {
+ alcSuspendContext( context );
+ if ( alGetError() != AL_NO_ERROR) {
+ SG_LOG( SG_GENERAL, SG_ALERT,
+ "Oops AL error after soundmgr pause()!" );
+ }
}
}
void
SGSoundMgr::resume ()
{
- ALCcontext *pCurContext = alcGetCurrentContext();
- alcProcessContext( pCurContext );
- if ( alGetError() != AL_NO_ERROR) {
- SG_LOG( SG_GENERAL, SG_ALERT,
- "Oops AL error after soundmgr resume()!" );
+ if (context) {
+ alcProcessContext( context );
+ if ( alGetError() != AL_NO_ERROR) {
+ SG_LOG( SG_GENERAL, SG_ALERT,
+ "Oops AL error after soundmgr resume()!" );
+ }
}
}
sample_map_iterator sample_it = samples.find( refname );
if ( sample_it != samples.end() ) {
- // first stop the sound from playing (so we don't bomb the
- // audio scheduler)
- SGSoundSample *sample = sample_it->second;
- delete sample;
+ // first stop the sound from playing (so we don't bomb the
+ // audio scheduler)
samples.erase( sample_it );
// cout << "sndmgr: removed -> " << refname << endl;
- return true;
+ return true;
} else {
// cout << "sndmgr: failed remove -> " << refname << endl;
return false;
bool SGSoundMgr::exists( const string &refname ) {
sample_map_iterator sample_it = samples.find( refname );
if ( sample_it != samples.end() ) {
- return true;
+ return true;
} else {
- return false;
+ return false;
}
}
SGSoundSample *SGSoundMgr::find( const string &refname ) {
sample_map_iterator sample_it = samples.find( refname );
if ( sample_it != samples.end() ) {
- return sample_it->second;
+ return sample_it->second;
} else {
- return NULL;
+ return NULL;
}
}
return true;
}
}
+
+
+// set source position of all managed sounds
+void SGSoundMgr::set_source_pos_all( ALfloat *pos ) {
+ if ( isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2]) ) {
+ // bail if a bad position is passed in
+ return;
+ }
+
+ sample_map_iterator sample_current = samples.begin();
+ sample_map_iterator sample_end = samples.end();
+ for ( ; sample_current != sample_end; ++sample_current ) {
+ SGSoundSample *sample = sample_current->second;
+ sample->set_source_pos( pos );
+ }
+}
+
+
+// set source velocity of all managed sounds
+void SGSoundMgr::set_source_vel_all( ALfloat *vel ) {
+ if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) {
+ // bail if a bad velocity is passed in
+ return;
+ }
+
+ sample_map_iterator sample_current = samples.begin();
+ sample_map_iterator sample_end = samples.end();
+ for ( ; sample_current != sample_end; ++sample_current ) {
+ SGSoundSample *sample = sample_current->second;
+ sample->set_source_vel( vel, listener_vel );
+ }
+}