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.
This commit is contained in:
ehofman
2005-01-24 15:51:37 +00:00
parent 1e87dd7903
commit f6314d3124
4 changed files with 211 additions and 146 deletions

View File

@@ -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");
}
}
void
SGSoundSample::set_volume( double v ) {
volume = v;
if (playing) {
alSourcef( source, AL_GAIN, volume );
print_openal_error("set_volume");
}
}
// destructor
SGSoundSample::~SGSoundSample() {
SG_LOG( SG_GENERAL, SG_INFO, "Deleting a sample" );
alDeleteSources(1, &source);
alDeleteBuffers(1, &buffer);
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;
}
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];
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 );
}
}
// play the sample
void SGSoundSample::play( bool _loop ) {
loop = _loop;
// make sure sound isn't already playing
alSourceStop( source );
alSourcei( source, AL_LOOPING, loop );
alSourcePlay( source );
}
// stop playing the sample
void SGSoundSample::stop() {
alSourceStop( source );
void
SGSoundSample::set_max_dist( ALfloat dist ) {
max_dist = dist;
if (playing) {
alSourcef( source, AL_MAX_DISTANCE, max_dist );
}
}

View 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 );
};

View File

@@ -27,11 +27,9 @@
#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()!" );

View File

@@ -44,8 +44,10 @@
#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];