#endif
#if defined( __APPLE__ )
-# include <OpenAL/alut.h>
+# include <ALUT/alut.h>
#else
# include <AL/alut.h>
#endif
#include <simgear/misc/sg_path.hxx>
#include <simgear/math/SGMath.hxx>
+using std::string;
+
extern bool isNaN(float *v);
#define MAX_SOURCES 128
+
+#ifndef ALC_ALL_DEVICES_SPECIFIER
+# define ALC_ALL_DEVICES_SPECIFIER 0x1013
+#endif
+
//
// Sound Manager
//
_geod_pos(SGGeod::fromCart(SGVec3d::zeros())),
_velocity(SGVec3d::zeros()),
_orientation(SGQuatd::zeros()),
- _bad_doppler(false)
+ _bad_doppler(false),
+ _renderer("unknown"),
+ _vendor("unknown")
{
#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
if (_alut_init == 0) {
}
}
_alut_init++;
+#else
+ //#error ALUT 1.1 required, ALUT 1.0 is no longer supported, please upgrade
#endif
}
}
}
+ _device = device;
ALCcontext *context = alcCreateContext(device, NULL);
+ testForALCError("context creation.");
if ( testForError(context, "Unable to create a valid context.") ) {
alcCloseDevice (device);
return;
else break;
}
- string vendor = alGetString(AL_VENDOR);
- string renderer = alGetString(AL_RENDERER);
- if ( vendor != "OpenAL Community" ||
- (renderer != "Software" && renderer != "OpenAL Sample Implementation")
+ _vendor = (const char *)alGetString(AL_VENDOR);
+ _renderer = (const char *)alGetString(AL_RENDERER);
+ if ( (_vendor != "Adalin" && _vendor != "Apple Computer Inc.") &&
+ (_vendor != "OpenAL Community" || (_renderer != "Software" &&
+ _renderer != "OpenAL Sample Implementation"))
)
{
_bad_doppler = true;
refUint ref = buffers_current->second;
ALuint buffer = ref.id;
alDeleteBuffers(1, &buffer);
- _buffers.erase( buffers_current );
}
_buffers.clear();
alcDestroyContext(_context);
alcCloseDevice(_device);
_context = NULL;
+
+ _renderer = "unknown";
+ _vendor = "unknown";
}
}
// run the audio scheduler
void SGSoundMgr::update( double dt ) {
if (_active) {
+ alcSuspendContext(_context);
+
if (_changed) {
update_pos_and_orientation();
}
testForALError("update");
_changed = false;
}
+
+ alcProcessContext(_context);
}
}
if ( !sample->is_valid_buffer() ) {
// sample was not yet loaded or removed again
string sample_name = sample->get_sample_name();
+ void *sample_data = NULL;
// see if the sample name is already cached
buffer_map_iterator buffer_it = _buffers.find( sample_name );
// sample name was not found in the buffer cache.
if ( sample->is_file() ) {
- size_t size;
int freq, format;
- void *data;
+ size_t size;
+ bool res;
+
+ res = load(sample_name, &sample_data, &format, &size, &freq);
+ if (res == false) return buffer;
- load(sample_name, &data, &format, &size, &freq);
- sample->set_data( &data );
sample->set_frequency( freq );
sample->set_format( format );
sample->set_size( size );
}
+ else
+ sample_data = sample->get_data();
// create an OpenAL buffer handle
alGenBuffers(1, &buffer);
if ( !testForALError("generate buffer") ) {
// Copy data to the internal OpenAL buffer
- const ALvoid *data = sample->get_data();
ALenum format = sample->get_format();
ALsizei size = sample->get_size();
ALsizei freq = sample->get_frequency();
- alBufferData( buffer, format, data, size, freq );
+ alBufferData( buffer, format, sample_data, size, freq );
- // If this sample was read from a file we have all the information
- // needed to read it again. For data buffers provided by the
- // program we don't; so don't delete it's data.
- if ( sample->is_file() ) sample->free_data();
+ if ( sample->is_file() ) free(sample_data);
if ( !testForALError("buffer add data") ) {
sample->set_buffer(buffer);
#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
ALfloat freqf;
+ // ignore previous errors to prevent the system from halting on silly errors
+ alGetError();
+ alcGetError(_device);
data = alutLoadMemoryFromFile(samplepath.c_str(), &format, &size, &freqf );
freq = (ALsizei)freqf;
- if (data == NULL) {
- int error = alutGetError();
+ int error = alutGetError();
+ if (data == NULL || error != ALUT_ERROR_NO_ERROR) {
string msg = "Failed to load wav file: ";
- msg.append(alutGetErrorString(error));
+ msg.append(alutGetErrorString(error));
throw sg_io_exception(msg.c_str(), sg_location(samplepath));
return false;
}
ALenum error = alGetError();
if ( error != AL_NO_ERROR ) {
string msg = "Failed to load wav file: ";
- msg.append(alGetString(error));
+ const ALchar *errorString = alGetString(error);
+ if (errorString) {
+ msg.append(errorString);
+ } else {
+ // alGetString returns NULL when an unexpected or OS specific error
+ // occurs: e.g. -43 on Mac when file is not found.
+ // In this case, alGetString() sets 'Invalid Enum' error, so
+ // showing with the original error number is helpful.
+ stringstream ss;
+ ss << alGetString(alGetError()) << "(" << error << ")";
+ msg.append(ss.str());
+ }
throw sg_io_exception(msg.c_str(), sg_location(samplepath));
return false;
}