From f83278bd61f271a261a894881a75fe769963aa38 Mon Sep 17 00:00:00 2001 From: Erik Hofman Date: Sun, 12 Dec 2010 14:07:44 +0100 Subject: [PATCH] Update the bad-doppler test and simplify it to only test for bad platforms. --- simgear/sound/aax/soundmgr_aax.cxx | 608 +++++++++++++++++++++++++++++ simgear/sound/aax/soundmgr_aax.hxx | 313 +++++++++++++++ simgear/sound/sample_group.cxx | 1 - simgear/sound/soundmgr_openal.cxx | 38 +- 4 files changed, 940 insertions(+), 20 deletions(-) create mode 100644 simgear/sound/aax/soundmgr_aax.cxx create mode 100644 simgear/sound/aax/soundmgr_aax.hxx diff --git a/simgear/sound/aax/soundmgr_aax.cxx b/simgear/sound/aax/soundmgr_aax.cxx new file mode 100644 index 00000000..d305ee4e --- /dev/null +++ b/simgear/sound/aax/soundmgr_aax.cxx @@ -0,0 +1,608 @@ +// soundmgr.cxx -- Sound effect management class +// +// Sound manager initially written by David Findlay +// 2001 +// +// C++-ified by Curtis Olson, started March 2001. +// Modified for the new SoundSystem by Erik Hofman, October 2009 +// +// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt +// Copyright (C) 2009 Erik Hofman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined( __APPLE__ ) +# include +#else +# include +#endif + +#include +#include + +#include "soundmgr_openal.hxx" + +#include +#include +#include +#include + +using std::string; + +extern bool isNaN(float *v); + +#define MAX_SOURCES 128 + + +// +// Sound Manager +// + +int SGSoundMgr::_alut_init = 0; + +// constructor +SGSoundMgr::SGSoundMgr() : + _working(false), + _active(false), + _changed(true), + _volume(0.0), + _device(NULL), + _context(NULL), + _absolute_pos(SGVec3d::zeros()), + _offset_pos(SGVec3d::zeros()), + _base_pos(SGVec3d::zeros()), + _geod_pos(SGGeod::fromCart(SGVec3d::zeros())), + _velocity(SGVec3d::zeros()), + _orientation(SGQuatd::zeros()), + _bad_doppler(false), + _renderer("unknown"), + _vendor("unknown") +{ +#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 + if (_alut_init == 0) { + if ( !alutInitWithoutContext(NULL, NULL) ) { + testForALUTError("alut initialization"); + return; + } + } + _alut_init++; +#else + //#error ALUT 1.1 required, ALUT 1.0 is no longer supported, please upgrade +#endif +} + +// destructor + +SGSoundMgr::~SGSoundMgr() { + + stop(); +#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 + _alut_init--; + if (_alut_init == 0) { + alutExit (); + } +#endif +} + +// initialize the sound manager +void SGSoundMgr::init(const char *devname) { + + SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" ); + + _config = aaxDriverOpenByName(devname, AAX_MODE_WRITE_STEREO); + if ( testForError(C-nfig, "Audio device not available, trying default") ) { + _config = aaxDriverOpenDefault(AAX_MODE_WRITE_STEREO); + if (testForError(_config, "Default Audio device not available.") ) { + return; + } + } + + aaxMixerInit(_config); + + aaxSensorSetGain(_config, 0.0); + aaxSensorSetIdentityMatrix(_config); + + aaxScenerySetDopplerFactor(_config, 340.3); + aaxScenerySetDistanceModel(_config, AAX_AL_INVERSE_DISTANCE_CLAMPED); + + // get a free source one at a time + // if an error is returned no more (hardware) sources are available + for (unsigned int i=0; isecond; + sgrp->activate(); + } + } +} + +// stop the sound manager +void SGSoundMgr::stop() { + + // first stop all sample groups + sample_group_map_iterator sample_grp_current = _sample_groups.begin(); + sample_group_map_iterator sample_grp_end = _sample_groups.end(); + for ( ; sample_grp_current != sample_grp_end; ++sample_grp_current ) { + SGSampleGroup *sgrp = sample_grp_current->second; + sgrp->stop(); + } + + // clear all OpenAL sources + for (unsigned int i=0; i<_free_sources.size(); i++) { + aaxEmitter source = _free_sources[i]; + aaxEmitterDestroy(source); + } + _free_sources.clear(); + + // clear any OpenAL buffers before shutting down + buffer_map_iterator buffers_current = _buffers.begin(); + buffer_map_iterator buffers_end = _buffers.end(); + for ( ; buffers_current != buffers_end; ++buffers_current ) { + refUint ref = buffers_current->second; + aaxBuffer buffer = ref.id; + aaxBufferDestroy(buffer); + } + _buffers.clear(); + + if (_working) { + _working = false; + _active = false; + + aaxDriverClose(_config); + aaxDriverFree(_config); + + _renderer = "unknown"; + _vendor = "unknown"; + } +} + +void SGSoundMgr::suspend() { + if (_working) { + sample_group_map_iterator sample_grp_current = _sample_groups.begin(); + sample_group_map_iterator sample_grp_end = _sample_groups.end(); + for ( ; sample_grp_current != sample_grp_end; ++sample_grp_current ) { + SGSampleGroup *sgrp = sample_grp_current->second; + sgrp->stop(); + } + _active = false; + } +} + +void SGSoundMgr::resume() { + if (_working) { + sample_group_map_iterator sample_grp_current = _sample_groups.begin(); + sample_group_map_iterator sample_grp_end = _sample_groups.end(); + for ( ; sample_grp_current != sample_grp_end; ++sample_grp_current ) { + SGSampleGroup *sgrp = sample_grp_current->second; + sgrp->resume(); + } + _active = true; + } +} + +void SGSoundMgr::bind () +{ + _free_sources.clear(); + _free_sources.reserve( MAX_SOURCES ); + _sources_in_use.clear(); + _sources_in_use.reserve( MAX_SOURCES ); +} + + +void SGSoundMgr::unbind () +{ + _sample_groups.clear(); + + // delete free sources + for (unsigned int i=0; i<_free_sources.size(); i++) { + aaxEmitter source = _free_sources[i]; + aaxEmitterDestroy(source); + } + + _free_sources.clear(); + _sources_in_use.clear(); +} + +// run the audio scheduler +void SGSoundMgr::update( double dt ) { + if (_active) { + if (_changed) { + update_pos_and_orientation(); + } + + sample_group_map_iterator sample_grp_current = _sample_groups.begin(); + sample_group_map_iterator sample_grp_end = _sample_groups.end(); + for ( ; sample_grp_current != sample_grp_end; ++sample_grp_current ) { + SGSampleGroup *sgrp = sample_grp_current->second; + sgrp->update(dt); + } + + if (_changed) { +#if 0 +if (isNaN(_at_up_vec)) printf("NaN in listener orientation\n"); +if (isNaN(toVec3f(_absolute_pos).data())) printf("NaN in listener position\n"); +if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); +#endif + + SGMatrix m = SGMatrix(_orientation); + aaxSensorSetMatrix(m.data()); + aaxSensorSetGain(_config, _volume); + + SGQuatd hlOr = SGQuatd::fromLonLat( _geod_pos ); + SGVec3d velocity = SGVec3d::zeros(); + if ( _velocity[0] || _velocity[1] || _velocity[2] ) { + velocity = hlOr.backTransform(_velocity*SG_FEET_TO_METER); + } + + aaxSensorSetVelocity(toVec3f(velocity).data()); + + // TODO: altitude dependent + // aaxScenerySetDopplerFactor(_config, 340.3); + _changed = false; + } + } +} + +// add a sample group, return true if successful +bool SGSoundMgr::add( SGSampleGroup *sgrp, const string& refname ) +{ + sample_group_map_iterator sample_grp_it = _sample_groups.find( refname ); + if ( sample_grp_it != _sample_groups.end() ) { + // sample group already exists + return false; + } + + if (_active) sgrp->activate(); + _sample_groups[refname] = sgrp; + + return true; +} + + +// remove a sound effect, return true if successful +bool SGSoundMgr::remove( const string &refname ) +{ + sample_group_map_iterator sample_grp_it = _sample_groups.find( refname ); + if ( sample_grp_it == _sample_groups.end() ) { + // sample group was not found. + return false; + } + + _sample_groups.erase( sample_grp_it ); + + return true; +} + + +// return true of the specified sound exists in the sound manager system +bool SGSoundMgr::exists( const string &refname ) { + sample_group_map_iterator sample_grp_it = _sample_groups.find( refname ); + if ( sample_grp_it == _sample_groups.end() ) { + // sample group was not found. + return false; + } + + return true; +} + + +// return a pointer to the SGSampleGroup if the specified sound exists +// in the sound manager system, otherwise return NULL +SGSampleGroup *SGSoundMgr::find( const string &refname, bool create ) { + sample_group_map_iterator sample_grp_it = _sample_groups.find( refname ); + if ( sample_grp_it == _sample_groups.end() ) { + // sample group was not found. + if (create) { + SGSampleGroup* sgrp = new SGSampleGroup(this, refname); + add( sgrp, refname ); + return sgrp; + } + else + return NULL; + } + + return sample_grp_it->second; +} + + +void SGSoundMgr::set_volume( float v ) +{ + _volume = v; + if (_volume > 1.0) _volume = 1.0; + if (_volume < 0.0) _volume = 0.0; + _changed = true; +} + +// Get an unused source id +// +// The Sound Manager should keep track of the sources in use, the distance +// of these sources to the listener and the volume (also based on audio cone +// and hence orientation) of the sources. +// +// The Sound Manager is (and should be) the only one knowing about source +// management. Sources further away should be suspendped to free resources for +// newly added sounds close by. +unsigned int SGSoundMgr::request_source() +{ + unsigned int source = NO_SOURCE; + + if (_free_sources.size() > 0) { + source = _free_sources.back(); + _free_sources.pop_back(); + _sources_in_use.push_back(source); + } + else + SG_LOG( SG_GENERAL, SG_INFO, "No more free sources available\n"); + + return source; +} + +// Free up a source id for further use +void SGSoundMgr::release_source( unsigned int source ) +{ + vector::iterator it; + + it = std::find(_sources_in_use.begin(), _sources_in_use.end(), source); + if ( it != _sources_in_use.end() ) { + ALint result; + + result = aaxEmitterGetStatus(source); + if ( result == AAX_STATUS_PLAYING ) { + aaxMixerDeregisterEmitter(_config, source); + aaxEmitterDestroy(source); + } + + _free_sources.push_back( source ); + _sources_in_use.erase( it ); + } +} + +unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) +{ + ALuint buffer = NO_BUFFER; + + 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 ); + if ( buffer_it != _buffers.end() ) { + buffer_it->second.refctr++; + buffer = buffer_it->second.id; + sample->set_buffer( buffer ); + return buffer; + } + + // sample name was not found in the buffer cache. + if ( sample->is_file() ) { + int freq, format; + size_t size; + bool res; + + res = load(sample_name, &sample_data, &format, &size, &freq); + if (res == false) return buffer; + + sample->set_frequency( freq ); + sample->set_format( format ); + sample->set_size( size ); + } + else + sample_data = sample->get_data(); + + // create a buffer handle + unsigned long size = sample->get_size(); + unsigned int freq = sample->get_frequency(); + enum aaxFormat fmt = sample->get_format(); + buffer = aaxBufferCreate(_config, sample_data, size, fmt, tracks); + aaxBufferSetFrequency(buffer, frequency); + + if ( sample->is_file() ) free(sample_data); + if ( !testForALError("buffer add data") ) { + sample->set_buffer(buffer); + _buffers[sample_name] = refUint(buffer); + } + } + else { + buffer = sample->get_buffer(); +} + + return buffer; +} + +void SGSoundMgr::release_buffer(SGSoundSample *sample) +{ + string sample_name = sample->get_sample_name(); + buffer_map_iterator buffer_it = _buffers.find( sample_name ); + if ( buffer_it == _buffers.end() ) { + // buffer was not found + return; + } + + sample->no_valid_buffer(); + buffer_it->second.refctr--; + if (buffer_it->second.refctr == 0) { + aaxBuffer buffer = buffer_it->second.id; + aaxBufferDestory(buffer); + _buffers.erase( buffer_it ); + testForALError("release buffer"); + } +} + +void SGSoundMgr::update_pos_and_orientation() { + /** + * Description: ORIENTATION is a pair of 3-tuples representing the + * 'at' direction vector and 'up' direction of the Object in + * Cartesian space. AL expects two vectors that are orthogonal to + * each other. These vectors are not expected to be normalized. If + * one or more vectors have zero length, implementation behavior + * is undefined. If the two vectors are linearly dependent, + * behavior is undefined. + * + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + */ + SGVec3d sgv_at = _orientation.backTransform(-SGVec3d::e3()); + SGVec3d sgv_up = _orientation.backTransform(SGVec3d::e2()); + _at_up_vec[0] = sgv_at[0]; + _at_up_vec[1] = sgv_at[1]; + _at_up_vec[2] = sgv_at[2]; + _at_up_vec[3] = sgv_up[0]; + _at_up_vec[4] = sgv_up[1]; + _at_up_vec[5] = sgv_up[2]; + + // static const SGQuatd q(-0.5, -0.5, 0.5, 0.5); + // SGQuatd hlOr = SGQuatd::fromLonLat(SGGeod::fromCart(_base_pos)); + // SGQuatd ec2body = hlOr*_orientation; + _absolute_pos = _base_pos; // + ec2body.backTransform( _offset_pos ); +} + +bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, + size_t *sz, int *frq ) +{ + if ( !_working ) return false; + + ALenum format; + ALsizei size; + ALsizei freq; + ALvoid *data; + +#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; + int error = alutGetError(); + if (data == NULL || error != ALUT_ERROR_NO_ERROR) { + string msg = "Failed to load wav file: "; + msg.append(alutGetErrorString(error)); + throw sg_io_exception(msg.c_str(), sg_location(samplepath)); + return false; + } + +#else + ALbyte *fname = (ALbyte *)samplepath.c_str(); +# if defined (__APPLE__) + alutLoadWAVFile( fname, &format, &data, &size, &freq ); +# else + ALboolean loop; + alutLoadWAVFile( fname, &format, &data, &size, &freq, &loop ); +# endif + ALenum error = alGetError(); + if ( error != AL_NO_ERROR ) { + string msg = "Failed to load wav file: "; + 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; + } +#endif + + *dbuf = (void *)data; + *fmt = (int)format; + *sz = (size_t)size; + *frq = (int)freq; + + return true; +} + +vector SGSoundMgr::get_available_devices() +{ + vector devices; + unsigned int x, max; + char *s; + + max = aaxDriverGetCount(); + for (x=0; x= 1 + ALenum error; + error = alutGetError (); + if (error != ALUT_ERROR_NO_ERROR) { + SG_LOG( SG_GENERAL, SG_ALERT, "ALUT Error (sound manager): " + << alutGetErrorString(error) << " at " + << s); + return true; + } +#endif + return false; +} diff --git a/simgear/sound/aax/soundmgr_aax.hxx b/simgear/sound/aax/soundmgr_aax.hxx new file mode 100644 index 00000000..3834ef9c --- /dev/null +++ b/simgear/sound/aax/soundmgr_aax.hxx @@ -0,0 +1,313 @@ +// soundmgr.hxx -- Sound effect management class +// +// Sound manager initially written by David Findlay +// 2001 +// +// C++-ified by Curtis Olson, started March 2001. +// Modified for the new SoundSystem by Erik Hofman, October 2009 +// +// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt +// Copyright (C) 2009 Erik Hofman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +/** + * \file soundmgr.hxx + * Provides a sound manager class to keep track of + * multiple sounds and manage playing them with different effects and + * timings. + */ + +#ifndef _SG_SOUNDMGR_AAX_HXX +#define _SG_SOUNDMGR_AAX_HXX 1 + +#include +#include +#include + +#include + +#include +#include +#include + +#include "sample_group.hxx" + +struct refUint { + unsigned int refctr; + ALuint id; + + refUint() { refctr = 0; id = (ALuint)-1; }; + refUint(ALuint i) { refctr = 1; id = i; }; + ~refUint() {}; +}; + +typedef std::map < std::string, refUint > buffer_map; +typedef buffer_map::iterator buffer_map_iterator; +typedef buffer_map::const_iterator const_buffer_map_iterator; + +typedef std::map < std::string, SGSharedPtr > sample_group_map; +typedef sample_group_map::iterator sample_group_map_iterator; +typedef sample_group_map::const_iterator const_sample_group_map_iterator; + +/** + * Manage a collection of SGSampleGroup instances + */ +class SGSoundMgr : public SGSubsystem +{ +public: + + SGSoundMgr(); + ~SGSoundMgr(); + + void init(const char *devname = NULL); + void bind(); + void unbind(); + void update(double dt); + + void suspend(); + void resume(); + void stop(); + + inline void reinit() { stop(); init(); } + + /** + * Test is the sound manager is in a working condition. + * @return true is the sound manager is working + */ + inline bool is_working() const { return _working; } + + /** + * Set the sound manager to a working condition. + */ + void activate(); + + /** + * Test is the sound manager is in an active and working condition. + * @return true is the sound manager is active + */ + inline bool is_active() const { return _active; } + + /** + * Register a sample group to the sound manager. + * @para sgrp Pointer to a sample group to add + * @param refname Reference name of the sample group + * @return true if successful, false otherwise + */ + bool add( SGSampleGroup *sgrp, const std::string& refname ); + + /** + * Remove a sample group from the sound manager. + * @param refname Reference name of the sample group to remove + * @return true if successful, false otherwise + */ + bool remove( const std::string& refname ); + + /** + * Test if a specified sample group is registered at the sound manager + * @param refname Reference name of the sample group test for + * @return true if the specified sample group exists + */ + bool exists( const std::string& refname ); + + /** + * Find a specified sample group in the sound manager + * @param refname Reference name of the sample group to find + * @return A pointer to the SGSampleGroup + */ + SGSampleGroup *find( const string& refname, bool create = false ); + + /** + * Set the Cartesian position of the sound manager. + * @param pos listener position + */ + void set_position( const SGVec3d& pos, const SGGeod& pos_geod ) { + _base_pos = pos; _geod_pos = pos_geod; _changed = true; + } + + void set_position_offset( const SGVec3d& pos ) { + _offset_pos = pos; _changed = true; + } + + /** + * Get the position of the sound manager. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * @return listener position + */ + SGVec3d& get_position() { return _absolute_pos; } + + /** + * Set the velocity vector (in meters per second) of the sound manager + * This is the horizontal local frame; x=north, y=east, z=down + * @param Velocity vector + */ + void set_velocity( const SGVec3d& vel ) { + _velocity = vel; _changed = true; + } + + /** + * Get the velocity vector of the sound manager + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @return Velocity vector of the listener + */ + inline SGVec3f get_velocity() { return toVec3f(_velocity); } + + /** + * Set the orientation of the sound manager + * @param ori Quaternation containing the orientation information + */ + void set_orientation( const SGQuatd& ori ) { + _orientation = ori; _changed = true; + } + + /** + * Get the orientation of the sound manager + * @return Quaternation containing the orientation information + */ + inline const SGQuatd& get_orientation() { return _orientation; } + + /** + * Get the direction vector of the sound manager + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @return Look-at direction of the listener + */ + SGVec3f get_direction() { + return SGVec3f(_at_up_vec[0], _at_up_vec[1], _at_up_vec[2]); + } + + enum { + NO_SOURCE = (unsigned int)-1, + NO_BUFFER = (unsigned int)-1 + }; + + /** + * Set the master volume. + * @param vol Volume (must be between 0.0 and 1.0) + */ + void set_volume( float vol ); + + /** + * Get the master volume. + * @return Volume (must be between 0.0 and 1.0) + */ + inline float get_volume() { return _volume; } + + /** + * Get a free source-id + * @return NO_SOURCE if no source is available + */ + unsigned int request_source(); + + /** + * Free an source-id for future use + * @param source source-id to free + */ + void release_source( unsigned int source ); + + /** + * Get a free buffer-id + * The buffer-id will be asigned to the sample by calling this function. + * @param sample Pointer to an audio sample to assign the buffer-id to + * @return NO_BUFFER if loading of the buffer failed. + */ + unsigned int request_buffer(SGSoundSample *sample); + + /** + * Free an buffer-id for this sample + * @param sample Pointer to an audio sample for which to free the buffer + */ + void release_buffer( SGSoundSample *sample ); + + /** + * Test if the position of the sound manager has changed. + * The value will be set to false upon the next call to update_late() + * @return true if the position has changed + */ + inline bool has_changed() { return _changed; } + + /** + * Some implementations seem to need the velocity miltyplied by a + * factor of 100 to make them distinct. I've not found if this is + * a problem in the implementation or in out code. Until then + * this function is used to detect the problematic implementations. + */ + inline bool bad_doppler_effect() { return _bad_doppler; } + + /** + * Load a sample file and return it's configuration and data. + * @param samplepath Path to the file to load + * @param data Pointer to a variable that points to the allocated data + * @param format Pointer to a vairable that gets the format + * @param size Pointer to a vairable that gets the sample size in bytes + * @param freq Pointer to a vairable that gets the sample frequency in Herz + * @return true if succesful, false on error + */ + bool load(string &samplepath, void **data, int *format, + size_t *size, int *freq ); + + /** + * Get a list of available playback devices. + */ + std::vector get_available_devices(); + + /** + * Get the current vendor or rendering backend. + */ + const std::string& get_vendor() { return _vendor; } + const std::string& get_renderer() { return _renderer; } + +private: + static int _alut_init; + + bool _working; + bool _active; + bool _changed; + float _volume; + + aaxConfig _config; + + // Position of the listener. + SGVec3d _absolute_pos; + SGVec3d _offset_pos; + SGVec3d _base_pos; + SGGeod _geod_pos; + + // Velocity of the listener. + SGVec3d _velocity; + + // Orientation of the listener. + // first 3 elements are "at" vector, second 3 are "up" vector + SGQuatd _orientation; + + sample_group_map _sample_groups; + buffer_map _buffers; + + std::vector _free_sources; + std::vector _sources_in_use; + + bool _bad_doppler; + std::string _renderer; + std::string _vendor; + + void update_pos_and_orientation(); + void update_sample_config( SGSampleGroup *sound ); +}; + + +#endif // _SG_SOUNDMGR_AAX_HXX + + diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 26da0f93..1610d088 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -273,7 +273,6 @@ SGSampleGroup::stop () ALint source = sample->get_source(); if ( sample->is_playing() ) { alSourceStop( source ); - alSourcei( source, AL_BUFFER, 0 ); } _smgr->release_source( source ); sample->no_valid_source(); diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index c3eda45a..3a0b2979 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -174,11 +174,11 @@ void SGSoundMgr::init(const char *devname) { _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")) - ) - { + + if (_vendor == "Creative Labs Inc.") { + _bad_doppler = true; + + } else if (_vendor == "OpenAL Community" && _renderer == "OpenAL Soft") { _bad_doppler = true; } @@ -438,11 +438,12 @@ void SGSoundMgr::release_source( unsigned int source ) ALint result; alGetSourcei( source, AL_SOURCE_STATE, &result ); - if ( result == AL_PLAYING ) + if ( result == AL_PLAYING ) { alSourceStop( source ); - testForALError("release source"); + } - alSourcei( source, AL_BUFFER, 0 ); + alSourcei( source, AL_BUFFER, 0 ); // detach the associated buffer + testForALError("release_source"); _free_sources.push_back( source ); _sources_in_use.erase( it ); } @@ -473,18 +474,20 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) try { bool res = load(sample_name, &sample_data, &format, &size, &freq); - if (res == false) return buffer; + if (res == false) return NO_BUFFER; } catch (sg_exception& e) { - SG_LOG(SG_GENERAL, SG_ALERT, "failed to load sound buffer:" << e.getFormattedMessage()); + SG_LOG(SG_GENERAL, SG_ALERT, + "failed to load sound buffer:" << e.getFormattedMessage()); return NO_BUFFER; } sample->set_frequency( freq ); sample->set_format( format ); sample->set_size( size ); - } - else + + } else { sample_data = sample->get_data(); + } // create an OpenAL buffer handle alGenBuffers(1, &buffer); @@ -496,17 +499,17 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) ALsizei freq = sample->get_frequency(); alBufferData( buffer, format, sample_data, size, freq ); - if ( sample->is_file() ) free(sample_data); - if ( !testForALError("buffer add data") ) { sample->set_buffer(buffer); _buffers[sample_name] = refUint(buffer); } } + + if ( sample->is_file() ) free(sample_data); } else { buffer = sample->get_buffer(); -} + } return buffer; } @@ -554,10 +557,7 @@ void SGSoundMgr::update_pos_and_orientation() { _at_up_vec[4] = sgv_up[1]; _at_up_vec[5] = sgv_up[2]; - // static const SGQuatd q(-0.5, -0.5, 0.5, 0.5); - // SGQuatd hlOr = SGQuatd::fromLonLat(SGGeod::fromCart(_base_pos)); - // SGQuatd ec2body = hlOr*_orientation; - _absolute_pos = _base_pos; // + ec2body.backTransform( _offset_pos ); + _absolute_pos = _base_pos; } bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, -- 2.39.5