]> git.mxchange.org Git - simgear.git/commitdiff
Erik Hofman
authorehofman <ehofman>
Mon, 24 Jan 2005 15:51:37 +0000 (15:51 +0000)
committerehofman <ehofman>
Mon, 24 Jan 2005 15:51:37 +0000 (15:51 +0000)
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
simgear/sound/sample_openal.hxx
simgear/sound/soundmgr_openal.cxx
simgear/sound/soundmgr_openal.hxx

index fa74a9063727652191ba8e79b1967ce4880474e5..eaa5452afc7f5a73d4e5e6c9e0c84e9ba28fdf53 100644 (file)
 //
 
 
-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 );
+    }
 }
index 6ed815d51ac54697f9e88d95467251ffaac520a0..68b7af7aeff01e0951bff9502dc33dfb9dc0243e 100644 (file)
@@ -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 );
 };
 
 
index bfdda68210b1e660c8e68e238890e3adb595125a..e16f76981857f70a986c431e48ae629af4f241ac 100644 (file)
 
 #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
 
@@ -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()!" );
index 70489973636c9ee7b482343b7b5f9122936f5c37..6c0d18429526257403ca2fccb1f75eaee7d4fc63 100644 (file)
 
 #if defined( __APPLE__ )
 # include <OpenAL/al.h>
+# include <OpenAL/alc.h>
 #else
 # include <AL/al.h>
+# include <AL/alc.h>
 #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];