//
-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;
}
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) ) {
// 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.");
}
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.");
}
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");
}
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" );
// 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;
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.");
}
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 );
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 );
+ }
}
double max_dist;
ALboolean loop;
+ bool playing;
+ bool bind_source();
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.
/**
* 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.
/**
* 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
/**
* 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 );
};