From c188f6e3cb210327723356386d07dc1d56326ab4 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 30 Sep 2012 19:41:51 +0100 Subject: [PATCH] Initial work on making OpenAL private to the sound code. --- CMakeLists.txt | 8 +- simgear/simgear_config_cmake.h.in | 1 + simgear/sound/CMakeLists.txt | 1 + simgear/sound/openal_test2.cxx | 2 + simgear/sound/openal_test3.cxx | 3 +- simgear/sound/openal_test4.cxx | 5 +- simgear/sound/sample_group.cxx | 4 + simgear/sound/sample_group.hxx | 41 ++-- simgear/sound/sample_openal.cxx | 2 + simgear/sound/sample_openal.hxx | 14 +- simgear/sound/sample_queue.cxx | 2 + simgear/sound/sample_queue.hxx | 1 - simgear/sound/soundmgr_openal.cxx | 278 +++++++++++++--------- simgear/sound/soundmgr_openal.hxx | 81 ++----- simgear/sound/soundmgr_openal_private.hxx | 66 +++++ simgear/sound/xmlsound.cxx | 7 +- simgear/sound/xmlsound.hxx | 16 +- 17 files changed, 314 insertions(+), 218 deletions(-) create mode 100644 simgear/sound/soundmgr_openal_private.hxx diff --git a/CMakeLists.txt b/CMakeLists.txt index 61824342..39dfab99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ option(JPEG_FACTORY "Enable JPEG-factory support" OFF) option(ENABLE_LIBSVN "Set to ON to build SimGear with libsvnclient support" ON) option(ENABLE_RTI "Set to ON to build SimGear with RTI support" OFF) option(ENABLE_TESTS "Set to OFF to disable building SimGear's test applications" ON) +option(ENABLE_SOUND "Set to OFF to disable building SimGear's sound support" ON) option(SYSTEM_EXPAT "Set to ON to build SimGear using the system libExpat" OFF) if (MSVC) @@ -134,10 +135,15 @@ set (BOOST_CXX_FLAGS "-DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_BIMAP_DI if(SIMGEAR_HEADLESS) message(STATUS "SimGear mode: HEADLESS") + set(ENABLE_SOUND 0) else() message(STATUS "SimGear mode: NORMAL") find_package(OpenGL REQUIRED) - find_package(OpenAL REQUIRED) + + if (ENABLE_SOUND) + find_package(OpenAL REQUIRED) + endif(ENABLE_SOUND) + find_package(OpenSceneGraph 3.0.0 REQUIRED osgText osgSim osgDB osgParticle osgGA osgUtil) endif(SIMGEAR_HEADLESS) diff --git a/simgear/simgear_config_cmake.h.in b/simgear/simgear_config_cmake.h.in index c571af2d..bb6d092b 100644 --- a/simgear/simgear_config_cmake.h.in +++ b/simgear/simgear_config_cmake.h.in @@ -20,3 +20,4 @@ #cmakedefine GCC_ATOMIC_BUILTINS_FOUND #cmakedefine SYSTEM_EXPAT +#cmakedefine ENABLE_SOUND diff --git a/simgear/sound/CMakeLists.txt b/simgear/sound/CMakeLists.txt index 51d365e3..cc1b45cc 100644 --- a/simgear/sound/CMakeLists.txt +++ b/simgear/sound/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES soundmgr_openal.cxx xmlsound.cxx readwav.cxx + soundmgr_openal_private.hxx ) simgear_scene_component(sound sound "${SOURCES}" "${HEADERS}") diff --git a/simgear/sound/openal_test2.cxx b/simgear/sound/openal_test2.cxx index a136c83e..be56118d 100644 --- a/simgear/sound/openal_test2.cxx +++ b/simgear/sound/openal_test2.cxx @@ -10,6 +10,8 @@ #include #include "soundmgr_openal.hxx" +#include "sample_group.hxx" +#include "sample_openal.hxx" int main( int argc, char *argv[] ) { diff --git a/simgear/sound/openal_test3.cxx b/simgear/sound/openal_test3.cxx index fafb4045..a36af07b 100644 --- a/simgear/sound/openal_test3.cxx +++ b/simgear/sound/openal_test3.cxx @@ -10,7 +10,8 @@ #include #include "soundmgr_openal.hxx" - +#include "sample_group.hxx" +#include "sample_openal.hxx" int main( int argc, char *argv[] ) { SGSampleGroup *sgr; diff --git a/simgear/sound/openal_test4.cxx b/simgear/sound/openal_test4.cxx index 1b595eff..866426d5 100644 --- a/simgear/sound/openal_test4.cxx +++ b/simgear/sound/openal_test4.cxx @@ -10,7 +10,8 @@ #include #include "soundmgr_openal.hxx" - +#include "sample_group.hxx" +#include "sample_openal.hxx" int main( int argc, char *argv[] ) { SGSampleQueue *squeue; @@ -31,7 +32,7 @@ int main( int argc, char *argv[] ) { void *data; size_t len; int freq, fmt; - string file = SRC_DIR"/jet.wav"; + std::string file = SRC_DIR"/jet.wav"; smgr->load(file, &data, &fmt, &len, &freq); squeue = new SGSampleQueue( freq, fmt ); diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index ee8080fa..af4ffe6a 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -25,10 +25,14 @@ #endif #include +#include #include "soundmgr_openal.hxx" +#include "soundmgr_openal_private.hxx" #include "sample_group.hxx" +using std::string; + bool isNaN(float *v) { return (isnan(v[0]) || isnan(v[1]) || isnan(v[2])); } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 7d17f761..7197f3e4 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -29,17 +29,6 @@ #ifndef _SG_SAMPLE_GROUP_OPENAL_HXX #define _SG_SAMPLE_GROUP_OPENAL_HXX 1 -#ifndef __cplusplus -# error This library requires C++ -#endif - -#if defined(__APPLE__) -# include -#elif defined(OPENALSDK) -# include -#else -# include -#endif #include #include @@ -54,10 +43,8 @@ #include "sample_openal.hxx" #include "sample_queue.hxx" -using std::map; -using std::string; -typedef map < string, SGSharedPtr > sample_map; +typedef std::map < std::string, SGSharedPtr > sample_map; typedef sample_map::iterator sample_map_iterator; typedef sample_map::const_iterator const_sample_map_iterator; @@ -80,7 +67,7 @@ public: * @param smgr Pointer to a pre-initialized sound manager class * @param refname Name of this group for reference purposes. */ - SGSampleGroup ( SGSoundMgr *smgr, const string &refname ); + SGSampleGroup ( SGSoundMgr *smgr, const std::string &refname ); /** * Destructor @@ -106,28 +93,28 @@ public: * @param refname Name of this audio sample for reference purposes * @return return true if successful */ - bool add( SGSharedPtr sound, const string& refname ); + bool add( SGSharedPtr sound, const std::string& refname ); /** * Remove an audio sample from this group. * @param refname Reference name of the audio sample to remove * @return return true if successful */ - bool remove( const string& refname ); + bool remove( const std::string& refname ); /** * Test if a specified audio sample is registered at this sample group * @param refname Reference name of the audio sample to test for * @return true if the specified audio sample exists */ - bool exists( const string& refname ); + bool exists( const std::string& refname ); /** * Find a specified audio sample in this sample group * @param refname Reference name of the audio sample to find * @return A pointer to the SGSoundSample */ - SGSoundSample *find( const string& refname ); + SGSoundSample *find( const std::string& refname ); /** * Stop all playing samples and set the source id to invalid. @@ -150,14 +137,14 @@ public: * @param looping Define if the sound should loop continuously * @return true if the audio sample exsists and is scheduled for playing */ - bool play( const string& refname, bool looping ); + bool play( const std::string& refname, bool looping ); /** * Request to start playing the referred audio sample looping. * @param refname Reference name of the audio sample to start playing * @return true if the audio sample exsists and is scheduled for playing */ - inline bool play_looped( const string& refname ) { + inline bool play_looped( const std::string& refname ) { return play( refname, true ); } @@ -166,7 +153,7 @@ public: * @param refname Reference name of the audio sample to start playing * @return true if the audio sample exists and is scheduled for playing */ - inline bool play_once( const string& refname ) { + inline bool play_once( const std::string& refname ) { return play( refname, false ); } @@ -175,14 +162,14 @@ public: * @param refname Reference name of the audio sample to test for * @return True of the specified sound is currently playing */ - bool is_playing( const string& refname ); + bool is_playing( const std::string& refname ); /** * Request to stop playing the referred audio sample. * @param refname Reference name of the audio sample to stop * @return true if the audio sample exists and is scheduled to stop */ - bool stop( const string& refname ); + bool stop( const std::string& refname ); /** * Set the master volume for this sample group. @@ -223,7 +210,7 @@ public: protected: SGSoundMgr *_smgr; - string _refname; + std::string _refname; bool _active; private: @@ -239,8 +226,8 @@ private: sample_map _samples; std::vector< SGSharedPtr > _removed_samples; - bool testForALError(string s); - bool testForError(void *p, string s); + bool testForALError(std::string s); + bool testForError(void *p, std::string s); void update_pos_and_orientation(); void update_sample_config( SGSoundSample *sound ); diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index ef4de1f2..827e5247 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -36,7 +36,9 @@ #include "soundmgr_openal.hxx" #include "sample_openal.hxx" +#include "soundmgr_openal_private.hxx" +using std::string; // // SGSoundSample diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 55ec41cb..706fa8d0 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -30,20 +30,20 @@ #ifndef _SG_SAMPLE_HXX #define _SG_SAMPLE_HXX 1 -#ifndef __cplusplus -# error This library requires C++ -#endif - #include -#include #include -#include #include #include - +#include + class SGPath; +#ifndef AL_FORMAT_MONO8 + #define AL_FORMAT_MONO8 0x1100 +#endif + + /** * manages everything we need to know for an individual audio sample */ diff --git a/simgear/sound/sample_queue.cxx b/simgear/sound/sample_queue.cxx index 2e7c69c4..a99a4a3d 100644 --- a/simgear/sound/sample_queue.cxx +++ b/simgear/sound/sample_queue.cxx @@ -35,7 +35,9 @@ #include "soundmgr_openal.hxx" #include "sample_queue.hxx" +#include "soundmgr_openal_private.hxx" +using std::string; // // SGSampleQueue diff --git a/simgear/sound/sample_queue.hxx b/simgear/sound/sample_queue.hxx index dada5d1e..dedaee3c 100644 --- a/simgear/sound/sample_queue.hxx +++ b/simgear/sound/sample_queue.hxx @@ -36,7 +36,6 @@ #include #include -#include #include #include diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 53f1fe3d..b1091aa5 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -33,9 +33,14 @@ #include #include +#include + #include "soundmgr_openal.hxx" #include "readwav.hxx" +#include "soundmgr_openal_private.hxx" +#include "sample_group.hxx" +#include #include #include #include @@ -43,9 +48,6 @@ using std::string; using std::vector; -#if 0 -extern bool isNaN(float *v); -#endif #define MAX_SOURCES 128 @@ -54,6 +56,69 @@ extern bool isNaN(float *v); # define ALC_ALL_DEVICES_SPECIFIER 0x1013 #endif +class SGSoundMgr::SoundManagerPrivate +{ +public: + SoundManagerPrivate() : + _device(NULL), + _context(NULL), + _absolute_pos(SGVec3d::zeros()), + _base_pos(SGVec3d::zeros()), + _orientation(SGQuatd::zeros()) + { + + + } + + void init() + { + _at_up_vec[0] = 0.0; _at_up_vec[1] = 0.0; _at_up_vec[2] = -1.0; + _at_up_vec[3] = 0.0; _at_up_vec[4] = 1.0; _at_up_vec[5] = 0.0; + } + + void 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]; + + _absolute_pos = _base_pos; + } + + ALCdevice *_device; + ALCcontext *_context; + + std::vector _free_sources; + std::vector _sources_in_use; + + SGVec3d _absolute_pos; + SGVec3d _base_pos; + SGQuatd _orientation; + // Orientation of the listener. + // first 3 elements are "at" vector, second 3 are "up" vector + ALfloat _at_up_vec[6]; + + sample_group_map _sample_groups; + buffer_map _buffers; +}; + + // // Sound Manager // @@ -63,18 +128,14 @@ SGSoundMgr::SGSoundMgr() : _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") { + d.reset(new SoundManagerPrivate); } // destructor @@ -83,7 +144,7 @@ SGSoundMgr::~SGSoundMgr() { if (is_working()) stop(); - _sample_groups.clear(); + d->_sample_groups.clear(); } // initialize the sound manager @@ -97,10 +158,10 @@ void SGSoundMgr::init() { SG_LOG( SG_SOUND, SG_INFO, "Initializing OpenAL sound manager" ); - _free_sources.clear(); - _free_sources.reserve( MAX_SOURCES ); - _sources_in_use.clear(); - _sources_in_use.reserve( MAX_SOURCES ); + d->_free_sources.clear(); + d->_free_sources.reserve( MAX_SOURCES ); + d->_sources_in_use.clear(); + d->_sources_in_use.reserve( MAX_SOURCES ); ALCdevice *device = NULL; const char* devname = _device_name.c_str(); @@ -133,18 +194,17 @@ void SGSoundMgr::init() { return; } - if (_context != NULL) + if (d->_context != NULL) { SG_LOG(SG_SOUND, SG_ALERT, "context is already assigned"); } - _context = context; - _device = device; - - _at_up_vec[0] = 0.0; _at_up_vec[1] = 0.0; _at_up_vec[2] = -1.0; - _at_up_vec[3] = 0.0; _at_up_vec[4] = 1.0; _at_up_vec[5] = 0.0; + + d->_context = context; + d->_device = device; + d->init(); alListenerf( AL_GAIN, 0.0f ); - alListenerfv( AL_ORIENTATION, _at_up_vec ); + alListenerfv( AL_ORIENTATION, d->_at_up_vec ); alListenerfv( AL_POSITION, SGVec3f::zeros().data() ); alListenerfv( AL_VELOCITY, SGVec3f::zeros().data() ); @@ -167,9 +227,11 @@ void SGSoundMgr::init() { alGenSources(1, &source); error = alGetError(); if ( error == AL_NO_ERROR ) { - _free_sources.push_back( source ); + d->_free_sources.push_back( source ); + } else { + SG_LOG(SG_SOUND, SG_INFO, "allocating source failed:" << i); + break; } - else break; } _vendor = (const char *)alGetString(AL_VENDOR); @@ -182,7 +244,7 @@ void SGSoundMgr::init() { _bad_doppler = true; } - if (_free_sources.size() == 0) { + if (d->_free_sources.empty()) { SG_LOG(SG_SOUND, SG_ALERT, "Unable to grab any OpenAL sources!"); } } @@ -206,8 +268,9 @@ void SGSoundMgr::reinit() void SGSoundMgr::activate() { if ( is_working() ) { _active = true; - sample_group_map_iterator sample_grp_current = _sample_groups.begin(); - sample_group_map_iterator sample_grp_end = _sample_groups.end(); + + sample_group_map_iterator sample_grp_current = d->_sample_groups.begin(); + sample_group_map_iterator sample_grp_end = d->_sample_groups.end(); for ( ; sample_grp_current != sample_grp_end; ++sample_grp_current ) { SGSampleGroup *sgrp = sample_grp_current->second; sgrp->activate(); @@ -219,39 +282,39 @@ void SGSoundMgr::activate() { 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(); + sample_group_map_iterator sample_grp_current = d->_sample_groups.begin(); + sample_group_map_iterator sample_grp_end = d->_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++) { - ALuint source = _free_sources[i]; + BOOST_FOREACH(ALuint source, d->_free_sources) { alDeleteSources( 1 , &source ); testForALError("SGSoundMgr::stop: delete sources"); } - _free_sources.clear(); + d->_free_sources.clear(); // clear any OpenAL buffers before shutting down - buffer_map_iterator buffers_current = _buffers.begin(); - buffer_map_iterator buffers_end = _buffers.end(); + buffer_map_iterator buffers_current = d->_buffers.begin(); + buffer_map_iterator buffers_end = d->_buffers.end(); for ( ; buffers_current != buffers_end; ++buffers_current ) { refUint ref = buffers_current->second; ALuint buffer = ref.id; alDeleteBuffers(1, &buffer); testForALError("SGSoundMgr::stop: delete buffers"); } - _buffers.clear(); - _sources_in_use.clear(); + + d->_buffers.clear(); + d->_sources_in_use.clear(); if (is_working()) { _active = false; - alcDestroyContext(_context); - alcCloseDevice(_device); - _context = NULL; - _device = NULL; + alcDestroyContext(d->_context); + alcCloseDevice(d->_device); + d->_context = NULL; + d->_device = NULL; _renderer = "unknown"; _vendor = "unknown"; @@ -260,8 +323,8 @@ void SGSoundMgr::stop() { void SGSoundMgr::suspend() { if (is_working()) { - sample_group_map_iterator sample_grp_current = _sample_groups.begin(); - sample_group_map_iterator sample_grp_end = _sample_groups.end(); + sample_group_map_iterator sample_grp_current = d->_sample_groups.begin(); + sample_group_map_iterator sample_grp_end = d->_sample_groups.end(); for ( ; sample_grp_current != sample_grp_end; ++sample_grp_current ) { SGSampleGroup *sgrp = sample_grp_current->second; sgrp->stop(); @@ -272,8 +335,8 @@ void SGSoundMgr::suspend() { void SGSoundMgr::resume() { if (is_working()) { - sample_group_map_iterator sample_grp_current = _sample_groups.begin(); - sample_group_map_iterator sample_grp_end = _sample_groups.end(); + sample_group_map_iterator sample_grp_current = d->_sample_groups.begin(); + sample_group_map_iterator sample_grp_end = d->_sample_groups.end(); for ( ; sample_grp_current != sample_grp_end; ++sample_grp_current ) { SGSampleGroup *sgrp = sample_grp_current->second; sgrp->resume(); @@ -285,14 +348,14 @@ void SGSoundMgr::resume() { // run the audio scheduler void SGSoundMgr::update( double dt ) { if (_active) { - alcSuspendContext(_context); + alcSuspendContext(d->_context); if (_changed) { - update_pos_and_orientation(); + d->update_pos_and_orientation(); } - sample_group_map_iterator sample_grp_current = _sample_groups.begin(); - sample_group_map_iterator sample_grp_end = _sample_groups.end(); + sample_group_map_iterator sample_grp_current = d->_sample_groups.begin(); + sample_group_map_iterator sample_grp_end = d->_sample_groups.end(); for ( ; sample_grp_current != sample_grp_end; ++sample_grp_current ) { SGSampleGroup *sgrp = sample_grp_current->second; sgrp->update(dt); @@ -305,7 +368,7 @@ if (isNaN(toVec3f(_absolute_pos).data())) printf("NaN in listener position\n"); if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); #endif alListenerf( AL_GAIN, _volume ); - alListenerfv( AL_ORIENTATION, _at_up_vec ); + alListenerfv( AL_ORIENTATION, d->_at_up_vec ); // alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() ); SGQuatd hlOr = SGQuatd::fromLonLat( _geod_pos ); @@ -324,21 +387,21 @@ if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); _changed = false; } - alcProcessContext(_context); + alcProcessContext(d->_context); } } // 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_map_iterator sample_grp_it = d->_sample_groups.find( refname ); + if ( sample_grp_it != d->_sample_groups.end() ) { // sample group already exists return false; } if (_active) sgrp->activate(); - _sample_groups[refname] = sgrp; + d->_sample_groups[refname] = sgrp; return true; } @@ -347,13 +410,13 @@ bool SGSoundMgr::add( SGSampleGroup *sgrp, const string& refname ) // 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_map_iterator sample_grp_it = d->_sample_groups.find( refname ); + if ( sample_grp_it == d->_sample_groups.end() ) { // sample group was not found. return false; } - _sample_groups.erase( sample_grp_it ); + d->_sample_groups.erase( sample_grp_it ); return true; } @@ -361,21 +424,16 @@ bool SGSoundMgr::remove( const string &refname ) // 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; + sample_group_map_iterator sample_grp_it = d->_sample_groups.find( refname ); + return ( sample_grp_it != d->_sample_groups.end() ); } // 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_map_iterator sample_grp_it = d->_sample_groups.find( refname ); + if ( sample_grp_it == d->_sample_groups.end() ) { // sample group was not found. if (create) { SGSampleGroup* sgrp = new SGSampleGroup(this, refname); @@ -393,8 +451,7 @@ SGSampleGroup *SGSoundMgr::find( const string &refname, bool create ) { void SGSoundMgr::set_volume( float v ) { _volume = v; - if (_volume > 1.0) _volume = 1.0; - if (_volume < 0.0) _volume = 0.0; + SG_CLAMP_RANGE(_volume, 0.0f, 1.0f); _changed = true; } @@ -411,10 +468,10 @@ 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); + if (!d->_free_sources.empty()) { + source = d->_free_sources.back(); + d->_free_sources.pop_back(); + d->_sources_in_use.push_back(source); } else SG_LOG( SG_SOUND, SG_BULK, "Sound manager: No more free sources available!\n"); @@ -427,8 +484,8 @@ 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() ) { + it = std::find(d->_sources_in_use.begin(), d->_sources_in_use.end(), source); + if ( it != d->_sources_in_use.end() ) { ALint result; alGetSourcei( source, AL_SOURCE_STATE, &result ); @@ -438,8 +495,8 @@ void SGSoundMgr::release_source( unsigned int source ) alSourcei( source, AL_BUFFER, 0 ); // detach the associated buffer testForALError("release_source"); - _free_sources.push_back( source ); - _sources_in_use.erase( it ); + d->_free_sources.push_back( source ); + d->_sources_in_use.erase( it ); } } @@ -453,8 +510,8 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) 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_map_iterator buffer_it = d->_buffers.find( sample_name ); + if ( buffer_it != d->_buffers.end() ) { buffer_it->second.refctr++; buffer = buffer_it->second.id; sample->set_buffer( buffer ); @@ -496,7 +553,7 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) if ( !testForALError("buffer add data") ) { sample->set_buffer(buffer); - _buffers[sample_name] = refUint(buffer); + d->_buffers[sample_name] = refUint(buffer); } } @@ -514,8 +571,8 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) if ( !sample->is_queue() ) { string sample_name = sample->get_sample_name(); - buffer_map_iterator buffer_it = _buffers.find( sample_name ); - if ( buffer_it == _buffers.end() ) { + buffer_map_iterator buffer_it = d->_buffers.find( sample_name ); + if ( buffer_it == d->_buffers.end() ) { // buffer was not found return; } @@ -525,36 +582,12 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) if (buffer_it->second.refctr == 0) { ALuint buffer = buffer_it->second.id; alDeleteBuffers(1, &buffer); - _buffers.erase( buffer_it ); + d->_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]; - - _absolute_pos = _base_pos; -} - bool SGSoundMgr::load(const string &samplepath, void **dbuf, int *fmt, size_t *sz, int *frq ) { @@ -567,9 +600,7 @@ bool SGSoundMgr::load(const string &samplepath, void **dbuf, int *fmt, ALvoid *data; ALfloat freqf; - // ignore previous errors to prevent the system from halting on silly errors - alGetError(); - alcGetError(_device); + data = simgear::loadWAVFromFile(samplepath, format, size, freqf ); freq = (ALsizei)freqf; if (data == NULL) { @@ -640,12 +671,43 @@ bool SGSoundMgr::testForALError(string s) bool SGSoundMgr::testForALCError(string s) { ALCenum error; - error = alcGetError(_device); + error = alcGetError(d->_device); if (error != ALC_NO_ERROR) { SG_LOG( SG_SOUND, SG_ALERT, "ALC Error (sound manager): " - << alcGetString(_device, error) << " at " + << alcGetString(d->_device, error) << " at " << s); return true; } return false; } + +bool SGSoundMgr::is_working() const +{ + return (d->_device != NULL); +} + +const SGQuatd& SGSoundMgr::get_orientation() const +{ + return d->_orientation; +} + +void SGSoundMgr::set_orientation( const SGQuatd& ori ) +{ + d->_orientation = ori; + _changed = true; +} + +const SGVec3d& SGSoundMgr::get_position() const +{ + return d->_absolute_pos; +} + +void SGSoundMgr::set_position( const SGVec3d& pos, const SGGeod& pos_geod ) +{ + d->_base_pos = pos; _geod_pos = pos_geod; _changed = true; +} + +SGVec3f SGSoundMgr::get_direction() const +{ + return SGVec3f(d->_at_up_vec[0], d->_at_up_vec[1], d->_at_up_vec[2]); +} diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 84d93baa..d60294dd 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -38,40 +38,15 @@ #include #include #include - -#if defined(__APPLE__) -# include -# include -#elif defined(OPENALSDK) -# include -# include -#else -# include -# include -#endif - +#include // for std::auto_ptr + #include #include -#include - -#include "sample_group.hxx" - -struct refUint { - unsigned int refctr; - ALuint id; +#include - 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; +// forward decls +class SGSampleGroup; +class SGSoundSample; /** * Manage a collection of SGSampleGroup instances @@ -102,7 +77,7 @@ public: * Test is the sound manager is in a working condition. * @return true is the sound manager is working */ - inline bool is_working() const { return (_device != NULL); } + bool is_working() const; /** * Set the sound manager to a working condition. @@ -142,15 +117,13 @@ public: * @param refname Reference name of the sample group to find * @return A pointer to the SGSampleGroup */ - SGSampleGroup *find( const string& refname, bool create = false ); + SGSampleGroup *find( const std::string& refname, bool create = false ); /** * Set the Cartesian position of the sound manager. * @param pos OpenAL listener position */ - void set_position( const SGVec3d& pos, const SGGeod& pos_geod ) { - _base_pos = pos; _geod_pos = pos_geod; _changed = true; - } + void set_position( const SGVec3d& pos, const SGGeod& pos_geod ); void set_position_offset( const SGVec3d& pos ) { _offset_pos = pos; _changed = true; @@ -161,7 +134,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @return OpenAL listener position */ - SGVec3d& get_position() { return _absolute_pos; } + const SGVec3d& get_position() const; /** * Set the velocity vector (in meters per second) of the sound manager @@ -183,24 +156,20 @@ public: * Set the orientation of the sound manager * @param ori Quaternation containing the orientation information */ - void set_orientation( const SGQuatd& ori ) { - _orientation = ori; _changed = true; - } + void set_orientation( const SGQuatd& ori ); /** * Get the orientation of the sound manager * @return Quaternation containing the orientation information */ - inline const SGQuatd& get_orientation() { return _orientation; } + const SGQuatd& get_orientation() const; /** * 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 OpenAL listener */ - SGVec3f get_direction() { - return SGVec3f(_at_up_vec[0], _at_up_vec[1], _at_up_vec[2]); - } + SGVec3f get_direction() const; enum { NO_SOURCE = (unsigned int)-1, @@ -270,7 +239,7 @@ public: * @param freq Pointer to a vairable that gets the sample frequency in Herz * @return true if succesful, false on error */ - bool load(const string &samplepath, void **data, int *format, + bool load(const std::string &samplepath, void **data, int *format, size_t *size, int *freq ); /** @@ -285,34 +254,21 @@ public: const std::string& get_renderer() { return _renderer; } private: - + class SoundManagerPrivate; + /// private implementation object + std::auto_ptr d; + bool _active; bool _changed; float _volume; - ALCdevice *_device; - ALCcontext *_context; - // 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; - ALfloat _at_up_vec[6]; - - 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; @@ -322,7 +278,6 @@ private: bool testForALCError(std::string s); bool testForError(void *p, std::string s); - void update_pos_and_orientation(); void update_sample_config( SGSampleGroup *sound ); }; diff --git a/simgear/sound/soundmgr_openal_private.hxx b/simgear/sound/soundmgr_openal_private.hxx new file mode 100644 index 00000000..26d128da --- /dev/null +++ b/simgear/sound/soundmgr_openal_private.hxx @@ -0,0 +1,66 @@ +// soundmgr_openal_prviate.hxx -- Implementation details of the soung manager +// +// 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$ + + +#ifndef _SG_SOUNDMGR_OPENAL_PRIVATE_HXX +#define _SG_SOUNDMGR_OPENAL_PRIVATE_HXX 1 + +#include +#include +#include + +#if defined(__APPLE__) +# include +# include +#elif defined(OPENALSDK) +# include +# include +#else +# include +# include +#endif + +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; + +#endif // _SG_SOUNDMGR_OPENAL_PRIVATE_HXX + + diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 51c04409..2629c29d 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -25,6 +25,9 @@ # include #endif +#include "xmlsound.hxx" + + #include #include @@ -35,8 +38,10 @@ #include #include -#include "xmlsound.hxx" +#include "sample_group.hxx" +#include "sample_openal.hxx" +using std::string; // static double _snd_lin(double v) { return v; } static double _snd_inv(double v) { return (v == 0) ? 1e99 : 1/v; } diff --git a/simgear/sound/xmlsound.hxx b/simgear/sound/xmlsound.hxx index 95582aab..34761df0 100644 --- a/simgear/sound/xmlsound.hxx +++ b/simgear/sound/xmlsound.hxx @@ -29,18 +29,20 @@ #ifndef _SG_SOUND_HXX #define _SG_SOUND_HXX 1 -#ifndef __cplusplus -# error This library requires C++ -#endif #include - +#include + #include #include +#include -#include "sample_group.hxx" -#include "sample_openal.hxx" +// forward decls +class SGSampleGroup; +class SGSoundSample; +class SGCondition; +class SGPath; static const double MAX_TRANSIT_TIME = 0.1; // 100 ms. @@ -144,7 +146,7 @@ private: SGPropertyNode_ptr _property; bool _active; - string _name; + std::string _name; int _mode; double _prev_value; double _dt_play; -- 2.39.5