//
// 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$
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
#if defined( __APPLE__ )
# define AL_ILLEGAL_ENUM AL_INVALID_ENUM
} else {
SG_LOG( SG_GENERAL, SG_ALERT, "Unhandled error code = " << error );
}
- return error;
+ return error != 0;
}
+// empty constructor
+SGSoundSample::SGSoundSample() :
+ buffer(0),
+ source(0),
+ pitch(1.0),
+ volume(1.0),
+ reference_dist(500.0),
+ max_dist(3000.),
+ loop(AL_FALSE),
+#ifdef USE_SOFTWARE_DOPPLER
+ doppler_pitch_factor(1),
+ doppler_volume_factor(1),
+#endif
+ playing(false),
+ no_Doppler_effect(true)
+{
+}
// constructor
-SGSoundSample::SGSoundSample( const char *path, const char *file,
- bool cleanup ) :
- data(NULL),
+SGSoundSample::SGSoundSample( const char *path, const char *file, bool _no_Doppler_effect ) :
buffer(0),
source(0),
pitch(1.0),
reference_dist(500.0),
max_dist(3000.),
loop(AL_FALSE),
- playing(false)
+#ifdef USE_SOFTWARE_DOPPLER
+ doppler_pitch_factor(1),
+ doppler_volume_factor(1),
+#endif
+ playing(false),
+ no_Doppler_effect(_no_Doppler_effect)
{
SGPath samplepath( path );
if ( strlen(file) ) {
samplepath.append( file );
}
-
sample_name = samplepath.str();
SG_LOG( SG_GENERAL, SG_DEBUG, "From file sounds sample = "
buffer = alutCreateBufferFromFile(samplepath.c_str());
if (buffer == AL_NONE) {
+ ALenum error = alutGetError ();
print_openal_error("constructor (alutCreateBufferFromFile)");
- throw sg_exception("Failed to load wav file.");
+ throw sg_io_exception("Failed to load wav file: ",
+ sg_location(string(alutGetErrorString (error))));
}
#else
//
// pre 1.0 alut version
//
-# if defined (__APPLE__)
- alutLoadWAVFile( (ALbyte *)samplepath.c_str(),
- &format, &data, &size, &freq );
-# else
- alutLoadWAVFile( (ALbyte *)samplepath.c_str(),
- &format, &data, &size, &freq, &loop );
-# endif
- if ( print_openal_error("constructor (alutLoadWAVFile)") ) {
- throw sg_exception("Failed to load wav file.");
- }
+ ALvoid* data = load_file(path, file);
// Copy data to the internal OpenAL buffer
alBufferData( buffer, format, data, size, freq );
if ( print_openal_error("constructor (alBufferData)") ) {
+ SG_LOG( SG_GENERAL, SG_ALERT, "Trying to use file " << file );
throw sg_exception("Failed to buffer data.");
}
- if ( cleanup ) {
- alutUnloadWAV( format, data, size, freq );
- data = NULL;
- }
+ alutUnloadWAV( format, data, size, freq );
#endif
print_openal_error("constructor return");
}
-
// constructor
-SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq,
- bool cleanup) :
- data(NULL),
+SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq, bool _no_Doppler_effect ) :
buffer(0),
source(0),
pitch(1.0),
reference_dist(500.0),
max_dist(3000.),
loop(AL_FALSE),
- playing(false)
+#ifdef USE_SOFTWARE_DOPPLER
+ doppler_pitch_factor(1),
+ doppler_volume_factor(1),
+#endif
+ playing(false),
+ no_Doppler_effect(_no_Doppler_effect)
{
SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" );
format = AL_FORMAT_MONO8;
size = len;
- data = _data;
freq = _freq;
- alBufferData( buffer, format, data, size, freq );
+ alBufferData( buffer, format, _data, size, freq );
if ( print_openal_error("constructor (alBufferData)") ) {
throw sg_exception("Failed to buffer data.");
}
- if ( cleanup ) {
- alutUnloadWAV( format, data, size, freq );
- data = NULL;
- }
-
print_openal_error("constructor return");
}
// destructor
SGSoundSample::~SGSoundSample() {
SG_LOG( SG_GENERAL, SG_INFO, "Deleting a sample" );
- alDeleteBuffers(1, &buffer);
+ if (buffer)
+ alDeleteBuffers(1, &buffer);
}
if ( playing ) {
return true;
}
+ if ( buffer == 0 ) {
+ return false;
+ }
// Bind buffer with a source.
alGetError();
}
alSourcei( source, AL_BUFFER, buffer );
+#ifndef USE_SOFTWARE_DOPPLER
alSourcef( source, AL_PITCH, pitch );
alSourcef( source, AL_GAIN, volume );
+#else
+ print_openal_error("bind_sources return");
+ alSourcef( source, AL_PITCH, pitch * doppler_pitch_factor );
+ alGetError(); // ignore if the pitch is clamped by the driver
+ alSourcef( source, AL_GAIN, volume * doppler_volume_factor );
+#endif
alSourcefv( source, AL_POSITION, source_pos );
alSourcefv( source, AL_DIRECTION, direction );
alSourcef( source, AL_CONE_INNER_ANGLE, inner );
alSourcef( source, AL_CONE_OUTER_ANGLE, outer );
alSourcef( source, AL_CONE_OUTER_GAIN, outergain);
+#ifdef USE_OPEN_AL_DOPPLER
alSourcefv( source, AL_VELOCITY, source_vel );
+#endif
alSourcei( source, AL_LOOPING, loop );
alSourcei( source, AL_SOURCE_RELATIVE, AL_TRUE );
if ( p > 2.0 ) { p = 2.0; }
pitch = p;
if (playing) {
+#ifndef USE_SOFTWARE_DOPPLER
alSourcef( source, AL_PITCH, pitch );
print_openal_error("set_pitch");
+#else
+ alSourcef( source, AL_PITCH, pitch * doppler_pitch_factor );
+ alGetError(); // ignore if the pitch is clamped by the driver
+#endif
}
}
SGSoundSample::set_volume( double v ) {
volume = v;
if (playing) {
+#ifndef USE_SOFTWARE_DOPPLER
alSourcef( source, AL_GAIN, volume );
+#else
+ alSourcef( source, AL_GAIN, volume * doppler_volume_factor );
+#endif
print_openal_error("set_volume");
}
}
sgAddVec3( final_pos, source_pos, offset_pos );
alSourcefv( source, AL_POSITION, final_pos );
+ print_openal_error("set_source_pos");
}
}
sgAddVec3( final_pos, source_pos, offset_pos );
alSourcefv( source, AL_POSITION, final_pos );
+ print_openal_error("set_offset_pos");
}
}
inner = inner_angle;
outer = outer_angle;
outergain = outer_gain;
+ direction[0] = dir[0];
+ direction[1] = dir[1];
+ direction[2] = dir[2];
if (playing) {
alSourcefv( source, AL_DIRECTION, dir);
alSourcef( source, AL_CONE_INNER_ANGLE, inner );
}
void
-SGSoundSample::set_source_vel( ALfloat *vel ) {
- source_vel[0] = vel[0];
- source_vel[1] = vel[1];
- source_vel[2] = vel[2];
+SGSoundSample::set_source_vel( ALfloat *vel, ALfloat *listener_vel ) {
+ if (no_Doppler_effect) {
+ source_vel[0] = listener_vel[0];
+ source_vel[1] = listener_vel[1];
+ source_vel[2] = listener_vel[2];
+ } else {
+ source_vel[0] = vel[0];
+ source_vel[1] = vel[1];
+ source_vel[2] = vel[2];
+ }
+#ifdef USE_OPEN_AL_DOPPLER
if (playing) {
alSourcefv( source, AL_VELOCITY, source_vel );
}
+#elif defined (USE_OPEN_AL_DOPPLER_WITH_FIXED_LISTENER)
+ if (playing) {
+ sgVec3 relative_vel;
+ sgSubVec3( relative_vel, source_vel, listener_vel );
+ alSourcefv( source, AL_VELOCITY, relative_vel );
+ }
+#else
+ if (no_Doppler_effect) {
+ doppler_pitch_factor = 1;
+ doppler_volume_factor = 1;
+ return;
+ }
+ double doppler, mfp;
+ sgVec3 final_pos;
+ sgAddVec3( final_pos, source_pos, offset_pos );
+ mfp = sgLengthVec3(final_pos);
+ if (mfp > 1e-6) {
+ double vls = -sgScalarProductVec3( listener_vel, final_pos ) / mfp;
+ double vss = -sgScalarProductVec3( source_vel, final_pos ) / mfp;
+ if (fabs(340 - vss) > 1e-6)
+ {
+ doppler = (340 - vls) / (340 - vss);
+ doppler = ( doppler > 0) ? ( ( doppler < 10) ? doppler : 10 ) : 0;
+ }
+ else
+ doppler = 0;
+ }
+ else
+ doppler = 1;
+ /* the OpenAL documentation of the Doppler calculation
+ SS: AL_SPEED_OF_SOUND = speed of sound (default value 343.3)
+ DF: AL_DOPPLER_FACTOR = Doppler factor (default 1.0)
+ vls: Listener velocity scalar (scalar, projected on source-to-listener vector)
+ vss: Source velocity scalar (scalar, projected on source-to-listener vector)
+ SL = source to listener vector
+ SV = Source Velocity vector
+ LV = Listener Velocity vector
+ vls = DotProduct(SL, LV) / Mag(SL)
+ vss = DotProduct(SL, SV) / Mag(SL)
+ Dopper Calculation:
+ vss = min(vss, SS/DF)
+ vls = min(vls, SS/DF)
+ f' = f * (SS - DF*vls) / (SS - DF*vss)
+ */
+ if (doppler > 0.1) {
+ if (doppler < 10) {
+ doppler_pitch_factor = doppler;
+ doppler_volume_factor = 1;
+ }
+ else {
+ doppler_pitch_factor = (doppler < 11) ? doppler : 11;
+ doppler_volume_factor = (doppler < 11) ? 11-doppler : 0;
+ }
+ }
+ else {
+ doppler_pitch_factor = 0.1;
+ doppler_volume_factor = (doppler > 0) ? doppler * 10 : 0;
+ }
+ if (playing) {
+ alSourcef( source, AL_GAIN, volume * doppler_volume_factor );
+ print_openal_error("set_source_vel: volume");
+ alSourcef( source, AL_PITCH, pitch * doppler_pitch_factor );
+ alGetError(); //ignore if the pitch is clamped
+ }
+#endif
}
void
alSourcef( source, AL_MAX_DISTANCE, max_dist );
}
}
+
+ALvoid *
+SGSoundSample::load_file(const char *path, const char *file)
+{
+ ALvoid* data = 0;
+
+ SGPath samplepath( path );
+ if ( strlen(file) ) {
+ samplepath.append( file );
+ }
+
+#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
+ ALfloat freqf;
+ data = alutLoadMemoryFromFile(samplepath.c_str(), &format, &size, &freqf );
+ if (data == NULL) {
+ throw sg_io_exception("Failed to load wav file.",
+ sg_location(samplepath.str()));
+ }
+ freq = (ALsizei)freqf;
+#else
+# if defined (__APPLE__)
+ alutLoadWAVFile( (ALbyte *)samplepath.c_str(),
+ &format, &data, &size, &freq );
+# else
+ alutLoadWAVFile( (ALbyte *)samplepath.c_str(),
+ &format, &data, &size, &freq, &loop );
+# endif
+ if ( print_openal_error("constructor (alutLoadWAVFile)") ) {
+ throw sg_io_exception("Failed to load wav file.",
+ sg_location(samplepath.str()));
+ }
+#endif
+
+ return data;
+}
+