From f6314d3124633a05ce249ece5fef6d4f7a07cb76 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 24 Jan 2005 15:51:37 +0000 Subject: [PATCH] Erik Hofman 1. Remove the dependency on alut which (on certein platforms) might pose some restrictuons on commercial use. 2. Create a sound source just prior to playing the sound and destroy it again when the sound has stopped. This should greatly reduce the error reports from Windows users. --- simgear/sound/sample_openal.cxx | 240 ++++++++++++++++++++++-------- simgear/sound/sample_openal.hxx | 87 ++--------- simgear/sound/soundmgr_openal.cxx | 17 +-- simgear/sound/soundmgr_openal.hxx | 5 + 4 files changed, 207 insertions(+), 142 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index fa74a906..eaa5452a 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -43,20 +43,24 @@ // -static void print_openal_error( ALuint error ) { - if ( error == AL_INVALID_NAME ) { - SG_LOG( SG_GENERAL, SG_ALERT, "AL_INVALID_NAME" ); +static bool print_openal_error(const string &s = "unknown") { + ALuint error = alGetError(); + if ( error == AL_NO_ERROR ) { + return false; + } else if ( error == AL_INVALID_NAME ) { + SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_INVALID_NAME): " << s ); } else if ( error == AL_ILLEGAL_ENUM ) { - SG_LOG( SG_GENERAL, SG_ALERT, "AL_ILLEGAL_ENUM" ); + SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_ILLEGAL_ENUM): " << s ); } else if ( error == AL_INVALID_VALUE ) { - SG_LOG( SG_GENERAL, SG_ALERT, "AL_INVALID_VALUE" ); + SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_INVALID_VALUE): " << s ); } else if ( error == AL_ILLEGAL_COMMAND ) { - SG_LOG( SG_GENERAL, SG_ALERT, "AL_ILLEGAL_COMMAND" ); + SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_ILLEGAL_COMMAND): " << s ); } else if ( error == AL_OUT_OF_MEMORY ) { - SG_LOG( SG_GENERAL, SG_ALERT, "AL_OUT_OF_MEMORY" ); + SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_OUT_OF_MEMORY): " << s ); } else { SG_LOG( SG_GENERAL, SG_ALERT, "Unhandled error code = " << error ); } + return error; } @@ -64,11 +68,14 @@ static void print_openal_error( ALuint error ) { SGSoundSample::SGSoundSample( const char *path, const char *file, bool cleanup ) : data(NULL), + buffer(0), + source(0), pitch(1.0), volume(1.0), reference_dist(500.0), max_dist(3000.), - loop(AL_FALSE) + loop(AL_FALSE), + playing(false) { SGPath samplepath( path ); if ( strlen(file) ) { @@ -91,9 +98,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file, // create an OpenAL buffer handle alGenBuffers(1, &buffer); - ALuint error = alGetError(); - if ( error != AL_NO_ERROR ) { - print_openal_error( error ); + if ( print_openal_error("constructor (alGenBuffers)") ) { throw sg_exception("Failed to gen OpenAL buffer."); } @@ -105,13 +110,13 @@ SGSoundSample::SGSoundSample( const char *path, const char *file, alutLoadWAVFile( (ALbyte *)samplepath.c_str(), &format, &data, &size, &freq, &loop ); #endif - if (alGetError() != AL_NO_ERROR) { + if ( print_openal_error("constructor (alutLoadWAVFile)") ) { throw sg_exception("Failed to load wav file."); } // Copy data to the internal OpenAL buffer alBufferData( buffer, format, data, size, freq ); - if (alGetError() != AL_NO_ERROR) { + if ( print_openal_error("constructor (alBufferData)") ) { throw sg_exception("Failed to buffer data."); } @@ -120,26 +125,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file, data = NULL; } - // Bind buffer with a source. - alGenSources(1, &source); - if (alGetError() != AL_NO_ERROR) { - throw sg_exception("Failed to gen source.\nPlease update your sound driver and try again."); - } - - alSourcei( source, AL_BUFFER, buffer ); - alSourcef( source, AL_PITCH, pitch ); - alSourcef( source, AL_GAIN, volume ); - 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); - alSourcefv( source, AL_VELOCITY, source_vel ); - alSourcei( source, AL_LOOPING, loop ); - - alSourcei( source, AL_SOURCE_RELATIVE, AL_TRUE ); - alSourcef( source, AL_REFERENCE_DISTANCE, reference_dist ); - alSourcef( source, AL_MAX_DISTANCE, max_dist ); + print_openal_error("constructor return"); } @@ -147,11 +133,14 @@ SGSoundSample::SGSoundSample( const char *path, const char *file, SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq, bool cleanup) : data(NULL), + buffer(0), + source(0), pitch(1.0), volume(1.0), reference_dist(500.0), max_dist(3000.), - loop(AL_FALSE) + loop(AL_FALSE), + playing(false) { SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); @@ -168,11 +157,8 @@ SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq, // Load wav data into a buffer. alGenBuffers(1, &buffer); - ALuint error = alGetError(); - if ( error != AL_NO_ERROR ) { - print_openal_error( error ); + if ( print_openal_error("constructor (alGenBuffers)") ) { throw sg_exception("Failed to gen buffer." ); - return; } format = AL_FORMAT_MONO8; @@ -181,7 +167,7 @@ SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq, freq = _freq; alBufferData( buffer, format, data, size, freq ); - if (alGetError() != AL_NO_ERROR) { + if ( print_openal_error("constructor (alBufferData)") ) { throw sg_exception("Failed to buffer data."); } @@ -190,10 +176,63 @@ SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq, data = NULL; } + print_openal_error("constructor return"); +} + + +// destructor +SGSoundSample::~SGSoundSample() { + SG_LOG( SG_GENERAL, SG_INFO, "Deleting a sample" ); + alDeleteBuffers(1, &buffer); +} + + +// play the sample +void SGSoundSample::play( bool _loop ) { + + if ( source ) { + alSourceStop( source ); + } + + playing = bind_source(); + if ( playing ) { + loop = _loop; + + alSourcei( source, AL_LOOPING, loop ); + alSourcePlay( source ); + + print_openal_error("play (alSourcePlay)"); + } +} + + +// stop playing the sample +void SGSoundSample::stop() { + if (playing) { + alSourceStop( source ); + alDeleteSources(1, &source); + source = 0; + print_openal_error("stop (alDeleteSources)"); + } + playing = false; +} + +// Generate sound source +bool +SGSoundSample::bind_source() { + + if ( playing ) { + return true; + } + // Bind buffer with a source. + alGetError(); alGenSources(1, &source); - if (alGetError() != AL_NO_ERROR) { - throw sg_exception("Failed to gen source.\nPlease update your sound driver and try again."); + if ( print_openal_error("bind_source (alGenSources)") ) { + // No biggy, better luck next time. + SG_LOG( SG_GENERAL, SG_ALERT, "Failed to generate audio source."); + // SG_LOG( SG_GENERAL, SG_ALERT, "Please update your sound driver and try again."); + return false; } alSourcei( source, AL_BUFFER, buffer ); @@ -203,37 +242,122 @@ SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq, 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 ); + alSourcef( source, AL_CONE_OUTER_GAIN, outergain); alSourcefv( source, AL_VELOCITY, source_vel ); alSourcei( source, AL_LOOPING, loop ); alSourcei( source, AL_SOURCE_RELATIVE, AL_TRUE ); alSourcef( source, AL_REFERENCE_DISTANCE, reference_dist ); alSourcef( source, AL_MAX_DISTANCE, max_dist ); + + print_openal_error("bind_sources return"); + + return true; } +void +SGSoundSample::set_pitch( double p ) { + // clamp in the range of 0.01 to 2.0 + if ( p < 0.01 ) { p = 0.01; } + if ( p > 2.0 ) { p = 2.0; } + pitch = p; + if (playing) { + alSourcef( source, AL_PITCH, pitch ); + print_openal_error("set_pitch"); + } +} -// destructor -SGSoundSample::~SGSoundSample() { - SG_LOG( SG_GENERAL, SG_INFO, "Deleting a sample" ); - alDeleteSources(1, &source); - alDeleteBuffers(1, &buffer); +void +SGSoundSample::set_volume( double v ) { + volume = v; + if (playing) { + alSourcef( source, AL_GAIN, volume ); + print_openal_error("set_volume"); + } } -// play the sample -void SGSoundSample::play( bool _loop ) { - loop = _loop; - - // make sure sound isn't already playing - alSourceStop( source ); +bool +SGSoundSample::is_playing( ) { + if (playing) { + ALint result; + alGetSourcei( source, AL_SOURCE_STATE, &result ); + if ( alGetError() != AL_NO_ERROR) { + SG_LOG( SG_GENERAL, SG_ALERT, + "Oops AL error in sample is_playing(): " << sample_name ); + } + return (result == AL_PLAYING) ; + } else + return false; +} - alSourcei( source, AL_LOOPING, loop ); - alSourcePlay( source ); +void +SGSoundSample::set_source_pos( ALfloat *pos ) { + source_pos[0] = pos[0]; + source_pos[1] = pos[1]; + source_pos[2] = pos[2]; + + if (playing) { + sgVec3 final_pos; + sgAddVec3( final_pos, source_pos, offset_pos ); + + alSourcefv( source, AL_POSITION, final_pos ); + } } +void +SGSoundSample::set_offset_pos( ALfloat *pos ) { + offset_pos[0] = pos[0]; + offset_pos[1] = pos[1]; + offset_pos[2] = pos[2]; -// stop playing the sample -void SGSoundSample::stop() { - alSourceStop( source ); + if (playing) { + sgVec3 final_pos; + sgAddVec3( final_pos, source_pos, offset_pos ); + + alSourcefv( source, AL_POSITION, final_pos ); + } +} + +void +SGSoundSample::set_orientation( ALfloat *dir, ALfloat inner_angle, + ALfloat outer_angle, + ALfloat outer_gain) +{ + inner = inner_angle; + outer = outer_angle; + outergain = outer_gain; + if (playing) { + alSourcefv( source, AL_DIRECTION, dir); + alSourcef( source, AL_CONE_INNER_ANGLE, inner ); + alSourcef( source, AL_CONE_OUTER_ANGLE, outer ); + alSourcef( source, AL_CONE_OUTER_GAIN, outergain ); + } +} + +void +SGSoundSample::set_source_vel( ALfloat *vel ) { + source_vel[0] = vel[0]; + source_vel[1] = vel[1]; + source_vel[2] = vel[2]; + if (playing) { + alSourcefv( source, AL_VELOCITY, source_vel ); + } +} + +void +SGSoundSample::set_reference_dist( ALfloat dist ) { + reference_dist = dist; + if (playing) { + alSourcef( source, AL_REFERENCE_DISTANCE, reference_dist ); + } +} + + +void +SGSoundSample::set_max_dist( ALfloat dist ) { + max_dist = dist; + if (playing) { + alSourcef( source, AL_MAX_DISTANCE, max_dist ); + } } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 6ed815d5..68b7af7a 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -93,6 +93,8 @@ private: double max_dist; ALboolean loop; + bool playing; + bool bind_source(); public: @@ -149,15 +151,7 @@ public: * Test if a sample is curretnly playing. * @return true if is is playing, false otherwise. */ - inline bool is_playing( ) { - ALint result; - alGetSourcei( source, AL_SOURCE_STATE, &result ); - if ( alGetError() != AL_NO_ERROR) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Oops AL error in sample is_playing(): " << sample_name ); - } - return (result == AL_PLAYING) ; - } + bool is_playing( ); /** * Get the current pitch setting of this sample. @@ -167,18 +161,7 @@ public: /** * Set the pitch of this sample. */ - inline void set_pitch( double p ) { - // clamp in the range of 0.01 to 2.0 - if ( p < 0.01 ) { p = 0.01; } - if ( p > 2.0 ) { p = 2.0; } - pitch = p; - alSourcef( source, AL_PITCH, pitch ); - if ( alGetError() != AL_NO_ERROR) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Oops AL error in sample set_pitch()! " << p - << " for " << sample_name ); - } - } + void set_pitch( double p ); /** * Get the current volume setting of this sample. @@ -188,15 +171,7 @@ public: /** * Set the volume of this sample. */ - inline void set_volume( double v ) { - volume = v; - alSourcef( source, AL_GAIN, volume ); - if ( alGetError() != AL_NO_ERROR) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Oops AL error in sample set_volume()! " << v - << " for " << sample_name ); - } - } + void set_volume( double v ); /** * Returns the size of the sounds sample @@ -215,78 +190,40 @@ public: /** * Set position of sound source (uses same coordinate system as opengl) */ - inline void set_source_pos( ALfloat *pos ) { - source_pos[0] = pos[0]; - source_pos[1] = pos[1]; - source_pos[2] = pos[2]; - - sgVec3 final_pos; - sgAddVec3( final_pos, source_pos, offset_pos ); - - alSourcefv( source, AL_POSITION, final_pos ); - } + void set_source_pos( ALfloat *pos ); /** * Set "constant" offset position of sound source (uses same * coordinate system as opengl) */ - inline void set_offset_pos( ALfloat *pos ) { - offset_pos[0] = pos[0]; - offset_pos[1] = pos[1]; - offset_pos[2] = pos[2]; - - sgVec3 final_pos; - sgAddVec3( final_pos, source_pos, offset_pos ); - - alSourcefv( source, AL_POSITION, final_pos ); - } + void set_offset_pos( ALfloat *pos ); /** * Set the orientation of the sound source, both for direction * and audio cut-off angles. */ - inline void set_orientation( ALfloat *dir, ALfloat inner_angle=360.0, + void set_orientation( ALfloat *dir, ALfloat inner_angle=360.0, ALfloat outer_angle=360.0, - ALfloat outer_gain=0.0) - { - inner = inner_angle; - outer = outer_angle; - outergain = outer_gain; - alSourcefv( source, AL_DIRECTION, dir); - alSourcef( source, AL_CONE_INNER_ANGLE, inner ); - alSourcef( source, AL_CONE_OUTER_ANGLE, outer ); - alSourcef( source, AL_CONE_OUTER_GAIN, outergain ); - } + ALfloat outer_gain=0.0); /** * Set velocity of sound source (uses same coordinate system as opengl) */ - inline void set_source_vel( ALfloat *vel ) { - source_vel[0] = vel[0]; - source_vel[1] = vel[1]; - source_vel[2] = vel[2]; - alSourcefv( source, AL_VELOCITY, source_vel ); - } + void set_source_vel( ALfloat *vel ); /** * Set reference distance of sound (the distance where the gain * will be half.) */ - inline void set_reference_dist( ALfloat dist ) { - reference_dist = dist; - alSourcef( source, AL_REFERENCE_DISTANCE, reference_dist ); - } + void set_reference_dist( ALfloat dist ); /** * Set maximume distance of sound (the distance where the sound is * no longer audible. */ - inline void set_max_dist( ALfloat dist ) { - max_dist = dist; - alSourcef( source, AL_MAX_DISTANCE, max_dist ); - } + void set_max_dist( ALfloat dist ); }; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index bfdda682..e16f7698 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -27,11 +27,9 @@ #if defined(__APPLE__) # include -# include # include #else # include -# include # include #endif @@ -71,11 +69,13 @@ SGSoundMgr::SGSoundMgr() { SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" ); // initialize OpenAL - alutInit( 0, NULL ); - atexit(alutExit); + if ( (dev = alcOpenDevice( NULL )) != NULL) { + context = alcCreateContext( dev, NULL ); + } - if ( alGetError() == AL_NO_ERROR) { + if ( (dev != NULL) && (context != NULL) ) { working = true; + alcMakeContextCurrent( context ); } else { working = false; SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" ); @@ -115,6 +115,7 @@ SGSoundMgr::SGSoundMgr() { SGSoundMgr::~SGSoundMgr() { + alcDestroyContext( context ); // // Remove the samples from the sample manager. // @@ -162,8 +163,7 @@ void SGSoundMgr::update( double dt ) { void SGSoundMgr::pause () { - ALCcontext *pCurContext = alcGetCurrentContext(); - alcSuspendContext( pCurContext ); + alcSuspendContext( context ); if ( alGetError() != AL_NO_ERROR) { SG_LOG( SG_GENERAL, SG_ALERT, "Oops AL error after soundmgr pause()!" ); @@ -174,8 +174,7 @@ SGSoundMgr::pause () void SGSoundMgr::resume () { - ALCcontext *pCurContext = alcGetCurrentContext(); - alcProcessContext( pCurContext ); + alcProcessContext( context ); if ( alGetError() != AL_NO_ERROR) { SG_LOG( SG_GENERAL, SG_ALERT, "Oops AL error after soundmgr resume()!" ); diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 70489973..6c0d1842 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -44,8 +44,10 @@ #if defined( __APPLE__ ) # include +# include #else # include +# include #endif #include "sample_openal.hxx" @@ -65,6 +67,9 @@ typedef sample_map::const_iterator const_sample_map_iterator; class SGSoundMgr { + ALCdevice *dev; + ALCcontext *context; + // Position of the listener. ALfloat listener_pos[3]; -- 2.39.5