]> git.mxchange.org Git - simgear.git/commitdiff
Initial work on making OpenAL private to the sound code.
authorJames Turner <zakalawe@mac.com>
Sun, 30 Sep 2012 18:41:51 +0000 (19:41 +0100)
committerJames Turner <zakalawe@mac.com>
Thu, 4 Oct 2012 15:47:13 +0000 (16:47 +0100)
17 files changed:
CMakeLists.txt
simgear/simgear_config_cmake.h.in
simgear/sound/CMakeLists.txt
simgear/sound/openal_test2.cxx
simgear/sound/openal_test3.cxx
simgear/sound/openal_test4.cxx
simgear/sound/sample_group.cxx
simgear/sound/sample_group.hxx
simgear/sound/sample_openal.cxx
simgear/sound/sample_openal.hxx
simgear/sound/sample_queue.cxx
simgear/sound/sample_queue.hxx
simgear/sound/soundmgr_openal.cxx
simgear/sound/soundmgr_openal.hxx
simgear/sound/soundmgr_openal_private.hxx [new file with mode: 0644]
simgear/sound/xmlsound.cxx
simgear/sound/xmlsound.hxx

index 61824342e6ffec623172d8179871e676026d4775..39dfab99bf448617b9fd805c265d61ebd3ac35ba 100644 (file)
@@ -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)
 
index c571af2dd820ac7ea942ec2abd7b1588b294345b..bb6d092b982c1dd37a3e3743ea7e83a5e4b9c41d 100644 (file)
@@ -20,3 +20,4 @@
 #cmakedefine GCC_ATOMIC_BUILTINS_FOUND
 
 #cmakedefine SYSTEM_EXPAT
+#cmakedefine ENABLE_SOUND
index 51d365e3dfd6b771d7a6d2c83d10bd21d98556b1..cc1b45ccce0ea9391e6dc77882eafa37124ddfd0 100644 (file)
@@ -16,6 +16,7 @@ set(SOURCES
     soundmgr_openal.cxx
     xmlsound.cxx
     readwav.cxx
+    soundmgr_openal_private.hxx
     )
 
 simgear_scene_component(sound sound "${SOURCES}" "${HEADERS}")
index a136c83e10173c8eee6e7776c2de6fc8a6c2004c..be56118d1320d32c9a8594aeace05e020971cd00 100644 (file)
@@ -10,6 +10,8 @@
 #include <simgear/misc/sg_path.hxx>
 
 #include "soundmgr_openal.hxx"
+#include "sample_group.hxx"
+#include "sample_openal.hxx"
 
 
 int main( int argc, char *argv[] ) {
index fafb404538bd1bfbe43bb78b799ddaffcb65d54d..a36af07bf6803b26608af43c4bc86df8d8532b76 100644 (file)
@@ -10,7 +10,8 @@
 #include <simgear/misc/sg_path.hxx>
 
 #include "soundmgr_openal.hxx"
-
+#include "sample_group.hxx"
+#include "sample_openal.hxx"
 
 int main( int argc, char *argv[] ) {
     SGSampleGroup *sgr;
index 1b595eff4bda6131ad48a2a38458dd66f77b7b1c..866426d577e56db7eb659adb2c0895dd4bd663a1 100644 (file)
@@ -10,7 +10,8 @@
 #include <simgear/misc/sg_path.hxx>
 
 #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 );
index ee8080fa045df8fd189f4dc672afdd907b00498c..af4ffe6aa74b5270d33b0bb68e4f2a7d4d447402 100644 (file)
 #endif
 
 #include <simgear/compiler.h>
+#include <simgear/debug/logstream.hxx>
 
 #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]));
 }
index 7d17f76126b1fc3452a74c08f833518ebb604aac..7197f3e40e21765b7e76232c7c69177b2ccc15f9 100644 (file)
 #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 <OpenAL/al.h>
-#elif defined(OPENALSDK)
-# include <al.h>
-#else
-# include <AL/al.h>
-#endif
 
 #include <string>
 #include <vector>
 #include "sample_openal.hxx"
 #include "sample_queue.hxx"
 
-using std::map;
-using std::string;
 
-typedef map < string, SGSharedPtr<SGSoundSample> > sample_map;
+typedef std::map < std::string, SGSharedPtr<SGSoundSample> > 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<SGSoundSample> sound, const string& refname );
+    bool add( SGSharedPtr<SGSoundSample> 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<SGSoundSample> > _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 );
index ef4de1f2475e6988e51b7f1490f74530adaf59fd..827e524764bab95105462ac905667f2a87307b58 100644 (file)
@@ -36,7 +36,9 @@
 
 #include "soundmgr_openal.hxx"
 #include "sample_openal.hxx"
+#include "soundmgr_openal_private.hxx"
 
+using std::string;
 
 //
 // SGSoundSample
index 55ec41cb39055d41b464376082be3f497e451dbd..706fa8d07383106ccf8bfe13667ac9d03f8180a2 100644 (file)
 #ifndef _SG_SAMPLE_HXX
 #define _SG_SAMPLE_HXX 1
 
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
 #include <string>
-#include <cstdlib>
 
 #include <simgear/compiler.h>
-#include <simgear/debug/logstream.hxx>
 #include <simgear/structure/SGReferenced.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
-
+#include <simgear/math/SGMath.hxx>
+     
 class SGPath;
 
+#ifndef AL_FORMAT_MONO8
+     #define AL_FORMAT_MONO8    0x1100
+#endif
+
 /**
  * manages everything we need to know for an individual audio sample
  */
index 2e7c69c4ab68c3eef45f05613fc176f9e0737513..a99a4a3d0074bada8aa2c6100bf491e385b9e37a 100644 (file)
@@ -35,7 +35,9 @@
 
 #include "soundmgr_openal.hxx"
 #include "sample_queue.hxx"
+#include "soundmgr_openal_private.hxx"
 
+using std::string;
 
 //
 // SGSampleQueue
index dada5d1eb048915352e6b699da5a46a9584da384..dedaee3ce43fbbfcb275775884a3198ca62d6ce3 100644 (file)
@@ -36,7 +36,6 @@
 #include <vector>
 
 #include <simgear/compiler.h>
-#include <simgear/debug/logstream.hxx>
 #include <simgear/structure/SGReferenced.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
 
index 53f1fe3d0b1d9fa7f0b9ab62759c6af91dde1d70..b1091aa59dcde6231ec2522346f5879a79d31137 100644 (file)
 #include <algorithm>
 #include <cstring>
 
+#include <boost/foreach.hpp>
+
 #include "soundmgr_openal.hxx"
 #include "readwav.hxx"
+#include "soundmgr_openal_private.hxx"
+#include "sample_group.hxx"
 
+#include <simgear/sg_inlines.h>
 #include <simgear/structure/exception.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/misc/sg_path.hxx>
@@ -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<ALuint> _free_sources;
+    std::vector<ALuint> _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<ALuint>::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]);
+}
index 84d93baafa2933fd44cfd59c6c90d1a42b8177cd..d60294dd236af65737617e49d88a9b444baa71d1 100644 (file)
 #include <string>
 #include <vector>
 #include <map>
-
-#if defined(__APPLE__)
-# include <OpenAL/al.h>
-# include <OpenAL/alc.h>
-#elif defined(OPENALSDK)
-# include <al.h>
-# include <alc.h>
-#else
-# include <AL/al.h>
-# include <AL/alc.h>
-#endif
-
+#include <memory> // for std::auto_ptr
+     
 #include <simgear/compiler.h>
 #include <simgear/structure/subsystem_mgr.hxx>
-#include <simgear/math/SGMathFwd.hxx>
-
-#include "sample_group.hxx"
-
-struct refUint {
-    unsigned int refctr;
-    ALuint id;
+#include <simgear/math/SGMath.hxx>
 
-    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<SGSampleGroup> > 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<SoundManagerPrivate> 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<ALuint> _free_sources;
-    std::vector<ALuint> _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 (file)
index 0000000..26d128d
--- /dev/null
@@ -0,0 +1,66 @@
+// soundmgr_openal_prviate.hxx -- Implementation details of the soung manager
+//
+// Sound manager initially written by David Findlay
+// <david_j_findlay@yahoo.com.au> 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 <erik@ehofman.com>
+//
+// 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 <string>
+#include <vector>
+#include <map>
+
+#if defined(__APPLE__)
+# include <OpenAL/al.h>
+# include <OpenAL/alc.h>
+#elif defined(OPENALSDK)
+# include <al.h>
+# include <alc.h>
+#else
+# include <AL/al.h>
+# include <AL/alc.h>
+#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<SGSampleGroup> > 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
+
+
index 51c04409545507f6e5d0f900dbb79f88ba65871d..2629c29d1f92cd0e7110cde9d6fb6fe96b783b0c 100644 (file)
@@ -25,6 +25,9 @@
 #  include <simgear_config.h>
 #endif
 
+#include "xmlsound.hxx"
+
+
 #include <simgear/compiler.h>
 
 #include <string.h>
 #include <simgear/structure/exception.hxx>
 #include <simgear/misc/sg_path.hxx>
 
-#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; }
index 95582aab12ca65cda2c5f8ec924653965c565464..34761df0e4733f3546073ecd1988283556527f5c 100644 (file)
 #ifndef _SG_SOUND_HXX
 #define _SG_SOUND_HXX 1
 
-#ifndef __cplusplus
-# error This library requires C++
-#endif
 
 #include <vector>
-
+#include <string>
+     
 #include <simgear/compiler.h>
 
 #include <simgear/props/propsfwd.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
 
-#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;