From ecb4dc57b48f06b2f830f62c254e4209303287f5 Mon Sep 17 00:00:00 2001 From: mfranz Date: Sun, 22 Jul 2007 13:50:24 +0000 Subject: [PATCH] Maik JUSTUS: workaround for broken Doppler effect in OpenAL mf: this patch is meant to be removed as soon as OpenAL got fixed. (The OpenAL developers acknowleged the bug and announced that it'll get fixed.) For removal try $ cd simgear/sound $ cvs diff -rAFTER_OPENAL_DOPPLER_WORKAROUND -rBEFORE_OPENAL_DOPPLER_WORKAROUND|patch --- simgear/sound/sample_openal.cxx | 96 +++++++++++++++++++++++++++++++ simgear/sound/sample_openal.hxx | 14 +++++ simgear/sound/soundmgr_openal.hxx | 2 + 3 files changed, 112 insertions(+) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index ec494392..7d112b24 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -75,6 +75,10 @@ SGSoundSample::SGSoundSample() : 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) { @@ -89,6 +93,10 @@ SGSoundSample::SGSoundSample( const char *path, const char *file , bool _no_Dopp 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(_no_Doppler_effect) { @@ -155,6 +163,10 @@ SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq , bool _n 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(_no_Doppler_effect) { @@ -250,14 +262,23 @@ SGSoundSample::bind_source() { } 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 ); @@ -276,8 +297,13 @@ SGSoundSample::set_pitch( double p ) { 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 } } @@ -285,7 +311,11 @@ void 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"); } } @@ -365,9 +395,75 @@ SGSoundSample::set_source_vel( ALfloat *vel , ALfloat *listener_vel ) { 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 diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index b1559801..861dfb55 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -52,6 +52,16 @@ # include #endif +#ifndef HAVE_WINDOWS_H + #ifdef AL_VERSION_1_2 + #define USE_OPEN_AL_DOPPLER should work + #else + #define USE_OPEN_AL_DOPPLER_WITH_FIXED_LISTENER better than nothing + #endif +#else +//the Open_AL Doppler calculation seem to be buggy on windows + #define USE_SOFTWARE_DOPPLER seem to be necessary +#endif SG_USING_STD(string); @@ -91,6 +101,10 @@ private: double pitch; double volume; +#ifdef USE_SOFTWARE_DOPPLER + double doppler_pitch_factor; + double doppler_volume_factor; +#endif double reference_dist; double max_dist; ALboolean loop; diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 9e8dcd0a..567dadf9 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -206,7 +206,9 @@ public: listener_vel[0] = vel[0]; listener_vel[1] = vel[1]; listener_vel[2] = vel[2]; +#ifdef USE_OPEN_AL_DOPPLER alListenerfv( AL_VELOCITY, listener_vel ); +#endif } /** -- 2.39.5