From e2e1524454d94db9e1b8cf591f337ca0a5fd06da Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 4 Oct 2009 13:52:27 +0000 Subject: [PATCH 01/85] Initial commit of the new sound system, expect more updates to follow --- simgear/environment/visual_enviro.cxx | 20 +- simgear/environment/visual_enviro.hxx | 6 +- simgear/sound/Makefile.am | 8 +- simgear/sound/jet.wav | Bin 35256 -> 34890 bytes simgear/sound/openal_test2.cxx | 100 +++-- simgear/sound/sample_group.cxx | 443 ++++++++++++++++++++ simgear/sound/sample_group.hxx | 181 ++++++++ simgear/sound/sample_openal.cxx | 563 +++++-------------------- simgear/sound/sample_openal.hxx | 319 ++++++++++---- simgear/sound/soundmgr_openal.cxx | 577 +++++++++++++++----------- simgear/sound/soundmgr_openal.hxx | 222 ++++------ simgear/sound/xmlsound.cxx | 37 +- simgear/sound/xmlsound.hxx | 8 +- simgear/structure/SGAtomic.cxx | 2 +- 14 files changed, 1514 insertions(+), 972 deletions(-) create mode 100644 simgear/sound/sample_group.cxx create mode 100644 simgear/sound/sample_group.hxx diff --git a/simgear/environment/visual_enviro.cxx b/simgear/environment/visual_enviro.cxx index 42b61fd0..71a0c5ea 100644 --- a/simgear/environment/visual_enviro.cxx +++ b/simgear/environment/visual_enviro.cxx @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -175,7 +175,7 @@ SGEnviro::SGEnviro() : lightning_enable_state(false), elapsed_time(0.0), dt(0.0), - soundMgr(NULL), + sampleGroup(NULL), snd_active(false), snd_dist(0.0), min_time_before_lt(0.0), @@ -189,6 +189,8 @@ SGEnviro::SGEnviro() : } SGEnviro::~SGEnviro(void) { + if (sampleGroup) delete sampleGroup; + // OSGFIXME return; list_of_lightning::iterator iLightning; @@ -530,8 +532,8 @@ void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed } -void SGEnviro::set_soundMgr(SGSoundMgr *mgr) { - soundMgr = mgr; +void SGEnviro::set_sampleGroup(SGSampleGroup *sgr) { + sampleGroup = sgr; } void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double hspeed) { @@ -616,7 +618,7 @@ void SGLightning::lt_build(void) { top[PY] = alt; top[PZ] = 0; lt_build_tree_branch(0, top, 1.0, 50, top[PY] / 8.0); - if( ! sgEnviro.soundMgr ) + if( ! sgEnviro.sampleGroup ) return; Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 ); Point3D dest( lon*SG_DEGREES_TO_RADIANS, lat*SG_DEGREES_TO_RADIANS, 0.0 ); @@ -751,15 +753,15 @@ void SGEnviro::drawLightning(void) { double ax = 0.0, ay = 0.0; ax = cos(course) * dist; ay = sin(course) * dist; - SGSharedPtr snd = soundMgr->find("thunder"); + SGSharedPtr snd = sampleGroup->find("thunder"); if( snd ) { - ALfloat pos[3]={ax, ay, -sgEnviro.last_alt }; - snd->set_source_pos(pos); + SGVec3d pos = SGVec3d(ax, ay, -sgEnviro.last_alt); + snd->set_base_position(pos); snd->play_once(); } } } else { - if( !soundMgr->is_playing("thunder") ) { + if( !sampleGroup->is_playing("thunder") ) { snd_active = false; snd_playing = false; } diff --git a/simgear/environment/visual_enviro.hxx b/simgear/environment/visual_enviro.hxx index 51a76a06..08830c0b 100644 --- a/simgear/environment/visual_enviro.hxx +++ b/simgear/environment/visual_enviro.hxx @@ -32,7 +32,7 @@ using std::vector; using std::string; class SGLightning; -class SGSoundMgr; +class SGSampleGroup; /** * Simulate some echo on a weather radar. @@ -84,7 +84,7 @@ private: sgVec4 fog_color; sgMat4 transform; double last_lon, last_lat, last_alt; - SGSoundMgr *soundMgr; + SGSampleGroup *sampleGroup; bool snd_active, snd_playing; double snd_timer, snd_wait, snd_pos_lat, snd_pos_lon, snd_dist; double min_time_before_lt; @@ -243,7 +243,7 @@ public: * Forward the sound manager instance to be able to play samples. * @param mgr a running sound manager */ - void set_soundMgr(SGSoundMgr *mgr); + void set_sampleGroup(SGSampleGroup *sgr); void setFOV( float w, float h ); void getFOV( float &w, float &h ); diff --git a/simgear/sound/Makefile.am b/simgear/sound/Makefile.am index e421cdef..57f3161a 100644 --- a/simgear/sound/Makefile.am +++ b/simgear/sound/Makefile.am @@ -7,11 +7,13 @@ lib_LIBRARIES = libsgsound.a noinst_HEADERS = include_HEADERS = \ + sample_group.hxx \ sample_openal.hxx \ soundmgr_openal.hxx \ xmlsound.hxx libsgsound_a_SOURCES = \ + sample_group.cxx \ sample_openal.cxx \ soundmgr_openal.cxx \ xmlsound.cxx @@ -27,10 +29,10 @@ libsgsound_a_SOURCES = \ #openal_test2_LDADD = \ # libsgsound.a \ +# $(top_builddir)/simgear/structure/libsgstructure.a \ +# $(top_builddir)/simgear/timing/libsgtiming.a \ # $(top_builddir)/simgear/debug/libsgdebug.a \ # $(top_builddir)/simgear/misc/libsgmisc.a \ -# $(top_builddir)/simgear/structure/libsgstructure.a \ -# $(openal_LIBS) \ -# -lOpenThreads +# $(openal_LIBS) INCLUDES = -I$(top_srcdir) -DSRC_DIR=\"$(top_srcdir)/simgear/sound\" diff --git a/simgear/sound/jet.wav b/simgear/sound/jet.wav index 891c84d0b2064d5e66e594d65e8809b0953c8b07..a06f2afeaebc8fdea8601d67ddb935db8cffef68 100644 GIT binary patch literal 34890 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 literal 35256 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 diff --git a/simgear/sound/openal_test2.cxx b/simgear/sound/openal_test2.cxx index da263620..46a0f621 100644 --- a/simgear/sound/openal_test2.cxx +++ b/simgear/sound/openal_test2.cxx @@ -7,48 +7,94 @@ static unsigned int sleep(unsigned int secs) { return 0; } #include // sleep() #endif -#include "sample_openal.hxx" +#include +#include + #include "soundmgr_openal.hxx" int main( int argc, char *argv[] ) { - SGSoundMgr sm; + SGSampleGroup *sgr; + SGSoundMgr *smgr; - SGSoundSample sample1( SRC_DIR, "jet.wav" ); - sample1.set_volume(0.5); - sample1.set_volume(0.2); - sample1.play_looped(); + smgr = new SGSoundMgr; + + smgr->bind(); + smgr->init(); + smgr->set_volume(0.9); + sgr = smgr->find("default", true); + + SGSoundSample *sample1 = new SGSoundSample( SRC_DIR, "jet.wav" ); + sample1->set_volume(1.0); + sample1->set_pitch(1.0); + sample1->play_looped(); + sgr->add(sample1, "sound1"); + smgr->update(1.0); + printf("playing sample1\n"); sleep(1); - SGSoundSample sample2( SRC_DIR, "jet.wav" ); - sample2.set_volume(0.5); - sample2.set_pitch(0.4); - sample2.play_looped(); + SGSoundSample *sample2 = new SGSoundSample( SRC_DIR, "jet.wav" ); + sample2->set_volume(0.5); + sample2->set_pitch(0.4); + sample2->play_looped(); + sgr->add(sample2, "sound2"); + smgr->update(1.0); + printf("playing sample2\n"); sleep(1); - SGSoundSample sample3( SRC_DIR, "jet.wav" ); - sample3.set_volume(0.5); - sample3.set_pitch(0.8); - sample3.play_looped(); + SGSoundSample *sample3 = new SGSoundSample( SRC_DIR, "jet.wav" ); + sample3->set_volume(0.5); + sample3->set_pitch(0.8); + sample3->play_looped(); + sgr->add(sample3, "sound3"); + smgr->update(1.0); + printf("playing sample3\n"); sleep(1); - SGSoundSample sample4( SRC_DIR, "jet.wav" ); - sample4.set_volume(0.5); - sample4.set_pitch(1.2); - sample4.play_looped(); + SGSoundSample *sample4 = new SGSoundSample( SRC_DIR, "jet.wav" ); + sample4->set_volume(0.5); + sample4->set_pitch(1.2); + sample4->play_looped(); + sgr->add(sample4, "sound4"); + smgr->update(1.0); + printf("playing sample4\n"); sleep(1); - SGSoundSample sample5( SRC_DIR, "jet.wav" ); - sample5.set_volume(0.5); - sample5.set_pitch(1.6); - sample5.play_looped(); + SGSoundSample *sample5 = new SGSoundSample( SRC_DIR, "jet.wav" ); + sample5->set_volume(0.5); + sample5->set_pitch(1.6); + sample5->play_looped(); + sgr->add(sample5, "sound5"); + smgr->update(1.0); + printf("playing sample5\n"); sleep(1); - SGSoundSample sample6( SRC_DIR, "jet.wav" ); - sample6.set_volume(0.5); - sample6.set_pitch(2.0); - sample6.play_looped(); + SGSoundSample *sample6 = new SGSoundSample( SRC_DIR, "jet.wav" ); + sample6->set_volume(0.5); + sample6->set_pitch(2.0); + sample6->play_looped(); + sgr->add(sample6, "sound6"); + smgr->update(1.0); + printf("playing sample6\n"); sleep(1); - sleep(10); + for (int i=0; i<10; i++) { + sleep(1); + smgr->update(1); + } + + sgr->stop("sound1"); + sgr->stop("sound2"); + sgr->stop("sound3"); + sleep(0.5); + sgr->update(0.5); + sgr->stop("sound4"); + sgr->stop("sound5"); + sgr->stop("sound6"); + sgr->update(1); + sleep(1); + + smgr->unbind(); + sleep(2); + delete smgr; } diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx new file mode 100644 index 00000000..ffa23e68 --- /dev/null +++ b/simgear/sound/sample_group.cxx @@ -0,0 +1,443 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#if defined (__APPLE__) +# ifdef __GNUC__ +# if ( __GNUC__ >= 3 ) && ( __GNUC_MINOR__ >= 3 ) +// # include +inline int (isnan)(double r) { return !(r <= 0 || r >= 0); } +# else + // any C++ header file undefines isinf and isnan + // so this should be included before + // the functions are STILL in libm (libSystem on mac os x) +extern "C" int isnan (double); +extern "C" int isinf (double); +# endif +# else +// inline int (isinf)(double r) { return isinf(r); } +// inline int (isnan)(double r) { return isnan(r); } +# endif +#endif + +#if defined (__FreeBSD__) +# if __FreeBSD_version < 500000 + extern "C" { + inline int isnan(double r) { return !(r <= 0 || r >= 0); } + } +# endif +#endif + +#if defined (__CYGWIN__) +# include +#endif + +#if defined(__MINGW32__) +# define isnan(x) _isnan(x) +#endif + +#include "soundmgr_openal.hxx" +#include "sample_group.hxx" + +SGSampleGroup::SGSampleGroup () : + _smgr(NULL), + _active(false), + _changed(true), + _position_changed(true), + _position(SGVec3d::zeros().data()), + _orientation(SGVec3f::zeros().data()) +{ + _samples.clear(); +} + +SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : + _smgr(smgr), + _active(false), + _changed(true), + _position_changed(true), + _position(SGVec3d::zeros().data()), + _orientation(SGVec3f::zeros().data()) +{ + _smgr->add(this, refname); + _active = _smgr->is_working(); + _samples.clear(); +} + +SGSampleGroup::~SGSampleGroup () +{ + _active = false; + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + + if ( sample->is_valid_source() && sample->is_playing() ) { + sample->no_valid_source(); + _smgr->release_source( sample->get_source() ); + } + } + + _smgr = 0; +} + +void SGSampleGroup::update( double dt ) { + + if ( !_active ) return; + + // testForALError("start of update!!\n"); + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + + if ( !sample->is_valid_source() && sample->is_playing() ) { + // + // a request to start playing a sound has been filed. + // + ALboolean looping = sample->get_looping() ? AL_TRUE : AL_FALSE; + + if ( !sample->is_valid_buffer() ) { + // sample was not yet loaded or removed again + +// TODO: Create a buffer cache that checks whether a file is already present +// as an OpenAL buffer since buffers can be shared among sources. + load_file(sample); + if ( testForALError("load sample") ) { + throw sg_exception("Failed to load sound sample."); + continue; + } + + // create an OpenAL buffer handle + ALuint buffer; + alGenBuffers(1, &buffer); + if ( testForALError("generate buffer") ) { + throw sg_exception("Failed to generate OpenAL buffer."); + continue; + } + + // Copy data to the internal OpenAL buffer + const ALvoid *data = sample->get_data(); + ALenum format = sample->get_format(); + ALsizei size = sample->get_size(); + ALsizei freq = sample->get_frequency(); + alBufferData( buffer, format, data, size, freq ); + sample->free_data(); + if ( testForALError("buffer add data") ) { + continue; + } + + sample->set_buffer(buffer); + } + + // start playing the sample + ALuint buffer = sample->get_buffer(); + ALuint source = _smgr->request_source(); + if (alIsSource(source) == AL_TRUE && alIsBuffer(buffer) == AL_TRUE) + { + sample->set_source( source ); + + alSourcei( source, AL_BUFFER, buffer ); + testForALError("assign buffer to source"); + + sample->set_source( source ); + update_sample_config( sample ); + + alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE ); + alSourcei( source, AL_LOOPING, looping ); + alSourcePlay( source ); + testForALError("sample play"); + } else { + if (alIsBuffer(buffer) == AL_FALSE) + SG_LOG( SG_GENERAL, SG_ALERT, "No such buffer!\n"); + // sample->no_valid_source(); + // sadly, no free source available at this time + } + + } else if ( sample->is_valid_source() && sample->has_changed() ) { + if ( !sample->is_playing() ) { + // a request to stop playing the sound has been filed. + + sample->no_valid_source(); + sample->stop(); + _smgr->release_source( sample->get_source() ); + } else { + update_sample_config( sample ); + } + + } else if ( sample->is_valid_source() ) { + // check if the sound has stopped by itself + + unsigned int source = sample->get_source(); + int result; + + alGetSourcei( source, AL_SOURCE_STATE, &result ); + if ( result == AL_STOPPED ) { + // sample is stoped because it wasn't looping + sample->no_valid_source(); + sample->stop(); + _smgr->release_source( source ); + + } + } + testForALError("update"); + } +} + +// add a sound effect, return true if successful +bool SGSampleGroup::add( SGSoundSample *sound, const string& refname ) { + + sample_map_iterator sample_it = _samples.find( refname ); + if ( sample_it != _samples.end() ) { + // sample name already exists + return false; + } + + _samples[refname] = sound; + return true; +} + + +// remove a sound effect, return true if successful +bool SGSampleGroup::remove( const string &refname ) { + + sample_map_iterator sample_it = _samples.find( refname ); + if ( sample_it == _samples.end() ) { + // sample was not found + return false; + } + + _samples.erase( sample_it ); + return true; +} + + +// return true of the specified sound exists in the sound manager system +bool SGSampleGroup::exists( const string &refname ) { + sample_map_iterator sample_it = _samples.find( refname ); + if ( sample_it == _samples.end() ) { + // sample was not found + return false; + } + + return true; +} + + +// return a pointer to the SGSoundSample if the specified sound exists +// in the sound manager system, otherwise return NULL +SGSoundSample *SGSampleGroup::find( const string &refname ) { + sample_map_iterator sample_it = _samples.find( refname ); + if ( sample_it == _samples.end() ) { + // sample was not found + return NULL; + } + + return sample_it->second; +} + + +// stop playing all associated samples +void +SGSampleGroup::suspend () +{ + _active = false; + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + + if ( sample->is_valid_source() && sample->is_playing() ) { + unsigned int source = sample->get_source(); + alSourcePause( source ); + } + } + testForALError("suspend"); +} + +// resume playing all associated samples +void +SGSampleGroup::resume () +{ + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + + if ( sample->is_valid_source() && sample->is_playing() ) { + unsigned int source = sample->get_source(); + alSourcePlay( source ); + } + } + testForALError("resume"); + _active = true; +} + + +// tell the scheduler to play the indexed sample in a continuous loop +bool SGSampleGroup::play( const string &refname, bool looping = false ) { + SGSoundSample *sample = find( refname ); + + if ( sample == NULL ) { + return false; + } + + sample->play( looping ); + return true; +} + + +// return true of the specified sound is currently being played +bool SGSampleGroup::is_playing( const string& refname ) { + SGSoundSample *sample = find( refname ); + + if ( sample == NULL ) { + return false; + } + + return ( sample->is_playing() ) ? true : false; +} + +// immediate stop playing the sound +bool SGSampleGroup::stop( const string& refname ) { + SGSoundSample *sample = find( refname ); + + if ( sample == NULL ) { + return false; + } + + sample->stop(); + return true; +} + + +// set source position of all managed sounds +void SGSampleGroup::set_position( SGVec3d pos ) { + if ( isnan(pos.data()[0]) || isnan(pos.data()[1]) || isnan(pos.data()[2]) ) + { + SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup postion"); + return; + } + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_base_position( pos ); + } +} + +// set source velocity of all managed sounds +void SGSampleGroup::set_velocity( SGVec3f vel ) { + if ( isnan(vel.data()[0]) || isnan(vel.data()[1]) || isnan(vel.data()[2]) ) + { + SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup velocity"); + return; + } + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_velocity( vel ); + } +} + +// ste the source orientation of all managed sounds +void SGSampleGroup::set_orientation( SGVec3f ori ) { + if ( isnan(ori.data()[0]) || isnan(ori.data()[1]) || isnan(ori.data()[2]) ) + { + SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup orientation"); + return; + } + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_orientation( ori ); + } +} + +void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { + if ( sample->is_valid_source() ) { + unsigned int source = sample->get_source(); + + alSourcefv( source, AL_POSITION, sample->get_position()); + alSourcefv( source, AL_DIRECTION, sample->get_direction() ); + alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); + testForALError("position and orientation"); + + alSourcef( source, AL_PITCH, sample->get_pitch() ); + alSourcef( source, AL_GAIN, sample->get_volume() ); + testForALError("pitch and gain"); + + if ( sample->has_static_data_changed() ) { + alSourcef( source, AL_CONE_INNER_ANGLE, sample->get_innerangle() ); + alSourcef( source, AL_CONE_OUTER_ANGLE, sample->get_outerangle() ); + alSourcef( source, AL_CONE_OUTER_GAIN, sample->get_outergain() ); + testForALError("audio cone"); + + alSourcef( source, AL_ROLLOFF_FACTOR, 1.0 ); + alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() ); + alSourcef( source, AL_REFERENCE_DISTANCE, + sample->get_reference_dist() ); + testForALError("distance rolloff"); + } + } +} + +ALvoid +SGSampleGroup::load_file(SGSoundSample *sample) { + if (sample->is_file()) { + unsigned int size; + int freq, format; + void *data; + + string sample_name = sample->get_sample_name(); + _smgr->load(sample_name, &data, &format, &size, &freq); + + sample->set_data( (unsigned char *)data ); + sample->set_frequency( freq ); + sample->set_format( format ); + sample->set_size( size ); + } +} + +void SGSampleGroup::set_volume( float vol ) +{ + _volume = vol; + if (_volume < 0.0) _volume = 0.0; + if (_volume > 1.0) _volume = 1.0; + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_master_volume( _volume ); + } +} + +bool SGSampleGroup::testForError(void *p, string s) +{ + if (p == NULL) { + SG_LOG( SG_GENERAL, SG_ALERT, "Error (sample group): " << s); + return true; + } + return false; +} + +bool SGSampleGroup::testForALError(string s) +{ + ALenum error = alGetError(); + if (error != AL_NO_ERROR) { + SG_LOG( SG_GENERAL, SG_ALERT, "AL Error (sample group): " + << alGetString(error) << " at " << s); + return true; + } + return false; +} + diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx new file mode 100644 index 00000000..3e277014 --- /dev/null +++ b/simgear/sound/sample_group.hxx @@ -0,0 +1,181 @@ +// soundmgr.hxx -- Sound effect management class +// +// Sampel Group handler initially written by Erik Hofman +// +// 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 sample_group.hxx + * sample groups contain all sounds related to one specific object and + * have to be added to the sound manager, otherwise they won't get processed. + */ + +#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 +#else +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include "sample_openal.hxx" + +using std::map; +using std::string; + +typedef map < string, SGSharedPtr > sample_map; +typedef sample_map::iterator sample_map_iterator; +typedef sample_map::const_iterator const_sample_map_iterator; + +class SGSoundMgr; + +class SGSampleGroup : public SGReferenced +{ +public: + SGSampleGroup (); + SGSampleGroup ( SGSoundMgr *smgr, const string &refname ); + ~SGSampleGroup (); + + virtual void update (double dt); + + /** + * add a sound effect, return true if successful + */ + bool add( SGSoundSample *sound, const string& refname ); + + /** + * remove a sound effect, return true if successful + */ + bool remove( const string& refname ); + + /** + * return true of the specified sound exists in the sound manager system + */ + bool exists( const string& refname ); + + /** + * return a pointer to the SGSoundSample if the specified sound + * exists in the sound manager system, otherwise return NULL + */ + SGSoundSample *find( const string& refname ); + + /** + * request to stop playing all associated samples until further notice + */ + void suspend(); + + /** + * request to resume playing all associated samples + */ + void resume(); + + + /** + * request to start playing the associated samples + */ + bool play( const string& refname, bool looping ); + + /** + * tell the scheduler to play the indexed sample in a continuous + * loop + */ + inline bool play_looped( const string& refname ) { + return play( refname, true ); + } + + /** + * tell the scheduler to play the indexed sample once + */ + inline bool play_once( const string& refname ) { + return play( refname, false ); + } + + /** + * return true of the specified sound is currently being played + */ + bool is_playing( const string& refname ); + + /** + * request to stop playing the associated samples + */ + bool stop( const string& refname ); + + /** + * set overall volume for the application. + * @param must be between 0.0 and 1.0 + */ + void set_volume( float vol ); + + /** + * set the positions of all managed sound sources + */ + void set_position( SGVec3d pos ); + + /** + * set the velocities of all managed sound sources + */ + void set_velocity( SGVec3f vel ); + + /** + * set the orientation of all managed sound sources + */ + void set_orientation( SGVec3f ori ); + + /** + * load the data of the sound sample + */ + void load_file(SGSoundSample *sound); + +protected: + SGSoundMgr *_smgr; + bool _active; + +private: + bool _changed; + bool _position_changed; + + float _volume; + + SGVec3d _position; + SGVec3f _orientation; + + sample_map _samples; + + bool testForALError(string s); + bool testForError(void *p, string s); + + void update_sample_config( SGSoundSample *sound ); +}; + +#endif // _SG_SAMPLE_GROUP_OPENAL_HXX + diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 52eaea18..917f0596 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -15,8 +15,8 @@ // 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. +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -24,20 +24,12 @@ # include #endif -#if defined( __APPLE__ ) -# define AL_ILLEGAL_ENUM AL_INVALID_ENUM -# define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION -# include -# include -#else -# include -# include -#endif - #include -#include #include +#include +#include +#include "soundmgr_openal.hxx" #include "sample_openal.hxx" @@ -45,477 +37,140 @@ // SGSoundSample // - -static bool print_openal_error(const string &s = "unknown") { - ALuint error = alGetError(); - if ( error == AL_NO_ERROR ) { - return false; - } else if ( error == AL_INVALID_NAME ) { - SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_INVALID_NAME): " << s ); - } else if ( error == AL_ILLEGAL_ENUM ) { - SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_ILLEGAL_ENUM): " << s ); - } else if ( error == AL_INVALID_VALUE ) { - SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_INVALID_VALUE): " << s ); - } else if ( error == AL_ILLEGAL_COMMAND ) { - SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_ILLEGAL_COMMAND): " << s ); - } else if ( error == AL_OUT_OF_MEMORY ) { - SG_LOG( SG_GENERAL, SG_ALERT, "OpenAL error (AL_OUT_OF_MEMORY): " << s ); - } else { - SG_LOG( SG_GENERAL, SG_ALERT, "Unhandled error code = " << error ); - } - return error != 0; -} - // empty constructor SGSoundSample::SGSoundSample() : - buffer(0), - source(0), - pitch(1.0), - volume(1.0), - reference_dist(500.0), - max_dist(3000.), - loop(AL_FALSE), -#ifdef USE_SOFTWARE_DOPPLER - doppler_pitch_factor(1), - doppler_volume_factor(1), -#endif - playing(false), - no_Doppler_effect(true) + _absolute_pos(SGVec3d::zeros().data()), + _relative_pos(SGVec3f::zeros().data()), + _base_pos(SGVec3d::zeros().data()), + _direction(SGVec3f::zeros().data()), + _velocity(SGVec3f::zeros().data()), + _sample_name(""), + _data(NULL), + _format(AL_FORMAT_MONO8), + _size(0), + _freq(0), + _valid_buffer(false), + _buffer(SGSoundMgr::NO_BUFFER), + _valid_source(false), + _source(SGSoundMgr::NO_SOURCE), + _inner_angle(360.0), + _outer_angle(360.0), + _outer_gain(0.0), + _pitch(1.0), + _volume(1.0), + _master_volume(1.0), + _reference_dist(500.0), + _max_dist(3000.0), + _loop(AL_FALSE), + _playing(false), + _changed(true), + _static_changed(true), + _is_file(false) { } // constructor -SGSoundSample::SGSoundSample( const char *path, const char *file, bool _no_Doppler_effect ) : - buffer(0), - source(0), - pitch(1.0), - volume(1.0), - reference_dist(500.0), - max_dist(3000.), - loop(AL_FALSE), -#ifdef USE_SOFTWARE_DOPPLER - doppler_pitch_factor(1), - doppler_volume_factor(1), -#endif - playing(false), - no_Doppler_effect(_no_Doppler_effect) +SGSoundSample::SGSoundSample( const char *path, const char *file ) : + _absolute_pos(SGVec3d::zeros().data()), + _relative_pos(SGVec3f::zeros().data()), + _base_pos(SGVec3d::zeros().data()), + _direction(SGVec3f::zeros().data()), + _velocity(SGVec3f::zeros().data()), + _format(AL_FORMAT_MONO8), + _size(0), + _freq(0), + _valid_buffer(false), + _buffer(SGSoundMgr::NO_BUFFER), + _valid_source(false), + _source(SGSoundMgr::NO_SOURCE), + _inner_angle(360.0), + _outer_angle(360.0), + _outer_gain(0.0), + _pitch(1.0), + _volume(1.0), + _master_volume(1.0), + _reference_dist(500.0), + _max_dist(3000.0), + _loop(AL_FALSE), + _playing(false), + _changed(true), + _static_changed(true), + _is_file(true) { SGPath samplepath( path ); if ( strlen(file) ) { samplepath.append( file ); } - sample_name = samplepath.str(); + _sample_name = samplepath.str(); - SG_LOG( SG_GENERAL, SG_DEBUG, "From file sounds sample = " + SG_LOG( SG_GENERAL, SG_DEBUG, "From file sounds sample = " << samplepath.str() ); - - source_pos[0] = 0.0; source_pos[1] = 0.0; source_pos[2] = 0.0; - offset_pos[0] = 0.0; offset_pos[1] = 0.0; offset_pos[2] = 0.0; - source_vel[0] = 0.0; source_vel[1] = 0.0; source_vel[2] = 0.0; - direction[0] = 0.0; direction[1] = 0.0; direction[2] = 0.0; - inner = outer = 360.0; outergain = 0.0; - - // clear errors from elsewhere? - alGetError(); - - // create an OpenAL buffer handle - alGenBuffers(1, &buffer); - if ( print_openal_error("constructor (alGenBuffers)") ) { - throw sg_exception("Failed to gen OpenAL buffer."); - } - - // Load the sample file -#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 - - buffer = alutCreateBufferFromFile(samplepath.c_str()); - if (buffer == AL_NONE) { - ALenum error = alutGetError (); - print_openal_error("constructor (alutCreateBufferFromFile)"); - throw sg_io_exception("Failed to load wav file: ", - sg_location(string(alutGetErrorString (error)))); - } - -#else - // - // pre 1.0 alut version - // - ALvoid* data = load_file(path, file); - - // Copy data to the internal OpenAL buffer - alBufferData( buffer, format, data, size, freq ); - - if ( print_openal_error("constructor (alBufferData)") ) { - SG_LOG( SG_GENERAL, SG_ALERT, "Trying to use file " << file ); - throw sg_exception("Failed to buffer data."); - } - - alutUnloadWAV( format, data, size, freq ); -#endif - - print_openal_error("constructor return"); } // constructor -SGSoundSample::SGSoundSample( unsigned char *_data, int len, int _freq, bool _no_Doppler_effect ) : - buffer(0), - source(0), - pitch(1.0), - volume(1.0), - reference_dist(500.0), - max_dist(3000.), - loop(AL_FALSE), -#ifdef USE_SOFTWARE_DOPPLER - doppler_pitch_factor(1), - doppler_volume_factor(1), -#endif - playing(false), - no_Doppler_effect(_no_Doppler_effect) +SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format ) : + _absolute_pos(SGVec3d::zeros().data()), + _relative_pos(SGVec3f::zeros().data()), + _base_pos(SGVec3d::zeros().data()), + _direction(SGVec3f::zeros().data()), + _velocity(SGVec3f::zeros().data()), + _data(data), + _format(format), + _size(len), + _freq(freq), + _valid_buffer(false), + _buffer(SGSoundMgr::NO_BUFFER), + _valid_source(false), + _source(SGSoundMgr::NO_SOURCE), + _inner_angle(360.0), + _outer_angle(360.0), + _outer_gain(0.0), + _pitch(1.0), + _volume(1.0), + _master_volume(1.0), + _reference_dist(500.0), + _max_dist(3000.0), + _loop(AL_FALSE), + _playing(false), + _changed(true), + _static_changed(true), + _is_file(false) { + _sample_name = "unknown, data supplied by caller"; SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); - - sample_name = "unknown, generated from data"; - - source_pos[0] = 0.0; source_pos[1] = 0.0; source_pos[2] = 0.0; - offset_pos[0] = 0.0; offset_pos[1] = 0.0; offset_pos[2] = 0.0; - source_vel[0] = 0.0; source_vel[1] = 0.0; source_vel[2] = 0.0; - direction[0] = 0.0; direction[1] = 0.0; direction[2] = 0.0; - inner = outer = 360.0; outergain = 0.0; - - // clear errors from elsewhere? - alGetError(); - - // Load wav data into a buffer. - alGenBuffers(1, &buffer); - if ( print_openal_error("constructor (alGenBuffers)") ) { - throw sg_exception("Failed to gen buffer." ); - } - - format = AL_FORMAT_MONO8; - size = len; - freq = _freq; - - alBufferData( buffer, format, _data, size, freq ); - if ( print_openal_error("constructor (alBufferData)") ) { - throw sg_exception("Failed to buffer data."); - } - - print_openal_error("constructor return"); } // destructor SGSoundSample::~SGSoundSample() { - SG_LOG( SG_GENERAL, SG_INFO, "Deleting a sample" ); - if (buffer) - alDeleteBuffers(1, &buffer); -} - - -// play the sample -void SGSoundSample::play( bool _loop ) { - - if ( source ) { - alSourceStop( source ); - } - - playing = bind_source(); - if ( playing ) { - loop = _loop; - - alSourcei( source, AL_LOOPING, loop ); - alSourcePlay( source ); - - print_openal_error("play (alSourcePlay)"); - } -} - - -// stop playing the sample -void SGSoundSample::stop() { - if (playing) { - alSourceStop( source ); - alDeleteSources(1, &source); - source = 0; - print_openal_error("stop (alDeleteSources)"); - } - playing = false; -} - -// Generate sound source -bool -SGSoundSample::bind_source() { - - if ( playing ) { - return true; - } - if ( buffer == 0 ) { - return false; - } - - // Bind buffer with a source. - alGetError(); - alGenSources(1, &source); - if ( print_openal_error("bind_source (alGenSources)") ) { - // No biggy, better luck next time. - SG_LOG( SG_GENERAL, SG_ALERT, "Failed to generate audio source."); - // SG_LOG( SG_GENERAL, SG_ALERT, "Please update your sound driver and try again."); - return false; - } - - alSourcei( source, AL_BUFFER, buffer ); -#ifndef USE_SOFTWARE_DOPPLER - alSourcef( source, AL_PITCH, pitch ); - alSourcef( source, AL_GAIN, volume ); -#else - print_openal_error("bind_sources return"); - alSourcef( source, AL_PITCH, pitch * doppler_pitch_factor ); - alGetError(); // ignore if the pitch is clamped by the driver - alSourcef( source, AL_GAIN, volume * doppler_volume_factor ); -#endif - alSourcefv( source, AL_POSITION, source_pos ); - alSourcefv( source, AL_DIRECTION, direction ); - alSourcef( source, AL_CONE_INNER_ANGLE, inner ); - alSourcef( source, AL_CONE_OUTER_ANGLE, outer ); - alSourcef( source, AL_CONE_OUTER_GAIN, outergain); -#ifdef USE_OPEN_AL_DOPPLER - alSourcefv( source, AL_VELOCITY, source_vel ); -#endif - alSourcei( source, AL_LOOPING, loop ); - - alSourcei( source, AL_SOURCE_RELATIVE, AL_TRUE ); - alSourcef( source, AL_REFERENCE_DISTANCE, reference_dist ); - alSourcef( source, AL_MAX_DISTANCE, max_dist ); - - print_openal_error("bind_sources return"); - - return true; -} - -void -SGSoundSample::set_pitch( double p ) { - // clamp in the range of 0.01 to 2.0 - if ( p < 0.01 ) { p = 0.01; } - if ( p > 2.0 ) { p = 2.0; } - pitch = p; - if (playing) { -#ifndef USE_SOFTWARE_DOPPLER - alSourcef( source, AL_PITCH, pitch ); - print_openal_error("set_pitch"); -#else - alSourcef( source, AL_PITCH, pitch * doppler_pitch_factor ); - alGetError(); // ignore if the pitch is clamped by the driver -#endif - } -} - -void -SGSoundSample::set_volume( double v ) { - volume = v; - if (playing) { -#ifndef USE_SOFTWARE_DOPPLER - alSourcef( source, AL_GAIN, volume ); -#else - alSourcef( source, AL_GAIN, volume * doppler_volume_factor ); -#endif - print_openal_error("set_volume"); - } -} - - -bool -SGSoundSample::is_playing( ) { - if (playing) { - ALint result; - alGetSourcei( source, AL_SOURCE_STATE, &result ); - if ( alGetError() != AL_NO_ERROR) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Oops AL error in sample is_playing(): " << sample_name ); - } - return (result == AL_PLAYING) ; - } else - return false; -} - -void -SGSoundSample::set_source_pos( ALfloat *pos ) { - source_pos[0] = pos[0]; - source_pos[1] = pos[1]; - source_pos[2] = pos[2]; - - if (playing) { - sgVec3 final_pos; - sgAddVec3( final_pos, source_pos, offset_pos ); - - alSourcefv( source, AL_POSITION, final_pos ); - print_openal_error("set_source_pos"); - } -} - -void -SGSoundSample::set_offset_pos( ALfloat *pos ) { - offset_pos[0] = pos[0]; - offset_pos[1] = pos[1]; - offset_pos[2] = pos[2]; - - if (playing) { - sgVec3 final_pos; - sgAddVec3( final_pos, source_pos, offset_pos ); - - alSourcefv( source, AL_POSITION, final_pos ); - print_openal_error("set_offset_pos"); - } -} - -void -SGSoundSample::set_orientation( ALfloat *dir, ALfloat inner_angle, - ALfloat outer_angle, - ALfloat outer_gain) -{ - inner = inner_angle; - outer = outer_angle; - outergain = outer_gain; - direction[0] = dir[0]; - direction[1] = dir[1]; - direction[2] = dir[2]; - if (playing) { - alSourcefv( source, AL_DIRECTION, dir); - alSourcef( source, AL_CONE_INNER_ANGLE, inner ); - alSourcef( source, AL_CONE_OUTER_ANGLE, outer ); - alSourcef( source, AL_CONE_OUTER_GAIN, outergain ); - } -} - -void -SGSoundSample::set_source_vel( ALfloat *vel, ALfloat *listener_vel ) { - if (no_Doppler_effect) { - source_vel[0] = listener_vel[0]; - source_vel[1] = listener_vel[1]; - source_vel[2] = listener_vel[2]; - } else { - source_vel[0] = vel[0]; - source_vel[1] = vel[1]; - source_vel[2] = vel[2]; - } -#ifdef USE_OPEN_AL_DOPPLER - if (playing) { - alSourcefv( source, AL_VELOCITY, source_vel ); - } -#elif defined (USE_OPEN_AL_DOPPLER_WITH_FIXED_LISTENER) - if (playing) { - sgVec3 relative_vel; - sgSubVec3( relative_vel, source_vel, listener_vel ); - alSourcefv( source, AL_VELOCITY, relative_vel ); - } -#else - if (no_Doppler_effect) { - doppler_pitch_factor = 1; - doppler_volume_factor = 1; - return; - } - double doppler, mfp; - sgVec3 final_pos; - sgAddVec3( final_pos, source_pos, offset_pos ); - mfp = sgLengthVec3(final_pos); - if (mfp > 1e-6) { - double vls = -sgScalarProductVec3( listener_vel, final_pos ) / mfp; - double vss = -sgScalarProductVec3( source_vel, final_pos ) / mfp; - if (fabs(340 - vss) > 1e-6) - { - doppler = (340 - vls) / (340 - vss); - doppler = ( doppler > 0) ? ( ( doppler < 10) ? doppler : 10 ) : 0; - } - else - doppler = 0; - } - else - doppler = 1; - /* the OpenAL documentation of the Doppler calculation - SS: AL_SPEED_OF_SOUND = speed of sound (default value 343.3) - DF: AL_DOPPLER_FACTOR = Doppler factor (default 1.0) - vls: Listener velocity scalar (scalar, projected on source-to-listener vector) - vss: Source velocity scalar (scalar, projected on source-to-listener vector) - SL = source to listener vector - SV = Source Velocity vector - LV = Listener Velocity vector - vls = DotProduct(SL, LV) / Mag(SL) - vss = DotProduct(SL, SV) / Mag(SL) - Dopper Calculation: - vss = min(vss, SS/DF) - vls = min(vls, SS/DF) - f' = f * (SS - DF*vls) / (SS - DF*vss) - */ - if (doppler > 0.1) { - if (doppler < 10) { - doppler_pitch_factor = doppler; - doppler_volume_factor = 1; - } - else { - doppler_pitch_factor = (doppler < 11) ? doppler : 11; - doppler_volume_factor = (doppler < 11) ? 11-doppler : 0; - } - } - else { - doppler_pitch_factor = 0.1; - doppler_volume_factor = (doppler > 0) ? doppler * 10 : 0; - } - if (playing) { - alSourcef( source, AL_GAIN, volume * doppler_volume_factor ); - print_openal_error("set_source_vel: volume"); - alSourcef( source, AL_PITCH, pitch * doppler_pitch_factor ); - alGetError(); //ignore if the pitch is clamped +#if 0 + if (_data != NULL) { + delete[] _data; + _data = NULL; } #endif } -void -SGSoundSample::set_reference_dist( ALfloat dist ) { - reference_dist = dist; - if (playing) { - alSourcef( source, AL_REFERENCE_DISTANCE, reference_dist ); - } +void SGSoundSample::set_base_position( SGVec3d pos ) { + _base_pos = pos; + update_absolute_position(); + _changed = true; } - -void -SGSoundSample::set_max_dist( ALfloat dist ) { - max_dist = dist; - if (playing) { - alSourcef( source, AL_MAX_DISTANCE, max_dist ); - } +void SGSoundSample::set_relative_position( SGVec3f pos ) { + _relative_pos = pos; + update_absolute_position(); + _changed = true; } -ALvoid * -SGSoundSample::load_file(const char *path, const char *file) -{ - ALvoid* data = 0; - - SGPath samplepath( path ); - if ( strlen(file) ) { - samplepath.append( file ); - } - -#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 - ALfloat freqf; - data = alutLoadMemoryFromFile(samplepath.c_str(), &format, &size, &freqf ); - if (data == NULL) { - throw sg_io_exception("Failed to load wav file.", - sg_location(samplepath.str())); - } - freq = (ALsizei)freqf; -#else -# if defined (__APPLE__) - alutLoadWAVFile( (ALbyte *)samplepath.c_str(), - &format, &data, &size, &freq ); -# else - alutLoadWAVFile( (ALbyte *)samplepath.c_str(), - &format, &data, &size, &freq, &loop ); -# endif - if ( print_openal_error("constructor (alutLoadWAVFile)") ) { - throw sg_io_exception("Failed to load wav file.", - sg_location(samplepath.str())); - } -#endif - - return data; +void SGSoundSample::set_orientation( SGVec3f dir ) { + _direction = dir; + update_absolute_position(); + _changed = true; } +void SGSoundSample::update_absolute_position() { + SGQuatf orient = SGQuatf::fromAngleAxis(_direction); + SGVec3f modified_relative_pos = orient.transform(_relative_pos); + _absolute_pos = _base_pos + toVec3d(modified_relative_pos); +} diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 1131981b..5d4baf62 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -32,37 +32,16 @@ # error This library requires C++ #endif -#include - #include +#include #include #include #include +#include #include -#if defined(__APPLE__) -# define AL_ILLEGAL_ENUM AL_INVALID_ENUM -# define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION -# include -# include -#else -# include -# include -#endif - -#ifndef HAVE_WINDOWS_H - #ifdef AL_VERSION_1_2 - #define USE_OPEN_AL_DOPPLER should work - #else - #define USE_OPEN_AL_DOPPLER_WITH_FIXED_LISTENER better than nothing - #endif -#else - // the Open_AL Doppler calculation seems to be buggy on windows - #define USE_SOFTWARE_DOPPLER seem to be necessary -#endif - using std::string; /** @@ -73,45 +52,51 @@ class SGSoundSample : public SGReferenced { private: - string sample_name; - - // Buffers hold sound data. - ALuint buffer; - - // Sources are points emitting sound. - ALuint source; - // Position of the source sound. - ALfloat source_pos[3]; - - // A constant offset to be applied to the final source_pos - ALfloat offset_pos[3]; + SGVec3d _absolute_pos; // absolute position + SGVec3f _relative_pos; // position relative to the base position + SGVec3d _base_pos; // base position // The orientation of the sound (direction and cut-off angles) - ALfloat direction[3]; - ALfloat inner, outer, outergain; + SGVec3f _direction; // Velocity of the source sound. - ALfloat source_vel[3]; + SGVec3f _velocity; + + string _sample_name; + unsigned char *_data; // configuration values - ALenum format; - ALsizei size; - ALsizei freq; + int _format; + int _size; + int _freq; - double pitch; - double volume; -#ifdef USE_SOFTWARE_DOPPLER - double doppler_pitch_factor; - double doppler_volume_factor; -#endif - double reference_dist; - double max_dist; - ALboolean loop; + // Buffers hold sound data. + bool _valid_buffer; + unsigned int _buffer; - bool playing; - bool bind_source(); - bool no_Doppler_effect; + // Sources are points emitting sound. + bool _valid_source; + unsigned int _source; + + // The orientation of the sound (direction and cut-off angles) + float _inner_angle; + float _outer_angle; + float _outer_gain; + + float _pitch; + float _volume; + float _master_volume; + float _reference_dist; + float _max_dist; + bool _loop; + + bool _playing; + bool _changed; + bool _static_changed; + bool _is_file; + + void update_absolute_position(); public: @@ -128,7 +113,7 @@ public: should usually be true unless you want to manipulate the data later.) */ - SGSoundSample( const char *path, const char *file, bool no_Doppler_effect = true ); + SGSoundSample( const char *path, const char *file ); /** * Constructor. @@ -139,23 +124,50 @@ public: should usually be true unless you want to manipulate the data later.) */ - SGSoundSample( unsigned char *_data, int len, int _freq, bool no_Doppler_effect = true ); + SGSoundSample( unsigned char *data, int len, int freq, int format = AL_FORMAT_MONO8 ); + + ~SGSoundSample (); + + /** + * detect wheter the sample holds the information of a sound file + */ + inline bool is_file() const { return _is_file; } + + /** + * Test whether this sample has a changed configuration since the last + * call. (Calling this function resets the value). + */ + inline bool has_changed() { + bool b = _changed; _changed = false; return b; + } + + inline bool has_static_data_changed() { + bool b = _static_changed; _static_changed = false; return b; + } - ~SGSoundSample(); /** * Start playing this sample. * * @param _loop Define whether the sound should be played in a loop. */ - void play( bool _loop ); + inline void play( bool loop ) { + _playing = true; _loop = loop; _changed = true; + } + + /** + * Return if the sample is looping or not. + */ + inline bool get_looping() { return _loop; } /** * Stop playing this sample. * * @param sched A pointer to the appropriate scheduler. */ - void stop(); + inline void stop() { + _playing = false; _changed = true; + } /** * Play this sample once. @@ -173,77 +185,226 @@ public: * Test if a sample is currently playing. * @return true if is is playing, false otherwise. */ - bool is_playing( ); + inline bool is_playing() { return _playing; } + + /** + * set the data associated with this sample + */ + inline void set_data( unsigned char* data ) { + _data = data; + } + + /** + * @return the data associated with this sample + */ + inline void* get_data() const { return _data; } + + /** + * free the data associated with this sample + */ + inline void free_data() { + if (_data != NULL) { delete[] _data; _data = NULL; } + } + + /** + * set the source id of this source + */ + inline void set_source(unsigned int s) { + _source = s; _valid_source = true; _changed = true; + } + + /** + * get the source id of this source + */ + inline unsigned int get_source() { return _source; } + + /** + * detect wheter the source id of the sample is valid + */ + inline bool is_valid_source() const { return _valid_source; } + + /** + * set the source id of the sample to invalid. + */ + inline void no_valid_source() { + _valid_source = false; + } + + /** + * set the buffer id of this source + */ + inline void set_buffer(unsigned int b) { + _buffer = b; _valid_buffer = true; _changed = true; + } + + /** + * get the buffer id of this source + */ + inline unsigned int get_buffer() { return _buffer; } + + /** + * detect wheter the source id of the sample is valid + */ + inline bool is_valid_buffer() const { return _valid_buffer; } + + /** + * set the source id of the sample to invalid. + */ + inline void no_valid_buffer() { + _valid_buffer = false; + } /** * Get the current pitch setting of this sample. */ - inline double get_pitch() const { return pitch; } + inline float get_pitch() { return _pitch; } /** * Set the pitch of this sample. */ - void set_pitch( double p ); + inline void set_pitch( float p ) { + _pitch = p; _changed = true; + } /** * Get the current volume setting of this sample. */ - inline double get_volume() const { return volume; } + inline float get_volume() { return _volume * _master_volume; } + + /** + * Set the master (sampel group) volume of this sample. + */ + inline void set_master_volume( float v ) { + _master_volume = v; _changed = true; + } /** * Set the volume of this sample. */ - void set_volume( double v ); + inline void set_volume( float v ) { + _volume = v; _changed = true; + } + + /** + * Set the format of the sounds sample + */ + inline void set_format( int format ) { + _format = format; + } + + /** + * Returns the format of the sounds sample + */ + inline int get_format() { return _format; } + + + /** + * Set the frequency of the sounds sample + */ + inline void set_frequency( int freq ) { + _freq = freq; _changed = true; + } + + /** + * Returns the frequency of the sounds sample + */ + inline int get_frequency() { return _freq; } /** * Returns the size of the sounds sample */ - inline int get_size() { - return size; + inline void set_size( int size ) { + _size = size; } /** - * Set position of sound source (uses same coordinate system as opengl) + * Returns the size of the sounds sample */ - void set_source_pos( ALfloat *pos ); + inline int get_size() const { return _size; } /** - * Set "constant" offset position of sound source (uses same - * coordinate system as opengl) + * Set position of the sound source (uses same coordinate system as opengl) */ - void set_offset_pos( ALfloat *pos ); + void set_base_position( SGVec3d pos ); + void set_relative_position( SGVec3f pos ); + + /** + * Get position of the sound source (uses same coordinate system as opengl) + */ + inline float *get_position() const { return toVec3f(_absolute_pos).data(); } /** * Set the orientation of the sound source, both for direction * and audio cut-off angles. */ - void set_orientation( ALfloat *dir, ALfloat inner_angle=360.0, - ALfloat outer_angle=360.0, - ALfloat outer_gain=0.0); + void set_orientation( SGVec3f dir ); /** - * Set velocity of sound source (uses same coordinate system as opengl) + * Define the audio cone parameters for directional audio */ - void set_source_vel( ALfloat *vel, ALfloat *listener_vel ); + inline void set_audio_cone( float inner, float outer, float gain ) { + _inner_angle = inner; + _outer_angle = outer; + _outer_gain = gain; + _static_changed = true; + } + + /** + * Get the orientation of the sound source, the inner or outer angle + * or outer gain. + */ + inline float *get_orientation() { return _direction.data(); } + inline float *get_direction() { return _direction.data(); } + inline float get_innerangle() { return _inner_angle; } + inline float get_outerangle() { return _outer_angle; } + inline float get_outergain() { return _outer_gain; } + + /** + * Set velocity of the sound source (uses same coordinate system as opengl) + */ + inline void set_velocity( SGVec3f vel ) { + _velocity = SGVec3f(vel); _changed = true; + } + + /** + * Get velocity of the sound source (uses same coordinate system as opengl) + */ + inline float *get_velocity() { return _velocity.data(); } /** * Set reference distance of sound (the distance where the gain * will be half.) */ - void set_reference_dist( ALfloat dist ); + inline void set_reference_dist( float dist ) { + _reference_dist = dist; _static_changed = true; + } + + /** + * Get reference distance of sound (the distance where the gain + * will be half.) + */ + inline float get_reference_dist() { return _reference_dist; } /** * Set maximum distance of sound (the distance where the sound is * no longer audible. */ - void set_max_dist( ALfloat dist ); + void set_max_dist( float dist ) { + _max_dist = dist; _static_changed = true; + } /** - * Load a sound file into a memory buffer only. + * Get maximum istance of sound (the distance where the sound is + * no longer audible. */ - ALvoid* load_file(const char *path, const char *file); + inline float get_max_dist() { return _max_dist; } + + /** + * Get the name of this sample + */ + inline string get_sample_name() { return _sample_name; } }; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index fb49d247..543960e0 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -18,8 +18,8 @@ // 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. +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -27,173 +27,192 @@ # include #endif -#include - -#if defined(__APPLE__) -# include -# include +#if defined( __APPLE__ ) +# include #else -# include -# include +# include #endif -#if defined (__APPLE__) -# ifdef __GNUC__ -# if ( __GNUC__ >= 3 ) && ( __GNUC_MINOR__ >= 3 ) -// # include -inline int (isnan)(double r) { return !(r <= 0 || r >= 0); } -# else - // any C++ header file undefines isinf and isnan - // so this should be included before - // the functions are STILL in libm (libSystem on mac os x) -extern "C" int isnan (double); -extern "C" int isinf (double); -# endif -# else -// inline int (isinf)(double r) { return isinf(r); } -// inline int (isnan)(double r) { return isnan(r); } -# endif -#endif - -#if defined (__FreeBSD__) -# if __FreeBSD_version < 500000 - extern "C" { - inline int isnan(double r) { return !(r <= 0 || r >= 0); } - } -# endif -#endif - -#if defined (__CYGWIN__) -#include -#endif - - #include -#include -#include - #include "soundmgr_openal.hxx" -#if defined(__MINGW32__) -#define isnan(x) _isnan(x) -#endif +#include +#include +#include +#include + + +#define MAX_SOURCES 128 // // Sound Manager // +int SGSoundMgr::_alut_init = 0; + // constructor -SGSoundMgr::SGSoundMgr() { - - SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" ); - - // initialize OpenAL +SGSoundMgr::SGSoundMgr() : + _working(false), + _changed(true), + _volume(0.5), + _device(NULL), + _context(NULL), + _listener_pos(SGVec3d::zeros().data()), + _listener_vel(SGVec3f::zeros().data()), + _devname(NULL) +{ #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 - if (!alutInit(NULL, NULL)) - { - ALenum error = alutGetError (); - SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" ); - SG_LOG( SG_GENERAL, SG_ALERT, " "+string(alutGetErrorString(error))); - working = false; - context = 0; - return; - } - else - { - working = true; - context = alcGetCurrentContext(); - } -#else - if ( (dev = alcOpenDevice( NULL )) != NULL - && ( context = alcCreateContext( dev, NULL )) != NULL ) { - working = true; - alcMakeContextCurrent( context ); - } else { - working = false; - context = 0; - SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" ); - return; + if (_alut_init == 0) { + if ( !alutInitWithoutContext(NULL, NULL) ) { + testForALUTError("alut initialization"); + return; + } + _alut_init++; } + _alut_init++; #endif - - listener_pos[0] = 0.0; - listener_pos[1] = 0.0; - listener_pos[2] = 0.0; - - listener_vel[0] = 0.0; - listener_vel[1] = 0.0; - listener_vel[2] = 0.0; - - listener_ori[0] = 0.0; - listener_ori[1] = 0.0; - listener_ori[2] = -1.0; - listener_ori[3] = 0.0; - listener_ori[4] = 1.0; - listener_ori[5] = 0.0; - - alListenerf( AL_GAIN, 0.0f ); - alListenerfv( AL_POSITION, listener_pos ); - alListenerfv( AL_VELOCITY, listener_vel ); - alListenerfv( AL_ORIENTATION, listener_ori ); - alGetError(); - if ( alGetError() != AL_NO_ERROR) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Oops AL error after audio initialization!" ); - } - - // exaggerate the ear candy? - alDopplerFactor(1.0); - alDopplerVelocity(340.0); // speed of sound in meters per second. } // destructor SGSoundMgr::~SGSoundMgr() { - + stop(); #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 - alutExit (); -#else - if (context) - alcDestroyContext( context ); + _alut_init--; + if (_alut_init == 0) { + alutExit (); + } #endif } - // initialize the sound manager void SGSoundMgr::init() { - // - // Remove the samples from the sample manager. - // - samples.clear(); + + SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" ); + + ALCdevice *device = alcOpenDevice(_devname); + if ( testForError(device, "No default audio device available.") ) { + return; + } + + ALCcontext *context = alcCreateContext(device, NULL); + if ( testForError(context, "Unable to create a valid context.") ) { + return; + } + + if ( !alcMakeContextCurrent(context) ) { + testForALCError("context initialization"); + return; + } + + _context = context; + _working = true; + + _listener_ori[0] = 0.0; _listener_ori[1] = 0.0; _listener_ori[2] = -1.0; + _listener_ori[3] = 0.0; _listener_ori[4] = 1.0; _listener_ori[5] = 0.0; + + alListenerf( AL_GAIN, 0.2f ); + alListenerfv( AL_POSITION, toVec3f(_listener_pos).data() ); + alListenerfv( AL_ORIENTATION, _listener_ori ); + alListenerfv( AL_VELOCITY, _listener_vel.data() ); + + alDopplerFactor(1.0); + alDopplerVelocity(340.3); // speed of sound in meters per second. + + if ( alIsExtensionPresent((const ALchar*)"EXT_exponent_distance") ) { + alDistanceModel(AL_EXPONENT_DISTANCE); + } else { + alDistanceModel(AL_INVERSE_DISTANCE); + } + + testForALError("listener initialization"); + + alGetError(); // clear any undetetced error, just to be sure + + // 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->suspend(); + } + } } void SGSoundMgr::bind () { - // no properties + _free_sources.clear(); + _free_sources.reserve( MAX_SOURCES ); + _sources_in_use.clear(); + _sources_in_use.reserve( MAX_SOURCES ); } void SGSoundMgr::unbind () { - // no properties + _sample_groups.clear(); + + // delete free sources + for (unsigned int i=0; i<_free_sources.size(); i++) { + ALuint source = _free_sources.at( i ); + alDeleteSources( 1 , &source ); + } + + _free_sources.clear(); + _sources_in_use.clear(); } // run the audio scheduler void SGSoundMgr::update( double dt ) { -} + 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->update(dt); + } - -void -SGSoundMgr::pause () -{ - if (context) { - alcSuspendContext( context ); - if ( alGetError() != AL_NO_ERROR) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Oops AL error after soundmgr pause()!" ); + if (_changed) { + alListenerf( AL_GAIN, _volume ); + alListenerfv( AL_VELOCITY, _listener_vel.data() ); + alListenerfv( AL_ORIENTATION, _listener_ori ); + alListenerfv( AL_POSITION, toVec3f(_listener_pos).data() ); + // alDopplerVelocity(340.3); // TODO: altitude dependent + testForALError("update"); + _changed = false; } } } @@ -202,151 +221,241 @@ SGSoundMgr::pause () void SGSoundMgr::resume () { - if (context) { - alcProcessContext( context ); - if ( alGetError() != AL_NO_ERROR) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Oops AL error after soundmgr 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(); } } } -// add a sound effect, return true if successful -bool SGSoundMgr::add( SGSoundSample *sound, const string& refname ) { - - sample_map_iterator sample_it = samples.find( refname ); - if ( sample_it != samples.end() ) { - // sound already exists +// add a sampel 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; } - samples[refname] = sound; + _sample_groups[refname] = sgrp; return true; } // remove a sound effect, return true if successful -bool SGSoundMgr::remove( const string &refname ) { - - sample_map_iterator sample_it = samples.find( refname ); - if ( sample_it != samples.end() ) { - // first stop the sound from playing (so we don't bomb the - // audio scheduler) - samples.erase( sample_it ); - - // cout << "sndmgr: removed -> " << refname << endl; - return true; - } else { - // cout << "sndmgr: failed remove -> " << refname << endl; +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( refname ); + + return true; } // return true of the specified sound exists in the sound manager system bool SGSoundMgr::exists( const string &refname ) { - sample_map_iterator sample_it = samples.find( refname ); - if ( sample_it != samples.end() ) { - return true; - } else { + 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 SGSoundSample if the specified sound exists +// return a pointer to the SGSampleGroup if the specified sound exists // in the sound manager system, otherwise return NULL -SGSoundSample *SGSoundMgr::find( const string &refname ) { - sample_map_iterator sample_it = samples.find( refname ); - if ( sample_it != samples.end() ) { - return sample_it->second; - } else { - 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); + return sgrp; + } + else + return NULL; } + + return sample_grp_it->second; } -// tell the scheduler to play the indexed sample in a continuous -// loop -bool SGSoundMgr::play_looped( const string &refname ) { - SGSoundSample *sample; +void SGSoundMgr::set_volume( float v ) +{ + _volume = v; + if (_volume > 1.0) _volume = 1.0; + if (_volume < 0.0) _volume = 0.0; + _changed = true; +} - if ( (sample = find( refname )) == NULL ) { +// 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); + } + + return source; +} + +// Free up a source id for further use +void SGSoundMgr::release_source( unsigned int source ) +{ + for (unsigned int i = 0; i<_sources_in_use.size(); i++) { + if ( _sources_in_use[i] == source ) { + ALint result; + + alGetSourcei( source, AL_SOURCE_STATE, &result ); + if ( result == AL_PLAYING ) { + alSourceStop( source ); + } + testForALError("free_source"); + + _free_sources.push_back(source); + _sources_in_use.erase(_sources_in_use.begin()+i, + _sources_in_use.begin()+i+1); + break; + } + } +} + +bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, + unsigned int *sz, int *frq ) +{ + ALenum format = (ALenum)*fmt; + ALsizei size = (ALsizei)*sz; + ALsizei freq = (ALsizei)*frq; + ALvoid *data; + +#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 + ALfloat freqf; + data = alutLoadMemoryFromFile(samplepath.c_str(), &format, &size, &freqf ); + freq = (ALsizei)freqf; + if (data == NULL) { + int error = alutGetError(); + string msg = "Failed to load wav file: "; + msg.append(alutGetErrorString(error)); + throw sg_io_exception(msg.c_str(), sg_location(samplepath)); return false; - } else { - sample->play( true ); + } + +#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 = alutGetError(); + if ( 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; + } +#endif + + *dbuf = (void *)data; + *fmt = (int)format; + *sz = (unsigned int)size; + *frq = (int)freq; + + return true; +} + + +/** + * set the orientation of the listener (in opengl coordinates) + * + * 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. + */ +void SGSoundMgr::set_orientation( SGQuatd ori ) +{ + SGVec3d sgv_up = ori.rotate(SGVec3d::e2()); + SGVec3d sgv_at = ori.rotate(SGVec3d::e3()); + for (int i=0; i<3; i++) { + _listener_ori[i] = sgv_at[i]; + _listener_ori[i+3] = sgv_up[i]; + } + _changed = true; +} + + +bool SGSoundMgr::testForError(void *p, string s) +{ + if (p == NULL) { + SG_LOG( SG_GENERAL, SG_ALERT, "Error: " << s); + return true; + } + return false; +} + + +bool SGSoundMgr::testForALError(string s) +{ + ALenum error = alGetError(); + if (error != AL_NO_ERROR) { + SG_LOG( SG_GENERAL, SG_ALERT, "AL Error (sound manager): " + << alGetString(error) << " at " << s); + return true; + } + return false; +} + +bool SGSoundMgr::testForALCError(string s) +{ + ALCenum error; + error = alcGetError(_device); + if (error != ALC_NO_ERROR) { + SG_LOG( SG_GENERAL, SG_ALERT, "ALC Error (sound manager): " + << alcGetString(_device, error) << " at " + << s); return true; } + return false; } - -// tell the scheduler to play the indexed sample once -bool SGSoundMgr::play_once( const string& refname ) { - SGSoundSample *sample; - - if ( (sample = find( refname )) == NULL ) { - return false; - } else { - sample->play( false ); +bool SGSoundMgr::testForALUTError(string s) +{ + 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; } -} - - -// return true of the specified sound is currently being played -bool SGSoundMgr::is_playing( const string& refname ) { - SGSoundSample *sample; - - if ( (sample = find( refname )) == NULL ) { - return false; - } else { - return ( sample->is_playing() ); - } -} - - -// immediate stop playing the sound -bool SGSoundMgr::stop( const string& refname ) { - SGSoundSample *sample; - - if ( (sample = find( refname )) == NULL ) { - return false; - } else { - sample->stop(); - return true; - } -} - - -// set source position of all managed sounds -void SGSoundMgr::set_source_pos_all( ALfloat *pos ) { - if ( isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2]) ) { - // bail if a bad position is passed in - return; - } - - sample_map_iterator sample_current = samples.begin(); - sample_map_iterator sample_end = samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_source_pos( pos ); - } -} - - -// set source velocity of all managed sounds -void SGSoundMgr::set_source_vel_all( ALfloat *vel ) { - if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) { - // bail if a bad velocity is passed in - return; - } - - sample_map_iterator sample_current = samples.begin(); - sample_map_iterator sample_end = samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_source_vel( vel, listener_vel ); - } + return false; } diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 59cb24e4..96109057 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -37,113 +37,68 @@ # error This library requires C++ #endif -#include - #include +#include #include -#if defined( __APPLE__ ) +#if defined(__APPLE__) +# define AL_ILLEGAL_ENUM AL_INVALID_ENUM +# define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION # include -# include +# include #else # include -# include +# include #endif +#include +#include +#include + +#include "sample_group.hxx" #include "sample_openal.hxx" using std::map; using std::string; - -typedef map < string, SGSharedPtr > sample_map; -typedef sample_map::iterator sample_map_iterator; -typedef sample_map::const_iterator const_sample_map_iterator; +typedef map < 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 SGSoundSample instances + * Manage a collection of SGSampleGroup instances */ -class SGSoundMgr +class SGSoundMgr : public SGSubsystem { - - ALCdevice *dev; - ALCcontext *context; - - // Position of the listener. - ALfloat listener_pos[3]; - - // Velocity of the listener. - ALfloat listener_vel[3]; - - // Orientation of the listener. (first 3 elements are "at", second - // 3 are "up") - ALfloat listener_ori[6]; - - sample_map samples; - - bool working; - double safety; - public: SGSoundMgr(); ~SGSoundMgr(); - - /** - * (re) initialize the sound manager. - */ void init(); - - - /** - * Bind properties for the sound manager. - */ void bind(); - - - /** - * Unbind properties for the sound manager. - */ void unbind(); - - - /** - * Run the audio scheduler. - */ void update(double dt); - - - /** - * Pause all sounds. - */ - void pause(); - - - /** - * Resume all sounds. - */ + + void suspend(); void resume(); + void stop(); + inline void reinit() { stop(); init(); } /** * is audio working? */ - inline bool is_working() const { return working; } + inline bool is_working() const { return _working; } /** - * reinitialize the sound manager + * add a sample group, return true if successful */ - inline void reinit() { init(); } - - /** - * add a sound effect, return true if successful - */ - bool add( SGSoundSample *sound, const string& refname); + bool add( SGSampleGroup *sgrp, const string& refname ); /** - * remove a sound effect, return true if successful + * remove a sample group, return true if successful */ bool remove( const string& refname ); @@ -153,94 +108,91 @@ public: bool exists( const string& refname ); /** - * return a pointer to the SGSoundSample if the specified sound + * return a pointer to the SGSampleGroup if the specified sound * exists in the sound manager system, otherwise return NULL */ - SGSoundSample *find( const string& refname ); - - /** - * tell the scheduler to play the indexed sample in a continuous - * loop - */ - bool play_looped( const string& refname ); - - /** - * tell the scheduler to play the indexed sample once - */ - bool play_once( const string& refname ); - - /** - * return true of the specified sound is currently being played - */ - bool is_playing( const string& refname ); - - /** - * immediate stop playing the sound - */ - bool stop( const string& refname ); - - /** - * set overall volume for the application. - * @param vol 1.0 is default, must be greater than 0 - */ - inline void set_volume( const ALfloat vol ) { - if ( vol > 0.0 ) { - alListenerf( AL_GAIN, vol ); - } - } + SGSampleGroup *find( const string& refname, bool create = false ); /** * set the position of the listener (in opengl coordinates) */ - inline void set_listener_pos( ALfloat *pos ) { - listener_pos[0] = pos[0]; - listener_pos[1] = pos[1]; - listener_pos[2] = pos[2]; - alListenerfv( AL_POSITION, listener_pos ); + inline void set_position( SGVec3d pos ) { + _listener_pos = pos; + _changed = true; + } + + inline double *get_position() { + return _listener_pos.data(); } /** * set the velocity of the listener (in opengl coordinates) */ - inline void set_listener_vel( ALfloat *vel ) { - listener_vel[0] = vel[0]; - listener_vel[1] = vel[1]; - listener_vel[2] = vel[2]; -#ifdef USE_OPEN_AL_DOPPLER - alListenerfv( AL_VELOCITY, listener_vel ); -#endif + inline void set_velocity( SGVec3f vel ) { + _listener_vel = vel; + _changed = true; } /** * set the orientation of the listener (in opengl coordinates) - * - * 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. */ - inline void set_listener_orientation( ALfloat *ori ) { - listener_ori[0] = ori[0]; - listener_ori[1] = ori[1]; - listener_ori[2] = ori[2]; - listener_ori[3] = ori[3]; - listener_ori[4] = ori[4]; - listener_ori[5] = ori[5]; - alListenerfv( AL_ORIENTATION, listener_ori ); - } + void set_orientation( SGQuatd ori ); + + enum { + NO_SOURCE = (unsigned int)-1, + NO_BUFFER = (unsigned int)-1 + }; + + void set_volume( float v ); + inline float get_volume() { return _volume; } /** - * set the positions of all managed sound sources + * get a new OpenAL source id + * returns NO_SOURCE is no source is available */ - void set_source_pos_all( ALfloat *pos ); + unsigned int request_source(); /** - * set the velocities of all managed sound sources + * give back an OpenAL source id for further use. */ - void set_source_vel_all( ALfloat *pos ); + void release_source( unsigned int source ); + + bool load(string &samplepath, void **data, int *format, unsigned int*size, + int *freq ); + + +private: + static int _alut_init; + + bool _working; + bool _changed; + float _volume; + + ALCdevice *_device; + ALCcontext *_context; + + // Position of the listener. + SGVec3d _listener_pos; + + // Velocity of the listener. + SGVec3f _listener_vel; + + // Orientation of the listener. + // first 3 elements are "at" vector, second 3 are "up" vector + ALfloat _listener_ori[6]; + + sample_group_map _sample_groups; + + vector _free_sources; + vector _sources_in_use; + + char *_devname; + + bool testForALError(string s); + bool testForALCError(string s); + bool testForALUTError(string s); + bool testForError(void *p, string s); + void update_sample_config( SGSampleGroup *sound ); }; diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 8dd8df93..919f0837 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -50,14 +50,11 @@ static const struct { const char *name; double (*fn)(double); } __sound_fn[] = { -// {"lin", _snd_lin}, {"inv", _snd_inv}, {"abs", _snd_abs}, {"sqrt", _snd_sqrt}, {"log", _snd_log10}, {"ln", _snd_log}, -// {"sqr", _snd_sqr}, -// {"pow3", _snd_pow3}, {"", NULL} }; @@ -84,18 +81,14 @@ SGXmlSound::~SGXmlSound() } void -SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGSoundMgr *sndmgr, - const string &path) +SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, + SGSampleGroup *sgrp, const string &path) { // // set global sound properties // - if (sndmgr->is_working() == false) { - return; - } - _name = node->getStringValue("name", ""); SG_LOG(SG_GENERAL, SG_DEBUG, "Loading sound information for: " << _name ); @@ -236,8 +229,7 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGSoundMgr *sndmgr, // // Relative position // - sgVec3 offset_pos; - sgSetVec3( offset_pos, 0.0, 0.0, 0.0 ); + SGVec3f offset_pos = SGVec3f::zeros(); SGPropertyNode_ptr pos = node->getChild("position"); if ( pos != NULL ) { offset_pos[0] = pos->getDoubleValue("x", 0.0); @@ -248,9 +240,8 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGSoundMgr *sndmgr, // // Orientation // - sgVec3 dir; + SGVec3f dir = SGVec3f::zeros(); float inner, outer, outer_gain; - sgSetVec3( dir, 0.0, 0.0, 0.0 ); inner = outer = 360.0; outer_gain = 0.0; pos = node->getChild("orientation"); @@ -266,8 +257,8 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGSoundMgr *sndmgr, // // Initialize the sample // - _mgr = sndmgr; - if ( (_sample = _mgr->find(_name)) == NULL ) { + _sgrp = sgrp; + if ( (_sample = _sgrp->find(_name)) == NULL ) { // FIXME: Does it make sense to overwrite a previous entry's // configuration just because a new entry has the same name? // Note that we can't match on identical "path" because we the @@ -276,17 +267,16 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGSoundMgr *sndmgr, // "alSource". The semantics of what is going on here seems // confused and needs to be thought through more carefully. _sample = new SGSoundSample( path.c_str(), - node->getStringValue("path", ""), - false ); - - _mgr->add( _sample, _name ); + node->getStringValue("path", "") ); + _sgrp->add( _sample, _name ); } - _sample->set_offset_pos( offset_pos ); - _sample->set_orientation(dir, inner, outer, outer_gain); - _sample->set_volume(v); + _sample->set_relative_position( offset_pos ); + _sample->set_orientation( dir ); + _sample->set_audio_cone(inner, outer, outer_gain); _sample->set_reference_dist( reference_dist ); _sample->set_max_dist( max_dist ); + _sample->set_volume(v); _sample->set_pitch(p); } @@ -316,7 +306,8 @@ SGXmlSound::update (double dt) ) ) { - if ((_mode != SGXmlSound::IN_TRANSIT) || (_stopping > MAX_TRANSIT_TIME)) { + if ((_mode != SGXmlSound::IN_TRANSIT) || (_stopping > MAX_TRANSIT_TIME)) + { if (_sample->is_playing()) { SG_LOG(SG_GENERAL, SG_DEBUG, "Stopping audio after " << _dt_play << " sec: " << _name ); diff --git a/simgear/sound/xmlsound.hxx b/simgear/sound/xmlsound.hxx index d161bbca..b5bc1f9f 100644 --- a/simgear/sound/xmlsound.hxx +++ b/simgear/sound/xmlsound.hxx @@ -38,8 +38,8 @@ #include #include +#include "sample_group.hxx" #include "sample_openal.hxx" -#include "soundmgr_openal.hxx" static const double MAX_TRANSIT_TIME = 0.1; // 100 ms. @@ -99,10 +99,10 @@ public: * @param root The root node of the programs property tree. * @param child A pointer to the location of the current event as defined * in the configuration file. - * @param sndmgr A pointer to a pre-initialized sound manager class. + * @param sgrp A pointer to a pre-initialized sample group class. * @param path The path where the audio files remain. */ - virtual void init (SGPropertyNode *, SGPropertyNode *, SGSoundMgr *, + virtual void init (SGPropertyNode *, SGPropertyNode *, SGSampleGroup *, const string &); /** @@ -135,7 +135,7 @@ protected: private: - SGSoundMgr * _mgr; + SGSampleGroup * _sgrp; SGSharedPtr _sample; SGSharedPtr _condition; diff --git a/simgear/structure/SGAtomic.cxx b/simgear/structure/SGAtomic.cxx index ee219d84..a31478f5 100644 --- a/simgear/structure/SGAtomic.cxx +++ b/simgear/structure/SGAtomic.cxx @@ -20,7 +20,7 @@ #include "SGAtomic.hxx" -#if defined(SGATOMIC_USE_GCC4_BUILTINS) && defined(__i386__) +#if !defined(SGATOMIC_USE_GCC4_BUILTINS) && defined (__i386__) // Usually the apropriate functions are inlined by gcc. // But if gcc is called with something aequivalent to -march=i386, From 579d384c04d441b9b49a7e55fbb0591e0a590ac6 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 5 Oct 2009 08:56:40 +0000 Subject: [PATCH 02/85] Rename update() to update_late() for the sound manager to be able to initialize it before any other class that uses it. This will allow the SoundManager to be safely accessed in the constructor of those classes. --- simgear/sound/sample_group.cxx | 3 ++- simgear/sound/sample_group.hxx | 2 ++ simgear/sound/soundmgr_openal.cxx | 10 ++++++++-- simgear/sound/soundmgr_openal.hxx | 5 +++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index ffa23e68..c01b0cbb 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -62,6 +62,7 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : { _smgr->add(this, refname); _active = _smgr->is_working(); + _refname = refname; _samples.clear(); } @@ -434,7 +435,7 @@ bool SGSampleGroup::testForALError(string s) { ALenum error = alGetError(); if (error != AL_NO_ERROR) { - SG_LOG( SG_GENERAL, SG_ALERT, "AL Error (sample group): " + SG_LOG( SG_GENERAL, SG_ALERT, "AL Error (" << _refname << "): " << alGetString(error) << " at " << s); return true; } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 3e277014..d9c27922 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -174,6 +174,8 @@ private: bool testForALError(string s); bool testForError(void *p, string s); + string _refname; + void update_sample_config( SGSoundSample *sound ); }; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 543960e0..ac2d8352 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -194,9 +194,15 @@ void SGSoundMgr::unbind () _sources_in_use.clear(); } +void SGSoundMgr::update( double dt ) +{ + // nothing to do in the regular update,e verything is done on the following + // function +} + // run the audio scheduler -void SGSoundMgr::update( double dt ) { +void SGSoundMgr::update_late( double dt ) { if (_working) { sample_group_map_iterator sample_grp_current = _sample_groups.begin(); sample_group_map_iterator sample_grp_end = _sample_groups.end(); @@ -334,7 +340,7 @@ void SGSoundMgr::release_source( unsigned int source ) if ( result == AL_PLAYING ) { alSourceStop( source ); } - testForALError("free_source"); + testForALError("release source"); _free_sources.push_back(source); _sources_in_use.erase(_sources_in_use.begin()+i, diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 96109057..2c40eeca 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -80,6 +80,7 @@ public: void bind(); void unbind(); void update(double dt); + void update_late(double dt); void suspend(); void resume(); @@ -157,8 +158,8 @@ public: */ void release_source( unsigned int source ); - bool load(string &samplepath, void **data, int *format, unsigned int*size, - int *freq ); + static bool load(string &samplepath, void **data, int *format, + unsigned int*size, int *freq ); private: From 023002ae7395d5244c25af2db98007785b61739f Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 5 Oct 2009 11:10:40 +0000 Subject: [PATCH 03/85] add the alc.h header file vor OpenAL context related code --- simgear/sound/soundmgr_openal.hxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 2c40eeca..84c33502 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -45,9 +45,11 @@ # define AL_ILLEGAL_ENUM AL_INVALID_ENUM # define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION # include +# include # include #else # include +# include # include #endif From 6b0ab9a49a5d900b92a6ca052a24232fd547511b Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 5 Oct 2009 13:42:12 +0000 Subject: [PATCH 04/85] default listener (master volume) default to 0.0 to save some ugly code in FlightGear --- simgear/sound/soundmgr_openal.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index ac2d8352..b204aa13 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -55,7 +55,7 @@ int SGSoundMgr::_alut_init = 0; SGSoundMgr::SGSoundMgr() : _working(false), _changed(true), - _volume(0.5), + _volume(0.0), _device(NULL), _context(NULL), _listener_pos(SGVec3d::zeros().data()), @@ -204,6 +204,8 @@ void SGSoundMgr::update( double dt ) // run the audio scheduler void SGSoundMgr::update_late( double dt ) { if (_working) { + // alcSuspendContext(_context); + 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 ) { @@ -220,6 +222,7 @@ void SGSoundMgr::update_late( double dt ) { testForALError("update"); _changed = false; } + // alcProcessContext(_context); } } From bcccd06cee0d2372df5b2d40cb4473d3156f3668 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 6 Oct 2009 12:09:28 +0000 Subject: [PATCH 05/85] (try to) properly align model and viewer --- simgear/sound/README | 40 +++++++++++++++++++++++++++++++ simgear/sound/sample_group.cxx | 2 +- simgear/sound/sample_openal.cxx | 6 ----- simgear/sound/soundmgr_openal.cxx | 4 ++-- 4 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 simgear/sound/README diff --git a/simgear/sound/README b/simgear/sound/README new file mode 100644 index 00000000..8f9546b5 --- /dev/null +++ b/simgear/sound/README @@ -0,0 +1,40 @@ + +All code in this directory uses the OpenAL coordinate system for maximum +useablity. The OpenAL coordinate system is equal to that of OpenGL with the +main difference that objects behind the viewer can still be heard: + - positive x is to the right + - positive y is upwards + - positive z is towards the back of the viewer/listener + +see: http://www.falloutsoftware.com/tutorials/gl/cartesian.gif + +All positions are in cartesian space with a unit length of one meter. + +Velocities are three tuples indicating speed and direction in the same space +as positions do (so they are not in the models local space). + + +There is one SoundMgr that handles multiple SoundGroup classes. +Each SoundGroup class handles multiple SoundSample classes. + +A SoundSample class defines the properties of each individual sound like +pitch, volume, position, orientation, sound cone paramters, etc. This +class can be created all over the code but *has* to be assigned to a +SampelGroup before you can hear it. Current sample groups are "atc", +"avionics" and "fx" for the master airplane effects. The position of a +SoundSample is relative to (0,0,0) of the model and hence relative to +the base position of the SampleGroup. + +A SampleGroup class has to be assigned to the SoundManager to be heard +and holds data of a group of samples (maybe 'sample cloud' might be a +good description). This class has to be created for each individual +model that can produce one or more sounds. The SampleGroup class can be +altered by modifying it's volume, position and orientation. +Repositioning this class also means repositioning all it's associated +samples. Altering it's orientation also means repositioning the absolute +(real world) position (and orientation) of the associated sound samples. + +The SoundMaganer can be repositioned which basically means moving the +listener around. It's also possible to alter the listener orientation en +velocity with this class, together with the master volume. + diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index c01b0cbb..54f6c000 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -149,6 +149,7 @@ void SGSampleGroup::update( double dt ) { alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE ); alSourcei( source, AL_LOOPING, looping ); + alSourcef( source, AL_ROLLOFF_FACTOR, 1.2 ) alSourcePlay( source ); testForALError("sample play"); } else { @@ -382,7 +383,6 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { alSourcef( source, AL_CONE_OUTER_GAIN, sample->get_outergain() ); testForALError("audio cone"); - alSourcef( source, AL_ROLLOFF_FACTOR, 1.0 ); alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() ); alSourcef( source, AL_REFERENCE_DISTANCE, sample->get_reference_dist() ); diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 917f0596..011e0fd3 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -143,12 +143,6 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format // destructor SGSoundSample::~SGSoundSample() { -#if 0 - if (_data != NULL) { - delete[] _data; - _data = NULL; - } -#endif } void SGSoundSample::set_base_position( SGVec3d pos ) { diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index b204aa13..9bc3e2a0 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -412,8 +412,8 @@ bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, */ void SGSoundMgr::set_orientation( SGQuatd ori ) { - SGVec3d sgv_up = ori.rotate(SGVec3d::e2()); - SGVec3d sgv_at = ori.rotate(SGVec3d::e3()); + SGVec3d sgv_up = ori.rotate(SGVec3d::e3()); + SGVec3d sgv_at = ori.rotate(SGVec3d::e2()); for (int i=0; i<3; i++) { _listener_ori[i] = sgv_at[i]; _listener_ori[i+3] = sgv_up[i]; From 5d14b849695653a5a0ff6684ce613286dbad6801 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 6 Oct 2009 12:11:33 +0000 Subject: [PATCH 06/85] fix a typo --- simgear/sound/sample_group.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 54f6c000..b9037811 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -149,7 +149,7 @@ void SGSampleGroup::update( double dt ) { alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE ); alSourcei( source, AL_LOOPING, looping ); - alSourcef( source, AL_ROLLOFF_FACTOR, 1.2 ) + alSourcef( source, AL_ROLLOFF_FACTOR, 1.2 ); alSourcePlay( source ); testForALError("sample play"); } else { From 199437e8591a6cf55cd30388405999540d227129 Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 7 Oct 2009 07:31:14 +0000 Subject: [PATCH 07/85] alut pre-1.0 doesn't support aletGetError but then again, this function doesn't get called in that case either so just comment it out at build time --- simgear/sound/soundmgr_openal.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 9bc3e2a0..b156b8c5 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -458,6 +458,7 @@ bool SGSoundMgr::testForALCError(string s) bool SGSoundMgr::testForALUTError(string s) { +#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 ALenum error; error = alutGetError (); if (error != ALUT_ERROR_NO_ERROR) { @@ -466,5 +467,6 @@ bool SGSoundMgr::testForALUTError(string s) << s); return true; } +#endif return false; } From 4cc6bd69ae1385d830822d7621d8f9a1b5623319 Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 7 Oct 2009 12:54:47 +0000 Subject: [PATCH 08/85] add the option to tie a SampleGroup to the listener position and orientation --- simgear/sound/sample_group.cxx | 28 +++++++++++++++++----------- simgear/sound/sample_group.hxx | 8 ++++---- simgear/sound/soundmgr_openal.cxx | 4 ++-- simgear/sound/soundmgr_openal.hxx | 22 +++++++++++++++++----- 4 files changed, 40 insertions(+), 22 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index b9037811..183a4894 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -44,10 +44,9 @@ extern "C" int isinf (double); SGSampleGroup::SGSampleGroup () : _smgr(NULL), _active(false), - _changed(true), - _position_changed(true), _position(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()) + _orientation(SGVec3f::zeros().data()), + _tied_to_listener(false) { _samples.clear(); } @@ -55,10 +54,9 @@ SGSampleGroup::SGSampleGroup () : SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _smgr(smgr), _active(false), - _changed(true), - _position_changed(true), _position(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()) + _orientation(SGVec3f::zeros().data()), + _tied_to_listener(false) { _smgr->add(this, refname); _active = _smgr->is_working(); @@ -134,6 +132,12 @@ void SGSampleGroup::update( double dt ) { sample->set_buffer(buffer); } + if ( _tied_to_listener && _smgr->has_changed() ) { + sample->set_base_position( _smgr->get_position_vec() ); + sample->set_orientation( _smgr->get_direction() ); + sample->set_velocity( _smgr->get_velocity() ); + } + // start playing the sample ALuint buffer = sample->get_buffer(); ALuint source = _smgr->request_source(); @@ -324,11 +328,13 @@ void SGSampleGroup::set_position( SGVec3d pos ) { return; } - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_base_position( pos ); + if ( !_tied_to_listener ) { + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_base_position( pos ); + } } } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index d9c27922..e1ca92d1 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -156,18 +156,18 @@ public: */ void load_file(SGSoundSample *sound); + inline void tie_to_listener() { _tied_to_listener = true; } + + protected: SGSoundMgr *_smgr; bool _active; private: - bool _changed; - bool _position_changed; - float _volume; - SGVec3d _position; SGVec3f _orientation; + bool _tied_to_listener; sample_map _samples; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index b156b8c5..98d7354b 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -204,7 +204,7 @@ void SGSoundMgr::update( double dt ) // run the audio scheduler void SGSoundMgr::update_late( double dt ) { if (_working) { - // alcSuspendContext(_context); + alcSuspendContext(_context); sample_group_map_iterator sample_grp_current = _sample_groups.begin(); sample_group_map_iterator sample_grp_end = _sample_groups.end(); @@ -222,7 +222,7 @@ void SGSoundMgr::update_late( double dt ) { testForALError("update"); _changed = false; } - // alcProcessContext(_context); + alcProcessContext(_context); } } diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 84c33502..24e8f159 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -18,8 +18,8 @@ // 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. +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -124,9 +124,8 @@ public: _changed = true; } - inline double *get_position() { - return _listener_pos.data(); - } + inline double *get_position() { return _listener_pos.data(); } + inline SGVec3d get_position_vec() { return _listener_pos; }; /** * set the velocity of the listener (in opengl coordinates) @@ -136,11 +135,17 @@ public: _changed = true; } + inline SGVec3f get_velocity() { return _listener_vel; } + /** * set the orientation of the listener (in opengl coordinates) */ void set_orientation( SGQuatd ori ); + inline SGVec3f get_direction() { + return SGVec3f(_listener_ori[0], _listener_ori[1], _listener_ori[2]); + } + enum { NO_SOURCE = (unsigned int)-1, NO_BUFFER = (unsigned int)-1 @@ -160,10 +165,17 @@ public: */ void release_source( unsigned int source ); + + /** + * returns true if the position has changed + */ + inline bool has_changed() { return _changed; } + static bool load(string &samplepath, void **data, int *format, unsigned int*size, int *freq ); + private: static int _alut_init; From 968f5d7693805d5df8c5e1a0a878ae0e57e1cb5a Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 9 Oct 2009 09:00:53 +0000 Subject: [PATCH 09/85] OpenAL buffer management; add a buffer cache to prevent loading the same sample in memory twice. Especially useful to save memory for multi-aircraft configurations and (later) for AI models. --- simgear/sound/sample_group.cxx | 61 +++------------- simgear/sound/sample_group.hxx | 5 -- simgear/sound/soundmgr_openal.cxx | 111 ++++++++++++++++++++++++++---- simgear/sound/soundmgr_openal.hxx | 32 +++++++-- 4 files changed, 133 insertions(+), 76 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 183a4894..dabf79bf 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -76,6 +76,7 @@ SGSampleGroup::~SGSampleGroup () if ( sample->is_valid_source() && sample->is_playing() ) { sample->no_valid_source(); _smgr->release_source( sample->get_source() ); + _smgr->release_buffer( sample ); } } @@ -97,40 +98,8 @@ void SGSampleGroup::update( double dt ) { // // a request to start playing a sound has been filed. // - ALboolean looping = sample->get_looping() ? AL_TRUE : AL_FALSE; - - if ( !sample->is_valid_buffer() ) { - // sample was not yet loaded or removed again - -// TODO: Create a buffer cache that checks whether a file is already present -// as an OpenAL buffer since buffers can be shared among sources. - load_file(sample); - if ( testForALError("load sample") ) { - throw sg_exception("Failed to load sound sample."); - continue; - } - - // create an OpenAL buffer handle - ALuint buffer; - alGenBuffers(1, &buffer); - if ( testForALError("generate buffer") ) { - throw sg_exception("Failed to generate OpenAL buffer."); - continue; - } - - // Copy data to the internal OpenAL buffer - const ALvoid *data = sample->get_data(); - ALenum format = sample->get_format(); - ALsizei size = sample->get_size(); - ALsizei freq = sample->get_frequency(); - alBufferData( buffer, format, data, size, freq ); - sample->free_data(); - if ( testForALError("buffer add data") ) { - continue; - } - - sample->set_buffer(buffer); - } + if ( _smgr->request_buffer(sample) == SGSoundMgr::NO_BUFFER ) + continue; if ( _tied_to_listener && _smgr->has_changed() ) { sample->set_base_position( _smgr->get_position_vec() ); @@ -139,6 +108,7 @@ void SGSampleGroup::update( double dt ) { } // start playing the sample + ALboolean looping = sample->get_looping() ? AL_TRUE : AL_FALSE; ALuint buffer = sample->get_buffer(); ALuint source = _smgr->request_source(); if (alIsSource(source) == AL_TRUE && alIsBuffer(buffer) == AL_TRUE) @@ -186,7 +156,6 @@ void SGSampleGroup::update( double dt ) { sample->no_valid_source(); sample->stop(); _smgr->release_source( source ); - } } testForALError("update"); @@ -216,7 +185,10 @@ bool SGSampleGroup::remove( const string &refname ) { return false; } - _samples.erase( sample_it ); + // remove the sources buffer + _smgr->release_buffer( sample_it->second ); + _samples.erase( refname ); + return true; } @@ -397,23 +369,6 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { } } -ALvoid -SGSampleGroup::load_file(SGSoundSample *sample) { - if (sample->is_file()) { - unsigned int size; - int freq, format; - void *data; - - string sample_name = sample->get_sample_name(); - _smgr->load(sample_name, &data, &format, &size, &freq); - - sample->set_data( (unsigned char *)data ); - sample->set_frequency( freq ); - sample->set_format( format ); - sample->set_size( size ); - } -} - void SGSampleGroup::set_volume( float vol ) { _volume = vol; diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index e1ca92d1..b3170696 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -151,11 +151,6 @@ public: */ void set_orientation( SGVec3f ori ); - /** - * load the data of the sound sample - */ - void load_file(SGSoundSample *sound); - inline void tie_to_listener() { _tied_to_listener = true; } diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 98d7354b..4f49416a 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -34,6 +34,7 @@ #endif #include +#include #include "soundmgr_openal.hxx" @@ -77,6 +78,7 @@ SGSoundMgr::SGSoundMgr() : // destructor SGSoundMgr::~SGSoundMgr() { + stop(); #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 _alut_init--; @@ -151,6 +153,16 @@ void SGSoundMgr::stop() { if (_working) { _working = false; + // 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; + ALuint buffer = ref.id; + alDeleteBuffers(1, &buffer); + _buffers.erase( buffers_current ); + } + _context = alcGetCurrentContext(); _device = alcGetContextsDevice(_context); alcMakeContextCurrent(NULL); @@ -196,7 +208,7 @@ void SGSoundMgr::unbind () void SGSoundMgr::update( double dt ) { - // nothing to do in the regular update,e verything is done on the following + // nothing to do in the regular update, everything is done on the following // function } @@ -325,7 +337,6 @@ unsigned int SGSoundMgr::request_source() if (_free_sources.size() > 0) { source = _free_sources.back(); _free_sources.pop_back(); - _sources_in_use.push_back(source); } @@ -335,21 +346,93 @@ unsigned int SGSoundMgr::request_source() // Free up a source id for further use void SGSoundMgr::release_source( unsigned int source ) { - for (unsigned int i = 0; i<_sources_in_use.size(); i++) { - if ( _sources_in_use[i] == source ) { - ALint result; + vector::iterator it; - alGetSourcei( source, AL_SOURCE_STATE, &result ); - if ( result == AL_PLAYING ) { - alSourceStop( source ); - } - testForALError("release source"); + it = std::find(_sources_in_use.begin(), _sources_in_use.end(), source); + if ( it != _sources_in_use.end() ) { + ALint result; - _free_sources.push_back(source); - _sources_in_use.erase(_sources_in_use.begin()+i, - _sources_in_use.begin()+i+1); - break; + alGetSourcei( source, AL_SOURCE_STATE, &result ); + if ( result == AL_PLAYING ) + alSourceStop( source ); + testForALError("release source"); + + _free_sources.push_back(source); + _sources_in_use.erase(it, it+1); + } +} + +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(); + + // 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() ) { + unsigned int size; + int freq, format; + void *data; + + load(sample_name, &data, &format, &size, &freq); + sample->set_data( (unsigned char *)data ); + sample->set_frequency( freq ); + sample->set_format( format ); + sample->set_size( size ); + } + + // create an OpenAL buffer handle + alGenBuffers(1, &buffer); + if ( !testForALError("generate buffer") ) { + // Copy data to the internal OpenAL buffer + + const ALvoid *data = sample->get_data(); + ALenum format = sample->get_format(); + ALsizei size = sample->get_size(); + ALsizei freq = sample->get_frequency(); + alBufferData( buffer, format, data, size, freq ); + sample->free_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) { + ALuint buffer = buffer_it->second.id; + _buffers.erase( buffer_it ); + alDeleteBuffers(1, &buffer); + testForALError("release buffer"); } } diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 24e8f159..ef46df8f 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -60,14 +60,25 @@ #include "sample_group.hxx" #include "sample_openal.hxx" -using std::map; using std::string; -typedef map < string, SGSharedPtr > sample_group_map; +struct refUint { + unsigned int refctr; + ALuint id; + + refUint() { refctr = 0; id = (ALuint)-1; }; + refUint(ALuint i) { refctr = 1; id = i; }; + ~refUint() {}; +}; + +typedef std::map < string, refUint > buffer_map; +typedef buffer_map::iterator buffer_map_iterator; +typedef buffer_map::const_iterator const_buffer_map_iterator; + +typedef std::map < 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 */ @@ -156,7 +167,7 @@ public: /** * get a new OpenAL source id - * returns NO_SOURCE is no source is available + * returns NO_SOURCE if no source is available */ unsigned int request_source(); @@ -165,6 +176,18 @@ public: */ void release_source( unsigned int source ); + /** + * get a new OpenAL buffer id + * returns NO_BUFFER if loading of the buffer failed. + */ + unsigned int request_buffer(SGSoundSample *sample); + + /** + * give back an OpenAL source id for further use. + */ + void release_buffer( SGSoundSample *sample ); + + /** * returns true if the position has changed @@ -197,6 +220,7 @@ private: ALfloat _listener_ori[6]; sample_group_map _sample_groups; + buffer_map _buffers; vector _free_sources; vector _sources_in_use; From babf58f8d2700b3ba84089e7b59f8838c685d6ca Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 11 Oct 2009 13:38:27 +0000 Subject: [PATCH 10/85] Correct (and verrified) position, orientation and velocity vector. Todo: proper sound orientation (the all face forward using the airplane orientation now) and disabling doppler effect when tied to the listener --- simgear/sound/sample_group.cxx | 46 ++++++++++++--------- simgear/sound/sample_group.hxx | 11 +++-- simgear/sound/sample_openal.cxx | 27 +++++++++++- simgear/sound/sample_openal.hxx | 15 +++++-- simgear/sound/soundmgr_openal.cxx | 69 ++++++++++++++++--------------- simgear/sound/soundmgr_openal.hxx | 34 +++++++++------ simgear/sound/xmlsound.cxx | 43 +++++++------------ 7 files changed, 142 insertions(+), 103 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index dabf79bf..22f9f9bf 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -43,24 +43,27 @@ extern "C" int isinf (double); SGSampleGroup::SGSampleGroup () : _smgr(NULL), + _refname(""), _active(false), - _position(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()), - _tied_to_listener(false) + _tied_to_listener(false), + _position(SGVec3d::zeros()), + _velocity(SGVec3f::zeros()), + _orientation(SGVec3f::zeros()) { _samples.clear(); } SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _smgr(smgr), + _refname(refname), _active(false), - _position(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()), - _tied_to_listener(false) + _tied_to_listener(false), + _position(SGVec3d::zeros()), + _velocity(SGVec3f::zeros()), + _orientation(SGVec3f::zeros()) { _smgr->add(this, refname); _active = _smgr->is_working(); - _refname = refname; _samples.clear(); } @@ -300,13 +303,14 @@ void SGSampleGroup::set_position( SGVec3d pos ) { return; } - if ( !_tied_to_listener ) { + if ( !_tied_to_listener && _position != pos ) { sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { SGSoundSample *sample = sample_current->second; sample->set_base_position( pos ); } + _position = pos; } } @@ -318,11 +322,13 @@ void SGSampleGroup::set_velocity( SGVec3f vel ) { return; } - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_velocity( vel ); + if (_velocity != vel) { + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_velocity( vel ); + } } } @@ -334,11 +340,13 @@ void SGSampleGroup::set_orientation( SGVec3f ori ) { return; } - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_orientation( ori ); + if (_orientation != ori) { + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_orientation( ori ); + } } } @@ -347,7 +355,7 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { unsigned int source = sample->get_source(); alSourcefv( source, AL_POSITION, sample->get_position()); - alSourcefv( source, AL_DIRECTION, sample->get_direction() ); + alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); testForALError("position and orientation"); diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index b3170696..1344df44 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -35,6 +35,8 @@ #if defined(__APPLE__) # include +#elif defined(_WIN32) +# include #else # include #endif @@ -156,21 +158,22 @@ public: protected: SGSoundMgr *_smgr; + string _refname; bool _active; private: float _volume; - SGVec3d _position; - SGVec3f _orientation; bool _tied_to_listener; + SGVec3d _position; + SGVec3f _velocity; + SGVec3f _orientation; + sample_map _samples; bool testForALError(string s); bool testForError(void *p, string s); - string _refname; - void update_sample_config( SGSoundSample *sound ); }; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 011e0fd3..8eb83a68 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -42,6 +42,7 @@ SGSoundSample::SGSoundSample() : _absolute_pos(SGVec3d::zeros().data()), _relative_pos(SGVec3f::zeros().data()), _base_pos(SGVec3d::zeros().data()), + _orientation(SGVec3f::zeros().data()), _direction(SGVec3f::zeros().data()), _velocity(SGVec3f::zeros().data()), _sample_name(""), @@ -74,6 +75,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _absolute_pos(SGVec3d::zeros().data()), _relative_pos(SGVec3f::zeros().data()), _base_pos(SGVec3d::zeros().data()), + _orientation(SGVec3f::zeros().data()), _direction(SGVec3f::zeros().data()), _velocity(SGVec3f::zeros().data()), _format(AL_FORMAT_MONO8), @@ -112,6 +114,7 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format _absolute_pos(SGVec3d::zeros().data()), _relative_pos(SGVec3f::zeros().data()), _base_pos(SGVec3d::zeros().data()), + _orientation(SGVec3f::zeros().data()), _direction(SGVec3f::zeros().data()), _velocity(SGVec3f::zeros().data()), _data(data), @@ -145,6 +148,16 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format SGSoundSample::~SGSoundSample() { } +float *SGSoundSample::get_orientation() { +#if 0 + SGQuatf quat = SGQuatf::fromAngleAxis(_orientation); + SGVec3f orient = quat.transform(_direction); + return orient.data(); +#else + return _orientation.data(); +#endif +} + void SGSoundSample::set_base_position( SGVec3d pos ) { _base_pos = pos; update_absolute_position(); @@ -157,14 +170,24 @@ void SGSoundSample::set_relative_position( SGVec3f pos ) { _changed = true; } -void SGSoundSample::set_orientation( SGVec3f dir ) { +void SGSoundSample::set_orientation( SGVec3f ori ) { + _orientation = ori; + update_absolute_position(); + _changed = true; +} + +void SGSoundSample::set_direction( SGVec3f dir ) { _direction = dir; update_absolute_position(); _changed = true; } void SGSoundSample::update_absolute_position() { - SGQuatf orient = SGQuatf::fromAngleAxis(_direction); +#if 0 + SGQuatf orient = SGQuatf::fromAngleAxis(_orientation); SGVec3f modified_relative_pos = orient.transform(_relative_pos); _absolute_pos = _base_pos + toVec3d(modified_relative_pos); +#else + _absolute_pos = _base_pos; +#endif } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 5d4baf62..f44596a8 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -58,7 +58,8 @@ private: SGVec3d _base_pos; // base position // The orientation of the sound (direction and cut-off angles) - SGVec3f _direction; + SGVec3f _orientation; // base orientation + SGVec3f _direction; // orientation offset // Velocity of the source sound. SGVec3f _velocity; @@ -337,7 +338,13 @@ public: * Set the orientation of the sound source, both for direction * and audio cut-off angles. */ - void set_orientation( SGVec3f dir ); + void set_orientation( SGVec3f ori ); + + /** + * Set the relative direction of the sound source, both for direction + * and audio cut-off angles. + */ + void set_direction( SGVec3f dir ); /** * Define the audio cone parameters for directional audio @@ -353,8 +360,8 @@ public: * Get the orientation of the sound source, the inner or outer angle * or outer gain. */ - inline float *get_orientation() { return _direction.data(); } - inline float *get_direction() { return _direction.data(); } + float *get_orientation(); + inline float get_innerangle() { return _inner_angle; } inline float get_outerangle() { return _outer_angle; } inline float get_outergain() { return _outer_gain; } diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 4f49416a..d082d6c3 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -59,8 +59,8 @@ SGSoundMgr::SGSoundMgr() : _volume(0.0), _device(NULL), _context(NULL), - _listener_pos(SGVec3d::zeros().data()), - _listener_vel(SGVec3f::zeros().data()), + _position(SGVec3d::zeros().data()), + _velocity(SGVec3f::zeros().data()), _devname(NULL) { #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 @@ -111,15 +111,15 @@ void SGSoundMgr::init() { _context = context; _working = true; - _listener_ori[0] = 0.0; _listener_ori[1] = 0.0; _listener_ori[2] = -1.0; - _listener_ori[3] = 0.0; _listener_ori[4] = 1.0; _listener_ori[5] = 0.0; + _orientation[0] = 0.0; _orientation[1] = 0.0; _orientation[2] = -1.0; + _orientation[3] = 0.0; _orientation[4] = 1.0; _orientation[5] = 0.0; alListenerf( AL_GAIN, 0.2f ); - alListenerfv( AL_POSITION, toVec3f(_listener_pos).data() ); - alListenerfv( AL_ORIENTATION, _listener_ori ); - alListenerfv( AL_VELOCITY, _listener_vel.data() ); + alListenerfv( AL_POSITION, toVec3f(_position).data() ); + alListenerfv( AL_ORIENTATION, _orientation ); + alListenerfv( AL_VELOCITY, _velocity.data() ); - alDopplerFactor(1.0); + alDopplerFactor(0.5); alDopplerVelocity(340.3); // speed of sound in meters per second. if ( alIsExtensionPresent((const ALchar*)"EXT_exponent_distance") ) { @@ -227,9 +227,9 @@ void SGSoundMgr::update_late( double dt ) { if (_changed) { alListenerf( AL_GAIN, _volume ); - alListenerfv( AL_VELOCITY, _listener_vel.data() ); - alListenerfv( AL_ORIENTATION, _listener_ori ); - alListenerfv( AL_POSITION, toVec3f(_listener_pos).data() ); + alListenerfv( AL_VELOCITY, _velocity.data() ); + alListenerfv( AL_ORIENTATION, _orientation ); + alListenerfv( AL_POSITION, toVec3f(_position).data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); _changed = false; @@ -321,6 +321,30 @@ void SGSoundMgr::set_volume( float v ) _changed = true; } +/** + * set the orientation of the listener (in opengl coordinates) + * + * 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. + */ +void SGSoundMgr::set_orientation( SGQuatd ori ) +{ + SGVec3d sgv_up = ori.rotate(SGVec3d::e2()); + SGVec3d sgv_at = ori.rotate(SGVec3d::e3()); + _orientation[0] = sgv_at[0]; + _orientation[1] = sgv_at[1]; + _orientation[2] = sgv_at[2]; + _orientation[3] = sgv_up[0]; + _orientation[4] = sgv_up[1]; + _orientation[5] = sgv_up[2]; + _changed = true; +} + // Get an unused source id // // The Sound Manager should keep track of the sources in use, the distance @@ -482,29 +506,6 @@ bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, } -/** - * set the orientation of the listener (in opengl coordinates) - * - * 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. - */ -void SGSoundMgr::set_orientation( SGQuatd ori ) -{ - SGVec3d sgv_up = ori.rotate(SGVec3d::e3()); - SGVec3d sgv_at = ori.rotate(SGVec3d::e2()); - for (int i=0; i<3; i++) { - _listener_ori[i] = sgv_at[i]; - _listener_ori[i+3] = sgv_up[i]; - } - _changed = true; -} - - bool SGSoundMgr::testForError(void *p, string s) { if (p == NULL) { diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index ef46df8f..ba1e5522 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -47,6 +47,10 @@ # include # include # include +#elif defined(_WIN32) +# include +# include +# include #else # include # include @@ -130,23 +134,27 @@ public: /** * set the position of the listener (in opengl coordinates) */ - inline void set_position( SGVec3d pos ) { - _listener_pos = pos; - _changed = true; + void set_position( SGVec3d pos ) { + if (_position != pos) { + _position = pos; + _changed = true; + } } - inline double *get_position() { return _listener_pos.data(); } - inline SGVec3d get_position_vec() { return _listener_pos; }; + inline double *get_position() { return _position.data(); } + inline SGVec3d get_position_vec() { return _position; }; /** * set the velocity of the listener (in opengl coordinates) */ - inline void set_velocity( SGVec3f vel ) { - _listener_vel = vel; - _changed = true; + void set_velocity( SGVec3f vel ) { + if (_velocity != vel) { + _velocity = vel; + _changed = true; + } } - inline SGVec3f get_velocity() { return _listener_vel; } + inline SGVec3f get_velocity() { return _velocity; } /** * set the orientation of the listener (in opengl coordinates) @@ -154,7 +162,7 @@ public: void set_orientation( SGQuatd ori ); inline SGVec3f get_direction() { - return SGVec3f(_listener_ori[0], _listener_ori[1], _listener_ori[2]); + return SGVec3f(_orientation[0], _orientation[1], _orientation[2]); } enum { @@ -210,14 +218,14 @@ private: ALCcontext *_context; // Position of the listener. - SGVec3d _listener_pos; + SGVec3d _position; // Velocity of the listener. - SGVec3f _listener_vel; + SGVec3f _velocity; // Orientation of the listener. // first 3 elements are "at" vector, second 3 are "up" vector - ALfloat _listener_ori[6]; + ALfloat _orientation[6]; sample_group_map _sample_groups; buffer_map _buffers; diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 919f0837..9fe4fdb1 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -230,11 +230,11 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, // Relative position // SGVec3f offset_pos = SGVec3f::zeros(); - SGPropertyNode_ptr pos = node->getChild("position"); - if ( pos != NULL ) { - offset_pos[0] = pos->getDoubleValue("x", 0.0); - offset_pos[1] = -pos->getDoubleValue("y", 0.0); - offset_pos[2] = pos->getDoubleValue("z", 0.0); + SGPropertyNode_ptr prop = node->getChild("position"); + if ( prop != NULL ) { + offset_pos[0] = prop->getDoubleValue("x", 0.0); + offset_pos[1] = -prop->getDoubleValue("y", 0.0); + offset_pos[2] = prop->getDoubleValue("z", 0.0); } // @@ -244,40 +244,29 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, float inner, outer, outer_gain; inner = outer = 360.0; outer_gain = 0.0; - pos = node->getChild("orientation"); - if ( pos != NULL ) { - dir[0] = pos->getDoubleValue("x", 0.0); - dir[1] = -pos->getDoubleValue("y", 0.0); - dir[2] = pos->getDoubleValue("z", 0.0); - inner = pos->getDoubleValue("inner-angle", 360.0); - outer = pos->getDoubleValue("outer-angle", 360.0); - outer_gain = pos->getDoubleValue("outer-gain", 0.0); + prop = node->getChild("orientation"); + if ( prop != NULL ) { + dir[0] = prop->getDoubleValue("x", 0.0); + dir[1] = -prop->getDoubleValue("y", 0.0); + dir[2] = prop->getDoubleValue("z", 0.0); + inner = prop->getDoubleValue("inner-angle", 360.0); + outer = prop->getDoubleValue("outer-angle", 360.0); + outer_gain = prop->getDoubleValue("outer-gain", 0.0); } // // Initialize the sample // _sgrp = sgrp; - if ( (_sample = _sgrp->find(_name)) == NULL ) { - // FIXME: Does it make sense to overwrite a previous entry's - // configuration just because a new entry has the same name? - // Note that we can't match on identical "path" because we the - // new entry could be at a different location with different - // configuration so we need a new sample which creates a new - // "alSource". The semantics of what is going on here seems - // confused and needs to be thought through more carefully. - _sample = new SGSoundSample( path.c_str(), - node->getStringValue("path", "") ); - _sgrp->add( _sample, _name ); - } - + _sample = new SGSoundSample( path.c_str(), node->getStringValue("path", "")); _sample->set_relative_position( offset_pos ); - _sample->set_orientation( dir ); + _sample->set_direction( dir ); _sample->set_audio_cone(inner, outer, outer_gain); _sample->set_reference_dist( reference_dist ); _sample->set_max_dist( max_dist ); _sample->set_volume(v); _sample->set_pitch(p); + _sgrp->add( _sample, _name ); } void From f16199283644236bd33eed77dc622a3ce70a995f Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 12 Oct 2009 17:22:41 +0000 Subject: [PATCH 11/85] Alex Buzin: I got an error with the Sunday CVS - FG crashed while exiting . gdb reports SIGSEGV error at file soundmgr_openal.cxx, line 159. Error was fixed by changing lines 157-159 from: buffer_map_iterator buffers_current = _buffers.begin(); buffer_map_iterator buffers_end = _buffers.end(); for ( ; buffers_current != buffers_end; ++buffers_current ) { to : buffer_map_iterator buffers_current; while(_buffers.size()){ buffers_current = _buffers.begin(); --- simgear/sound/soundmgr_openal.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index d082d6c3..11a10fde 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -154,9 +154,9 @@ void SGSoundMgr::stop() { _working = false; // 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 ) { + buffer_map_iterator buffers_current; + while(_buffers.size()){ + buffers_current = _buffers.begin(); refUint ref = buffers_current->second; ALuint buffer = ref.id; alDeleteBuffers(1, &buffer); From eab9da98f22ae95fb23c6c2f1412857cb94258e4 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 15 Oct 2009 09:18:21 +0000 Subject: [PATCH 12/85] give the sample class as much info as possible to properly position and orientate the sounds. unfortunately at this time orientation seems to be from straight behind which means that sounds that have outer-gain set to 0.0 will not be heard yet. --- simgear/sound/sample_group.cxx | 102 ++++++++++++++---------------- simgear/sound/sample_group.hxx | 20 +++--- simgear/sound/sample_openal.cxx | 81 +++++++++++------------- simgear/sound/sample_openal.hxx | 40 ++++++------ simgear/sound/soundmgr_openal.cxx | 33 +++++----- simgear/sound/soundmgr_openal.hxx | 32 +++++----- simgear/sound/xmlsound.cxx | 10 +-- 7 files changed, 150 insertions(+), 168 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 22f9f9bf..c85e386f 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -46,9 +46,9 @@ SGSampleGroup::SGSampleGroup () : _refname(""), _active(false), _tied_to_listener(false), - _position(SGVec3d::zeros()), - _velocity(SGVec3f::zeros()), - _orientation(SGVec3f::zeros()) + _velocity(SGVec3d::zeros()), + _position(SGGeod()), + _orientation(SGQuatd::zeros()) { _samples.clear(); } @@ -58,9 +58,9 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _refname(refname), _active(false), _tied_to_listener(false), - _position(SGVec3d::zeros()), - _velocity(SGVec3f::zeros()), - _orientation(SGVec3f::zeros()) + _velocity(SGVec3d::zeros()), + _position(SGGeod()), + _orientation(SGQuatd::zeros()) { _smgr->add(this, refname); _active = _smgr->is_working(); @@ -104,12 +104,6 @@ void SGSampleGroup::update( double dt ) { if ( _smgr->request_buffer(sample) == SGSoundMgr::NO_BUFFER ) continue; - if ( _tied_to_listener && _smgr->has_changed() ) { - sample->set_base_position( _smgr->get_position_vec() ); - sample->set_orientation( _smgr->get_direction() ); - sample->set_velocity( _smgr->get_velocity() ); - } - // start playing the sample ALboolean looping = sample->get_looping() ? AL_TRUE : AL_FALSE; ALuint buffer = sample->get_buffer(); @@ -294,29 +288,9 @@ bool SGSampleGroup::stop( const string& refname ) { return true; } - -// set source position of all managed sounds -void SGSampleGroup::set_position( SGVec3d pos ) { - if ( isnan(pos.data()[0]) || isnan(pos.data()[1]) || isnan(pos.data()[2]) ) - { - SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup postion"); - return; - } - - if ( !_tied_to_listener && _position != pos ) { - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_base_position( pos ); - } - _position = pos; - } -} - // set source velocity of all managed sounds -void SGSampleGroup::set_velocity( SGVec3f vel ) { - if ( isnan(vel.data()[0]) || isnan(vel.data()[1]) || isnan(vel.data()[2]) ) +void SGSampleGroup::set_velocity( SGVec3d &vel ) { + if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) { SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup velocity"); return; @@ -329,16 +303,25 @@ void SGSampleGroup::set_velocity( SGVec3f vel ) { SGSoundSample *sample = sample_current->second; sample->set_velocity( vel ); } + _velocity = vel; } } // ste the source orientation of all managed sounds -void SGSampleGroup::set_orientation( SGVec3f ori ) { - if ( isnan(ori.data()[0]) || isnan(ori.data()[1]) || isnan(ori.data()[2]) ) - { - SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup orientation"); - return; +void SGSampleGroup::set_position( SGGeod pos ) { + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_position( pos ); } + _position = pos; +} + + +// ste the source orientation of all managed sounds +void SGSampleGroup::set_orientation( SGQuatd ori ) { if (_orientation != ori) { sample_map_iterator sample_current = _samples.begin(); @@ -347,6 +330,21 @@ void SGSampleGroup::set_orientation( SGVec3f ori ) { SGSoundSample *sample = sample_current->second; sample->set_orientation( ori ); } + _orientation = ori; + } +} + +void SGSampleGroup::set_volume( float vol ) +{ + _volume = vol; + if (_volume < 0.0) _volume = 0.0; + if (_volume > 1.0) _volume = 1.0; + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_master_volume( _volume ); } } @@ -354,9 +352,15 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { if ( sample->is_valid_source() ) { unsigned int source = sample->get_source(); - alSourcefv( source, AL_POSITION, sample->get_position()); - alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); - alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); + if ( _tied_to_listener && _smgr->has_changed() ) { + alSourcefv( source, AL_POSITION, _smgr->get_position().data() ); + alSourcefv( source, AL_DIRECTION, _smgr->get_direction().data() ); + alSourcefv( source, AL_VELOCITY, _smgr->get_velocity().data() ); + } else { + alSourcefv( source, AL_POSITION, sample->get_position()); + alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); + alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); + } testForALError("position and orientation"); alSourcef( source, AL_PITCH, sample->get_pitch() ); @@ -377,20 +381,6 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { } } -void SGSampleGroup::set_volume( float vol ) -{ - _volume = vol; - if (_volume < 0.0) _volume = 0.0; - if (_volume > 1.0) _volume = 1.0; - - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_master_volume( _volume ); - } -} - bool SGSampleGroup::testForError(void *p, string s) { if (p == NULL) { diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 1344df44..5bb504a9 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -138,20 +138,20 @@ public: */ void set_volume( float vol ); - /** - * set the positions of all managed sound sources - */ - void set_position( SGVec3d pos ); - /** * set the velocities of all managed sound sources */ - void set_velocity( SGVec3f vel ); + void set_velocity( SGVec3d& vel ); + + /** + * set the position of all managed sound sources + */ + void set_position( SGGeod pos ); /** * set the orientation of all managed sound sources */ - void set_orientation( SGVec3f ori ); + void set_orientation( SGQuatd ori ); inline void tie_to_listener() { _tied_to_listener = true; } @@ -165,9 +165,9 @@ private: float _volume; bool _tied_to_listener; - SGVec3d _position; - SGVec3f _velocity; - SGVec3f _orientation; + SGVec3d _velocity; + SGGeod _position; + SGQuatd _orientation; sample_map _samples; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 8eb83a68..526e27c7 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -39,12 +39,12 @@ // empty constructor SGSoundSample::SGSoundSample() : - _absolute_pos(SGVec3d::zeros().data()), - _relative_pos(SGVec3f::zeros().data()), - _base_pos(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()), - _direction(SGVec3f::zeros().data()), - _velocity(SGVec3f::zeros().data()), + _absolute_pos(SGVec3d::zeros()), + _relative_pos(SGVec3f::zeros()), + _direction(SGVec3d::zeros()), + _velocity(SGVec3d::zeros()), + _base_pos(SGGeod()), + _orientation(SGQuatd::zeros()), _sample_name(""), _data(NULL), _format(AL_FORMAT_MONO8), @@ -72,12 +72,12 @@ SGSoundSample::SGSoundSample() : // constructor SGSoundSample::SGSoundSample( const char *path, const char *file ) : - _absolute_pos(SGVec3d::zeros().data()), - _relative_pos(SGVec3f::zeros().data()), - _base_pos(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()), - _direction(SGVec3f::zeros().data()), - _velocity(SGVec3f::zeros().data()), + _absolute_pos(SGVec3d::zeros()), + _relative_pos(SGVec3f::zeros()), + _direction(SGVec3d::zeros()), + _velocity(SGVec3d::zeros()), + _base_pos(SGGeod()), + _orientation(SGQuatd::zeros()), _format(AL_FORMAT_MONO8), _size(0), _freq(0), @@ -111,12 +111,12 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : // constructor SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format ) : - _absolute_pos(SGVec3d::zeros().data()), - _relative_pos(SGVec3f::zeros().data()), - _base_pos(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()), - _direction(SGVec3f::zeros().data()), - _velocity(SGVec3f::zeros().data()), + _absolute_pos(SGVec3d::zeros()), + _relative_pos(SGVec3f::zeros()), + _direction(SGVec3d::zeros()), + _velocity(SGVec3d::zeros()), + _base_pos(SGGeod()), + _orientation(SGQuatd::zeros()), _data(data), _format(format), _size(len), @@ -148,46 +148,37 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format SGSoundSample::~SGSoundSample() { } -float *SGSoundSample::get_orientation() { -#if 0 - SGQuatf quat = SGQuatf::fromAngleAxis(_orientation); - SGVec3f orient = quat.transform(_direction); - return orient.data(); -#else - return _orientation.data(); -#endif -} - -void SGSoundSample::set_base_position( SGVec3d pos ) { - _base_pos = pos; +void SGSoundSample::set_orientation( SGQuatd ori ) { + _orientation = ori; update_absolute_position(); _changed = true; } +void SGSoundSample::set_direction( SGVec3d dir ) { + _direction = dir; + update_absolute_position(); + _changed = true; +} + +float *SGSoundSample::get_orientation() { + SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; + SGVec3d orivec = -orient.rotate(_direction); + return toVec3f(orivec).data(); +} + void SGSoundSample::set_relative_position( SGVec3f pos ) { _relative_pos = pos; update_absolute_position(); _changed = true; } -void SGSoundSample::set_orientation( SGVec3f ori ) { - _orientation = ori; - update_absolute_position(); - _changed = true; -} - -void SGSoundSample::set_direction( SGVec3f dir ) { - _direction = dir; +void SGSoundSample::set_position( SGGeod pos ) { + _base_pos = pos; update_absolute_position(); _changed = true; } void SGSoundSample::update_absolute_position() { -#if 0 - SGQuatf orient = SGQuatf::fromAngleAxis(_orientation); - SGVec3f modified_relative_pos = orient.transform(_relative_pos); - _absolute_pos = _base_pos + toVec3d(modified_relative_pos); -#else - _absolute_pos = _base_pos; -#endif + _absolute_pos = -SGVec3d::fromGeod(_base_pos); + // TODO: add relative position } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index f44596a8..59d26581 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -40,9 +40,7 @@ #include #include -#include - -using std::string; +// #include /** * manages everything we need to know for an individual sound sample @@ -55,16 +53,14 @@ private: // Position of the source sound. SGVec3d _absolute_pos; // absolute position SGVec3f _relative_pos; // position relative to the base position - SGVec3d _base_pos; // base position + SGVec3d _direction; // orientation offset + SGVec3d _velocity; // Velocity of the source sound. - // The orientation of the sound (direction and cut-off angles) - SGVec3f _orientation; // base orientation - SGVec3f _direction; // orientation offset + // The position and orientation of the sound + SGGeod _base_pos; + SGQuatd _orientation; // base orientation - // Velocity of the source sound. - SGVec3f _velocity; - - string _sample_name; + std::string _sample_name; unsigned char *_data; // configuration values @@ -326,7 +322,6 @@ public: /** * Set position of the sound source (uses same coordinate system as opengl) */ - void set_base_position( SGVec3d pos ); void set_relative_position( SGVec3f pos ); /** @@ -335,16 +330,20 @@ public: inline float *get_position() const { return toVec3f(_absolute_pos).data(); } /** - * Set the orientation of the sound source, both for direction - * and audio cut-off angles. + * Set the position of the sound source */ - void set_orientation( SGVec3f ori ); + void set_position( SGGeod pos ); + + /** + * Set the orientation of the sound source + */ + void set_orientation( SGQuatd ori ); /** * Set the relative direction of the sound source, both for direction * and audio cut-off angles. */ - void set_direction( SGVec3f dir ); + void set_direction( SGVec3d dir ); /** * Define the audio cone parameters for directional audio @@ -369,14 +368,15 @@ public: /** * Set velocity of the sound source (uses same coordinate system as opengl) */ - inline void set_velocity( SGVec3f vel ) { - _velocity = SGVec3f(vel); _changed = true; + inline void set_velocity( SGVec3d& vel ) { + _velocity = vel; + _changed = true; } /** * Get velocity of the sound source (uses same coordinate system as opengl) */ - inline float *get_velocity() { return _velocity.data(); } + inline float *get_velocity() { return toVec3f(_velocity).data(); } /** @@ -411,7 +411,7 @@ public: /** * Get the name of this sample */ - inline string get_sample_name() { return _sample_name; } + inline std::string get_sample_name() { return _sample_name; } }; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 11a10fde..12c4b954 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -59,8 +59,9 @@ SGSoundMgr::SGSoundMgr() : _volume(0.0), _device(NULL), _context(NULL), - _position(SGVec3d::zeros().data()), - _velocity(SGVec3f::zeros().data()), + _position(SGVec3d::zeros()), + _velocity(SGVec3d::zeros()), + _orientation(SGQuatd::zeros()), _devname(NULL) { #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 @@ -111,13 +112,13 @@ void SGSoundMgr::init() { _context = context; _working = true; - _orientation[0] = 0.0; _orientation[1] = 0.0; _orientation[2] = -1.0; - _orientation[3] = 0.0; _orientation[4] = 1.0; _orientation[5] = 0.0; + _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; alListenerf( AL_GAIN, 0.2f ); - alListenerfv( AL_POSITION, toVec3f(_position).data() ); - alListenerfv( AL_ORIENTATION, _orientation ); - alListenerfv( AL_VELOCITY, _velocity.data() ); + alListenerfv( AL_POSITION, SGVec3f::zeros().data() ); + alListenerfv( AL_ORIENTATION, _at_up_vec ); + alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); alDopplerFactor(0.5); alDopplerVelocity(340.3); // speed of sound in meters per second. @@ -227,9 +228,9 @@ void SGSoundMgr::update_late( double dt ) { if (_changed) { alListenerf( AL_GAIN, _volume ); - alListenerfv( AL_VELOCITY, _velocity.data() ); - alListenerfv( AL_ORIENTATION, _orientation ); + alListenerfv( AL_ORIENTATION, _at_up_vec ); alListenerfv( AL_POSITION, toVec3f(_position).data() ); + alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); _changed = false; @@ -334,14 +335,16 @@ void SGSoundMgr::set_volume( float v ) */ void SGSoundMgr::set_orientation( SGQuatd ori ) { + _orientation = ori; + SGVec3d sgv_up = ori.rotate(SGVec3d::e2()); SGVec3d sgv_at = ori.rotate(SGVec3d::e3()); - _orientation[0] = sgv_at[0]; - _orientation[1] = sgv_at[1]; - _orientation[2] = sgv_at[2]; - _orientation[3] = sgv_up[0]; - _orientation[4] = sgv_up[1]; - _orientation[5] = sgv_up[2]; + _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]; _changed = true; } diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index ba1e5522..4baad69b 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -134,35 +134,32 @@ public: /** * set the position of the listener (in opengl coordinates) */ - void set_position( SGVec3d pos ) { - if (_position != pos) { - _position = pos; - _changed = true; - } + void set_position( const SGVec3d& pos ) { + _position = -pos; + _changed = true; } - inline double *get_position() { return _position.data(); } - inline SGVec3d get_position_vec() { return _position; }; + inline SGVec3f get_position() { return toVec3f(_position); } /** - * set the velocity of the listener (in opengl coordinates) + * set the velocity direction of the listener (in opengl coordinates) */ - void set_velocity( SGVec3f vel ) { - if (_velocity != vel) { - _velocity = vel; - _changed = true; - } + void set_velocity( SGVec3d& dir ) { + _velocity = dir; + _changed = true; } - inline SGVec3f get_velocity() { return _velocity; } + inline SGVec3f get_velocity() { return toVec3f(_velocity); } /** * set the orientation of the listener (in opengl coordinates) */ void set_orientation( SGQuatd ori ); + inline const SGQuatd& get_orientation() { return _orientation; } + inline SGVec3f get_direction() { - return SGVec3f(_orientation[0], _orientation[1], _orientation[2]); + return SGVec3f(_at_up_vec[0], _at_up_vec[1], _at_up_vec[2]); } enum { @@ -221,11 +218,12 @@ private: SGVec3d _position; // Velocity of the listener. - SGVec3f _velocity; + SGVec3d _velocity; // Orientation of the listener. // first 3 elements are "at" vector, second 3 are "up" vector - ALfloat _orientation[6]; + SGQuatd _orientation; + ALfloat _at_up_vec[6]; sample_group_map _sample_groups; buffer_map _buffers; diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 9fe4fdb1..4edad960 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -240,20 +240,20 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, // // Orientation // - SGVec3f dir = SGVec3f::zeros(); + SGVec3d dir = SGVec3d::zeros(); float inner, outer, outer_gain; inner = outer = 360.0; outer_gain = 0.0; prop = node->getChild("orientation"); if ( prop != NULL ) { - dir[0] = prop->getDoubleValue("x", 0.0); - dir[1] = -prop->getDoubleValue("y", 0.0); - dir[2] = prop->getDoubleValue("z", 0.0); + dir = SGVec3d(-prop->getDoubleValue("x", 0.0), + -prop->getDoubleValue("y", 0.0), + -prop->getDoubleValue("z", 0.0)); inner = prop->getDoubleValue("inner-angle", 360.0); outer = prop->getDoubleValue("outer-angle", 360.0); outer_gain = prop->getDoubleValue("outer-gain", 0.0); } - + // // Initialize the sample // From f23e8bfb0209d5c12ac3099e69bfb7fe844dc8c8 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 15 Oct 2009 12:00:20 +0000 Subject: [PATCH 13/85] fix for latest changes --- simgear/environment/visual_enviro.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simgear/environment/visual_enviro.cxx b/simgear/environment/visual_enviro.cxx index 71a0c5ea..e18ebede 100644 --- a/simgear/environment/visual_enviro.cxx +++ b/simgear/environment/visual_enviro.cxx @@ -755,8 +755,8 @@ void SGEnviro::drawLightning(void) { ay = sin(course) * dist; SGSharedPtr snd = sampleGroup->find("thunder"); if( snd ) { - SGVec3d pos = SGVec3d(ax, ay, -sgEnviro.last_alt); - snd->set_base_position(pos); + SGVec3f pos = SGVec3f(ax, ay, -sgEnviro.last_alt); + snd->set_relative_position(pos); snd->play_once(); } } From 6fe057e27795a7ca9624dc126a1549b8d06500b3 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 15 Oct 2009 12:33:32 +0000 Subject: [PATCH 14/85] add a debugging statement --- simgear/sound/soundmgr_openal.cxx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 12c4b954..450b5714 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -101,11 +101,14 @@ void SGSoundMgr::init() { ALCcontext *context = alcCreateContext(device, NULL); if ( testForError(context, "Unable to create a valid context.") ) { + alcCloseDevice (device); return; } if ( !alcMakeContextCurrent(context) ) { testForALCError("context initialization"); + alcDestroyContext (context); + alcCloseDevice (device); return; } @@ -116,11 +119,11 @@ void SGSoundMgr::init() { _at_up_vec[3] = 0.0; _at_up_vec[4] = 1.0; _at_up_vec[5] = 0.0; alListenerf( AL_GAIN, 0.2f ); - alListenerfv( AL_POSITION, SGVec3f::zeros().data() ); alListenerfv( AL_ORIENTATION, _at_up_vec ); - alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); + alListenerfv( AL_POSITION, SGVec3f::zeros().data() ); + alListenerfv( AL_VELOCITY, SGVec3f::zeros().data() ); - alDopplerFactor(0.5); + alDopplerFactor(1.0); alDopplerVelocity(340.3); // speed of sound in meters per second. if ( alIsExtensionPresent((const ALchar*)"EXT_exponent_distance") ) { @@ -131,8 +134,6 @@ void SGSoundMgr::init() { testForALError("listener initialization"); - alGetError(); // clear any undetetced error, just to be sure - // get a free source one at a time // if an error is returned no more (hardware) sources are available for (unsigned int i=0; i Date: Thu, 15 Oct 2009 17:08:45 +0000 Subject: [PATCH 15/85] Initialization was done much earlier than expected resulting in some sample groups not being activated (and sample loading using OpenAL/ALUT functions to be scheduled before OpenAL was initilialized). fix alutInit counter remove left over static declaration fro SGSoundMgr::load --- simgear/sound/sample_group.cxx | 1 - simgear/sound/sample_group.hxx | 1 + simgear/sound/soundmgr_openal.cxx | 14 ++++++++++---- simgear/sound/soundmgr_openal.hxx | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index c85e386f..3d1dd084 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -63,7 +63,6 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _orientation(SGQuatd::zeros()) { _smgr->add(this, refname); - _active = _smgr->is_working(); _samples.clear(); } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 5bb504a9..70b844c3 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -155,6 +155,7 @@ public: inline void tie_to_listener() { _tied_to_listener = true; } + inline void activate() { _active = true; } protected: SGSoundMgr *_smgr; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 450b5714..c8bd635c 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -70,7 +70,6 @@ SGSoundMgr::SGSoundMgr() : testForALUTError("alut initialization"); return; } - _alut_init++; } _alut_init++; #endif @@ -152,6 +151,13 @@ void SGSoundMgr::init() { if (_free_sources.size() == 0) { SG_LOG(SG_GENERAL, SG_ALERT, "Unable to grab any OpenAL sources!"); } + + 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->activate(); + } } // suspend the sound manager @@ -471,9 +477,9 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, unsigned int *sz, int *frq ) { - ALenum format = (ALenum)*fmt; - ALsizei size = (ALsizei)*sz; - ALsizei freq = (ALsizei)*frq; + ALenum format; + ALsizei size; + ALsizei freq; ALvoid *data; #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 4baad69b..e2e2be40 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -199,7 +199,7 @@ public: */ inline bool has_changed() { return _changed; } - static bool load(string &samplepath, void **data, int *format, + bool load(string &samplepath, void **data, int *format, unsigned int*size, int *freq ); From fdfdfedf01776fafa4d769b93e95585e018a00d4 Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 16 Oct 2009 09:45:00 +0000 Subject: [PATCH 16/85] Alut < 1.0 fixes and finaly fix the sound orientation --- simgear/sound/sample_group.cxx | 6 +++--- simgear/sound/sample_group.hxx | 4 ++-- simgear/sound/sample_openal.cxx | 18 +++++++++--------- simgear/sound/sample_openal.hxx | 10 +++++----- simgear/sound/soundmgr_openal.cxx | 5 +++-- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 3d1dd084..fb2f31f0 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -306,7 +306,7 @@ void SGSampleGroup::set_velocity( SGVec3d &vel ) { } } -// ste the source orientation of all managed sounds +// set the source position of all managed sounds void SGSampleGroup::set_position( SGGeod pos ) { sample_map_iterator sample_current = _samples.begin(); @@ -319,7 +319,7 @@ void SGSampleGroup::set_position( SGGeod pos ) { } -// ste the source orientation of all managed sounds +// set the source orientation of all managed sounds void SGSampleGroup::set_orientation( SGQuatd ori ) { if (_orientation != ori) { @@ -356,7 +356,7 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { alSourcefv( source, AL_DIRECTION, _smgr->get_direction().data() ); alSourcefv( source, AL_VELOCITY, _smgr->get_velocity().data() ); } else { - alSourcefv( source, AL_POSITION, sample->get_position()); + alSourcefv( source, AL_POSITION, sample->get_position() ); alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 70b844c3..9cfd8dfb 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -153,9 +153,9 @@ public: */ void set_orientation( SGQuatd ori ); - inline void tie_to_listener() { _tied_to_listener = true; } + void tie_to_listener() { _tied_to_listener = true; } - inline void activate() { _active = true; } + void activate() { _active = true; } protected: SGSoundMgr *_smgr; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 526e27c7..939e5619 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -66,7 +66,8 @@ SGSoundSample::SGSoundSample() : _playing(false), _changed(true), _static_changed(true), - _is_file(false) + _is_file(false), + _orivec(SGVec3f::zeros()) { } @@ -97,7 +98,8 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _playing(false), _changed(true), _static_changed(true), - _is_file(true) + _is_file(true), + _orivec(SGVec3f::zeros()) { SGPath samplepath( path ); if ( strlen(file) ) { @@ -137,7 +139,8 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format _playing(false), _changed(true), _static_changed(true), - _is_file(false) + _is_file(false), + _orivec(SGVec3f::zeros()) { _sample_name = "unknown, data supplied by caller"; SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); @@ -160,12 +163,6 @@ void SGSoundSample::set_direction( SGVec3d dir ) { _changed = true; } -float *SGSoundSample::get_orientation() { - SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; - SGVec3d orivec = -orient.rotate(_direction); - return toVec3f(orivec).data(); -} - void SGSoundSample::set_relative_position( SGVec3f pos ) { _relative_pos = pos; update_absolute_position(); @@ -179,6 +176,9 @@ void SGSoundSample::set_position( SGGeod pos ) { } void SGSoundSample::update_absolute_position() { + SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; + _orivec = -toVec3f(orient.rotate(_direction)); + _absolute_pos = -SGVec3d::fromGeod(_base_pos); // TODO: add relative position } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 59d26581..49a7c01e 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -93,6 +93,7 @@ private: bool _static_changed; bool _is_file; + SGVec3f _orivec; void update_absolute_position(); public: @@ -359,11 +360,10 @@ public: * Get the orientation of the sound source, the inner or outer angle * or outer gain. */ - float *get_orientation(); - - inline float get_innerangle() { return _inner_angle; } - inline float get_outerangle() { return _outer_angle; } - inline float get_outergain() { return _outer_gain; } + float *get_orientation() { return _orivec.data(); } + float get_innerangle() { return _inner_angle; } + float get_outerangle() { return _outer_angle; } + float get_outergain() { return _outer_gain; } /** * Set velocity of the sound source (uses same coordinate system as opengl) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index c8bd635c..cbb137ef 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -274,6 +274,7 @@ bool SGSoundMgr::add( SGSampleGroup *sgrp, const string& refname ) return false; } + if (_working) sgrp->activate(); _sample_groups[refname] = sgrp; return true; @@ -502,8 +503,8 @@ bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, ALboolean loop; alutLoadWAVFile( fname, &format, &data, &size, &freq, &loop ); # endif - ALenum error = alutGetError(); - if ( error != ALUT_ERROR_NO_ERROR ) { + ALenum error = alGetError(); + if ( error != AL_NO_ERROR ) { string msg = "Failed to load wav file: "; msg.append(alutGetErrorString(error)); throw sg_io_exception(msg.c_str(), sg_location(samplepath)); From 600a9ee4c52c4867bb2075a9df5728cc061413ec Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 16 Oct 2009 11:37:52 +0000 Subject: [PATCH 17/85] _data is not an array of pointer --- simgear/sound/sample_openal.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 49a7c01e..acc7fb73 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -52,7 +52,7 @@ private: // Position of the source sound. SGVec3d _absolute_pos; // absolute position - SGVec3f _relative_pos; // position relative to the base position + SGVec3d _relative_pos; // position relative to the base position SGVec3d _direction; // orientation offset SGVec3d _velocity; // Velocity of the source sound. @@ -201,7 +201,7 @@ public: * free the data associated with this sample */ inline void free_data() { - if (_data != NULL) { delete[] _data; _data = NULL; } + if (_data != NULL) { delete _data; _data = NULL; } } /** From 24c7941f65aa7d3fab3ee54fe982111c1f52656d Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 16 Oct 2009 13:19:36 +0000 Subject: [PATCH 18/85] convert _relative_pos to a vector of doubles and set the relative offset --- simgear/sound/sample_openal.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 939e5619..655a7e27 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -40,7 +40,7 @@ // empty constructor SGSoundSample::SGSoundSample() : _absolute_pos(SGVec3d::zeros()), - _relative_pos(SGVec3f::zeros()), + _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _base_pos(SGGeod()), @@ -74,7 +74,7 @@ SGSoundSample::SGSoundSample() : // constructor SGSoundSample::SGSoundSample( const char *path, const char *file ) : _absolute_pos(SGVec3d::zeros()), - _relative_pos(SGVec3f::zeros()), + _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _base_pos(SGGeod()), @@ -114,7 +114,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : // constructor SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format ) : _absolute_pos(SGVec3d::zeros()), - _relative_pos(SGVec3f::zeros()), + _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _base_pos(SGGeod()), @@ -164,7 +164,7 @@ void SGSoundSample::set_direction( SGVec3d dir ) { } void SGSoundSample::set_relative_position( SGVec3f pos ) { - _relative_pos = pos; + _relative_pos = toVec3d(pos); update_absolute_position(); _changed = true; } @@ -179,6 +179,6 @@ void SGSoundSample::update_absolute_position() { SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; _orivec = -toVec3f(orient.rotate(_direction)); - _absolute_pos = -SGVec3d::fromGeod(_base_pos); - // TODO: add relative position + orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; + _absolute_pos = -SGVec3d::fromGeod(_base_pos) -orient.rotate(SGVec3d::e1()); } From e2b8a21ff51630ad3c437d5cde927a3879654bd6 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 17 Oct 2009 12:36:48 +0000 Subject: [PATCH 19/85] documentation, licensing, copyright and small api updates. --- simgear/sound/sample_group.cxx | 36 ++- simgear/sound/sample_group.hxx | 107 +++++--- simgear/sound/sample_openal.cxx | 36 +-- simgear/sound/sample_openal.hxx | 397 +++++++++++++++++------------- simgear/sound/soundmgr_openal.cxx | 15 +- simgear/sound/soundmgr_openal.hxx | 106 ++++++-- 6 files changed, 438 insertions(+), 259 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index fb2f31f0..1c63e3ee 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -1,3 +1,25 @@ +// sample_group.cxx -- Manage a group of samples relative to a base position +// +// Written for the new SoundSystem by Erik Hofman, October 2009 +// +// 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 @@ -47,8 +69,8 @@ SGSampleGroup::SGSampleGroup () : _active(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), - _position(SGGeod()), - _orientation(SGQuatd::zeros()) + _orientation(SGQuatd::zeros()), + _position(SGGeod()) { _samples.clear(); } @@ -59,8 +81,8 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _active(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), - _position(SGGeod()), - _orientation(SGQuatd::zeros()) + _orientation(SGQuatd::zeros()), + _position(SGGeod()) { _smgr->add(this, refname); _samples.clear(); @@ -288,7 +310,7 @@ bool SGSampleGroup::stop( const string& refname ) { } // set source velocity of all managed sounds -void SGSampleGroup::set_velocity( SGVec3d &vel ) { +void SGSampleGroup::set_velocity( const SGVec3d &vel ) { if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) { SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup velocity"); @@ -307,7 +329,7 @@ void SGSampleGroup::set_velocity( SGVec3d &vel ) { } // set the source position of all managed sounds -void SGSampleGroup::set_position( SGGeod pos ) { +void SGSampleGroup::set_position( const SGGeod& pos ) { sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); @@ -320,7 +342,7 @@ void SGSampleGroup::set_position( SGGeod pos ) { // set the source orientation of all managed sounds -void SGSampleGroup::set_orientation( SGQuatd ori ) { +void SGSampleGroup::set_orientation( const SGQuatd& ori ) { if (_orientation != ori) { sample_map_iterator sample_current = _samples.begin(); diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 9cfd8dfb..e98596c3 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -1,8 +1,8 @@ -// soundmgr.hxx -- Sound effect management class +// sample_group.hxx -- Manage a group of samples relative to a base position // -// Sampel Group handler initially written by Erik Hofman +// Written for the new SoundSystem by Erik Hofman, October 2009 // -// Copyright (C) 2009 Erik Hofman - +// 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 @@ -64,99 +64,150 @@ class SGSoundMgr; class SGSampleGroup : public SGReferenced { public: + + /** + * Empty constructor for class encapsulation. + * Note: The sample group should still be activated before use + */ SGSampleGroup (); + + /** + * Constructor + * Register this sample group at the sound manager using refname + * Note: The sample group should still be activated before use + * @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 ); + + /** + * Destructor + */ ~SGSampleGroup (); + /** + * Set the status of this sample group to active. + */ + inline void activate() { _active = true; } + + /** + * Update function. + * Call this function periodically to update the OpenAL state of all + * samples associated with this class. None op the configuration changes + * take place without a call to this function. + */ virtual void update (double dt); /** - * add a sound effect, return true if successful + * Register an audio sample to this group. + * @param sound Pointer to a pre-initialized audio sample + * @param refname Name of this audio sample for reference purposes + * @return return true if successful */ bool add( SGSoundSample *sound, const string& refname ); /** - * remove a sound effect, return true if successful + * 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 ); /** - * return true of the specified sound exists in the sound manager system + * 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 ); /** - * return a pointer to the SGSoundSample if the specified sound - * exists in the sound manager system, otherwise return NULL + * 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 ); /** - * request to stop playing all associated samples until further notice + * Request to stop playing all audio samples until further notice. */ void suspend(); /** - * request to resume playing all associated samples + * Request to resume playing all audio samples. */ void resume(); - /** - * request to start playing the associated samples + * Request to start playing the refered audio sample. + * @param refname Reference name of the audio sample to start playing + * @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 ); /** - * tell the scheduler to play the indexed sample in a continuous - * loop + * Request to start playing the refered 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 ) { return play( refname, true ); } /** - * tell the scheduler to play the indexed sample once + * Request to start playing the refered audio sample once. + * @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_once( const string& refname ) { return play( refname, false ); } /** - * return true of the specified sound is currently being played + * Test if a referenced sample is playing or not. + * @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 ); /** - * request to stop playing the associated samples + * Request to stop playing the refered audio sample. + * @param refname Reference name of the audio sample to stop + * @return true if the audio sample exsists and is scheduled to stop */ bool stop( const string& refname ); /** - * set overall volume for the application. - * @param must be between 0.0 and 1.0 + * Set the master volume for this sample group. + * @param vol Volume (must be between 0.0 and 1.0) */ void set_volume( float vol ); /** - * set the velocities of all managed sound sources + * Set the velocity vector of this sample group. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @param vel Velocity vector */ - void set_velocity( SGVec3d& vel ); + void set_velocity( const SGVec3d& vel ); /** - * set the position of all managed sound sources + * Set the position of this sample group. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @param pos Base position */ - void set_position( SGGeod pos ); + void set_position( const SGGeod& pos ); /** - * set the orientation of all managed sound sources + * Set the orientation of this sample group. + * @param ori Quaternation containing the orientation information */ - void set_orientation( SGQuatd ori ); + void set_orientation( const SGQuatd& ori ); + /** + * Tie this sample group to the listener position, orientation and velocity + */ void tie_to_listener() { _tied_to_listener = true; } - void activate() { _active = true; } - protected: SGSoundMgr *_smgr; string _refname; @@ -167,8 +218,8 @@ private: bool _tied_to_listener; SGVec3d _velocity; - SGGeod _position; SGQuatd _orientation; + SGGeod _position; sample_map _samples; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 655a7e27..191877ae 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -1,8 +1,10 @@ -// sample.cxx -- Sound sample encapsulation class +// sample_openal.cxx -- Audio sample encapsulation class // // Written by Curtis Olson, started April 2004. +// Modified to match the new SoundSystem by Erik Hofman, October 2009 // // Copyright (C) 2004 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 @@ -43,9 +45,10 @@ SGSoundSample::SGSoundSample() : _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), - _base_pos(SGGeod()), _orientation(SGQuatd::zeros()), - _sample_name(""), + _orivec(SGVec3f::zeros()), + _base_pos(SGGeod()), + _refname(""), _data(NULL), _format(AL_FORMAT_MONO8), _size(0), @@ -66,8 +69,7 @@ SGSoundSample::SGSoundSample() : _playing(false), _changed(true), _static_changed(true), - _is_file(false), - _orivec(SGVec3f::zeros()) + _is_file(false) { } @@ -77,8 +79,9 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), - _base_pos(SGGeod()), _orientation(SGQuatd::zeros()), + _orivec(SGVec3f::zeros()), + _base_pos(SGGeod()), _format(AL_FORMAT_MONO8), _size(0), _freq(0), @@ -98,14 +101,13 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _playing(false), _changed(true), _static_changed(true), - _is_file(true), - _orivec(SGVec3f::zeros()) + _is_file(true) { SGPath samplepath( path ); if ( strlen(file) ) { samplepath.append( file ); } - _sample_name = samplepath.str(); + _refname = samplepath.str(); SG_LOG( SG_GENERAL, SG_DEBUG, "From file sounds sample = " << samplepath.str() ); @@ -117,8 +119,9 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), - _base_pos(SGGeod()), _orientation(SGQuatd::zeros()), + _orivec(SGVec3f::zeros()), + _base_pos(SGGeod()), _data(data), _format(format), _size(len), @@ -139,10 +142,9 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format _playing(false), _changed(true), _static_changed(true), - _is_file(false), - _orivec(SGVec3f::zeros()) + _is_file(false) { - _sample_name = "unknown, data supplied by caller"; + _refname = "unknown, data supplied by caller"; SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); } @@ -151,25 +153,25 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format SGSoundSample::~SGSoundSample() { } -void SGSoundSample::set_orientation( SGQuatd ori ) { +void SGSoundSample::set_orientation( const SGQuatd& ori ) { _orientation = ori; update_absolute_position(); _changed = true; } -void SGSoundSample::set_direction( SGVec3d dir ) { +void SGSoundSample::set_direction( const SGVec3d& dir ) { _direction = dir; update_absolute_position(); _changed = true; } -void SGSoundSample::set_relative_position( SGVec3f pos ) { +void SGSoundSample::set_relative_position( const SGVec3f& pos ) { _relative_pos = toVec3d(pos); update_absolute_position(); _changed = true; } -void SGSoundSample::set_position( SGGeod pos ) { +void SGSoundSample::set_position( const SGGeod& pos ) { _base_pos = pos; update_absolute_position(); _changed = true; diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index acc7fb73..448e0812 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -1,8 +1,10 @@ -// sample.hxx -- Sound sample encapsulation class +// sample_openal.hxx -- Audio sample encapsulation class // // Written by Curtis Olson, started April 2004. +// Modified to match the new SoundSystem by Erik Hofman, October 2009 // // Copyright (C) 2004 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 @@ -15,14 +17,14 @@ // 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. +// 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 sample.hxx - * Provides a sound sample encapsulation + * \file audio sample.hxx + * Provides a audio sample encapsulation */ #ifndef _SG_SAMPLE_HXX @@ -43,59 +45,10 @@ // #include /** - * manages everything we need to know for an individual sound sample + * manages everything we need to know for an individual audio sample */ class SGSoundSample : public SGReferenced { - -private: - - // Position of the source sound. - SGVec3d _absolute_pos; // absolute position - SGVec3d _relative_pos; // position relative to the base position - SGVec3d _direction; // orientation offset - SGVec3d _velocity; // Velocity of the source sound. - - // The position and orientation of the sound - SGGeod _base_pos; - SGQuatd _orientation; // base orientation - - std::string _sample_name; - unsigned char *_data; - - // configuration values - int _format; - int _size; - int _freq; - - // Buffers hold sound data. - bool _valid_buffer; - unsigned int _buffer; - - // Sources are points emitting sound. - bool _valid_source; - unsigned int _source; - - // The orientation of the sound (direction and cut-off angles) - float _inner_angle; - float _outer_angle; - float _outer_gain; - - float _pitch; - float _volume; - float _master_volume; - float _reference_dist; - float _max_dist; - bool _loop; - - bool _playing; - bool _changed; - bool _static_changed; - bool _is_file; - - SGVec3f _orivec; - void update_absolute_position(); - public: /** @@ -115,241 +68,269 @@ public: /** * Constructor. - * @param _data Pointer to a memory buffer containing the sample data - the application is responsible for freeing the buffer data. + * @param data Pointer to a memory buffer containing this audio sample data + buffer data is freed by this audio sample manager. * @param len Byte length of array - * @param _freq Frequency of the provided data (bytes per second) - should usually be true unless you want to manipulate the data - later.) + * @param freq Frequency of the provided data (bytes per second) + * @param format OpenAL format id of the data */ - SGSoundSample( unsigned char *data, int len, int freq, int format = AL_FORMAT_MONO8 ); + SGSoundSample( unsigned char *data, int len, int freq, + int format = AL_FORMAT_MONO8 ); + /** + * Destructor + */ ~SGSoundSample (); /** - * detect wheter the sample holds the information of a sound file + * Detect wheter this audio sample holds the information of a sound file. + * @return Return true if this audio sample is to be constructed from a file. */ inline bool is_file() const { return _is_file; } /** - * Test whether this sample has a changed configuration since the last - * call. (Calling this function resets the value). + * Test if this audio sample configuration has changed since the last call. + * Calling this function will reset the flag so calling it a second + * time in a row will return false. + * @return Return true is the configuration has changed in the mean time. */ - inline bool has_changed() { + bool has_changed() { bool b = _changed; _changed = false; return b; } - inline bool has_static_data_changed() { + /** + * Test if static dataa of audio sample configuration has changed. + * Calling this function will reset the flag so calling it a second + * time in a row will return false. + * @return Return true is the static data has changed in the mean time. + */ + bool has_static_data_changed() { bool b = _static_changed; _static_changed = false; return b; } - /** - * Start playing this sample. - * - * @param _loop Define whether the sound should be played in a loop. + * Schedule this audio sample for playing. Actual playing will only start + * at the next call op SoundGroup::update() + * @param _loop Define whether this sound should be played in a loop. */ - inline void play( bool loop ) { + void play( bool loop ) { _playing = true; _loop = loop; _changed = true; } /** - * Return if the sample is looping or not. + * Check if this audio sample is set to be continuous looping. + * @return Return true if this audio sample is set to looping. */ inline bool get_looping() { return _loop; } /** - * Stop playing this sample. - * - * @param sched A pointer to the appropriate scheduler. + * Schedule this audio sample to stop playing. */ - inline void stop() { + void stop() { _playing = false; _changed = true; } /** - * Play this sample once. + * Schedule this audio sample to play once. * @see #play */ inline void play_once() { play(false); } /** - * Play this sample looped. + * Schedule this audio sample to play looped. * @see #play */ inline void play_looped() { play(true); } /** - * Test if a sample is currently playing. - * @return true if is is playing, false otherwise. + * Test if a audio sample is scheduled for playing. + * @return true if this audio sample is playing, false otherwise. */ inline bool is_playing() { return _playing; } /** - * set the data associated with this sample + * sSt the data associated with this audio sample + * @param data Pointer to a memory block containg this audio sample data. */ - inline void set_data( unsigned char* data ) { - _data = data; - } + inline void set_data( unsigned char* data ) { _data = data; } /** - * @return the data associated with this sample + * Return the data associated with this audio sample. + * @return A pointer to this sound data of this audio sample. */ inline void* get_data() const { return _data; } /** - * free the data associated with this sample + * Free the data associated with this audio sample */ - inline void free_data() { + void free_data() { if (_data != NULL) { delete _data; _data = NULL; } } /** - * set the source id of this source + * Set the source id of this source + * @param sid OpenAL source-id */ - inline void set_source(unsigned int s) { - _source = s; _valid_source = true; _changed = true; + void set_source(unsigned int sid) { + _source = sid; _valid_source = true; _changed = true; } /** - * get the source id of this source + * Get the OpenAL source id of this source + * @return OpenAL source-id */ inline unsigned int get_source() { return _source; } /** - * detect wheter the source id of the sample is valid + * Test if the source-id of this audio sample may be passed to OpenAL. + * @return true if the source-id is valid */ inline bool is_valid_source() const { return _valid_source; } /** - * set the source id of the sample to invalid. + * Set the source-id of this audio sample to invalid. */ - inline void no_valid_source() { - _valid_source = false; - } + inline void no_valid_source() { _valid_source = false; } /** - * set the buffer id of this source + * Set the OpenAL buffer-id of this source + * @param bid OpenAL buffer-id */ - inline void set_buffer(unsigned int b) { - _buffer = b; _valid_buffer = true; _changed = true; + void set_buffer(unsigned int bid) { + _buffer = bid; _valid_buffer = true; _changed = true; } /** - * get the buffer id of this source + * Get the OpenAL buffer-id of this source + * @return OpenAL buffer-id */ inline unsigned int get_buffer() { return _buffer; } /** - * detect wheter the source id of the sample is valid + * Test if the buffer-id of this audio sample may be passed to OpenAL. + * @return true if the buffer-id is valid */ inline bool is_valid_buffer() const { return _valid_buffer; } /** - * set the source id of the sample to invalid. + * Set the buffer-id of this audio sample to invalid. */ - inline void no_valid_buffer() { - _valid_buffer = false; - } + inline void no_valid_buffer() { _valid_buffer = false; } /** - * Get the current pitch setting of this sample. + * Set the playback pitch of this audio sample. + * Should be between 0.0 and 2.0 for maximum compatibility. + * @param p Pitch + */ + inline void set_pitch( float p ) { _pitch = p; _changed = true; } + + /** + * Get the current pitch value of this audio sample. + * @return Pitch */ inline float get_pitch() { return _pitch; } /** - * Set the pitch of this sample. - */ - inline void set_pitch( float p ) { - _pitch = p; _changed = true; - } - - /** - * Get the current volume setting of this sample. - */ - inline float get_volume() { return _volume * _master_volume; } - - /** - * Set the master (sampel group) volume of this sample. + * Set the master volume of this sample. Should be between 0.0 and 1.0. + * The final volume is calculated by multiplying the master and audio sample + * volume. + * @param v Volume */ inline void set_master_volume( float v ) { _master_volume = v; _changed = true; } /** - * Set the volume of this sample. + * Set the volume of this audio sample. Should be between 0.0 and 1.0. + * The final volume is calculated by multiplying the master and audio sample + * volume. + * @param v Volume */ - inline void set_volume( float v ) { - _volume = v; _changed = true; - } + inline void set_volume( float v ) { _volume = v; _changed = true; } /** - * Set the format of the sounds sample + * Get the final volume value of this audio sample. + * @return Volume */ - inline void set_format( int format ) { - _format = format; - } + inline float get_volume() { return _volume * _master_volume; } /** - * Returns the format of the sounds sample + * Set the OpenAL format of this audio sample. + * @param format OpenAL format-id + */ + inline void set_format( int format ) { _format = format; } + + /** + * Returns the format of this audio sample. + * @return OpenAL format-id */ inline int get_format() { return _format; } - /** - * Set the frequency of the sounds sample + * Set the frequency (in Herz) of this audio sample. + * @param freq Frequency */ - inline void set_frequency( int freq ) { - _freq = freq; _changed = true; - } + inline void set_frequency( int freq ) { _freq = freq; _changed = true; } /** - * Returns the frequency of the sounds sample + * Returns the frequency (in Herz) of this audio sample. + * @return Frequency */ inline int get_frequency() { return _freq; } /** - * Returns the size of the sounds sample + * Sets the size (in bytes) of this audio sample. + * @param size Data size */ - inline void set_size( int size ) { - _size = size; - } + inline void set_size( size_t size ) { _size = size; } /** - * Returns the size of the sounds sample + * Returns the size (in bytes) of this audio sample. + * @return Data size */ - inline int get_size() const { return _size; } + inline size_t get_size() const { return _size; } /** - * Set position of the sound source (uses same coordinate system as opengl) + * Set the position of this sound relative to the base position. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @param pos Relative position of this sound */ - void set_relative_position( SGVec3f pos ); + void set_relative_position( const SGVec3f& pos ); /** - * Get position of the sound source (uses same coordinate system as opengl) + * Set the base position of this sound in Geodetic coordinates. + * @param pos Geodetic position */ - inline float *get_position() const { return toVec3f(_absolute_pos).data(); } + void set_position( const SGGeod& pos ); /** - * Set the position of the sound source + * Get the absolute position of this sound. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @return Absolute position */ - void set_position( SGGeod pos ); + float *get_position() const { return toVec3f(_absolute_pos).data(); } /** - * Set the orientation of the sound source + * Set the orientation of this sound. + * @param ori Quaternation containing the orientation information */ - void set_orientation( SGQuatd ori ); + void set_orientation( const SGQuatd& ori ); /** - * Set the relative direction of the sound source, both for direction - * and audio cut-off angles. + * Set direction of this sound relative to the orientation. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * @param dir Sound emission direction */ - void set_direction( SGVec3d dir ); + void set_direction( const SGVec3d& dir ); /** - * Define the audio cone parameters for directional audio + * Define the audio cone parameters for directional audio. + * Note: setting it to 1 degree will result in 0.5 degrees to both sides. + * @param inner Inner cone angle (0 - 360 degrees) + * @param outer Outer cone angle (0 - 360 degrees) + * @param gain Remaining gain at the edge of the outer cone (0.0 - 1.0) */ - inline void set_audio_cone( float inner, float outer, float gain ) { + void set_audio_cone( float inner, float outer, float gain ) { _inner_angle = inner; _outer_angle = outer; _outer_gain = gain; @@ -357,61 +338,133 @@ public: } /** - * Get the orientation of the sound source, the inner or outer angle - * or outer gain. + * Get the orientation vector of this sound. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * @return Orientaton vector */ float *get_orientation() { return _orivec.data(); } + + /** + * Get the inner angle of the audio cone. + * @return Inner angle in degrees + */ float get_innerangle() { return _inner_angle; } + + /** + * Get the outer angle of the audio cone. + * @return Outer angle in degrees + */ float get_outerangle() { return _outer_angle; } + + /** + * Get the remaining gain at the edge of the outer cone. + * @return Gain + */ float get_outergain() { return _outer_gain; } /** - * Set velocity of the sound source (uses same coordinate system as opengl) + * Set the velocity vector (in meters per second) of this sound. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * @param Velocity vector */ - inline void set_velocity( SGVec3d& vel ) { - _velocity = vel; - _changed = true; + inline void set_velocity( const SGVec3d& vel ) { + _velocity = vel; _changed = true; } /** - * Get velocity of the sound source (uses same coordinate system as opengl) + * Get velocity vector (in meters per second) of this sound. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * @return Velocity vector */ - inline float *get_velocity() { return toVec3f(_velocity).data(); } + float *get_velocity() { return toVec3f(_velocity).data(); } /** - * Set reference distance of sound (the distance where the gain - * will be half.) + * Set reference distance (in meters) of this sound. + * This is the distance where the gain will be half. + * @param dist Reference distance */ inline void set_reference_dist( float dist ) { _reference_dist = dist; _static_changed = true; } /** - * Get reference distance of sound (the distance where the gain - * will be half.) + * Get reference distance ((in meters) of this sound. + * This is the distance where the gain will be half. + * @return Reference distance */ inline float get_reference_dist() { return _reference_dist; } /** - * Set maximum distance of sound (the distance where the sound is - * no longer audible. + * Set maximum distance (in meters) of this sound. + * This is the distance where this sound is no longer audible. + * @param dist Maximum distance */ - void set_max_dist( float dist ) { + inline void set_max_dist( float dist ) { _max_dist = dist; _static_changed = true; } /** - * Get maximum istance of sound (the distance where the sound is - * no longer audible. + * Get maximum distance (in meters) of this sound. + * This is the distance where this sound is no longer audible. + * @return dist Maximum distance */ inline float get_max_dist() { return _max_dist; } /** - * Get the name of this sample + * Get the reference name of this audio sample. + * @return Sample name */ - inline std::string get_sample_name() { return _sample_name; } + inline std::string get_sample_name() const { return _refname; } + +private: + + // Position of the source sound. + SGVec3d _absolute_pos; // absolute position + SGVec3d _relative_pos; // position relative to the base position + SGVec3d _direction; // orientation offset + SGVec3d _velocity; // Velocity of the source sound. + + // The position and orientation of this sound + SGQuatd _orientation; // base orientation + SGVec3f _orivec; // orientation vector for OpenAL + SGGeod _base_pos; // base position + + std::string _refname; // name or file path + unsigned char *_data; + + // configuration values + int _format; + size_t _size; + int _freq; + + // Buffers hold sound data. + bool _valid_buffer; + unsigned int _buffer; + + // Sources are points emitting sound. + bool _valid_source; + unsigned int _source; + + // The orientation of this sound (direction and cut-off angles) + float _inner_angle; + float _outer_angle; + float _outer_gain; + + float _pitch; + float _volume; + float _master_volume; + float _reference_dist; + float _max_dist; + bool _loop; + + bool _playing; + bool _changed; + bool _static_changed; + bool _is_file; + + void update_absolute_position(); }; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index cbb137ef..10d406e0 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -4,8 +4,10 @@ // 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 @@ -218,13 +220,6 @@ void SGSoundMgr::unbind () _sources_in_use.clear(); } -void SGSoundMgr::update( double dt ) -{ - // nothing to do in the regular update, everything is done on the following - // function -} - - // run the audio scheduler void SGSoundMgr::update_late( double dt ) { if (_working) { @@ -420,7 +415,7 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) // sample name was not found in the buffer cache. if ( sample->is_file() ) { - unsigned int size; + size_t size; int freq, format; void *data; @@ -476,7 +471,7 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) } bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, - unsigned int *sz, int *frq ) + size_t *sz, int *frq ) { ALenum format; ALsizei size; @@ -514,7 +509,7 @@ bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, *dbuf = (void *)data; *fmt = (int)format; - *sz = (unsigned int)size; + *sz = (size_t)size; *frq = (int)freq; return true; diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index e2e2be40..3b4572be 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -4,8 +4,10 @@ // 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 @@ -96,7 +98,7 @@ public: void init(); void bind(); void unbind(); - void update(double dt); + void update(double dt) {}; void update_late(double dt); void suspend(); @@ -106,59 +108,92 @@ public: inline void reinit() { stop(); init(); } /** - * is audio working? + * 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; } /** - * add a sample group, return true if successful + * 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 string& refname ); /** - * remove a sample group, return true if successful + * 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 string& refname ); /** - * return true of the specified sound exists in the sound manager system + * 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 string& refname ); /** - * return a pointer to the SGSampleGroup if the specified sound - * exists in the sound manager system, otherwise return NULL + * 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 position of the listener (in opengl coordinates) + * Set the position of the sound manager. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @param pos OpenAL listener position */ void set_position( const SGVec3d& pos ) { _position = -pos; _changed = true; } - inline SGVec3f get_position() { return toVec3f(_position); } + /** + * Get the position of the sound manager. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * @return OpenAL listener position + */ + SGVec3f get_position() { return toVec3f(_position); } /** - * set the velocity direction of the listener (in opengl coordinates) + * Set the velocity vector of the sound manager + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * @param vel Velocity vector of the OpenAL listener */ void set_velocity( SGVec3d& dir ) { _velocity = dir; _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 OpenAL listener + */ inline SGVec3f get_velocity() { return toVec3f(_velocity); } /** - * set the orientation of the listener (in opengl coordinates) + * Set the orientation of the sound manager + * @param ori Quaternation containing the orientation information */ void set_orientation( SGQuatd ori ); + /** + * Get the orientation of the sound manager + * @return Quaternation containing the orientation information + */ inline const SGQuatd& get_orientation() { return _orientation; } - inline SGVec3f get_direction() { + /** + * 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]); } @@ -167,42 +202,62 @@ public: NO_BUFFER = (unsigned int)-1 }; - void set_volume( float v ); + /** + * 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 new OpenAL source id - * returns NO_SOURCE if no source is available + * Get a free OpenAL source-id + * @return NO_SOURCE if no source is available */ unsigned int request_source(); /** - * give back an OpenAL source id for further use. + * Free an OpenAL source-id for future use + * @param source OpenAL source-id to free */ void release_source( unsigned int source ); /** - * get a new OpenAL buffer id - * returns NO_BUFFER if loading of the buffer failed. + * Get a free OpenAL 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); /** - * give back an OpenAL source id for further use. + * Free an OpenAL buffer-id for this sample + * @param sample Pointer to an audio sample for which to free the buffer */ void release_buffer( SGSoundSample *sample ); - - /** - * returns true if the position has changed + * 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; } + /** + * 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 OpenAL 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, - unsigned int*size, int *freq ); - - + size_t *size, int *freq ); private: static int _alut_init; @@ -237,6 +292,7 @@ private: bool testForALCError(string s); bool testForALUTError(string s); bool testForError(void *p, string s); + void update_sample_config( SGSampleGroup *sound ); }; From 811cd0653f6f48f336563ceeea50a4a9db1775c2 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 17 Oct 2009 13:09:27 +0000 Subject: [PATCH 20/85] make sure update_late isn't executed when dt=0 --- simgear/sound/sample_openal.cxx | 3 +++ simgear/sound/soundmgr_openal.cxx | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 191877ae..d82c42a2 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -183,4 +183,7 @@ void SGSoundSample::update_absolute_position() { orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; _absolute_pos = -SGVec3d::fromGeod(_base_pos) -orient.rotate(SGVec3d::e1()); + + float vel = length(_velocity); + _velocity = toVec3d(_orivec * vel); } diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 10d406e0..1ab11035 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -222,7 +222,7 @@ void SGSoundMgr::unbind () // run the audio scheduler void SGSoundMgr::update_late( double dt ) { - if (_working) { + if (_working && dt != 0.0) { alcSuspendContext(_context); sample_group_map_iterator sample_grp_current = _sample_groups.begin(); From e6bfe7d40c41c003b2fe41385de552c015f27bb2 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 18 Oct 2009 08:48:34 +0000 Subject: [PATCH 21/85] revert to previous version --- simgear/structure/SGAtomic.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/structure/SGAtomic.cxx b/simgear/structure/SGAtomic.cxx index a31478f5..e7dd76c2 100644 --- a/simgear/structure/SGAtomic.cxx +++ b/simgear/structure/SGAtomic.cxx @@ -20,7 +20,7 @@ #include "SGAtomic.hxx" -#if !defined(SGATOMIC_USE_GCC4_BUILTINS) && defined (__i386__) +#if defined(SGATOMIC_USE_GCC4_BUILTINS) && defined (__i386__) // Usually the apropriate functions are inlined by gcc. // But if gcc is called with something aequivalent to -march=i386, From 0d5634475c189169a12a89b64e565120cd89d4b8 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 18 Oct 2009 09:34:24 +0000 Subject: [PATCH 22/85] Don't delete the sample data if it wasn't constructed as a file. It's now deleted when calling free_data() by the owner or in the destructor. --- simgear/sound/sample_openal.cxx | 4 ++++ simgear/sound/sample_openal.hxx | 6 +++--- simgear/sound/soundmgr_openal.cxx | 6 +++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index d82c42a2..5fc257cc 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -151,6 +151,10 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format // destructor SGSoundSample::~SGSoundSample() { + if (_data != NULL) { + delete _data; + _data = NULL; + } } void SGSoundSample::set_orientation( const SGQuatd& ori ) { diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 448e0812..f673f304 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -61,15 +61,15 @@ public: * Constructor * @param path Path name to sound * @param file File name of sound - should usually be true unless you want to manipulate the data - later.) + Buffer data is freed by the sample group */ SGSoundSample( const char *path, const char *file ); /** * Constructor. * @param data Pointer to a memory buffer containing this audio sample data - buffer data is freed by this audio sample manager. + The application may free the data by calling free_data(), otherwise it + will be resident untill the class is destroyed. * @param len Byte length of array * @param freq Frequency of the provided data (bytes per second) * @param format OpenAL format id of the data diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 1ab11035..45bd022f 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -436,7 +436,11 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) ALsizei size = sample->get_size(); ALsizei freq = sample->get_frequency(); alBufferData( buffer, format, data, size, freq ); - sample->free_data(); + + // If this sample was read from a file we have all the information + // needed to read it again. For data buffers provided by the + // program we don't; so don't delete it's data. + if (sample->is_file()) sample->free_data(); if ( !testForALError("buffer add data") ) { sample->set_buffer(buffer); From 7287509feff5372057cbfda468c841fa0a8cdef6 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 18 Oct 2009 13:44:38 +0000 Subject: [PATCH 23/85] Start the sound manager in a deactived state. This means the code now has to activate it explicitly when desired. A non active state means the update function will no be executed. --- simgear/sound/sample_group.hxx | 2 -- simgear/sound/soundmgr_openal.cxx | 43 +++++++++++++------------------ simgear/sound/soundmgr_openal.hxx | 16 +++++++++--- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index e98596c3..a4e7b653 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -35,8 +35,6 @@ #if defined(__APPLE__) # include -#elif defined(_WIN32) -# include #else # include #endif diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 45bd022f..22c486da 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -57,6 +57,7 @@ int SGSoundMgr::_alut_init = 0; // constructor SGSoundMgr::SGSoundMgr() : _working(false), + _active(false), _changed(true), _volume(0.0), _device(NULL), @@ -162,10 +163,11 @@ void SGSoundMgr::init() { } } -// suspend the sound manager +// stop the sound manager void SGSoundMgr::stop() { if (_working) { _working = false; + _active = false; // clear any OpenAL buffers before shutting down buffer_map_iterator buffers_current; @@ -177,25 +179,34 @@ void SGSoundMgr::stop() { _buffers.erase( buffers_current ); } - _context = alcGetCurrentContext(); - _device = alcGetContextsDevice(_context); - alcMakeContextCurrent(NULL); alcDestroyContext(_context); alcCloseDevice(_device); } } void SGSoundMgr::suspend() { - if (_working) { + if (_active) { 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->suspend(); } + _active = false; } } +void SGSoundMgr::resume() { + if (!_active) { + 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 () { @@ -222,9 +233,7 @@ void SGSoundMgr::unbind () // run the audio scheduler void SGSoundMgr::update_late( double dt ) { - if (_working && dt != 0.0) { - alcSuspendContext(_context); - + if (_active) { 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 ) { @@ -241,26 +250,10 @@ void SGSoundMgr::update_late( double dt ) { testForALError("update"); _changed = false; } - alcProcessContext(_context); } } - -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(); - } - } -} - - -// add a sampel group, return true if successful +// 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 ); diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 3b4572be..1c05024d 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -49,10 +49,6 @@ # include # include # include -#elif defined(_WIN32) -# include -# include -# include #else # include # include @@ -113,6 +109,17 @@ public: */ inline bool is_working() const { return _working; } + /** + * Set the sound manager to a working condition. + */ + inline void activate() { _active = true; } + + /** + * 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 (_working && _active); } + /** * Register a sample group to the sound manager. * @para sgrp Pointer to a sample group to add @@ -263,6 +270,7 @@ private: static int _alut_init; bool _working; + bool _active; bool _changed; float _volume; From b3bc36b2534d05c37e5f687f8deccfc9f8659abe Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 18 Oct 2009 13:55:21 +0000 Subject: [PATCH 24/85] restore some part of the code to prevent an untwanted segmentationf fault. --- simgear/sound/soundmgr_openal.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 22c486da..4ff36eee 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -179,6 +179,8 @@ void SGSoundMgr::stop() { _buffers.erase( buffers_current ); } + _context = alcGetCurrentContext(); + _device = alcGetContextsDevice(_context); alcDestroyContext(_context); alcCloseDevice(_device); } From ae58f89fbfd7994079c89232abd81528ce14e083 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 18 Oct 2009 18:52:15 +0000 Subject: [PATCH 25/85] sigh, forgot another alut* at the wrong place. --- simgear/sound/soundmgr_openal.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 4ff36eee..b8c11928 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -500,7 +500,7 @@ bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, ALenum error = alGetError(); if ( error != AL_NO_ERROR ) { string msg = "Failed to load wav file: "; - msg.append(alutGetErrorString(error)); + msg.append(alGetErrorString(error)); throw sg_io_exception(msg.c_str(), sg_location(samplepath)); return false; } From 31dd77c6949818f8b3b51832bbf06038ea4b7427 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 19 Oct 2009 10:40:13 +0000 Subject: [PATCH 26/85] do not yet add the relative sound position to the absolute position, it's generating NaN's at the moment. Fix a bunch of other small bugs --- simgear/sound/openal_test1.cxx | 4 ++++ simgear/sound/sample_group.cxx | 10 ++++------ simgear/sound/sample_group.hxx | 2 ++ simgear/sound/sample_openal.cxx | 22 ++++++++++++++++------ simgear/sound/sample_openal.hxx | 1 + simgear/sound/soundmgr_openal.cxx | 19 ++++++++++--------- simgear/sound/soundmgr_openal.hxx | 4 ++++ 7 files changed, 41 insertions(+), 21 deletions(-) diff --git a/simgear/sound/openal_test1.cxx b/simgear/sound/openal_test1.cxx index 5342ddf1..94e3e451 100644 --- a/simgear/sound/openal_test1.cxx +++ b/simgear/sound/openal_test1.cxx @@ -14,6 +14,10 @@ static unsigned int sleep(unsigned int secs) { return 0; } # include # include # include +#elif defined(OPENALSDK) +# include +# include +# include #else # include # include diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 1c63e3ee..815fb460 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -111,7 +111,7 @@ void SGSampleGroup::update( double dt ) { if ( !_active ) return; - // testForALError("start of update!!\n"); + testForALError("start of update!!\n"); sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); @@ -141,7 +141,7 @@ void SGSampleGroup::update( double dt ) { alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE ); alSourcei( source, AL_LOOPING, looping ); - alSourcef( source, AL_ROLLOFF_FACTOR, 1.2 ); + alSourcef( source, AL_ROLLOFF_FACTOR, 1.0 ); alSourcePlay( source ); testForALError("sample play"); } else { @@ -247,8 +247,7 @@ SGSampleGroup::suspend () SGSoundSample *sample = sample_current->second; if ( sample->is_valid_source() && sample->is_playing() ) { - unsigned int source = sample->get_source(); - alSourcePause( source ); + alSourcePause( sample->get_source() ); } } testForALError("suspend"); @@ -264,8 +263,7 @@ SGSampleGroup::resume () SGSoundSample *sample = sample_current->second; if ( sample->is_valid_source() && sample->is_playing() ) { - unsigned int source = sample->get_source(); - alSourcePlay( source ); + alSourcePlay( sample->get_source() ); } } testForALError("resume"); diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index a4e7b653..88f86bcd 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -35,6 +35,8 @@ #if defined(__APPLE__) # include +#elif defined(OPENALSDK) +# include #else # include #endif diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 5fc257cc..0423f2c4 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -26,6 +26,8 @@ # include #endif +#include // rand() + #include #include #include @@ -48,7 +50,7 @@ SGSoundSample::SGSoundSample() : _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGGeod()), - _refname(""), + _refname(random_string()), _data(NULL), _format(AL_FORMAT_MONO8), _size(0), @@ -122,6 +124,7 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGGeod()), + _refname(random_string()), _data(data), _format(format), _size(len), @@ -144,7 +147,6 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format _static_changed(true), _is_file(false) { - _refname = "unknown, data supplied by caller"; SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); } @@ -186,8 +188,16 @@ void SGSoundSample::update_absolute_position() { _orivec = -toVec3f(orient.rotate(_direction)); orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; - _absolute_pos = -SGVec3d::fromGeod(_base_pos) -orient.rotate(SGVec3d::e1()); - - float vel = length(_velocity); - _velocity = toVec3d(_orivec * vel); + _absolute_pos = -SGVec3d::fromGeod(_base_pos); // -orient.rotate(SGVec3d::e1()); +} + +string SGSoundSample::random_string() { + static const char *r = "0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + string rstr; + for (int i=0; i<10; i++) { + rstr.push_back( r[rand() % strlen(r)] ); + } + + return rstr; } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index f673f304..017cdc93 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -465,6 +465,7 @@ private: bool _is_file; void update_absolute_position(); + string random_string(); }; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index b8c11928..e4cf60ff 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -120,7 +120,7 @@ void SGSoundMgr::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; - alListenerf( AL_GAIN, 0.2f ); + alListenerf( AL_GAIN, 0.0f ); alListenerfv( AL_ORIENTATION, _at_up_vec ); alListenerfv( AL_POSITION, SGVec3f::zeros().data() ); alListenerfv( AL_VELOCITY, SGVec3f::zeros().data() ); @@ -170,14 +170,14 @@ void SGSoundMgr::stop() { _active = false; // clear any OpenAL buffers before shutting down - buffer_map_iterator buffers_current; - while(_buffers.size()){ - buffers_current = _buffers.begin(); + 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; ALuint buffer = ref.id; alDeleteBuffers(1, &buffer); - _buffers.erase( buffers_current ); } + _buffers.clear(); _context = alcGetCurrentContext(); _device = alcGetContextsDevice(_context); @@ -435,7 +435,7 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) // If this sample was read from a file we have all the information // needed to read it again. For data buffers provided by the // program we don't; so don't delete it's data. - if (sample->is_file()) sample->free_data(); + if ( sample->is_file() ) sample->free_data(); if ( !testForALError("buffer add data") ) { sample->set_buffer(buffer); @@ -452,7 +452,6 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) 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 @@ -463,7 +462,7 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) buffer_it->second.refctr--; if (buffer_it->second.refctr == 0) { ALuint buffer = buffer_it->second.id; - _buffers.erase( buffer_it ); + _buffers.erase( sample_name ); alDeleteBuffers(1, &buffer); testForALError("release buffer"); } @@ -472,6 +471,8 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, size_t *sz, int *frq ) { + if ( !_working ) return false; + ALenum format; ALsizei size; ALsizei freq; @@ -500,7 +501,7 @@ bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, ALenum error = alGetError(); if ( error != AL_NO_ERROR ) { string msg = "Failed to load wav file: "; - msg.append(alGetErrorString(error)); + msg.append(alGetString(error)); throw sg_io_exception(msg.c_str(), sg_location(samplepath)); return false; } diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 1c05024d..ac94788f 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -49,6 +49,10 @@ # include # include # include +#elif defined(OPENALSDK) +# include +# include +# include #else # include # include From b3e16ce8e0941365485116dff1113b3d5d3904e9 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 19 Oct 2009 14:09:21 +0000 Subject: [PATCH 27/85] use auto_ptr instead --- simgear/sound/sample_openal.cxx | 9 +++------ simgear/sound/sample_openal.hxx | 13 ++++++++----- simgear/sound/soundmgr_openal.cxx | 5 ++++- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 0423f2c4..a4efd08a 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -116,7 +116,8 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : } // constructor -SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format ) : +SGSoundSample::SGSoundSample( std::auto_ptr& data, + int len, int freq, int format ) : _absolute_pos(SGVec3d::zeros()), _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), @@ -125,7 +126,7 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format _orivec(SGVec3f::zeros()), _base_pos(SGGeod()), _refname(random_string()), - _data(data), + _data(data.release()), _format(format), _size(len), _freq(freq), @@ -153,10 +154,6 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format // destructor SGSoundSample::~SGSoundSample() { - if (_data != NULL) { - delete _data; - _data = NULL; - } } void SGSoundSample::set_orientation( const SGQuatd& ori ) { diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 017cdc93..ae985eba 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -35,6 +35,7 @@ #endif #include +#include #include #include @@ -74,7 +75,7 @@ public: * @param freq Frequency of the provided data (bytes per second) * @param format OpenAL format id of the data */ - SGSoundSample( unsigned char *data, int len, int freq, + SGSoundSample( std::auto_ptr& data, int len, int freq, int format = AL_FORMAT_MONO8 ); /** @@ -152,19 +153,21 @@ public: * sSt the data associated with this audio sample * @param data Pointer to a memory block containg this audio sample data. */ - inline void set_data( unsigned char* data ) { _data = data; } + inline void set_data( std::auto_ptr& data ) { + _data = data; + } /** * Return the data associated with this audio sample. * @return A pointer to this sound data of this audio sample. */ - inline void* get_data() const { return _data; } + inline void* get_data() const { return _data.get(); } /** * Free the data associated with this audio sample */ void free_data() { - if (_data != NULL) { delete _data; _data = NULL; } + delete _data.release(); } /** @@ -432,7 +435,7 @@ private: SGGeod _base_pos; // base position std::string _refname; // name or file path - unsigned char *_data; + std::auto_ptr _data; // configuration values int _format; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index e4cf60ff..eb0a76e4 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -415,7 +415,10 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) void *data; load(sample_name, &data, &format, &size, &freq); - sample->set_data( (unsigned char *)data ); + std::auto_ptr ptr; + ptr.reset((unsigned char *)data); + + sample->set_data( ptr ); sample->set_frequency( freq ); sample->set_format( format ); sample->set_size( size ); From feba9024eb791f3fca56405bdff728cd103ace28 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 20 Oct 2009 11:31:00 +0000 Subject: [PATCH 28/85] Fix a pause situation where more code was executed than expected. Unbind an OpenAL buffer from an OpenAL source when requested to stop playing. --- simgear/sound/sample_group.cxx | 31 ++++++++++++++++++++++++------ simgear/sound/sample_group.hxx | 6 +++++- simgear/sound/soundmgr_openal.cxx | 32 ++++++++++++++++++------------- simgear/sound/soundmgr_openal.hxx | 4 ++-- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 815fb460..5d460be1 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -67,6 +67,7 @@ SGSampleGroup::SGSampleGroup () : _smgr(NULL), _refname(""), _active(false), + _pause(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), @@ -79,6 +80,7 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _smgr(smgr), _refname(refname), _active(false), + _pause(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), @@ -109,10 +111,28 @@ SGSampleGroup::~SGSampleGroup () void SGSampleGroup::update( double dt ) { - if ( !_active ) return; + if ( !_active || _pause ) return; testForALError("start of update!!\n"); + // Delete any OpenAL buffers that might still be in use. + unsigned int size = _removed_samples.size(); + for (unsigned int i=0; iget_source(), AL_SOURCE_STATE, &result ); + if ( result == AL_STOPPED ) { + ALuint buffer = sample->get_buffer(); + alDeleteBuffers( 1, &buffer ); + testForALError("buffer remove"); + _removed_samples.erase( _removed_samples.begin()+i ); + size--; + continue; + } + i++; + } + sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { @@ -203,9 +223,8 @@ bool SGSampleGroup::remove( const string &refname ) { return false; } - // remove the sources buffer - _smgr->release_buffer( sample_it->second ); - _samples.erase( refname ); + _removed_samples.push_back( sample_it->second ); + _samples.erase( sample_it ); return true; } @@ -240,7 +259,7 @@ SGSoundSample *SGSampleGroup::find( const string &refname ) { void SGSampleGroup::suspend () { - _active = false; + _pause = true; sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { @@ -267,7 +286,7 @@ SGSampleGroup::resume () } } testForALError("resume"); - _active = true; + _pause = false; } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 88f86bcd..7a3dff70 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -42,6 +42,7 @@ #endif #include +#include #include #include @@ -55,7 +56,8 @@ using std::map; using std::string; -typedef map < string, SGSharedPtr > sample_map; +typedef SGSharedPtr SGSoundSample_ptr; +typedef map < string, SGSoundSample_ptr > sample_map; typedef sample_map::iterator sample_map_iterator; typedef sample_map::const_iterator const_sample_map_iterator; @@ -214,6 +216,7 @@ protected: bool _active; private: + bool _pause; float _volume; bool _tied_to_listener; @@ -222,6 +225,7 @@ private: SGGeod _position; sample_map _samples; + std::vector _removed_samples; bool testForALError(string s); bool testForError(void *p, string s); diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index eb0a76e4..ee5320da 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -154,12 +154,17 @@ void SGSoundMgr::init() { if (_free_sources.size() == 0) { SG_LOG(SG_GENERAL, SG_ALERT, "Unable to grab any OpenAL sources!"); } +} - 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->activate(); +void SGSoundMgr::activate() { + if ( _working ) { + _active = true; + 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->activate(); + } } } @@ -187,7 +192,7 @@ void SGSoundMgr::stop() { } void SGSoundMgr::suspend() { - if (_active) { + 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 ) { @@ -199,7 +204,7 @@ void SGSoundMgr::suspend() { } void SGSoundMgr::resume() { - if (!_active) { + 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 ) { @@ -225,7 +230,7 @@ void SGSoundMgr::unbind () // delete free sources for (unsigned int i=0; i<_free_sources.size(); i++) { - ALuint source = _free_sources.at( i ); + ALuint source = _free_sources[i]; alDeleteSources( 1 , &source ); } @@ -264,7 +269,7 @@ bool SGSoundMgr::add( SGSampleGroup *sgrp, const string& refname ) return false; } - if (_working) sgrp->activate(); + if (_active) sgrp->activate(); _sample_groups[refname] = sgrp; return true; @@ -280,7 +285,7 @@ bool SGSoundMgr::remove( const string &refname ) return false; } - _sample_groups.erase( refname ); + _sample_groups.erase( sample_grp_it ); return true; } @@ -386,8 +391,9 @@ void SGSoundMgr::release_source( unsigned int source ) alSourceStop( source ); testForALError("release source"); - _free_sources.push_back(source); - _sources_in_use.erase(it, it+1); + alSourcei( source, AL_BUFFER, 0 ); + _free_sources.push_back( source ); + _sources_in_use.erase( it ); } } @@ -465,8 +471,8 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) buffer_it->second.refctr--; if (buffer_it->second.refctr == 0) { ALuint buffer = buffer_it->second.id; - _buffers.erase( sample_name ); alDeleteBuffers(1, &buffer); + _buffers.erase( buffer_it ); testForALError("release buffer"); } } diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index ac94788f..5d86c6be 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -116,13 +116,13 @@ public: /** * Set the sound manager to a working condition. */ - inline void activate() { _active = true; } + 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 (_working && _active); } + inline bool is_active() const { return _active; } /** * Register a sample group to the sound manager. From ea513d392e050578fcc017e0c888a3374f0dcead Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 21 Oct 2009 16:52:02 +0000 Subject: [PATCH 29/85] Updates to the test utilies. --- simgear/sound/Makefile.am | 27 ++++++++++++++------------- simgear/sound/openal_test1.cxx | 2 ++ simgear/sound/openal_test2.cxx | 21 +++++++++++---------- simgear/sound/sample_openal.cxx | 4 +++- simgear/sound/xmlsound.cxx | 14 +++++++------- 5 files changed, 37 insertions(+), 31 deletions(-) diff --git a/simgear/sound/Makefile.am b/simgear/sound/Makefile.am index 57f3161a..67d91110 100644 --- a/simgear/sound/Makefile.am +++ b/simgear/sound/Makefile.am @@ -18,21 +18,22 @@ libsgsound_a_SOURCES = \ soundmgr_openal.cxx \ xmlsound.cxx -#noinst_PROGRAMS = openal_test1 openal_test2 +check_PROGRAMS = openal_test1 openal_test2 -#openal_test1_SOURCES = openal_test1.cxx -#openal_test2_SOURCES = openal_test2.cxx +openal_test1_SOURCES = openal_test1.cxx +openal_test2_SOURCES = openal_test2.cxx -#openal_test1_LDADD = \ -# $(top_builddir)/simgear/debug/libsgdebug.a \ -# $(openal_LIBS) +openal_test1_LDADD = \ + $(top_builddir)/simgear/debug/libsgdebug.a \ + $(openal_LIBS) -#openal_test2_LDADD = \ -# libsgsound.a \ -# $(top_builddir)/simgear/structure/libsgstructure.a \ -# $(top_builddir)/simgear/timing/libsgtiming.a \ -# $(top_builddir)/simgear/debug/libsgdebug.a \ -# $(top_builddir)/simgear/misc/libsgmisc.a \ -# $(openal_LIBS) +openal_test2_LDADD = \ + libsgsound.a \ + $(top_builddir)/simgear/structure/libsgstructure.a \ + $(top_builddir)/simgear/timing/libsgtiming.a \ + $(top_builddir)/simgear/debug/libsgdebug.a \ + $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/math/libsgmath.a \ + $(openal_LIBS) INCLUDES = -I$(top_srcdir) -DSRC_DIR=\"$(top_srcdir)/simgear/sound\" diff --git a/simgear/sound/openal_test1.cxx b/simgear/sound/openal_test1.cxx index 94e3e451..dd2a77f0 100644 --- a/simgear/sound/openal_test1.cxx +++ b/simgear/sound/openal_test1.cxx @@ -50,6 +50,8 @@ int main( int argc, char *argv[] ) { ALCdevice *dev; ALCcontext *context; + sglog().setLogLevels( SG_ALL, SG_ALERT ); + // initialize OpenAL if ( (dev = alcOpenDevice( NULL )) != NULL && ( context = alcCreateContext( dev, NULL )) != NULL ) { diff --git a/simgear/sound/openal_test2.cxx b/simgear/sound/openal_test2.cxx index 46a0f621..ac65e555 100644 --- a/simgear/sound/openal_test2.cxx +++ b/simgear/sound/openal_test2.cxx @@ -21,15 +21,16 @@ int main( int argc, char *argv[] ) { smgr->bind(); smgr->init(); - smgr->set_volume(0.9); sgr = smgr->find("default", true); + smgr->set_volume(0.9); + smgr->activate(); SGSoundSample *sample1 = new SGSoundSample( SRC_DIR, "jet.wav" ); sample1->set_volume(1.0); sample1->set_pitch(1.0); sample1->play_looped(); sgr->add(sample1, "sound1"); - smgr->update(1.0); + smgr->update_late(1.0); printf("playing sample1\n"); sleep(1); @@ -38,7 +39,7 @@ int main( int argc, char *argv[] ) { sample2->set_pitch(0.4); sample2->play_looped(); sgr->add(sample2, "sound2"); - smgr->update(1.0); + smgr->update_late(1.0); printf("playing sample2\n"); sleep(1); @@ -47,7 +48,7 @@ int main( int argc, char *argv[] ) { sample3->set_pitch(0.8); sample3->play_looped(); sgr->add(sample3, "sound3"); - smgr->update(1.0); + smgr->update_late(1.0); printf("playing sample3\n"); sleep(1); @@ -56,7 +57,7 @@ int main( int argc, char *argv[] ) { sample4->set_pitch(1.2); sample4->play_looped(); sgr->add(sample4, "sound4"); - smgr->update(1.0); + smgr->update_late(1.0); printf("playing sample4\n"); sleep(1); @@ -65,7 +66,7 @@ int main( int argc, char *argv[] ) { sample5->set_pitch(1.6); sample5->play_looped(); sgr->add(sample5, "sound5"); - smgr->update(1.0); + smgr->update_late(1.0); printf("playing sample5\n"); sleep(1); @@ -74,24 +75,24 @@ int main( int argc, char *argv[] ) { sample6->set_pitch(2.0); sample6->play_looped(); sgr->add(sample6, "sound6"); - smgr->update(1.0); + smgr->update_late(1.0); printf("playing sample6\n"); sleep(1); for (int i=0; i<10; i++) { sleep(1); - smgr->update(1); + smgr->update_late(1); } sgr->stop("sound1"); sgr->stop("sound2"); sgr->stop("sound3"); sleep(0.5); - sgr->update(0.5); + smgr->update_late(0.5); sgr->stop("sound4"); sgr->stop("sound5"); sgr->stop("sound6"); - sgr->update(1); + smgr->update_late(1); sleep(1); smgr->unbind(); diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index a4efd08a..92acd8ad 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -183,9 +183,11 @@ void SGSoundSample::set_position( const SGGeod& pos ) { void SGSoundSample::update_absolute_position() { SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; _orivec = -toVec3f(orient.rotate(_direction)); +printf("ori: %f %f %f\n", _orivec[0], _orivec[1], _orivec[2]); - orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; + orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; _absolute_pos = -SGVec3d::fromGeod(_base_pos); // -orient.rotate(SGVec3d::e1()); +printf("pos: %f %f %f\n", _absolute_pos[0], _absolute_pos[1], _absolute_pos[2]); } string SGSoundSample::random_string() { diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 4edad960..54f3e4b1 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -171,7 +171,7 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, } - float reference_dist = node->getDoubleValue("reference-dist", 500.0); + float reference_dist = node->getDoubleValue("reference-dist", 50.0); float max_dist = node->getDoubleValue("max-dist", 3000.0); // @@ -241,9 +241,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, // Orientation // SGVec3d dir = SGVec3d::zeros(); - float inner, outer, outer_gain; - inner = outer = 360.0; - outer_gain = 0.0; + float inner = 360.0; + float outer = 360.0; + float outer_gain = 0.0;; prop = node->getChild("orientation"); if ( prop != NULL ) { dir = SGVec3d(-prop->getDoubleValue("x", 0.0), @@ -261,11 +261,11 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, _sample = new SGSoundSample( path.c_str(), node->getStringValue("path", "")); _sample->set_relative_position( offset_pos ); _sample->set_direction( dir ); - _sample->set_audio_cone(inner, outer, outer_gain); + _sample->set_audio_cone( inner, outer, outer_gain ); _sample->set_reference_dist( reference_dist ); _sample->set_max_dist( max_dist ); - _sample->set_volume(v); - _sample->set_pitch(p); + _sample->set_volume( v ); + _sample->set_pitch( p ); _sgrp->add( _sample, _name ); } From 796427092998420fc2dd9dab8a12724479f27aab Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 22 Oct 2009 08:32:04 +0000 Subject: [PATCH 30/85] fix a memory leak and add some temporary debugging statements. --- simgear/sound/openal_test1.cxx | 2 ++ simgear/sound/sample_group.cxx | 8 +++++--- simgear/sound/sample_openal.cxx | 4 ++-- simgear/sound/soundmgr_openal.cxx | 8 ++++++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/simgear/sound/openal_test1.cxx b/simgear/sound/openal_test1.cxx index dd2a77f0..66678f8b 100644 --- a/simgear/sound/openal_test1.cxx +++ b/simgear/sound/openal_test1.cxx @@ -50,6 +50,7 @@ int main( int argc, char *argv[] ) { ALCdevice *dev; ALCcontext *context; + alutInit(&argc, argv); sglog().setLogLevels( SG_ALL, SG_ALERT ); // initialize OpenAL @@ -164,6 +165,7 @@ int main( int argc, char *argv[] ) { alSourcePlay( source ); sleep(10); + alutExit(); return 0; } diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 5d460be1..cab19896 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -175,8 +175,8 @@ void SGSampleGroup::update( double dt ) { if ( !sample->is_playing() ) { // a request to stop playing the sound has been filed. - sample->no_valid_source(); sample->stop(); + sample->no_valid_source(); _smgr->release_source( sample->get_source() ); } else { update_sample_config( sample ); @@ -191,9 +191,10 @@ void SGSampleGroup::update( double dt ) { alGetSourcei( source, AL_SOURCE_STATE, &result ); if ( result == AL_STOPPED ) { // sample is stoped because it wasn't looping - sample->no_valid_source(); sample->stop(); + sample->no_valid_source(); _smgr->release_source( source ); + _smgr->release_buffer( sample ); } } testForALError("update"); @@ -223,7 +224,8 @@ bool SGSampleGroup::remove( const string &refname ) { return false; } - _removed_samples.push_back( sample_it->second ); + if ( sample_it->second->is_valid_buffer() ) + _removed_samples.push_back( sample_it->second ); _samples.erase( sample_it ); return true; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 92acd8ad..c5ced562 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -183,11 +183,11 @@ void SGSoundSample::set_position( const SGGeod& pos ) { void SGSoundSample::update_absolute_position() { SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; _orivec = -toVec3f(orient.rotate(_direction)); -printf("ori: %f %f %f\n", _orivec[0], _orivec[1], _orivec[2]); +//printf("ori: %f %f %f\n", _orivec[0], _orivec[1], _orivec[2]); orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; _absolute_pos = -SGVec3d::fromGeod(_base_pos); // -orient.rotate(SGVec3d::e1()); -printf("pos: %f %f %f\n", _absolute_pos[0], _absolute_pos[1], _absolute_pos[2]); +//printf("pos: %f %f %f\n", _absolute_pos[0], _absolute_pos[1], _absolute_pos[2]); } string SGSoundSample::random_string() { diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index ee5320da..9a49d547 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -94,6 +94,7 @@ SGSoundMgr::~SGSoundMgr() { // initialize the sound manager void SGSoundMgr::init() { +printf("Initializing OpenAL sound manager\n"); SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" ); ALCdevice *device = alcOpenDevice(_devname); @@ -114,6 +115,8 @@ void SGSoundMgr::init() { return; } + if (_context != NULL) + SG_LOG(SG_GENERAL, SG_ALERT, "context is already assigned"); _context = context; _working = true; @@ -171,6 +174,7 @@ void SGSoundMgr::activate() { // stop the sound manager void SGSoundMgr::stop() { if (_working) { +printf("Stopping Sound Manager\n"); _working = false; _active = false; @@ -193,6 +197,7 @@ void SGSoundMgr::stop() { void SGSoundMgr::suspend() { if (_working) { +printf("SoundManager suspend\n"); 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 ) { @@ -205,6 +210,7 @@ void SGSoundMgr::suspend() { void SGSoundMgr::resume() { if (_working) { +printf("SoundManager resume\n"); 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 ) { @@ -217,6 +223,7 @@ void SGSoundMgr::resume() { void SGSoundMgr::bind () { +printf("SoundManager bind\n"); _free_sources.clear(); _free_sources.reserve( MAX_SOURCES ); _sources_in_use.clear(); @@ -226,6 +233,7 @@ void SGSoundMgr::bind () void SGSoundMgr::unbind () { +printf("SoundManager unbind\n"); _sample_groups.clear(); // delete free sources From 5d731ad8c39abf3e41f6b84901669cbab6dc8ed8 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 22 Oct 2009 08:58:40 +0000 Subject: [PATCH 31/85] a few more temporarty debugging statements --- simgear/sound/sample_group.cxx | 5 +++-- simgear/sound/soundmgr_openal.cxx | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index cab19896..ed4d466b 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -146,7 +146,6 @@ void SGSampleGroup::update( double dt ) { continue; // start playing the sample - ALboolean looping = sample->get_looping() ? AL_TRUE : AL_FALSE; ALuint buffer = sample->get_buffer(); ALuint source = _smgr->request_source(); if (alIsSource(source) == AL_TRUE && alIsBuffer(buffer) == AL_TRUE) @@ -159,9 +158,10 @@ void SGSampleGroup::update( double dt ) { sample->set_source( source ); update_sample_config( sample ); - alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE ); + ALboolean looping = sample->get_looping() ? AL_TRUE : AL_FALSE; alSourcei( source, AL_LOOPING, looping ); alSourcef( source, AL_ROLLOFF_FACTOR, 1.0 ); + alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE ); alSourcePlay( source ); testForALError("sample play"); } else { @@ -169,6 +169,7 @@ void SGSampleGroup::update( double dt ) { SG_LOG( SG_GENERAL, SG_ALERT, "No such buffer!\n"); // sample->no_valid_source(); // sadly, no free source available at this time +printf("No free source found."); } } else if ( sample->is_valid_source() && sample->has_changed() ) { diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 9a49d547..b22a1835 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -154,6 +154,7 @@ printf("Initializing OpenAL sound manager\n"); else break; } +printf("%i free sources found\n", _free_sources.size() ); if (_free_sources.size() == 0) { SG_LOG(SG_GENERAL, SG_ALERT, "Unable to grab any OpenAL sources!"); } From cd8e7bbdca855089c788933652e36e71a97427f1 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 22 Oct 2009 12:07:56 +0000 Subject: [PATCH 32/85] should use free instead of delete for malloced data. --- simgear/sound/sample_openal.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index ae985eba..070cba89 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -167,7 +167,7 @@ public: * Free the data associated with this audio sample */ void free_data() { - delete _data.release(); + free( _data.release() ); } /** From 6a7b8858918e90842ecce5d59026a20364799345 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 22 Oct 2009 12:10:35 +0000 Subject: [PATCH 33/85] revert some test code --- simgear/sound/sample_openal.cxx | 5 +++-- simgear/sound/xmlsound.cxx | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index c5ced562..2ec3c96d 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -182,8 +182,9 @@ void SGSoundSample::set_position( const SGGeod& pos ) { void SGSoundSample::update_absolute_position() { SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; - _orivec = -toVec3f(orient.rotate(_direction)); -//printf("ori: %f %f %f\n", _orivec[0], _orivec[1], _orivec[2]); + _orivec = -toVec3f(orient.rotate(-SGVec3d::e1())); +printf("ori: %f %f %f\n", _orivec[0], _orivec[1], _orivec[2]); +printf("vel: %f %f %f\n", _velocity[0], _velocity[1], _velocity[2]); orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; _absolute_pos = -SGVec3d::fromGeod(_base_pos); // -orient.rotate(SGVec3d::e1()); diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 54f3e4b1..39cfdfe0 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -171,7 +171,7 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, } - float reference_dist = node->getDoubleValue("reference-dist", 50.0); + float reference_dist = node->getDoubleValue("reference-dist", 500.0); float max_dist = node->getDoubleValue("max-dist", 3000.0); // @@ -243,7 +243,7 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGVec3d dir = SGVec3d::zeros(); float inner = 360.0; float outer = 360.0; - float outer_gain = 0.0;; + float outer_gain = 0.0; prop = node->getChild("orientation"); if ( prop != NULL ) { dir = SGVec3d(-prop->getDoubleValue("x", 0.0), From 5f9befebaed1c185a196acd709b2677247461a0f Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 22 Oct 2009 12:11:06 +0000 Subject: [PATCH 34/85] .. and remove some debugging code --- simgear/sound/sample_openal.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 2ec3c96d..91b08527 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -183,12 +183,9 @@ void SGSoundSample::set_position( const SGGeod& pos ) { void SGSoundSample::update_absolute_position() { SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; _orivec = -toVec3f(orient.rotate(-SGVec3d::e1())); -printf("ori: %f %f %f\n", _orivec[0], _orivec[1], _orivec[2]); -printf("vel: %f %f %f\n", _velocity[0], _velocity[1], _velocity[2]); orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; _absolute_pos = -SGVec3d::fromGeod(_base_pos); // -orient.rotate(SGVec3d::e1()); -//printf("pos: %f %f %f\n", _absolute_pos[0], _absolute_pos[1], _absolute_pos[2]); } string SGSoundSample::random_string() { From 7c5de29b61de09b181672572164064ee3ca375cc Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 24 Oct 2009 08:18:09 +0000 Subject: [PATCH 35/85] get rid of aut_ptr, it only works with objects that can destroyed with delete (and not even delete[]) which is too limited. take drastic actions to find the sound-not-playing-bug: set all positions and orientations to default all the time. --- simgear/sound/sample_group.cxx | 9 ++++++- simgear/sound/sample_openal.cxx | 43 +++++++++++++++++++++++++++++-- simgear/sound/sample_openal.hxx | 23 ++++++++++------- simgear/sound/soundmgr_openal.cxx | 14 +++------- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index ed4d466b..44dabc1f 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -169,7 +169,6 @@ void SGSampleGroup::update( double dt ) { SG_LOG( SG_GENERAL, SG_ALERT, "No such buffer!\n"); // sample->no_valid_source(); // sadly, no free source available at this time -printf("No free source found."); } } else if ( sample->is_valid_source() && sample->has_changed() ) { @@ -393,6 +392,7 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { if ( sample->is_valid_source() ) { unsigned int source = sample->get_source(); +#if 0 if ( _tied_to_listener && _smgr->has_changed() ) { alSourcefv( source, AL_POSITION, _smgr->get_position().data() ); alSourcefv( source, AL_DIRECTION, _smgr->get_direction().data() ); @@ -402,6 +402,11 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); } +#else + alSourcefv( source, AL_POSITION, SGVec3f::zeros().data() ); + alSourcefv( source, AL_DIRECTION, SGVec3f::zeros().data() ); + alSourcefv( source, AL_VELOCITY, SGVec3f::zeros().data() ); +#endif testForALError("position and orientation"); alSourcef( source, AL_PITCH, sample->get_pitch() ); @@ -409,9 +414,11 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { testForALError("pitch and gain"); if ( sample->has_static_data_changed() ) { +#if 0 alSourcef( source, AL_CONE_INNER_ANGLE, sample->get_innerangle() ); alSourcef( source, AL_CONE_OUTER_ANGLE, sample->get_outerangle() ); alSourcef( source, AL_CONE_OUTER_GAIN, sample->get_outergain() ); +#endif testForALError("audio cone"); alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() ); diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 91b08527..96581b8b 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -84,6 +84,8 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGGeod()), + _refname(file), + _data(NULL), _format(AL_FORMAT_MONO8), _size(0), _freq(0), @@ -116,7 +118,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : } // constructor -SGSoundSample::SGSoundSample( std::auto_ptr& data, +SGSoundSample::SGSoundSample( const unsigned char** data, int len, int freq, int format ) : _absolute_pos(SGVec3d::zeros()), _relative_pos(SGVec3d::zeros()), @@ -126,7 +128,6 @@ SGSoundSample::SGSoundSample( std::auto_ptr& data, _orivec(SGVec3f::zeros()), _base_pos(SGGeod()), _refname(random_string()), - _data(data.release()), _format(format), _size(len), _freq(freq), @@ -149,11 +150,49 @@ SGSoundSample::SGSoundSample( std::auto_ptr& data, _is_file(false) { SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); + _data = (unsigned char*)data; *data = NULL; +} + +// constructor +SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : + _absolute_pos(SGVec3d::zeros()), + _relative_pos(SGVec3d::zeros()), + _direction(SGVec3d::zeros()), + _velocity(SGVec3d::zeros()), + _orientation(SGQuatd::zeros()), + _orivec(SGVec3f::zeros()), + _base_pos(SGGeod()), + _refname(random_string()), + _format(format), + _size(len), + _freq(freq), + _valid_buffer(false), + _buffer(SGSoundMgr::NO_BUFFER), + _valid_source(false), + _source(SGSoundMgr::NO_SOURCE), + _inner_angle(360.0), + _outer_angle(360.0), + _outer_gain(0.0), + _pitch(1.0), + _volume(1.0), + _master_volume(1.0), + _reference_dist(500.0), + _max_dist(3000.0), + _loop(AL_FALSE), + _playing(false), + _changed(true), + _static_changed(true), + _is_file(false) +{ + SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); + _data = (unsigned char*)data; *data = NULL; } // destructor SGSoundSample::~SGSoundSample() { + if (_data) free( _data ); + _data = NULL; } void SGSoundSample::set_orientation( const SGQuatd& ori ) { diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 070cba89..7042a70a 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -35,7 +35,6 @@ #endif #include -#include #include #include @@ -70,12 +69,14 @@ public: * Constructor. * @param data Pointer to a memory buffer containing this audio sample data The application may free the data by calling free_data(), otherwise it - will be resident untill the class is destroyed. + will be resident untill the class is destroyed. This pointer will be + set to NULL after calling this function. * @param len Byte length of array * @param freq Frequency of the provided data (bytes per second) * @param format OpenAL format id of the data */ - SGSoundSample( std::auto_ptr& data, int len, int freq, + SGSoundSample( void** data, int len, int freq, int format=AL_FORMAT_MONO8 ); + SGSoundSample( const unsigned char** data, int len, int freq, int format = AL_FORMAT_MONO8 ); /** @@ -150,24 +151,28 @@ public: inline bool is_playing() { return _playing; } /** - * sSt the data associated with this audio sample + * Set the data associated with this audio sample * @param data Pointer to a memory block containg this audio sample data. + This pointer will be set to NULL after calling this function. */ - inline void set_data( std::auto_ptr& data ) { - _data = data; + inline void set_data( const unsigned char **data ) { + _data = (unsigned char*)*data; *data = NULL; + } + inline void set_data( void **data ) { + _data = (unsigned char*)*data; *data = NULL; } /** * Return the data associated with this audio sample. * @return A pointer to this sound data of this audio sample. */ - inline void* get_data() const { return _data.get(); } + inline void* get_data() const { return _data; } /** * Free the data associated with this audio sample */ void free_data() { - free( _data.release() ); + if ( _data ) free( _data ); _data = NULL; } /** @@ -435,7 +440,7 @@ private: SGGeod _base_pos; // base position std::string _refname; // name or file path - std::auto_ptr _data; + unsigned char* _data; // configuration values int _format; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index b22a1835..0e52d5c5 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -94,7 +94,6 @@ SGSoundMgr::~SGSoundMgr() { // initialize the sound manager void SGSoundMgr::init() { -printf("Initializing OpenAL sound manager\n"); SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" ); ALCdevice *device = alcOpenDevice(_devname); @@ -154,7 +153,6 @@ printf("Initializing OpenAL sound manager\n"); else break; } -printf("%i free sources found\n", _free_sources.size() ); if (_free_sources.size() == 0) { SG_LOG(SG_GENERAL, SG_ALERT, "Unable to grab any OpenAL sources!"); } @@ -175,7 +173,6 @@ void SGSoundMgr::activate() { // stop the sound manager void SGSoundMgr::stop() { if (_working) { -printf("Stopping Sound Manager\n"); _working = false; _active = false; @@ -198,7 +195,6 @@ printf("Stopping Sound Manager\n"); void SGSoundMgr::suspend() { if (_working) { -printf("SoundManager suspend\n"); 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 ) { @@ -211,7 +207,6 @@ printf("SoundManager suspend\n"); void SGSoundMgr::resume() { if (_working) { -printf("SoundManager resume\n"); 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 ) { @@ -224,7 +219,6 @@ printf("SoundManager resume\n"); void SGSoundMgr::bind () { -printf("SoundManager bind\n"); _free_sources.clear(); _free_sources.reserve( MAX_SOURCES ); _sources_in_use.clear(); @@ -234,7 +228,6 @@ printf("SoundManager bind\n"); void SGSoundMgr::unbind () { -printf("SoundManager unbind\n"); _sample_groups.clear(); // delete free sources @@ -259,9 +252,11 @@ void SGSoundMgr::update_late( double dt ) { if (_changed) { alListenerf( AL_GAIN, _volume ); +#if 0 alListenerfv( AL_ORIENTATION, _at_up_vec ); alListenerfv( AL_POSITION, toVec3f(_position).data() ); alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); +#endif // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); _changed = false; @@ -430,10 +425,7 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) void *data; load(sample_name, &data, &format, &size, &freq); - std::auto_ptr ptr; - ptr.reset((unsigned char *)data); - - sample->set_data( ptr ); + sample->set_data( &data ); sample->set_frequency( freq ); sample->set_format( format ); sample->set_size( size ); From a06a15e769bccda83ac904f524e20f73da10b1a6 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 24 Oct 2009 12:57:11 +0000 Subject: [PATCH 36/85] Use shared pointers for any reference to SGSoundSample, fix the constructor of SGSoundSample where data is supplied by the calling program. --- simgear/sound/sample_group.cxx | 2 +- simgear/sound/sample_group.hxx | 7 +++---- simgear/sound/sample_openal.cxx | 4 ++-- simgear/sound/soundmgr_openal.cxx | 5 ++++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 44dabc1f..f9813fec 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -202,7 +202,7 @@ void SGSampleGroup::update( double dt ) { } // add a sound effect, return true if successful -bool SGSampleGroup::add( SGSoundSample *sound, const string& refname ) { +bool SGSampleGroup::add( SGSharedPtr sound, const string& refname ) { sample_map_iterator sample_it = _samples.find( refname ); if ( sample_it != _samples.end() ) { diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 7a3dff70..af85e312 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -56,8 +56,7 @@ using std::map; using std::string; -typedef SGSharedPtr SGSoundSample_ptr; -typedef map < string, SGSoundSample_ptr > sample_map; +typedef map < string, SGSharedPtr > sample_map; typedef sample_map::iterator sample_map_iterator; typedef sample_map::const_iterator const_sample_map_iterator; @@ -106,7 +105,7 @@ public: * @param refname Name of this audio sample for reference purposes * @return return true if successful */ - bool add( SGSoundSample *sound, const string& refname ); + bool add( SGSharedPtr sound, const string& refname ); /** * Remove an audio sample from this group. @@ -225,7 +224,7 @@ private: SGGeod _position; sample_map _samples; - std::vector _removed_samples; + std::vector< SGSharedPtr > _removed_samples; bool testForALError(string s); bool testForError(void *p, string s); diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 96581b8b..307b2385 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -150,7 +150,7 @@ SGSoundSample::SGSoundSample( const unsigned char** data, _is_file(false) { SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); - _data = (unsigned char*)data; *data = NULL; + _data = (unsigned char*)*data; *data = NULL; } // constructor @@ -185,7 +185,7 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : _is_file(false) { SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" ); - _data = (unsigned char*)data; *data = NULL; + _data = (unsigned char*)*data; *data = NULL; } diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 0e52d5c5..37b138c5 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -377,6 +377,8 @@ unsigned int SGSoundMgr::request_source() _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; } @@ -453,8 +455,9 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) } } } - else + else { buffer = sample->get_buffer(); +} return buffer; } From ae1625734c48d7616123f81137f18936bbfee59e Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 26 Oct 2009 09:05:19 +0000 Subject: [PATCH 37/85] move all isnan() declarations from sample_group.cxx to compiler.h since it's too important not to have available everywhere. --- simgear/compiler.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/simgear/compiler.h b/simgear/compiler.h index da0020cc..cfa91f86 100644 --- a/simgear/compiler.h +++ b/simgear/compiler.h @@ -131,9 +131,35 @@ // #ifdef __APPLE__ +# ifdef __GNUC__ +# if ( __GNUC__ >= 3 ) && ( __GNUC_MINOR__ >= 3 ) inline int (isnan)(double r) { return !(r <= 0 || r >= 0); } -#else +# else + // any C++ header file undefines isinf and isnan + // so this should be included before + // the functions are STILL in libm (libSystem on mac os x) +extern "C" int isnan (double); +extern "C" int isinf (double); +# endif +# else +inline int (isnan)(double r) { return !(r <= 0 || r >= 0); } +# endif +#endif +#if defined (__FreeBSD__) +# if __FreeBSD_version < 500000 + extern "C" { + inline int isnan(double r) { return !(r <= 0 || r >= 0); } + } +# endif +#endif + +#if defined (__CYGWIN__) +# include // isnan +#endif + +#if defined(__MINGW32__) +# define isnan(x) _isnan(x) #endif From 84dc82506a2b57ab1871ba313072238bc38d47af Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 26 Oct 2009 10:47:31 +0000 Subject: [PATCH 38/85] re-enable sound positioning and velocity, test for NaN's and print a message when it happens (debugging, should be removed later on). --- simgear/sound/sample_group.cxx | 49 ++++++++----------------------- simgear/sound/soundmgr_openal.cxx | 9 ++++-- simgear/sound/xmlsound.cxx | 3 -- 3 files changed, 19 insertions(+), 42 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index f9813fec..d3ee7fb7 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -26,40 +26,6 @@ #include -#if defined (__APPLE__) -# ifdef __GNUC__ -# if ( __GNUC__ >= 3 ) && ( __GNUC_MINOR__ >= 3 ) -// # include -inline int (isnan)(double r) { return !(r <= 0 || r >= 0); } -# else - // any C++ header file undefines isinf and isnan - // so this should be included before - // the functions are STILL in libm (libSystem on mac os x) -extern "C" int isnan (double); -extern "C" int isinf (double); -# endif -# else -// inline int (isinf)(double r) { return isinf(r); } -// inline int (isnan)(double r) { return isnan(r); } -# endif -#endif - -#if defined (__FreeBSD__) -# if __FreeBSD_version < 500000 - extern "C" { - inline int isnan(double r) { return !(r <= 0 || r >= 0); } - } -# endif -#endif - -#if defined (__CYGWIN__) -# include -#endif - -#if defined(__MINGW32__) -# define isnan(x) _isnan(x) -#endif - #include "soundmgr_openal.hxx" #include "sample_group.hxx" @@ -195,6 +161,7 @@ void SGSampleGroup::update( double dt ) { sample->no_valid_source(); _smgr->release_source( source ); _smgr->release_buffer( sample ); + remove( sample->get_sample_name() ); } } testForALError("update"); @@ -392,15 +359,23 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { if ( sample->is_valid_source() ) { unsigned int source = sample->get_source(); -#if 0 +#if 1 if ( _tied_to_listener && _smgr->has_changed() ) { alSourcefv( source, AL_POSITION, _smgr->get_position().data() ); - alSourcefv( source, AL_DIRECTION, _smgr->get_direction().data() ); alSourcefv( source, AL_VELOCITY, _smgr->get_velocity().data() ); +#if 0 + alSourcefv( source, AL_DIRECTION, _smgr->get_direction().data() ); +#endif } else { +float *pos = sample->get_position(); +if (isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2])) printf("NaN detected in source position\n"); alSourcefv( source, AL_POSITION, sample->get_position() ); - alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); +float *vel = sample->get_velocity(); +if (isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2])) printf("NaN detected in source velocity\n"); alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); +#if 0 + alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); +#endif } #else alSourcefv( source, AL_POSITION, SGVec3f::zeros().data() ); diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 37b138c5..bfe0a2e7 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -254,9 +254,14 @@ void SGSoundMgr::update_late( double dt ) { alListenerf( AL_GAIN, _volume ); #if 0 alListenerfv( AL_ORIENTATION, _at_up_vec ); - alListenerfv( AL_POSITION, toVec3f(_position).data() ); - alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); #endif +double *pos = _position.data(); +if (isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2])) printf("NaN detected in listener position\n"); + alListenerfv( AL_POSITION, toVec3f(_position).data() ); + +double *vel = _velocity.data(); +if (isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2])) printf("NaN detected in listener velocity\n"); + alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); _changed = false; diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 39cfdfe0..9e3ae813 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -101,9 +101,6 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, } else { _mode = SGXmlSound::ONCE; - - if ( strcmp(mode_str, "") ) - SG_LOG(SG_GENERAL,SG_INFO, "Unknown sound mode for '" << _name << "', default to 'once'"); } _property = root->getNode(node->getStringValue("property", ""), true); From 76c79dba8e9c14d06356d6ceb227d2c9490b9d24 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 26 Oct 2009 21:06:45 +0000 Subject: [PATCH 39/85] FGViewer::recalcLookFrom turned out to be an excellent source of information for prosition and orientation --- simgear/sound/sample_group.cxx | 16 ---------------- simgear/sound/sample_openal.cxx | 31 +++++++++++++++++++++++-------- simgear/sound/soundmgr_openal.cxx | 7 ------- simgear/sound/soundmgr_openal.hxx | 2 +- simgear/sound/xmlsound.cxx | 10 +++++----- 5 files changed, 29 insertions(+), 37 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index d3ee7fb7..8bd5eb9b 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -359,29 +359,15 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { if ( sample->is_valid_source() ) { unsigned int source = sample->get_source(); -#if 1 if ( _tied_to_listener && _smgr->has_changed() ) { alSourcefv( source, AL_POSITION, _smgr->get_position().data() ); alSourcefv( source, AL_VELOCITY, _smgr->get_velocity().data() ); -#if 0 alSourcefv( source, AL_DIRECTION, _smgr->get_direction().data() ); -#endif } else { -float *pos = sample->get_position(); -if (isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2])) printf("NaN detected in source position\n"); alSourcefv( source, AL_POSITION, sample->get_position() ); -float *vel = sample->get_velocity(); -if (isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2])) printf("NaN detected in source velocity\n"); alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); -#if 0 alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); -#endif } -#else - alSourcefv( source, AL_POSITION, SGVec3f::zeros().data() ); - alSourcefv( source, AL_DIRECTION, SGVec3f::zeros().data() ); - alSourcefv( source, AL_VELOCITY, SGVec3f::zeros().data() ); -#endif testForALError("position and orientation"); alSourcef( source, AL_PITCH, sample->get_pitch() ); @@ -389,11 +375,9 @@ if (isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2])) printf("NaN detected in sou testForALError("pitch and gain"); if ( sample->has_static_data_changed() ) { -#if 0 alSourcef( source, AL_CONE_INNER_ANGLE, sample->get_innerangle() ); alSourcef( source, AL_CONE_OUTER_ANGLE, sample->get_outerangle() ); alSourcef( source, AL_CONE_OUTER_GAIN, sample->get_outergain() ); -#endif testForALError("audio cone"); alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() ); diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 307b2385..451ece25 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -49,7 +49,7 @@ SGSoundSample::SGSoundSample() : _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), - _base_pos(SGGeod()), + _base_pos(SGGeod::fromDeg(0,0)), _refname(random_string()), _data(NULL), _format(AL_FORMAT_MONO8), @@ -83,7 +83,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), - _base_pos(SGGeod()), + _base_pos(SGGeod::fromDeg(0,0)), _refname(file), _data(NULL), _format(AL_FORMAT_MONO8), @@ -126,7 +126,7 @@ SGSoundSample::SGSoundSample( const unsigned char** data, _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), - _base_pos(SGGeod()), + _base_pos(SGGeod::fromDeg(0,0)), _refname(random_string()), _format(format), _size(len), @@ -161,7 +161,7 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), - _base_pos(SGGeod()), + _base_pos(SGGeod::fromDeg(0,0)), _refname(random_string()), _format(format), _size(len), @@ -220,11 +220,26 @@ void SGSoundSample::set_position( const SGGeod& pos ) { } void SGSoundSample::update_absolute_position() { - SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; - _orivec = -toVec3f(orient.rotate(-SGVec3d::e1())); + // SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; + // _orivec = -toVec3f(orient.rotate(-SGVec3d::e1())); - orient = SGQuatd::fromRealImag(0, _relative_pos) * _orientation; - _absolute_pos = -SGVec3d::fromGeod(_base_pos); // -orient.rotate(SGVec3d::e1()); + // The rotation rotating from the earth centerd frame to + // the horizontal local frame + SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos); + + // Compute the eyepoints orientation and position + // wrt the earth centered frame - that is global coorinates + SGQuatd ec2body = hlOr*_orientation; + + // This is rotates the x-forward, y-right, z-down coordinate system where + // simulation runs into the OpenGL camera system with x-right, y-up, z-back. + SGQuatd q(-0.5, -0.5, 0.5, 0.5); + + // The cartesian position of the basic view coordinate + SGVec3d position = SGVec3d::fromGeod(_base_pos); + + _absolute_pos = position + (ec2body*q).backTransform(_relative_pos); + _orivec = toVec3f( (ec2body*q).backTransform(_direction) ); } string SGSoundSample::random_string() { diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index bfe0a2e7..2d37e30e 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -252,15 +252,8 @@ void SGSoundMgr::update_late( double dt ) { if (_changed) { alListenerf( AL_GAIN, _volume ); -#if 0 alListenerfv( AL_ORIENTATION, _at_up_vec ); -#endif -double *pos = _position.data(); -if (isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2])) printf("NaN detected in listener position\n"); alListenerfv( AL_POSITION, toVec3f(_position).data() ); - -double *vel = _velocity.data(); -if (isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2])) printf("NaN detected in listener velocity\n"); alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 5d86c6be..58e63111 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -159,7 +159,7 @@ public: * @param pos OpenAL listener position */ void set_position( const SGVec3d& pos ) { - _position = -pos; + _position = pos; _changed = true; } diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 9e3ae813..45b303a1 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -41,8 +41,8 @@ static double _snd_inv(double v) { return (v == 0) ? 1e99 : 1/v; } static double _snd_abs(double v) { return (v >= 0) ? v : -v; } static double _snd_sqrt(double v) { return sqrt(fabs(v)); } -static double _snd_log10(double v) { return log10(fabs(v)); } -static double _snd_log(double v) { return log(fabs(v)); } +static double _snd_log10(double v) { return log10(fabs(v)+1e-9); } +static double _snd_log(double v) { return log(fabs(v)+1e-9); } // static double _snd_sqr(double v) { return v*v; } // static double _snd_pow3(double v) { return v*v*v; } @@ -243,9 +243,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, float outer_gain = 0.0; prop = node->getChild("orientation"); if ( prop != NULL ) { - dir = SGVec3d(-prop->getDoubleValue("x", 0.0), - -prop->getDoubleValue("y", 0.0), - -prop->getDoubleValue("z", 0.0)); + dir = SGVec3d(prop->getDoubleValue("y", 0.0), + prop->getDoubleValue("z", 0.0), + prop->getDoubleValue("x", 0.0)); inner = prop->getDoubleValue("inner-angle", 360.0); outer = prop->getDoubleValue("outer-angle", 360.0); outer_gain = prop->getDoubleValue("outer-gain", 0.0); From 0051bea03492f49de46ed8d88a48bef1ad9a8748 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 27 Oct 2009 12:10:42 +0000 Subject: [PATCH 40/85] small code reorganization and addition of debugging tests. --- simgear/sound/sample_group.cxx | 29 +++++++++++++++++++------ simgear/sound/sample_openal.cxx | 38 ++++++--------------------------- simgear/sound/sample_openal.hxx | 20 ++++++++++++----- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 8bd5eb9b..63ae7197 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -29,6 +29,10 @@ #include "soundmgr_openal.hxx" #include "sample_group.hxx" +bool isNaN(float *v) { + return (isnan(v[0]) || isnan(v[1]) || isnan(v[2])); +} + SGSampleGroup::SGSampleGroup () : _smgr(NULL), _refname(""), @@ -359,15 +363,26 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { if ( sample->is_valid_source() ) { unsigned int source = sample->get_source(); - if ( _tied_to_listener && _smgr->has_changed() ) { - alSourcefv( source, AL_POSITION, _smgr->get_position().data() ); - alSourcefv( source, AL_VELOCITY, _smgr->get_velocity().data() ); - alSourcefv( source, AL_DIRECTION, _smgr->get_direction().data() ); + float *position, *orientation, *velocity; + if ( _tied_to_listener ) { + position = _smgr->get_position().data(); + orientation = _smgr->get_velocity().data(); + velocity = _smgr->get_direction().data(); } else { - alSourcefv( source, AL_POSITION, sample->get_position() ); - alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); - alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); + sample->update_absolute_position(); + position = sample->get_position(); + orientation = sample->get_velocity(); + velocity = sample->get_orientation(); } + if (dist(_smgr->get_position(), sample->get_position_vec()) > 50000) + printf("source and listener distance greater than 50km!\n"); + if (isNaN(position)) printf("NaN in source position\n"); + if (isNaN(orientation)) printf("NaN in source orientation\n"); + if (isNaN(velocity)) printf("NaN in source velocity\n"); + + alSourcefv( source, AL_POSITION, position ); + alSourcefv( source, AL_VELOCITY, velocity ); + alSourcefv( source, AL_DIRECTION, orientation ); testForALError("position and orientation"); alSourcef( source, AL_PITCH, sample->get_pitch() ); diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 451ece25..21f81a39 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -195,51 +195,24 @@ SGSoundSample::~SGSoundSample() { _data = NULL; } -void SGSoundSample::set_orientation( const SGQuatd& ori ) { - _orientation = ori; - update_absolute_position(); - _changed = true; -} - -void SGSoundSample::set_direction( const SGVec3d& dir ) { - _direction = dir; - update_absolute_position(); - _changed = true; -} - -void SGSoundSample::set_relative_position( const SGVec3f& pos ) { - _relative_pos = toVec3d(pos); - update_absolute_position(); - _changed = true; -} - -void SGSoundSample::set_position( const SGGeod& pos ) { - _base_pos = pos; - update_absolute_position(); - _changed = true; -} - void SGSoundSample::update_absolute_position() { - // SGQuatd orient = SGQuatd::fromLonLat(_base_pos) * _orientation; - // _orivec = -toVec3f(orient.rotate(-SGVec3d::e1())); - // The rotation rotating from the earth centerd frame to // the horizontal local frame SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos); - // Compute the eyepoints orientation and position + // Compute the sounds orientation and position // wrt the earth centered frame - that is global coorinates - SGQuatd ec2body = hlOr*_orientation; + SGQuatd sc2body = _orientation*hlOr; // This is rotates the x-forward, y-right, z-down coordinate system where // simulation runs into the OpenGL camera system with x-right, y-up, z-back. SGQuatd q(-0.5, -0.5, 0.5, 0.5); - // The cartesian position of the basic view coordinate + // The cartesian position of the base sound coordinate SGVec3d position = SGVec3d::fromGeod(_base_pos); - _absolute_pos = position + (ec2body*q).backTransform(_relative_pos); - _orivec = toVec3f( (ec2body*q).backTransform(_direction) ); + _absolute_pos = position + (sc2body*q).backTransform(_relative_pos); + _orivec = toVec3f( (sc2body*q).backTransform(_direction) ); } string SGSoundSample::random_string() { @@ -252,3 +225,4 @@ string SGSoundSample::random_string() { return rstr; } + diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 7042a70a..abef4c7b 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -303,13 +303,17 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @param pos Relative position of this sound */ - void set_relative_position( const SGVec3f& pos ); + inline void set_relative_position( const SGVec3f& pos ) { + _relative_pos = toVec3d(pos); _changed = true; + } /** * Set the base position of this sound in Geodetic coordinates. * @param pos Geodetic position */ - void set_position( const SGGeod& pos ); + inline void set_position( const SGGeod& pos ) { + _base_pos = pos; _changed = true; + } /** * Get the absolute position of this sound. @@ -317,19 +321,24 @@ public: * @return Absolute position */ float *get_position() const { return toVec3f(_absolute_pos).data(); } + SGVec3f get_position_vec() const { return toVec3f(_absolute_pos); } /** * Set the orientation of this sound. * @param ori Quaternation containing the orientation information */ - void set_orientation( const SGQuatd& ori ); + inline void set_orientation( const SGQuatd& ori ) { + _orientation = ori; _changed = true; + } /** * Set direction of this sound relative to the orientation. * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @param dir Sound emission direction */ - void set_direction( const SGVec3d& dir ); + inline void set_direction( const SGVec3d& dir ) { + _direction = dir; _changed = true; + } /** * Define the audio cone parameters for directional audio. @@ -426,6 +435,8 @@ public: */ inline std::string get_sample_name() const { return _refname; } + void update_absolute_position(); + private: // Position of the source sound. @@ -472,7 +483,6 @@ private: bool _static_changed; bool _is_file; - void update_absolute_position(); string random_string(); }; From 9fe75dc5211c9e6b420053d48847700822bbd6e8 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 27 Oct 2009 12:21:56 +0000 Subject: [PATCH 41/85] also test for NaN in listener code --- simgear/sound/soundmgr_openal.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 2d37e30e..217039a6 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -45,6 +45,7 @@ #include #include +extern bool isNaN(float *v); #define MAX_SOURCES 128 @@ -251,6 +252,9 @@ void SGSoundMgr::update_late( double dt ) { } if (_changed) { +if (isNaN(_at_up_vec)) printf("NaN in listener orientation\n"); +if (isNaN(toVec3f(_position).data())) printf("NaN in listener position\n"); +if (isNaN(toVec3f(_velocity).data())) printf("NaN in listener velocity\n"); alListenerf( AL_GAIN, _volume ); alListenerfv( AL_ORIENTATION, _at_up_vec ); alListenerfv( AL_POSITION, toVec3f(_position).data() ); From af14d65a9856119264f987cec44fa8c37c26d6c6 Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 28 Oct 2009 14:27:47 +0000 Subject: [PATCH 42/85] Fix a bug where a sample was removed from the sample list before it was stopped. Proper listener orientation when inside the airplane (need to find a good solution for outside view). --- simgear/sound/openal_test2.cxx | 18 +++++++++--------- simgear/sound/sample_group.cxx | 23 ++++++++++++++++------- simgear/sound/sample_openal.cxx | 8 ++------ simgear/sound/sample_openal.hxx | 2 +- simgear/sound/soundmgr_openal.cxx | 10 ++++++---- simgear/sound/soundmgr_openal.hxx | 12 ++++++------ 6 files changed, 40 insertions(+), 33 deletions(-) diff --git a/simgear/sound/openal_test2.cxx b/simgear/sound/openal_test2.cxx index ac65e555..6ab355e3 100644 --- a/simgear/sound/openal_test2.cxx +++ b/simgear/sound/openal_test2.cxx @@ -30,7 +30,7 @@ int main( int argc, char *argv[] ) { sample1->set_pitch(1.0); sample1->play_looped(); sgr->add(sample1, "sound1"); - smgr->update_late(1.0); + smgr->update(1.0); printf("playing sample1\n"); sleep(1); @@ -39,7 +39,7 @@ int main( int argc, char *argv[] ) { sample2->set_pitch(0.4); sample2->play_looped(); sgr->add(sample2, "sound2"); - smgr->update_late(1.0); + smgr->update(1.0); printf("playing sample2\n"); sleep(1); @@ -48,7 +48,7 @@ int main( int argc, char *argv[] ) { sample3->set_pitch(0.8); sample3->play_looped(); sgr->add(sample3, "sound3"); - smgr->update_late(1.0); + smgr->update(1.0); printf("playing sample3\n"); sleep(1); @@ -57,7 +57,7 @@ int main( int argc, char *argv[] ) { sample4->set_pitch(1.2); sample4->play_looped(); sgr->add(sample4, "sound4"); - smgr->update_late(1.0); + smgr->update(1.0); printf("playing sample4\n"); sleep(1); @@ -66,7 +66,7 @@ int main( int argc, char *argv[] ) { sample5->set_pitch(1.6); sample5->play_looped(); sgr->add(sample5, "sound5"); - smgr->update_late(1.0); + smgr->update(1.0); printf("playing sample5\n"); sleep(1); @@ -75,24 +75,24 @@ int main( int argc, char *argv[] ) { sample6->set_pitch(2.0); sample6->play_looped(); sgr->add(sample6, "sound6"); - smgr->update_late(1.0); + smgr->update(1.0); printf("playing sample6\n"); sleep(1); for (int i=0; i<10; i++) { sleep(1); - smgr->update_late(1); + smgr->update(1); } sgr->stop("sound1"); sgr->stop("sound2"); sgr->stop("sound3"); sleep(0.5); - smgr->update_late(0.5); + smgr->update(0.5); sgr->stop("sound4"); sgr->stop("sound5"); sgr->stop("sound6"); - smgr->update_late(1); + smgr->update(1); sleep(1); smgr->unbind(); diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 63ae7197..90278dc5 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -89,9 +89,17 @@ void SGSampleGroup::update( double dt ) { unsigned int size = _removed_samples.size(); for (unsigned int i=0; iis_valid_source() ) { + if ( sample->is_looping() ) { + sample->no_valid_source(); + _smgr->release_source( sample->get_source() ); + } + else + alGetSourcei( sample->get_source(), AL_SOURCE_STATE, &result ); + } - alGetSourcei( sample->get_source(), AL_SOURCE_STATE, &result ); if ( result == AL_STOPPED ) { ALuint buffer = sample->get_buffer(); alDeleteBuffers( 1, &buffer ); @@ -128,7 +136,7 @@ void SGSampleGroup::update( double dt ) { sample->set_source( source ); update_sample_config( sample ); - ALboolean looping = sample->get_looping() ? AL_TRUE : AL_FALSE; + ALboolean looping = sample->is_looping() ? AL_TRUE : AL_FALSE; alSourcei( source, AL_LOOPING, looping ); alSourcef( source, AL_ROLLOFF_FACTOR, 1.0 ); alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE ); @@ -366,14 +374,15 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { float *position, *orientation, *velocity; if ( _tied_to_listener ) { position = _smgr->get_position().data(); - orientation = _smgr->get_velocity().data(); - velocity = _smgr->get_direction().data(); + orientation = _smgr->get_direction().data(); + velocity = _smgr->get_velocity().data(); } else { sample->update_absolute_position(); position = sample->get_position(); - orientation = sample->get_velocity(); - velocity = sample->get_orientation(); + orientation = sample->get_orientation(); + velocity = sample->get_velocity(); } + if (dist(_smgr->get_position(), sample->get_position_vec()) > 50000) printf("source and listener distance greater than 50km!\n"); if (isNaN(position)) printf("NaN in source position\n"); diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 21f81a39..05fc1ed8 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -112,9 +112,6 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : samplepath.append( file ); } _refname = samplepath.str(); - - SG_LOG( SG_GENERAL, SG_DEBUG, "From file sounds sample = " - << samplepath.str() ); } // constructor @@ -191,8 +188,7 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : // destructor SGSoundSample::~SGSoundSample() { - if (_data) free( _data ); - _data = NULL; + if (_data) free(_data); } void SGSoundSample::update_absolute_position() { @@ -218,7 +214,7 @@ void SGSoundSample::update_absolute_position() { string SGSoundSample::random_string() { static const char *r = "0123456789abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - string rstr; + string rstr = "System generated name: "; for (int i=0; i<10; i++) { rstr.push_back( r[rand() % strlen(r)] ); } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index abef4c7b..972a57c4 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -123,7 +123,7 @@ public: * Check if this audio sample is set to be continuous looping. * @return Return true if this audio sample is set to looping. */ - inline bool get_looping() { return _loop; } + inline bool is_looping() { return _loop; } /** * Schedule this audio sample to stop playing. diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 217039a6..dcb06b5a 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -66,6 +66,7 @@ SGSoundMgr::SGSoundMgr() : _position(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), + _orient_offs(SGQuatd::zeros()), _devname(NULL) { #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 @@ -242,7 +243,7 @@ void SGSoundMgr::unbind () } // run the audio scheduler -void SGSoundMgr::update_late( double dt ) { +void SGSoundMgr::update( double dt ) { if (_active) { sample_group_map_iterator sample_grp_current = _sample_groups.begin(); sample_group_map_iterator sample_grp_end = _sample_groups.end(); @@ -346,12 +347,13 @@ void SGSoundMgr::set_volume( float v ) * is undefined. If the two vectors are linearly dependent, * behavior is undefined. */ -void SGSoundMgr::set_orientation( SGQuatd ori ) +void SGSoundMgr::set_orientation( const SGQuatd& ori, const SGQuatd& offs ) { _orientation = ori; + _orient_offs = offs; - SGVec3d sgv_up = ori.rotate(SGVec3d::e2()); - SGVec3d sgv_at = ori.rotate(SGVec3d::e3()); + SGVec3d sgv_up = _orient_offs.rotate(SGVec3d::e2()); + SGVec3d sgv_at = _orient_offs.rotate(SGVec3d::e3()); _at_up_vec[0] = sgv_at[0]; _at_up_vec[1] = sgv_at[1]; _at_up_vec[2] = sgv_at[2]; diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 58e63111..bc3851f9 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -98,8 +98,7 @@ public: void init(); void bind(); void unbind(); - void update(double dt) {}; - void update_late(double dt); + void update(double dt); void suspend(); void resume(); @@ -175,9 +174,8 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @param vel Velocity vector of the OpenAL listener */ - void set_velocity( SGVec3d& dir ) { - _velocity = dir; - _changed = true; + void set_velocity( SGVec3d& vel ) { + _velocity = vel; _changed = true; } /** @@ -191,13 +189,14 @@ public: * Set the orientation of the sound manager * @param ori Quaternation containing the orientation information */ - void set_orientation( SGQuatd ori ); + void set_orientation( const SGQuatd& ori, const SGQuatd& offs ); /** * Get the orientation of the sound manager * @return Quaternation containing the orientation information */ inline const SGQuatd& get_orientation() { return _orientation; } + inline const SGQuatd& get_orientation_offset() { return _orient_offs; } /** * Get the direction vector of the sound manager @@ -290,6 +289,7 @@ private: // Orientation of the listener. // first 3 elements are "at" vector, second 3 are "up" vector SGQuatd _orientation; + SGQuatd _orient_offs; ALfloat _at_up_vec[6]; sample_group_map _sample_groups; From f6358694ae8d32cd908408ccacf7ba04adbc3d10 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 29 Oct 2009 12:53:20 +0000 Subject: [PATCH 43/85] another test program, using real world locations --- simgear/sound/Makefile.am | 12 +++++++- simgear/sound/openal_test2.cxx | 10 +++---- simgear/sound/openal_test3.cxx | 55 ++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 simgear/sound/openal_test3.cxx diff --git a/simgear/sound/Makefile.am b/simgear/sound/Makefile.am index 67d91110..dd271496 100644 --- a/simgear/sound/Makefile.am +++ b/simgear/sound/Makefile.am @@ -18,10 +18,11 @@ libsgsound_a_SOURCES = \ soundmgr_openal.cxx \ xmlsound.cxx -check_PROGRAMS = openal_test1 openal_test2 +check_PROGRAMS = openal_test1 openal_test2 openal_test3 openal_test1_SOURCES = openal_test1.cxx openal_test2_SOURCES = openal_test2.cxx +openal_test3SOURCES = openal_test3.cxx openal_test1_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ @@ -36,4 +37,13 @@ openal_test2_LDADD = \ $(top_builddir)/simgear/math/libsgmath.a \ $(openal_LIBS) +openal_test3_LDADD = \ + libsgsound.a \ + $(top_builddir)/simgear/structure/libsgstructure.a \ + $(top_builddir)/simgear/timing/libsgtiming.a \ + $(top_builddir)/simgear/debug/libsgdebug.a \ + $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/math/libsgmath.a \ + $(openal_LIBS) -lstdc++ + INCLUDES = -I$(top_srcdir) -DSRC_DIR=\"$(top_srcdir)/simgear/sound\" diff --git a/simgear/sound/openal_test2.cxx b/simgear/sound/openal_test2.cxx index 6ab355e3..c28957b8 100644 --- a/simgear/sound/openal_test2.cxx +++ b/simgear/sound/openal_test2.cxx @@ -1,10 +1,9 @@ #include -#ifdef __MINGW32__ -// This is broken, but allows the file to compile without a POSIX -// environment. -static unsigned int sleep(unsigned int secs) { return 0; } +#ifdef _WIN32 +#include +#define sleep(x) Sleep(x*1000) #else -#include // sleep() +#include #endif #include @@ -23,6 +22,7 @@ int main( int argc, char *argv[] ) { smgr->init(); sgr = smgr->find("default", true); smgr->set_volume(0.9); + smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(0,0)) ); smgr->activate(); SGSoundSample *sample1 = new SGSoundSample( SRC_DIR, "jet.wav" ); diff --git a/simgear/sound/openal_test3.cxx b/simgear/sound/openal_test3.cxx new file mode 100644 index 00000000..c5f124f7 --- /dev/null +++ b/simgear/sound/openal_test3.cxx @@ -0,0 +1,55 @@ +#include +#ifdef _WIN32 +#include +#define sleep(x) Sleep(x*1000) +#else +#include +#endif + +#include +#include + +#include "soundmgr_openal.hxx" + + +int main( int argc, char *argv[] ) { + SGSampleGroup *sgr; + SGSoundMgr *smgr; + + smgr = new SGSoundMgr; + + smgr->bind(); + smgr->init(); + sgr = smgr->find("default", true); + smgr->set_volume(0.9); + smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(0,0)) ); + smgr->activate(); + + printf("default position and orientation\n"); + SGSoundSample *sample1 = new SGSoundSample( SRC_DIR, "jet.wav" ); + sample1->set_volume(1.0); + sample1->set_pitch(1.0); + sample1->play_looped(); + sgr->add(sample1, "sound1"); + smgr->update(1.0); + printf("playing sample\n"); + sleep(3); + sgr->stop("sound1"); + smgr->update(3.0); + sleep(1); + + printf("source at lat,lon = (10,-10), listener at (0.999,-0.999)\n"); + sample1->set_position( SGGeod::fromDeg(10,-10) ); + smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(9.99,-9.99)) ); + sample1->play_looped(); + smgr->update(1.0); + printf("playing sample\n"); + sleep(3); + sgr->stop("sound1"); + smgr->update(3.0); + sleep(1); + + smgr->unbind(); + sleep(2); + delete smgr; +} From 191ee3a0edfb52444714c7a8a1fae64016bde1f5 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 29 Oct 2009 13:33:52 +0000 Subject: [PATCH 44/85] Commit the current state of affairs to see if it fixes the position code for others --- simgear/sound/openal_test3.cxx | 7 +-- simgear/sound/sample_group.cxx | 73 +++++++++++++++---------------- simgear/sound/sample_group.hxx | 4 +- simgear/sound/sample_openal.cxx | 6 ++- simgear/sound/sample_openal.hxx | 16 +++---- simgear/sound/soundmgr_openal.cxx | 8 ++-- simgear/sound/soundmgr_openal.hxx | 8 ++-- simgear/sound/xmlsound.cxx | 14 +++--- 8 files changed, 69 insertions(+), 67 deletions(-) diff --git a/simgear/sound/openal_test3.cxx b/simgear/sound/openal_test3.cxx index c5f124f7..79269f10 100644 --- a/simgear/sound/openal_test3.cxx +++ b/simgear/sound/openal_test3.cxx @@ -34,21 +34,22 @@ int main( int argc, char *argv[] ) { smgr->update(1.0); printf("playing sample\n"); sleep(3); - sgr->stop("sound1"); + sample1->stop(); smgr->update(3.0); sleep(1); - printf("source at lat,lon = (10,-10), listener at (0.999,-0.999)\n"); + printf("source at lat,lon = (10,-10), listener at (9.99,-9.99)\n"); sample1->set_position( SGGeod::fromDeg(10,-10) ); smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(9.99,-9.99)) ); sample1->play_looped(); smgr->update(1.0); printf("playing sample\n"); sleep(3); - sgr->stop("sound1"); + sample1->stop(); smgr->update(3.0); sleep(1); + sgr->remove("sound1"); smgr->unbind(); sleep(2); delete smgr; diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 90278dc5..eed424c1 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -156,7 +156,7 @@ void SGSampleGroup::update( double dt ) { sample->stop(); sample->no_valid_source(); _smgr->release_source( sample->get_source() ); - } else { + } else if ( _smgr->has_changed() ) { update_sample_config( sample ); } @@ -308,7 +308,7 @@ bool SGSampleGroup::stop( const string& refname ) { } // set source velocity of all managed sounds -void SGSampleGroup::set_velocity( const SGVec3d &vel ) { +void SGSampleGroup::set_velocity( const SGVec3f &vel ) { if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) { SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup velocity"); @@ -368,47 +368,46 @@ void SGSampleGroup::set_volume( float vol ) } void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { - if ( sample->is_valid_source() ) { - unsigned int source = sample->get_source(); + SGVec3f orientation, velocity; + SGVec3d position; - float *position, *orientation, *velocity; - if ( _tied_to_listener ) { - position = _smgr->get_position().data(); - orientation = _smgr->get_direction().data(); - velocity = _smgr->get_velocity().data(); - } else { - sample->update_absolute_position(); - position = sample->get_position(); - orientation = sample->get_orientation(); - velocity = sample->get_velocity(); - } + if ( _tied_to_listener ) { + orientation = _smgr->get_direction(); + position = _smgr->get_position(); + velocity = _smgr->get_velocity(); + } else { + sample->update_absolute_position(); + orientation = sample->get_orientation(); + position = sample->get_position(); + velocity = sample->get_velocity(); + } - if (dist(_smgr->get_position(), sample->get_position_vec()) > 50000) - printf("source and listener distance greater than 50km!\n"); - if (isNaN(position)) printf("NaN in source position\n"); - if (isNaN(orientation)) printf("NaN in source orientation\n"); - if (isNaN(velocity)) printf("NaN in source velocity\n"); + if (dist(position, _smgr->get_position()) > 10000) + printf("source and listener distance greater than 20km!\n"); + if (isNaN(position)) printf("NaN in source position\n"); + if (isNaN(orientation)) printf("NaN in source orientation\n"); + if (isNaN(velocity)) printf("NaN in source velocity\n"); - alSourcefv( source, AL_POSITION, position ); - alSourcefv( source, AL_VELOCITY, velocity ); - alSourcefv( source, AL_DIRECTION, orientation ); - testForALError("position and orientation"); + unsigned int source = sample->get_source(); + alSourcefv( source, AL_POSITION, toVec3f(position).data() ); + alSourcefv( source, AL_VELOCITY, velocity.data() ); + alSourcefv( source, AL_DIRECTION, orientation.data() ); + testForALError("position and orientation"); - alSourcef( source, AL_PITCH, sample->get_pitch() ); - alSourcef( source, AL_GAIN, sample->get_volume() ); - testForALError("pitch and gain"); + alSourcef( source, AL_PITCH, sample->get_pitch() ); + alSourcef( source, AL_GAIN, sample->get_volume() ); + testForALError("pitch and gain"); - if ( sample->has_static_data_changed() ) { - alSourcef( source, AL_CONE_INNER_ANGLE, sample->get_innerangle() ); - alSourcef( source, AL_CONE_OUTER_ANGLE, sample->get_outerangle() ); - alSourcef( source, AL_CONE_OUTER_GAIN, sample->get_outergain() ); - testForALError("audio cone"); + if ( sample->has_static_data_changed() ) { + alSourcef( source, AL_CONE_INNER_ANGLE, sample->get_innerangle() ); + alSourcef( source, AL_CONE_OUTER_ANGLE, sample->get_outerangle() ); + alSourcef( source, AL_CONE_OUTER_GAIN, sample->get_outergain() ); + testForALError("audio cone"); - alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() ); - alSourcef( source, AL_REFERENCE_DISTANCE, - sample->get_reference_dist() ); - testForALError("distance rolloff"); - } + alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() ); + alSourcef( source, AL_REFERENCE_DISTANCE, + sample->get_reference_dist() ); + testForALError("distance rolloff"); } } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index af85e312..d74866e7 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -189,7 +189,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @param vel Velocity vector */ - void set_velocity( const SGVec3d& vel ); + void set_velocity( const SGVec3f& vel ); /** * Set the position of this sample group. @@ -219,7 +219,7 @@ private: float _volume; bool _tied_to_listener; - SGVec3d _velocity; + SGVec3f _velocity; SGQuatd _orientation; SGGeod _position; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 05fc1ed8..75d663a5 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -207,8 +207,10 @@ void SGSoundSample::update_absolute_position() { // The cartesian position of the base sound coordinate SGVec3d position = SGVec3d::fromGeod(_base_pos); - _absolute_pos = position + (sc2body*q).backTransform(_relative_pos); - _orivec = toVec3f( (sc2body*q).backTransform(_direction) ); + _absolute_pos = position; // + (sc2body*q).backTransform(_relative_pos); + if ( !(_direction[0] == 0 && _direction[1] == 0 && _direction[2] == 0) ) { + _orivec = toVec3f((sc2body*q).backTransform(toVec3d(_direction))); + } } string SGSoundSample::random_string() { diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 972a57c4..0d924246 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -320,8 +320,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @return Absolute position */ - float *get_position() const { return toVec3f(_absolute_pos).data(); } - SGVec3f get_position_vec() const { return toVec3f(_absolute_pos); } + SGVec3d& get_position() { return _absolute_pos; } /** * Set the orientation of this sound. @@ -336,7 +335,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @param dir Sound emission direction */ - inline void set_direction( const SGVec3d& dir ) { + inline void set_direction( const SGVec3f& dir ) { _direction = dir; _changed = true; } @@ -359,7 +358,8 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @return Orientaton vector */ - float *get_orientation() { return _orivec.data(); } + SGVec3f& get_orientation() { return _orivec; } + SGVec3f& get_direction() { return _direction; } /** * Get the inner angle of the audio cone. @@ -384,7 +384,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @param Velocity vector */ - inline void set_velocity( const SGVec3d& vel ) { + inline void set_velocity( const SGVec3f& vel ) { _velocity = vel; _changed = true; } @@ -393,7 +393,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @return Velocity vector */ - float *get_velocity() { return toVec3f(_velocity).data(); } + SGVec3f& get_velocity() { return _velocity; } /** @@ -442,8 +442,8 @@ private: // Position of the source sound. SGVec3d _absolute_pos; // absolute position SGVec3d _relative_pos; // position relative to the base position - SGVec3d _direction; // orientation offset - SGVec3d _velocity; // Velocity of the source sound. + SGVec3f _direction; // orientation offset + SGVec3f _velocity; // Velocity of the source sound. // The position and orientation of this sound SGQuatd _orientation; // base orientation diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index dcb06b5a..6b530e53 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -255,11 +255,11 @@ void SGSoundMgr::update( double dt ) { if (_changed) { if (isNaN(_at_up_vec)) printf("NaN in listener orientation\n"); if (isNaN(toVec3f(_position).data())) printf("NaN in listener position\n"); -if (isNaN(toVec3f(_velocity).data())) printf("NaN in listener velocity\n"); +if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); alListenerf( AL_GAIN, _volume ); alListenerfv( AL_ORIENTATION, _at_up_vec ); alListenerfv( AL_POSITION, toVec3f(_position).data() ); - alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); + alListenerfv( AL_VELOCITY, _velocity.data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); _changed = false; @@ -352,8 +352,8 @@ void SGSoundMgr::set_orientation( const SGQuatd& ori, const SGQuatd& offs ) _orientation = ori; _orient_offs = offs; - SGVec3d sgv_up = _orient_offs.rotate(SGVec3d::e2()); - SGVec3d sgv_at = _orient_offs.rotate(SGVec3d::e3()); + SGVec3d sgv_up = offs.rotate(SGVec3d::e2()); + SGVec3d sgv_at = offs.rotate(SGVec3d::e3()); _at_up_vec[0] = sgv_at[0]; _at_up_vec[1] = sgv_at[1]; _at_up_vec[2] = sgv_at[2]; diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index bc3851f9..74e6b89f 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -167,14 +167,14 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @return OpenAL listener position */ - SGVec3f get_position() { return toVec3f(_position); } + SGVec3d& get_position() { return _position; } /** * Set the velocity vector of the sound manager * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @param vel Velocity vector of the OpenAL listener */ - void set_velocity( SGVec3d& vel ) { + void set_velocity( SGVec3f& vel ) { _velocity = vel; _changed = true; } @@ -183,7 +183,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @return Velocity vector of the OpenAL listener */ - inline SGVec3f get_velocity() { return toVec3f(_velocity); } + inline SGVec3f& get_velocity() { return _velocity; } /** * Set the orientation of the sound manager @@ -284,7 +284,7 @@ private: SGVec3d _position; // Velocity of the listener. - SGVec3d _velocity; + SGVec3f _velocity; // Orientation of the listener. // first 3 elements are "at" vector, second 3 are "up" vector diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 45b303a1..04b8e060 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -237,18 +237,18 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, // // Orientation // - SGVec3d dir = SGVec3d::zeros(); + SGVec3f dir = SGVec3f::zeros(); float inner = 360.0; float outer = 360.0; float outer_gain = 0.0; prop = node->getChild("orientation"); if ( prop != NULL ) { - dir = SGVec3d(prop->getDoubleValue("y", 0.0), - prop->getDoubleValue("z", 0.0), - prop->getDoubleValue("x", 0.0)); - inner = prop->getDoubleValue("inner-angle", 360.0); - outer = prop->getDoubleValue("outer-angle", 360.0); - outer_gain = prop->getDoubleValue("outer-gain", 0.0); + dir = SGVec3f(prop->getFloatValue("y", 0.0), + prop->getFloatValue("z", 0.0), + prop->getFloatValue("x", 0.0)); + inner = prop->getFloatValue("inner-angle", 360.0); + outer = prop->getFloatValue("outer-angle", 360.0); + outer_gain = prop->getFloatValue("outer-gain", 0.0); } // From 06f0b6030a4d372f3e3253e67f01d5763ce64e3c Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 29 Oct 2009 14:58:02 +0000 Subject: [PATCH 45/85] multiply quats in the right order --- simgear/sound/sample_openal.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 75d663a5..561f06ed 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -198,7 +198,7 @@ void SGSoundSample::update_absolute_position() { // Compute the sounds orientation and position // wrt the earth centered frame - that is global coorinates - SGQuatd sc2body = _orientation*hlOr; + SGQuatd sc2body = hlOr*_orientation; // This is rotates the x-forward, y-right, z-down coordinate system where // simulation runs into the OpenGL camera system with x-right, y-up, z-back. From 145a7fa1467c028f80e141a324950b2c47e34b7b Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 29 Oct 2009 17:03:16 +0000 Subject: [PATCH 46/85] pass the float pointer to the isNaN function instead of the SGVec3 type --- simgear/sound/sample_group.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index eed424c1..a5d19641 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -384,9 +384,9 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { if (dist(position, _smgr->get_position()) > 10000) printf("source and listener distance greater than 20km!\n"); - if (isNaN(position)) printf("NaN in source position\n"); - if (isNaN(orientation)) printf("NaN in source orientation\n"); - if (isNaN(velocity)) printf("NaN in source velocity\n"); + if (isNaN(toVec3f(position).data())) printf("NaN in source position\n"); + if (isNaN(orientation.data())) printf("NaN in source orientation\n"); + if (isNaN(velocity.data())) printf("NaN in source velocity\n"); unsigned int source = sample->get_source(); alSourcefv( source, AL_POSITION, toVec3f(position).data() ); From bcb95f647d750a867ed7e9415edcaa4670cea5f6 Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 30 Oct 2009 12:59:53 +0000 Subject: [PATCH 47/85] add relative pos back in --- simgear/sound/sample_openal.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 561f06ed..b66c3628 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -207,7 +207,12 @@ void SGSoundSample::update_absolute_position() { // The cartesian position of the base sound coordinate SGVec3d position = SGVec3d::fromGeod(_base_pos); - _absolute_pos = position; // + (sc2body*q).backTransform(_relative_pos); + _absolute_pos = position; + if ( !(_relative_pos[0] == 0 && _relative_pos[1] == 0 && + _relative_pos[2] == 0) ) + { + _absolute_pos += (sc2body*q).backTransform(_relative_pos); + } if ( !(_direction[0] == 0 && _direction[1] == 0 && _direction[2] == 0) ) { _orivec = toVec3f((sc2body*q).backTransform(toVec3d(_direction))); } From aefe9bc11682f39b3936b9f01a0d37e9d6428078 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 31 Oct 2009 08:41:07 +0000 Subject: [PATCH 48/85] MacOS X fix --- simgear/compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simgear/compiler.h b/simgear/compiler.h index cfa91f86..5f02adb2 100644 --- a/simgear/compiler.h +++ b/simgear/compiler.h @@ -138,8 +138,8 @@ inline int (isnan)(double r) { return !(r <= 0 || r >= 0); } // any C++ header file undefines isinf and isnan // so this should be included before // the functions are STILL in libm (libSystem on mac os x) -extern "C" int isnan (double); -extern "C" int isinf (double); +extern "C" int (isnan)(double); +extern "C" int (isinf)(double); # endif # else inline int (isnan)(double r) { return !(r <= 0 || r >= 0); } From bbeb48a60d00e3d736e11195f77e58e2b5f70d99 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 31 Oct 2009 08:46:46 +0000 Subject: [PATCH 49/85] fix a gcc version test --- simgear/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/compiler.h b/simgear/compiler.h index 5f02adb2..eca95fe5 100644 --- a/simgear/compiler.h +++ b/simgear/compiler.h @@ -132,7 +132,7 @@ #ifdef __APPLE__ # ifdef __GNUC__ -# if ( __GNUC__ >= 3 ) && ( __GNUC_MINOR__ >= 3 ) +# if ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 3 ) inline int (isnan)(double r) { return !(r <= 0 || r >= 0); } # else // any C++ header file undefines isinf and isnan From 4ffd70a42a4a0a8babaa421c56b19cce5410bc4b Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 31 Oct 2009 08:53:55 +0000 Subject: [PATCH 50/85] fix a typo --- simgear/sound/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/sound/Makefile.am b/simgear/sound/Makefile.am index dd271496..d14c9fb7 100644 --- a/simgear/sound/Makefile.am +++ b/simgear/sound/Makefile.am @@ -22,7 +22,7 @@ check_PROGRAMS = openal_test1 openal_test2 openal_test3 openal_test1_SOURCES = openal_test1.cxx openal_test2_SOURCES = openal_test2.cxx -openal_test3SOURCES = openal_test3.cxx +openal_test3_SOURCES = openal_test3.cxx openal_test1_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ From c89db53ebfab014fc3966d62c3abe22b32c81fa8 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 31 Oct 2009 14:18:41 +0000 Subject: [PATCH 51/85] another attempt at getting something useful without any result. --- simgear/sound/openal_test3.cxx | 6 +-- simgear/sound/sample_group.cxx | 8 ++-- simgear/sound/sample_group.hxx | 4 +- simgear/sound/sample_openal.cxx | 8 ++-- simgear/sound/sample_openal.hxx | 6 +-- simgear/sound/soundmgr_openal.cxx | 75 ++++++++++++++++++------------- simgear/sound/soundmgr_openal.hxx | 31 ++++++++----- 7 files changed, 79 insertions(+), 59 deletions(-) diff --git a/simgear/sound/openal_test3.cxx b/simgear/sound/openal_test3.cxx index 79269f10..dccbd3d5 100644 --- a/simgear/sound/openal_test3.cxx +++ b/simgear/sound/openal_test3.cxx @@ -22,7 +22,7 @@ int main( int argc, char *argv[] ) { smgr->init(); sgr = smgr->find("default", true); smgr->set_volume(0.9); - smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(0,0)) ); + smgr->set_position_geod( SGGeod::fromDeg(0,0) ); smgr->activate(); printf("default position and orientation\n"); @@ -39,8 +39,8 @@ int main( int argc, char *argv[] ) { sleep(1); printf("source at lat,lon = (10,-10), listener at (9.99,-9.99)\n"); - sample1->set_position( SGGeod::fromDeg(10,-10) ); - smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(9.99,-9.99)) ); + sample1->set_position_geod( SGGeod::fromDeg(10,-10) ); + smgr->set_position( SGGeod::fromDeg(9.99,-9.99) ); sample1->play_looped(); smgr->update(1.0); printf("playing sample\n"); diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index a5d19641..82c4e6e7 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -327,13 +327,13 @@ void SGSampleGroup::set_velocity( const SGVec3f &vel ) { } // set the source position of all managed sounds -void SGSampleGroup::set_position( const SGGeod& pos ) { +void SGSampleGroup::set_position_geod( const SGGeod& pos ) { sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { SGSoundSample *sample = sample_current->second; - sample->set_position( pos ); + sample->set_position_geod( pos ); } _position = pos; } @@ -376,13 +376,13 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { position = _smgr->get_position(); velocity = _smgr->get_velocity(); } else { - sample->update_absolute_position(); + sample->update_pos_and_orientation(); orientation = sample->get_orientation(); position = sample->get_position(); velocity = sample->get_velocity(); } - if (dist(position, _smgr->get_position()) > 10000) + if (length(position -_smgr->get_position()) > 20000) printf("source and listener distance greater than 20km!\n"); if (isNaN(toVec3f(position).data())) printf("NaN in source position\n"); if (isNaN(orientation.data())) printf("NaN in source orientation\n"); diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index d74866e7..645e18b8 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -186,7 +186,7 @@ public: /** * Set the velocity vector of this sample group. - * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * This is in the local frame coordinate system; x=north, y=east, z=down * @param vel Velocity vector */ void set_velocity( const SGVec3f& vel ); @@ -196,7 +196,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @param pos Base position */ - void set_position( const SGGeod& pos ); + void set_position_geod( const SGGeod& pos ); /** * Set the orientation of this sample group. diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index b66c3628..7e06a64e 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -191,7 +191,7 @@ SGSoundSample::~SGSoundSample() { if (_data) free(_data); } -void SGSoundSample::update_absolute_position() { +void SGSoundSample::update_pos_and_orientation() { // The rotation rotating from the earth centerd frame to // the horizontal local frame SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos); @@ -208,12 +208,10 @@ void SGSoundSample::update_absolute_position() { SGVec3d position = SGVec3d::fromGeod(_base_pos); _absolute_pos = position; - if ( !(_relative_pos[0] == 0 && _relative_pos[1] == 0 && - _relative_pos[2] == 0) ) - { + if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { _absolute_pos += (sc2body*q).backTransform(_relative_pos); } - if ( !(_direction[0] == 0 && _direction[1] == 0 && _direction[2] == 0) ) { + if ( _direction[0] || _direction[1] || _direction[2] ) { _orivec = toVec3f((sc2body*q).backTransform(toVec3d(_direction))); } } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 0d924246..d419d767 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -311,7 +311,7 @@ public: * Set the base position of this sound in Geodetic coordinates. * @param pos Geodetic position */ - inline void set_position( const SGGeod& pos ) { + inline void set_position_geod( const SGGeod& pos ) { _base_pos = pos; _changed = true; } @@ -381,7 +381,7 @@ public: /** * Set the velocity vector (in meters per second) of this sound. - * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * This is in the local frame coordinate system; x=north, y=east, z=down * @param Velocity vector */ inline void set_velocity( const SGVec3f& vel ) { @@ -435,7 +435,7 @@ public: */ inline std::string get_sample_name() const { return _refname; } - void update_absolute_position(); + void update_pos_and_orientation(); private: diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 6b530e53..c01f144f 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -63,7 +63,9 @@ SGSoundMgr::SGSoundMgr() : _volume(0.0), _device(NULL), _context(NULL), - _position(SGVec3d::zeros()), + _position_geod(SGGeod::fromDeg(0,0)), + _position_offs(SGVec3d::zeros()), + _absolute_pos(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _orient_offs(SGQuatd::zeros()), @@ -254,11 +256,12 @@ void SGSoundMgr::update( double dt ) { if (_changed) { if (isNaN(_at_up_vec)) printf("NaN in listener orientation\n"); -if (isNaN(toVec3f(_position).data())) printf("NaN in listener position\n"); +if (isNaN(toVec3f(_absolute_pos).data())) printf("NaN in listener position\n"); if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); + update_pos_and_orientation(); alListenerf( AL_GAIN, _volume ); alListenerfv( AL_ORIENTATION, _at_up_vec ); - alListenerfv( AL_POSITION, toVec3f(_position).data() ); + alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() ); alListenerfv( AL_VELOCITY, _velocity.data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); @@ -336,33 +339,6 @@ void SGSoundMgr::set_volume( float v ) _changed = true; } -/** - * set the orientation of the listener (in opengl coordinates) - * - * 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. - */ -void SGSoundMgr::set_orientation( const SGQuatd& ori, const SGQuatd& offs ) -{ - _orientation = ori; - _orient_offs = offs; - - SGVec3d sgv_up = offs.rotate(SGVec3d::e2()); - SGVec3d sgv_at = offs.rotate(SGVec3d::e3()); - _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]; - _changed = true; -} - // Get an unused source id // // The Sound Manager should keep track of the sources in use, the distance @@ -485,6 +461,45 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) } } +void SGSoundMgr::update_pos_and_orientation() { + // The rotation rotating from the earth centerd frame to + // the horizontal local frame + SGQuatd hlOr = SGQuatd::fromLonLat( _position_geod ); + + // Compute the listeners orientation and position + // wrt the earth centered frame - that is global coorinates + SGQuatd lc2body = hlOr*_orientation; + + // cartesian position of the listener + SGVec3d position = SGVec3d::fromGeod( _position_geod ); + + // This is rotates the x-forward, y-right, z-down coordinate system where + // simulation runs into the OpenGL camera system with x-right, y-up, z-back. + SGQuatd q(-0.5, -0.5, 0.5, 0.5); + + _absolute_pos = position + (lc2body*q).backTransform( _position_offs ); + + /** + * 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. + */ + SGQuatd lViewOrientation = lc2body*_orient_offs*q; + SGVec3d sgv_up = lViewOrientation.rotate(SGVec3d::e2()); + SGVec3d sgv_at = lViewOrientation.rotate(SGVec3d::e3()); + _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]; +} + bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, size_t *sz, int *frq ) { diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 74e6b89f..8cba4ac7 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -153,13 +153,15 @@ public: SGSampleGroup *find( const string& refname, bool create = false ); /** - * Set the position of the sound manager. - * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * Set the Geodetic position of the sound manager. * @param pos OpenAL listener position */ - void set_position( const SGVec3d& pos ) { - _position = pos; - _changed = true; + void set_position_geod( const SGGeod& pos ) { + _position_geod = pos; _changed = true; + } + + void set_position_offset( const SGVec3d& pos ) { + _position_offs = pos; _changed = true; } /** @@ -167,14 +169,14 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @return OpenAL listener position */ - SGVec3d& get_position() { return _position; } + SGVec3d& get_position() { return _absolute_pos; } /** - * Set the velocity vector of the sound manager - * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. - * @param vel Velocity vector of the OpenAL listener + * 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( SGVec3f& vel ) { + void set_velocity( const SGVec3f& vel ) { _velocity = vel; _changed = true; } @@ -189,7 +191,9 @@ public: * Set the orientation of the sound manager * @param ori Quaternation containing the orientation information */ - void set_orientation( const SGQuatd& ori, const SGQuatd& offs ); + void set_orientation( const SGQuatd& ori, const SGQuatd& offs ) { + _orientation = ori; _orient_offs = offs; _changed = true; + } /** * Get the orientation of the sound manager @@ -281,7 +285,9 @@ private: ALCcontext *_context; // Position of the listener. - SGVec3d _position; + SGGeod _position_geod; + SGVec3d _position_offs; + SGVec3d _absolute_pos; // Velocity of the listener. SGVec3f _velocity; @@ -305,6 +311,7 @@ private: bool testForALUTError(string s); bool testForError(void *p, string s); + void update_pos_and_orientation(); void update_sample_config( SGSampleGroup *sound ); }; From 6ccad915373fe367f8d63eb69282146054d0a401 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 1 Nov 2009 14:51:10 +0000 Subject: [PATCH 52/85] proper orientation(?) and comment out relative position and direction code since it messes with OpenAL in such a way that volume doesn't work properly anymore --- simgear/sound/sample_openal.cxx | 14 ++++++++------ simgear/sound/sample_openal.hxx | 5 ++--- simgear/sound/soundmgr_openal.cxx | 11 ++++++++--- simgear/sound/xmlsound.cxx | 6 +++--- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 7e06a64e..4be9d811 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -46,7 +46,7 @@ SGSoundSample::SGSoundSample() : _absolute_pos(SGVec3d::zeros()), _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), - _velocity(SGVec3d::zeros()), + _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGGeod::fromDeg(0,0)), @@ -80,7 +80,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _absolute_pos(SGVec3d::zeros()), _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), - _velocity(SGVec3d::zeros()), + _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGGeod::fromDeg(0,0)), @@ -120,7 +120,7 @@ SGSoundSample::SGSoundSample( const unsigned char** data, _absolute_pos(SGVec3d::zeros()), _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), - _velocity(SGVec3d::zeros()), + _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGGeod::fromDeg(0,0)), @@ -155,7 +155,7 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : _absolute_pos(SGVec3d::zeros()), _relative_pos(SGVec3d::zeros()), _direction(SGVec3d::zeros()), - _velocity(SGVec3d::zeros()), + _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGGeod::fromDeg(0,0)), @@ -204,15 +204,17 @@ void SGSoundSample::update_pos_and_orientation() { // simulation runs into the OpenGL camera system with x-right, y-up, z-back. SGQuatd q(-0.5, -0.5, 0.5, 0.5); - // The cartesian position of the base sound coordinate + // The cartesian position of the sounds base location SGVec3d position = SGVec3d::fromGeod(_base_pos); _absolute_pos = position; +#if 0 if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { _absolute_pos += (sc2body*q).backTransform(_relative_pos); } +#endif if ( _direction[0] || _direction[1] || _direction[2] ) { - _orivec = toVec3f((sc2body*q).backTransform(toVec3d(_direction))); + _orivec = toVec3f( (sc2body*q).backTransform(_direction) ); } } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index d419d767..8f310233 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -336,7 +336,7 @@ public: * @param dir Sound emission direction */ inline void set_direction( const SGVec3f& dir ) { - _direction = dir; _changed = true; + _direction = toVec3d(dir); _changed = true; } /** @@ -359,7 +359,6 @@ public: * @return Orientaton vector */ SGVec3f& get_orientation() { return _orivec; } - SGVec3f& get_direction() { return _direction; } /** * Get the inner angle of the audio cone. @@ -442,7 +441,7 @@ private: // Position of the source sound. SGVec3d _absolute_pos; // absolute position SGVec3d _relative_pos; // position relative to the base position - SGVec3f _direction; // orientation offset + SGVec3d _direction; // orientation offset SGVec3f _velocity; // Velocity of the source sound. // The position and orientation of this sound diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index c01f144f..b6177948 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -477,7 +477,12 @@ void SGSoundMgr::update_pos_and_orientation() { // simulation runs into the OpenGL camera system with x-right, y-up, z-back. SGQuatd q(-0.5, -0.5, 0.5, 0.5); - _absolute_pos = position + (lc2body*q).backTransform( _position_offs ); + _absolute_pos = position; +#if 0 + if (_position_offs[0] || _position_offs[1] || _position_offs[2] ) { + _absolute_pos += (lc2body*q).backTransform( _position_offs ); + } +#endif /** * Description: ORIENTATION is a pair of 3-tuples representing the @@ -489,8 +494,8 @@ void SGSoundMgr::update_pos_and_orientation() { * behavior is undefined. * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. */ - SGQuatd lViewOrientation = lc2body*_orient_offs*q; - SGVec3d sgv_up = lViewOrientation.rotate(SGVec3d::e2()); + SGQuatd lViewOrientation = hlOr*_orient_offs*q; + SGVec3d sgv_up = -lViewOrientation.rotate(SGVec3d::e2()); SGVec3d sgv_at = lViewOrientation.rotate(SGVec3d::e3()); _at_up_vec[0] = sgv_at[0]; _at_up_vec[1] = sgv_at[1]; diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 04b8e060..29bf06b5 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -229,9 +229,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGVec3f offset_pos = SGVec3f::zeros(); SGPropertyNode_ptr prop = node->getChild("position"); if ( prop != NULL ) { - offset_pos[0] = prop->getDoubleValue("x", 0.0); - offset_pos[1] = -prop->getDoubleValue("y", 0.0); - offset_pos[2] = prop->getDoubleValue("z", 0.0); + offset_pos[0] = prop->getDoubleValue("y", 0.0); + offset_pos[1] = prop->getDoubleValue("z", 0.0); + offset_pos[2] = prop->getDoubleValue("x", 0.0); } // From fd90dbb123adf798d0769e2572c8ed5a9924d05f Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 1 Nov 2009 17:34:25 +0000 Subject: [PATCH 53/85] silently clip pitch and gain to their maximum values --- simgear/sound/sample_openal.hxx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 8f310233..a0fb812e 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -230,7 +230,10 @@ public: * Should be between 0.0 and 2.0 for maximum compatibility. * @param p Pitch */ - inline void set_pitch( float p ) { _pitch = p; _changed = true; } + inline void set_pitch( float p ) { + if (p > 2.0) p = 2.0; else if (p < 0.01) p = 0.01; + _pitch = p; _changed = true; + } /** * Get the current pitch value of this audio sample. @@ -245,6 +248,7 @@ public: * @param v Volume */ inline void set_master_volume( float v ) { + if (v > 1.0) v = 1.0; else if (v < 0.0) v = 0.0; _master_volume = v; _changed = true; } @@ -254,7 +258,10 @@ public: * volume. * @param v Volume */ - inline void set_volume( float v ) { _volume = v; _changed = true; } + inline void set_volume( float v ) { + if (v > 1.0) v = 1.0; else if (v < 0.0) v = 0.0; + _volume = v; _changed = true; + } /** * Get the final volume value of this audio sample. From 1ac944b7c1e7236e6d3493a7c23ea2c099109261 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 2 Nov 2009 10:31:05 +0000 Subject: [PATCH 54/85] Position and orientation fixes thanks to Tim Moore (finaly). Code optimizations by moving code over from SGSoundSample to SGSampleGroup which means it will only run once for every sample group instead of once for every sample. --- simgear/sound/sample_group.cxx | 69 +++++++++++++++++++++---------- simgear/sound/sample_group.hxx | 15 +++++-- simgear/sound/sample_openal.cxx | 41 ++++++++---------- simgear/sound/sample_openal.hxx | 28 ++++++++++--- simgear/sound/soundmgr_openal.cxx | 32 +++----------- simgear/sound/soundmgr_openal.hxx | 12 ++---- 6 files changed, 110 insertions(+), 87 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 82c4e6e7..43235d86 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -37,11 +37,14 @@ SGSampleGroup::SGSampleGroup () : _smgr(NULL), _refname(""), _active(false), + _changed(false), _pause(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), - _position(SGGeod()) + _position(SGVec3d::zeros()), + _pos_offs(SGVec3d::zeros()), + _position_geod(SGGeod()) { _samples.clear(); } @@ -50,11 +53,14 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _smgr(smgr), _refname(refname), _active(false), + _changed(false), _pause(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), - _position(SGGeod()) + _position(SGVec3d::zeros()), + _pos_offs(SGVec3d::zeros()), + _position_geod(SGGeod()) { _smgr->add(this, refname); _samples.clear(); @@ -111,6 +117,12 @@ void SGSampleGroup::update( double dt ) { i++; } + // Update the position and orientation information for all samples. + if ( _changed ) { + update_pos_and_orientation(); + _changed = false; + } + sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { @@ -327,29 +339,42 @@ void SGSampleGroup::set_velocity( const SGVec3f &vel ) { } // set the source position of all managed sounds -void SGSampleGroup::set_position_geod( const SGGeod& pos ) { +void SGSampleGroup::update_pos_and_orientation() { + + SGVec3d position = SGVec3d::fromGeod( _position_geod ); + SGVec3d pos_offs = SGVec3d::fromGeod( _smgr->get_position_geod() ); + + if (_position != position || _pos_offs != pos_offs) { + _position = position; + _pos_offs = pos_offs; + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_position( _position ); + sample->set_position_offset( _pos_offs ); + } + } + + // The rotation rotating from the earth centerd frame to + // the horizontal local frame + SGQuatd hlOr = SGQuatd::fromLonLat(_position_geod); + + // Rotate the x-forward, y-right, z-down coordinate system + // into the OpenGL camera system with x-right, y-up, z-back. + SGQuatd q(-0.5, -0.5, 0.5, 0.5); + + // Compute the sounds orientation and position + // wrt the earth centered frame - that is global coorinates + SGQuatd sc2body = hlOr*_orientation*q; sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { SGSoundSample *sample = sample_current->second; - sample->set_position_geod( pos ); - } - _position = pos; -} - - -// set the source orientation of all managed sounds -void SGSampleGroup::set_orientation( const SGQuatd& ori ) { - - if (_orientation != ori) { - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_orientation( ori ); - } - _orientation = ori; + sample->set_orientation( _orientation ); + sample->set_rotation( sc2body ); } } @@ -382,11 +407,13 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { velocity = sample->get_velocity(); } - if (length(position -_smgr->get_position()) > 20000) +#if 0 + if (length(position) > 20000) printf("source and listener distance greater than 20km!\n"); if (isNaN(toVec3f(position).data())) printf("NaN in source position\n"); if (isNaN(orientation.data())) printf("NaN in source orientation\n"); if (isNaN(velocity.data())) printf("NaN in source velocity\n"); +#endif unsigned int source = sample->get_source(); alSourcefv( source, AL_POSITION, toVec3f(position).data() ); diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 645e18b8..316cb43e 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -196,13 +196,17 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @param pos Base position */ - void set_position_geod( const SGGeod& pos ); + void set_position_geod( const SGGeod& pos ) { + _position_geod = pos; _changed = true; + } /** * Set the orientation of this sample group. * @param ori Quaternation containing the orientation information */ - void set_orientation( const SGQuatd& ori ); + void set_orientation( const SGQuatd& ori ) { + _orientation = ori; _changed = true; + } /** * Tie this sample group to the listener position, orientation and velocity @@ -215,13 +219,17 @@ protected: bool _active; private: + bool _changed; bool _pause; float _volume; bool _tied_to_listener; SGVec3f _velocity; SGQuatd _orientation; - SGGeod _position; + SGVec3d _position; + SGVec3d _pos_offs; + + SGGeod _position_geod; sample_map _samples; std::vector< SGSharedPtr > _removed_samples; @@ -229,6 +237,7 @@ private: bool testForALError(string s); bool testForError(void *p, 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 4be9d811..5c20c1c9 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -48,8 +48,10 @@ SGSoundSample::SGSoundSample() : _direction(SGVec3d::zeros()), _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), + _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), - _base_pos(SGGeod::fromDeg(0,0)), + _base_pos(SGVec3d::zeros()), + _base_offs(SGVec3d::zeros()), _refname(random_string()), _data(NULL), _format(AL_FORMAT_MONO8), @@ -82,8 +84,10 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _direction(SGVec3d::zeros()), _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), + _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), - _base_pos(SGGeod::fromDeg(0,0)), + _base_pos(SGVec3d::zeros()), + _base_offs(SGVec3d::zeros()), _refname(file), _data(NULL), _format(AL_FORMAT_MONO8), @@ -122,8 +126,10 @@ SGSoundSample::SGSoundSample( const unsigned char** data, _direction(SGVec3d::zeros()), _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), + _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), - _base_pos(SGGeod::fromDeg(0,0)), + _base_pos(SGVec3d::zeros()), + _base_offs(SGVec3d::zeros()), _refname(random_string()), _format(format), _size(len), @@ -157,8 +163,10 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : _direction(SGVec3d::zeros()), _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), + _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), - _base_pos(SGGeod::fromDeg(0,0)), + _base_pos(SGVec3d::zeros()), + _base_offs(SGVec3d::zeros()), _refname(random_string()), _format(format), _size(len), @@ -192,30 +200,17 @@ SGSoundSample::~SGSoundSample() { } void SGSoundSample::update_pos_and_orientation() { - // The rotation rotating from the earth centerd frame to - // the horizontal local frame - SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos); - // Compute the sounds orientation and position - // wrt the earth centered frame - that is global coorinates - SGQuatd sc2body = hlOr*_orientation; - - // This is rotates the x-forward, y-right, z-down coordinate system where - // simulation runs into the OpenGL camera system with x-right, y-up, z-back. - SGQuatd q(-0.5, -0.5, 0.5, 0.5); - - // The cartesian position of the sounds base location - SGVec3d position = SGVec3d::fromGeod(_base_pos); - - _absolute_pos = position; -#if 0 + _absolute_pos = _base_pos - _base_offs; if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { - _absolute_pos += (sc2body*q).backTransform(_relative_pos); + _absolute_pos += _rotation.backTransform(_relative_pos); } -#endif + if ( _direction[0] || _direction[1] || _direction[2] ) { - _orivec = toVec3f( (sc2body*q).backTransform(_direction) ); + _orivec = toVec3f( _rotation.rotate(_direction) ); } + else + _orivec = SGVec3f::zeros(); } string SGSoundSample::random_string() { diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index a0fb812e..56fc3d3a 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -315,11 +315,19 @@ public: } /** - * Set the base position of this sound in Geodetic coordinates. - * @param pos Geodetic position + * Set the base position in Cartesian coordinates + * @param pos position in Cartesian coordinates */ - inline void set_position_geod( const SGGeod& pos ) { - _base_pos = pos; _changed = true; + inline void set_position( const SGVec3d& pos ) { + _base_pos = pos; _changed = true; + } + + /** + * Set the base position offset in Cartesian coordinates + * @param offs offset in Cartesian coordinates + */ + inline void set_position_offset( const SGVec3d& offs ) { + _base_offs = offs; _changed = true; } /** @@ -337,6 +345,14 @@ public: _orientation = ori; _changed = true; } + /** + * Set the rotation quatgernion of this sound. + * @param rotation Quaternion containing the rotation information + */ + inline void set_rotation( const SGQuatd& rotation ) { + _rotation = rotation; _changed = true; + } + /** * Set direction of this sound relative to the orientation. * This is in the same coordinate system as OpenGL; y=up, z=back, x=right @@ -453,8 +469,10 @@ private: // The position and orientation of this sound SGQuatd _orientation; // base orientation + SGQuatd _rotation; // rotation vector for relative offsets SGVec3f _orivec; // orientation vector for OpenAL - SGGeod _base_pos; // base position + SGVec3d _base_pos; // base position + SGVec3d _base_offs; // base offset position std::string _refname; // name or file path unsigned char* _data; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index b6177948..76b3f138 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -64,11 +64,9 @@ SGSoundMgr::SGSoundMgr() : _device(NULL), _context(NULL), _position_geod(SGGeod::fromDeg(0,0)), - _position_offs(SGVec3d::zeros()), _absolute_pos(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), - _orient_offs(SGQuatd::zeros()), _devname(NULL) { #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 @@ -255,13 +253,15 @@ void SGSoundMgr::update( double 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 update_pos_and_orientation(); alListenerf( AL_GAIN, _volume ); alListenerfv( AL_ORIENTATION, _at_up_vec ); - alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() ); + // alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() ); alListenerfv( AL_VELOCITY, _velocity.data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); @@ -462,27 +462,8 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) } void SGSoundMgr::update_pos_and_orientation() { - // The rotation rotating from the earth centerd frame to - // the horizontal local frame - SGQuatd hlOr = SGQuatd::fromLonLat( _position_geod ); - - // Compute the listeners orientation and position - // wrt the earth centered frame - that is global coorinates - SGQuatd lc2body = hlOr*_orientation; - // cartesian position of the listener - SGVec3d position = SGVec3d::fromGeod( _position_geod ); - - // This is rotates the x-forward, y-right, z-down coordinate system where - // simulation runs into the OpenGL camera system with x-right, y-up, z-back. - SGQuatd q(-0.5, -0.5, 0.5, 0.5); - - _absolute_pos = position; -#if 0 - if (_position_offs[0] || _position_offs[1] || _position_offs[2] ) { - _absolute_pos += (lc2body*q).backTransform( _position_offs ); - } -#endif + _absolute_pos = SGVec3d::fromGeod( _position_geod ); /** * Description: ORIENTATION is a pair of 3-tuples representing the @@ -494,9 +475,8 @@ void SGSoundMgr::update_pos_and_orientation() { * behavior is undefined. * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. */ - SGQuatd lViewOrientation = hlOr*_orient_offs*q; - SGVec3d sgv_up = -lViewOrientation.rotate(SGVec3d::e2()); - SGVec3d sgv_at = lViewOrientation.rotate(SGVec3d::e3()); + 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]; diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 8cba4ac7..1be7eebd 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -160,16 +160,13 @@ public: _position_geod = pos; _changed = true; } - void set_position_offset( const SGVec3d& pos ) { - _position_offs = 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 OpenAL listener position */ SGVec3d& get_position() { return _absolute_pos; } + SGGeod& get_position_geod() { return _position_geod; } /** * Set the velocity vector (in meters per second) of the sound manager @@ -191,8 +188,8 @@ public: * Set the orientation of the sound manager * @param ori Quaternation containing the orientation information */ - void set_orientation( const SGQuatd& ori, const SGQuatd& offs ) { - _orientation = ori; _orient_offs = offs; _changed = true; + void set_orientation( const SGQuatd& ori ) { + _orientation = ori; _changed = true; } /** @@ -200,7 +197,6 @@ public: * @return Quaternation containing the orientation information */ inline const SGQuatd& get_orientation() { return _orientation; } - inline const SGQuatd& get_orientation_offset() { return _orient_offs; } /** * Get the direction vector of the sound manager @@ -286,7 +282,6 @@ private: // Position of the listener. SGGeod _position_geod; - SGVec3d _position_offs; SGVec3d _absolute_pos; // Velocity of the listener. @@ -295,7 +290,6 @@ private: // Orientation of the listener. // first 3 elements are "at" vector, second 3 are "up" vector SGQuatd _orientation; - SGQuatd _orient_offs; ALfloat _at_up_vec[6]; sample_group_map _sample_groups; From 5b15426cc63036594ab332971ec831a1b5cbccd2 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 2 Nov 2009 11:39:37 +0000 Subject: [PATCH 55/85] Small code reorganization, mostly removing unneeded code --- simgear/sound/sample_group.cxx | 18 +----------------- simgear/sound/sample_group.hxx | 3 --- simgear/sound/sample_openal.cxx | 6 +----- simgear/sound/sample_openal.hxx | 9 --------- 4 files changed, 2 insertions(+), 34 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 43235d86..4ba82f56 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -42,8 +42,6 @@ SGSampleGroup::SGSampleGroup () : _tied_to_listener(false), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), - _position(SGVec3d::zeros()), - _pos_offs(SGVec3d::zeros()), _position_geod(SGGeod()) { _samples.clear(); @@ -58,8 +56,6 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _tied_to_listener(false), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), - _position(SGVec3d::zeros()), - _pos_offs(SGVec3d::zeros()), _position_geod(SGGeod()) { _smgr->add(this, refname); @@ -344,19 +340,6 @@ void SGSampleGroup::update_pos_and_orientation() { SGVec3d position = SGVec3d::fromGeod( _position_geod ); SGVec3d pos_offs = SGVec3d::fromGeod( _smgr->get_position_geod() ); - if (_position != position || _pos_offs != pos_offs) { - _position = position; - _pos_offs = pos_offs; - - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_position( _position ); - sample->set_position_offset( _pos_offs ); - } - } - // The rotation rotating from the earth centerd frame to // the horizontal local frame SGQuatd hlOr = SGQuatd::fromLonLat(_position_geod); @@ -373,6 +356,7 @@ void SGSampleGroup::update_pos_and_orientation() { sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { SGSoundSample *sample = sample_current->second; + sample->set_position( position - pos_offs ); sample->set_orientation( _orientation ); sample->set_rotation( sc2body ); } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index 316cb43e..c13883b3 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -226,9 +226,6 @@ private: SGVec3f _velocity; SGQuatd _orientation; - SGVec3d _position; - SGVec3d _pos_offs; - SGGeod _position_geod; sample_map _samples; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 5c20c1c9..0d00083c 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -51,7 +51,6 @@ SGSoundSample::SGSoundSample() : _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), - _base_offs(SGVec3d::zeros()), _refname(random_string()), _data(NULL), _format(AL_FORMAT_MONO8), @@ -87,7 +86,6 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), - _base_offs(SGVec3d::zeros()), _refname(file), _data(NULL), _format(AL_FORMAT_MONO8), @@ -129,7 +127,6 @@ SGSoundSample::SGSoundSample( const unsigned char** data, _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), - _base_offs(SGVec3d::zeros()), _refname(random_string()), _format(format), _size(len), @@ -166,7 +163,6 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), - _base_offs(SGVec3d::zeros()), _refname(random_string()), _format(format), _size(len), @@ -201,7 +197,7 @@ SGSoundSample::~SGSoundSample() { void SGSoundSample::update_pos_and_orientation() { - _absolute_pos = _base_pos - _base_offs; + _absolute_pos = _base_pos; if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { _absolute_pos += _rotation.backTransform(_relative_pos); } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 56fc3d3a..cef5889d 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -322,14 +322,6 @@ public: _base_pos = pos; _changed = true; } - /** - * Set the base position offset in Cartesian coordinates - * @param offs offset in Cartesian coordinates - */ - inline void set_position_offset( const SGVec3d& offs ) { - _base_offs = offs; _changed = true; - } - /** * Get the absolute position of this sound. * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. @@ -472,7 +464,6 @@ private: SGQuatd _rotation; // rotation vector for relative offsets SGVec3f _orivec; // orientation vector for OpenAL SGVec3d _base_pos; // base position - SGVec3d _base_offs; // base offset position std::string _refname; // name or file path unsigned char* _data; From 5ac2abe3abe399858e7a8c7288ce71338daf20bf Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 2 Nov 2009 21:38:39 +0000 Subject: [PATCH 56/85] Remove more unneeded code and properly set relative position and sound direction --- simgear/sound/sample_group.cxx | 52 +++++++++++-------------------- simgear/sound/sample_group.hxx | 4 +-- simgear/sound/sample_openal.cxx | 8 ++--- simgear/sound/sample_openal.hxx | 9 ------ simgear/sound/soundmgr_openal.cxx | 4 --- simgear/sound/soundmgr_openal.hxx | 4 +-- simgear/sound/xmlsound.cxx | 8 ++--- 7 files changed, 28 insertions(+), 61 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 4ba82f56..6cccf634 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -41,8 +41,8 @@ SGSampleGroup::SGSampleGroup () : _pause(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), - _orientation(SGQuatd::zeros()), - _position_geod(SGGeod()) + _base_pos(SGVec3d::zeros()), + _orientation(SGQuatd::zeros()) { _samples.clear(); } @@ -55,8 +55,8 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _pause(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), - _orientation(SGQuatd::zeros()), - _position_geod(SGGeod()) + _base_pos(SGVec3d::zeros()), + _orientation(SGQuatd::zeros()) { _smgr->add(this, refname); _samples.clear(); @@ -334,34 +334,6 @@ void SGSampleGroup::set_velocity( const SGVec3f &vel ) { } } -// set the source position of all managed sounds -void SGSampleGroup::update_pos_and_orientation() { - - SGVec3d position = SGVec3d::fromGeod( _position_geod ); - SGVec3d pos_offs = SGVec3d::fromGeod( _smgr->get_position_geod() ); - - // The rotation rotating from the earth centerd frame to - // the horizontal local frame - SGQuatd hlOr = SGQuatd::fromLonLat(_position_geod); - - // Rotate the x-forward, y-right, z-down coordinate system - // into the OpenGL camera system with x-right, y-up, z-back. - SGQuatd q(-0.5, -0.5, 0.5, 0.5); - - // Compute the sounds orientation and position - // wrt the earth centered frame - that is global coorinates - SGQuatd sc2body = hlOr*_orientation*q; - - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_position( position - pos_offs ); - sample->set_orientation( _orientation ); - sample->set_rotation( sc2body ); - } -} - void SGSampleGroup::set_volume( float vol ) { _volume = vol; @@ -376,13 +348,27 @@ void SGSampleGroup::set_volume( float vol ) } } +// set the source position and orientation of all managed sounds +void SGSampleGroup::update_pos_and_orientation() { + + SGVec3d position = _base_pos - _smgr->get_position(); + + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_position( position ); + sample->set_orientation( _orientation ); + } +} + void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { SGVec3f orientation, velocity; SGVec3d position; if ( _tied_to_listener ) { orientation = _smgr->get_direction(); - position = _smgr->get_position(); + position = SGVec3d::zeros(); velocity = _smgr->get_velocity(); } else { sample->update_pos_and_orientation(); diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index c13883b3..e6bb10e2 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -197,7 +197,7 @@ public: * @param pos Base position */ void set_position_geod( const SGGeod& pos ) { - _position_geod = pos; _changed = true; + _base_pos = SGVec3d::fromGeod( pos ); _changed = true; } /** @@ -225,8 +225,8 @@ private: bool _tied_to_listener; SGVec3f _velocity; + SGVec3d _base_pos; SGQuatd _orientation; - SGGeod _position_geod; sample_map _samples; std::vector< SGSharedPtr > _removed_samples; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 0d00083c..4abbb7cb 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -48,7 +48,6 @@ SGSoundSample::SGSoundSample() : _direction(SGVec3d::zeros()), _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), - _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), _refname(random_string()), @@ -83,7 +82,6 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _direction(SGVec3d::zeros()), _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), - _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), _refname(file), @@ -124,7 +122,6 @@ SGSoundSample::SGSoundSample( const unsigned char** data, _direction(SGVec3d::zeros()), _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), - _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), _refname(random_string()), @@ -160,7 +157,6 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : _direction(SGVec3d::zeros()), _velocity(SGVec3f::zeros()), _orientation(SGQuatd::zeros()), - _rotation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), _refname(random_string()), @@ -199,11 +195,11 @@ void SGSoundSample::update_pos_and_orientation() { _absolute_pos = _base_pos; if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { - _absolute_pos += _rotation.backTransform(_relative_pos); + _absolute_pos += _orientation.backTransform(_relative_pos); } if ( _direction[0] || _direction[1] || _direction[2] ) { - _orivec = toVec3f( _rotation.rotate(_direction) ); + _orivec = toVec3f( _orientation.rotate(_direction) ); } else _orivec = SGVec3f::zeros(); diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index cef5889d..9a4cb06a 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -337,14 +337,6 @@ public: _orientation = ori; _changed = true; } - /** - * Set the rotation quatgernion of this sound. - * @param rotation Quaternion containing the rotation information - */ - inline void set_rotation( const SGQuatd& rotation ) { - _rotation = rotation; _changed = true; - } - /** * Set direction of this sound relative to the orientation. * This is in the same coordinate system as OpenGL; y=up, z=back, x=right @@ -461,7 +453,6 @@ private: // The position and orientation of this sound SGQuatd _orientation; // base orientation - SGQuatd _rotation; // rotation vector for relative offsets SGVec3f _orivec; // orientation vector for OpenAL SGVec3d _base_pos; // base position diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 76b3f138..1cb6c409 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -63,7 +63,6 @@ SGSoundMgr::SGSoundMgr() : _volume(0.0), _device(NULL), _context(NULL), - _position_geod(SGGeod::fromDeg(0,0)), _absolute_pos(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), @@ -462,9 +461,6 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) } void SGSoundMgr::update_pos_and_orientation() { - // cartesian position of the listener - _absolute_pos = SGVec3d::fromGeod( _position_geod ); - /** * Description: ORIENTATION is a pair of 3-tuples representing the * 'at' direction vector and 'up' direction of the Object in diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 1be7eebd..676d6d53 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -157,7 +157,7 @@ public: * @param pos OpenAL listener position */ void set_position_geod( const SGGeod& pos ) { - _position_geod = pos; _changed = true; + _absolute_pos = SGVec3d::fromGeod( pos ); _changed = true; } /** @@ -166,7 +166,6 @@ public: * @return OpenAL listener position */ SGVec3d& get_position() { return _absolute_pos; } - SGGeod& get_position_geod() { return _position_geod; } /** * Set the velocity vector (in meters per second) of the sound manager @@ -281,7 +280,6 @@ private: ALCcontext *_context; // Position of the listener. - SGGeod _position_geod; SGVec3d _absolute_pos; // Velocity of the listener. diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 29bf06b5..fcfe41e5 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -230,8 +230,8 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGPropertyNode_ptr prop = node->getChild("position"); if ( prop != NULL ) { offset_pos[0] = prop->getDoubleValue("y", 0.0); - offset_pos[1] = prop->getDoubleValue("z", 0.0); - offset_pos[2] = prop->getDoubleValue("x", 0.0); + offset_pos[1] = -prop->getDoubleValue("z", 0.0); + offset_pos[2] = -prop->getDoubleValue("x", 0.0); } // @@ -244,8 +244,8 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, prop = node->getChild("orientation"); if ( prop != NULL ) { dir = SGVec3f(prop->getFloatValue("y", 0.0), - prop->getFloatValue("z", 0.0), - prop->getFloatValue("x", 0.0)); + -prop->getFloatValue("z", 0.0), + -prop->getFloatValue("x", 0.0)); inner = prop->getFloatValue("inner-angle", 360.0); outer = prop->getFloatValue("outer-angle", 360.0); outer_gain = prop->getFloatValue("outer-gain", 0.0); From b1571e4437696063f9bdc6d2786f2cf626ddd7a1 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 3 Nov 2009 09:59:19 +0000 Subject: [PATCH 57/85] some small fixes --- simgear/sound/sample_openal.hxx | 10 ++++------ simgear/sound/soundmgr_openal.hxx | 4 ++-- simgear/sound/xmlsound.cxx | 12 ++++++------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 9a4cb06a..d1965601 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -285,7 +285,7 @@ public: * Set the frequency (in Herz) of this audio sample. * @param freq Frequency */ - inline void set_frequency( int freq ) { _freq = freq; _changed = true; } + inline void set_frequency( int freq ) { _freq = freq; } /** * Returns the frequency (in Herz) of this audio sample. @@ -343,20 +343,18 @@ public: * @param dir Sound emission direction */ inline void set_direction( const SGVec3f& dir ) { - _direction = toVec3d(dir); _changed = true; + _direction = toVec3d(dir); _static_changed = true; } /** * Define the audio cone parameters for directional audio. - * Note: setting it to 1 degree will result in 0.5 degrees to both sides. + * Note: setting it to 2 degree will result in 1 degree to both sides. * @param inner Inner cone angle (0 - 360 degrees) * @param outer Outer cone angle (0 - 360 degrees) * @param gain Remaining gain at the edge of the outer cone (0.0 - 1.0) */ void set_audio_cone( float inner, float outer, float gain ) { - _inner_angle = inner; - _outer_angle = outer; - _outer_gain = gain; + _inner_angle = inner; _outer_angle = outer; _outer_gain = gain; _static_changed = true; } diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 676d6d53..c24afc57 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -156,8 +156,8 @@ public: * Set the Geodetic position of the sound manager. * @param pos OpenAL listener position */ - void set_position_geod( const SGGeod& pos ) { - _absolute_pos = SGVec3d::fromGeod( pos ); _changed = true; + void set_position( const SGVec3d& pos ) { + _absolute_pos = pos; _changed = true; } /** diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index fcfe41e5..9ef15ca4 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -229,9 +229,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGVec3f offset_pos = SGVec3f::zeros(); SGPropertyNode_ptr prop = node->getChild("position"); if ( prop != NULL ) { - offset_pos[0] = prop->getDoubleValue("y", 0.0); - offset_pos[1] = -prop->getDoubleValue("z", 0.0); - offset_pos[2] = -prop->getDoubleValue("x", 0.0); + offset_pos[0] = -prop->getDoubleValue("x", 0.0); + offset_pos[1] = prop->getDoubleValue("y", 0.0); + offset_pos[2] = -prop->getDoubleValue("z", 0.0); } // @@ -243,9 +243,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, float outer_gain = 0.0; prop = node->getChild("orientation"); if ( prop != NULL ) { - dir = SGVec3f(prop->getFloatValue("y", 0.0), - -prop->getFloatValue("z", 0.0), - -prop->getFloatValue("x", 0.0)); + dir = SGVec3f(-prop->getFloatValue("x", 0.0), + prop->getFloatValue("y", 0.0), + -prop->getFloatValue("z", 0.0)); inner = prop->getFloatValue("inner-angle", 360.0); outer = prop->getFloatValue("outer-angle", 360.0); outer_gain = prop->getFloatValue("outer-gain", 0.0); From 346a22f684eb900f56b9d862c9fbd2010219d4ec Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 3 Nov 2009 10:16:46 +0000 Subject: [PATCH 58/85] adjust to recent changes --- simgear/sound/openal_test3.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/simgear/sound/openal_test3.cxx b/simgear/sound/openal_test3.cxx index dccbd3d5..9377dcef 100644 --- a/simgear/sound/openal_test3.cxx +++ b/simgear/sound/openal_test3.cxx @@ -22,7 +22,6 @@ int main( int argc, char *argv[] ) { smgr->init(); sgr = smgr->find("default", true); smgr->set_volume(0.9); - smgr->set_position_geod( SGGeod::fromDeg(0,0) ); smgr->activate(); printf("default position and orientation\n"); @@ -39,8 +38,8 @@ int main( int argc, char *argv[] ) { sleep(1); printf("source at lat,lon = (10,-10), listener at (9.99,-9.99)\n"); - sample1->set_position_geod( SGGeod::fromDeg(10,-10) ); - smgr->set_position( SGGeod::fromDeg(9.99,-9.99) ); + sample1->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(10,-10)) ); + smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(9.99,-9.99)) ); sample1->play_looped(); smgr->update(1.0); printf("playing sample\n"); From 8d551c266430b283da04e1a9e4fdf70e8f63362f Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 3 Nov 2009 11:42:32 +0000 Subject: [PATCH 59/85] fix directional sound orientation --- simgear/sound/sample_group.cxx | 2 ++ simgear/sound/sample_group.hxx | 2 ++ simgear/sound/sample_openal.cxx | 8 ++++++-- simgear/sound/sample_openal.hxx | 6 ++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 6cccf634..c10d2dce 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -352,6 +352,7 @@ void SGSampleGroup::set_volume( float vol ) void SGSampleGroup::update_pos_and_orientation() { SGVec3d position = _base_pos - _smgr->get_position(); + SGQuatd hlOr = SGQuatd::fromLonLat(_position_geod) * _orientation; sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); @@ -359,6 +360,7 @@ void SGSampleGroup::update_pos_and_orientation() { SGSoundSample *sample = sample_current->second; sample->set_position( position ); sample->set_orientation( _orientation ); + sample->set_rotation( hlOr ); } } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index e6bb10e2..f4ae23d2 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -197,6 +197,7 @@ public: * @param pos Base position */ void set_position_geod( const SGGeod& pos ) { + _position_geod = pos; _base_pos = SGVec3d::fromGeod( pos ); _changed = true; } @@ -226,6 +227,7 @@ private: SGVec3f _velocity; SGVec3d _base_pos; + SGGeod _position_geod; SGQuatd _orientation; sample_map _samples; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 4abbb7cb..f716f4a1 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -50,6 +50,7 @@ SGSoundSample::SGSoundSample() : _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), + _rotation(SGQuatd::zeros()), _refname(random_string()), _data(NULL), _format(AL_FORMAT_MONO8), @@ -84,6 +85,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), + _rotation(SGQuatd::zeros()), _refname(file), _data(NULL), _format(AL_FORMAT_MONO8), @@ -124,6 +126,7 @@ SGSoundSample::SGSoundSample( const unsigned char** data, _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), + _rotation(SGQuatd::zeros()), _refname(random_string()), _format(format), _size(len), @@ -159,6 +162,7 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : _orientation(SGQuatd::zeros()), _orivec(SGVec3f::zeros()), _base_pos(SGVec3d::zeros()), + _rotation(SGQuatd::zeros()), _refname(random_string()), _format(format), _size(len), @@ -195,11 +199,11 @@ void SGSoundSample::update_pos_and_orientation() { _absolute_pos = _base_pos; if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { - _absolute_pos += _orientation.backTransform(_relative_pos); + _absolute_pos += _rotation.backTransform(_relative_pos); } if ( _direction[0] || _direction[1] || _direction[2] ) { - _orivec = toVec3f( _orientation.rotate(_direction) ); + _orivec = toVec3f(_rotation.rotate(_direction) ); } else _orivec = SGVec3f::zeros(); diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index d1965601..f8516018 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -337,6 +337,10 @@ public: _orientation = ori; _changed = true; } + inline void set_rotation( const SGQuatd& ori ) { + _rotation = ori; _changed = true; + } + /** * Set direction of this sound relative to the orientation. * This is in the same coordinate system as OpenGL; y=up, z=back, x=right @@ -454,6 +458,8 @@ private: SGVec3f _orivec; // orientation vector for OpenAL SGVec3d _base_pos; // base position + SGQuatd _rotation; + std::string _refname; // name or file path unsigned char* _data; From 0f39f05fa13b0cf185f0a2b5a7b1f262d72a4b35 Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 4 Nov 2009 10:25:59 +0000 Subject: [PATCH 60/85] small fixes --- simgear/environment/visual_enviro.cxx | 4 ++-- simgear/sound/sample_group.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/simgear/environment/visual_enviro.cxx b/simgear/environment/visual_enviro.cxx index e18ebede..b0cb2190 100644 --- a/simgear/environment/visual_enviro.cxx +++ b/simgear/environment/visual_enviro.cxx @@ -755,8 +755,8 @@ void SGEnviro::drawLightning(void) { ay = sin(course) * dist; SGSharedPtr snd = sampleGroup->find("thunder"); if( snd ) { - SGVec3f pos = SGVec3f(ax, ay, -sgEnviro.last_alt); - snd->set_relative_position(pos); + SGVec3d pos = SGVec3d(ax, ay, -sgEnviro.last_alt); + snd->set_position(pos); snd->play_once(); } } diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index c10d2dce..539ab61b 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -114,7 +114,7 @@ void SGSampleGroup::update( double dt ) { } // Update the position and orientation information for all samples. - if ( _changed ) { + if ( _changed || _smgr->has_changed() ) { update_pos_and_orientation(); _changed = false; } From 59df72c4b07bb7873f39f9a7b4ce1948c52e550a Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 9 Nov 2009 10:28:21 +0000 Subject: [PATCH 61/85] allow sound effects in the configuration file to be added to the 'avionics' sample group by setting 'avionics'. --- simgear/sound/xmlsound.cxx | 14 ++++++++++++-- simgear/sound/xmlsound.hxx | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 9ef15ca4..7fa893d8 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -82,7 +82,8 @@ SGXmlSound::~SGXmlSound() void SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, - SGSampleGroup *sgrp, const string &path) + SGSampleGroup *sgrp, SGSampleGroup *avionics, + const string &path) { // @@ -103,6 +104,11 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, _mode = SGXmlSound::ONCE; } + bool is_avionics = false; + const char *type_str = node->getStringValue("type", "fx"); + if ( !strcmp(type_str, "avionics") ) + is_avionics = true; + _property = root->getNode(node->getStringValue("property", ""), true); SGPropertyNode *condition = node->getChild("condition"); if (condition != NULL) @@ -254,7 +260,11 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, // // Initialize the sample // - _sgrp = sgrp; + if (is_avionics) { + _sgrp = avionics; + } else { + _sgrp = sgrp; + } _sample = new SGSoundSample( path.c_str(), node->getStringValue("path", "")); _sample->set_relative_position( offset_pos ); _sample->set_direction( dir ); diff --git a/simgear/sound/xmlsound.hxx b/simgear/sound/xmlsound.hxx index b5bc1f9f..141f5eef 100644 --- a/simgear/sound/xmlsound.hxx +++ b/simgear/sound/xmlsound.hxx @@ -100,10 +100,11 @@ public: * @param child A pointer to the location of the current event as defined * in the configuration file. * @param sgrp A pointer to a pre-initialized sample group class. + * @param avionics A pointer to the pre-initialized avionics sample group. * @param path The path where the audio files remain. */ virtual void init (SGPropertyNode *, SGPropertyNode *, SGSampleGroup *, - const string &); + SGSampleGroup *, const string &); /** * Check whether an event has happened and if action has to be taken. From 5b2af1f6b353078e0662453bb74bc7d80dc31a6b Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 10 Nov 2009 14:28:28 +0000 Subject: [PATCH 62/85] also recalculate the velocity in update_pos_and_orienation, so pass the north-east-down velocity directly and orientate position, orientation and velocity to OpenGL/OpenAL frames (x-right, y-up and z-back) --- simgear/sound/sample_group.cxx | 37 +++++++++++-------------------- simgear/sound/sample_group.hxx | 12 +++++----- simgear/sound/sample_openal.cxx | 4 ++-- simgear/sound/soundmgr_openal.hxx | 2 +- simgear/sound/xmlsound.cxx | 8 +++---- 5 files changed, 26 insertions(+), 37 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 539ab61b..f76d98b9 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -41,7 +41,6 @@ SGSampleGroup::SGSampleGroup () : _pause(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), - _base_pos(SGVec3d::zeros()), _orientation(SGQuatd::zeros()) { _samples.clear(); @@ -55,7 +54,6 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _pause(false), _tied_to_listener(false), _velocity(SGVec3d::zeros()), - _base_pos(SGVec3d::zeros()), _orientation(SGQuatd::zeros()) { _smgr->add(this, refname); @@ -315,25 +313,6 @@ bool SGSampleGroup::stop( const string& refname ) { return true; } -// set source velocity of all managed sounds -void SGSampleGroup::set_velocity( const SGVec3f &vel ) { - if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) - { - SG_LOG( SG_GENERAL, SG_ALERT, "NAN's found in SampleGroup velocity"); - return; - } - - if (_velocity != vel) { - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_velocity( vel ); - } - _velocity = vel; - } -} - void SGSampleGroup::set_volume( float vol ) { _volume = vol; @@ -351,16 +330,26 @@ void SGSampleGroup::set_volume( float vol ) // set the source position and orientation of all managed sounds void SGSampleGroup::update_pos_and_orientation() { - SGVec3d position = _base_pos - _smgr->get_position(); - SGQuatd hlOr = SGQuatd::fromLonLat(_position_geod) * _orientation; + static const SGQuatd q(-0.5, -0.5, 0.5, 0.5); + + SGVec3d position = SGVec3d::fromGeod(_base_pos) - _smgr->get_position(); + + SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos); + SGQuatd ec2gl = hlOr*_orientation*q; + + SGVec3f velocity = SGVec3f::zeros(); + if ( _velocity[0] || _velocity[1] || _velocity[2] ) { + velocity = toVec3f( (hlOr*q).backTransform(_velocity) ); + } sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { SGSoundSample *sample = sample_current->second; sample->set_position( position ); + sample->set_velocity( velocity ); sample->set_orientation( _orientation ); - sample->set_rotation( hlOr ); + sample->set_rotation( ec2gl ); } } diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index f4ae23d2..c0b0fdc6 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -189,7 +189,9 @@ public: * This is in the local frame coordinate system; x=north, y=east, z=down * @param vel Velocity vector */ - void set_velocity( const SGVec3f& vel ); + void set_velocity( const SGVec3d& vel ) { + _velocity = vel; _changed = true; + } /** * Set the position of this sample group. @@ -197,8 +199,7 @@ public: * @param pos Base position */ void set_position_geod( const SGGeod& pos ) { - _position_geod = pos; - _base_pos = SGVec3d::fromGeod( pos ); _changed = true; + _base_pos = pos; _changed = true; } /** @@ -225,9 +226,8 @@ private: float _volume; bool _tied_to_listener; - SGVec3f _velocity; - SGVec3d _base_pos; - SGGeod _position_geod; + SGVec3d _velocity; + SGGeod _base_pos; SGQuatd _orientation; sample_map _samples; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index f716f4a1..2c87ec22 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -199,11 +199,11 @@ void SGSoundSample::update_pos_and_orientation() { _absolute_pos = _base_pos; if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { - _absolute_pos += _rotation.backTransform(_relative_pos); + _absolute_pos += _rotation.backTransform( _relative_pos ); } if ( _direction[0] || _direction[1] || _direction[2] ) { - _orivec = toVec3f(_rotation.rotate(_direction) ); + _orivec = toVec3f( _rotation.rotate(_direction) ); } else _orivec = SGVec3f::zeros(); diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index c24afc57..6a4df530 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -153,7 +153,7 @@ public: SGSampleGroup *find( const string& refname, bool create = false ); /** - * Set the Geodetic position of the sound manager. + * Set the Cartesian position of the sound manager. * @param pos OpenAL listener position */ void set_position( const SGVec3d& pos ) { diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 7fa893d8..88bef765 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -235,9 +235,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGVec3f offset_pos = SGVec3f::zeros(); SGPropertyNode_ptr prop = node->getChild("position"); if ( prop != NULL ) { - offset_pos[0] = -prop->getDoubleValue("x", 0.0); + offset_pos[0] = prop->getDoubleValue("z", 0.0); offset_pos[1] = prop->getDoubleValue("y", 0.0); - offset_pos[2] = -prop->getDoubleValue("z", 0.0); + offset_pos[2] = prop->getDoubleValue("x", 0.0); } // @@ -249,9 +249,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, float outer_gain = 0.0; prop = node->getChild("orientation"); if ( prop != NULL ) { - dir = SGVec3f(-prop->getFloatValue("x", 0.0), + dir = SGVec3f(prop->getFloatValue("z", 0.0), prop->getFloatValue("y", 0.0), - -prop->getFloatValue("z", 0.0)); + prop->getFloatValue("x", 0.0)); inner = prop->getFloatValue("inner-angle", 360.0); outer = prop->getFloatValue("outer-angle", 360.0); outer_gain = prop->getFloatValue("outer-gain", 0.0); From e3f70b712545bc42a43175a2a88174dacce9ce73 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 12 Nov 2009 20:41:19 +0000 Subject: [PATCH 63/85] temporarily remove listener (viewer) and source offsets. they mess things up --- simgear/sound/sample_group.cxx | 38 ++++++++++++------------------- simgear/sound/sample_openal.cxx | 7 +++--- simgear/sound/sample_openal.hxx | 4 ++-- simgear/sound/soundmgr_openal.cxx | 12 ++++++++++ simgear/sound/soundmgr_openal.hxx | 8 ++++++- 5 files changed, 39 insertions(+), 30 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index f76d98b9..e56d37e5 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -318,38 +318,28 @@ void SGSampleGroup::set_volume( float vol ) _volume = vol; if (_volume < 0.0) _volume = 0.0; if (_volume > 1.0) _volume = 1.0; +} + +// set the source position and orientation of all managed sounds +void SGSampleGroup::update_pos_and_orientation() { + + SGVec3d position = SGVec3d::fromGeod(_base_pos) - _smgr->get_position(); + SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos) * _orientation; + + SGVec3f velocity = SGVec3f::zeros(); + if ( _velocity[0] || _velocity[1] || _velocity[2] ) { + velocity = toVec3f( hlOr.backTransform(_velocity*SG_FEET_TO_METER) ); + } sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { SGSoundSample *sample = sample_current->second; sample->set_master_volume( _volume ); - } -} - -// set the source position and orientation of all managed sounds -void SGSampleGroup::update_pos_and_orientation() { - - static const SGQuatd q(-0.5, -0.5, 0.5, 0.5); - - SGVec3d position = SGVec3d::fromGeod(_base_pos) - _smgr->get_position(); - - SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos); - SGQuatd ec2gl = hlOr*_orientation*q; - - SGVec3f velocity = SGVec3f::zeros(); - if ( _velocity[0] || _velocity[1] || _velocity[2] ) { - velocity = toVec3f( (hlOr*q).backTransform(_velocity) ); - } - - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; + sample->set_orientation( _orientation ); + sample->set_rotation( hlOr ); sample->set_position( position ); sample->set_velocity( velocity ); - sample->set_orientation( _orientation ); - sample->set_rotation( ec2gl ); } } diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 2c87ec22..21e7cf71 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -198,15 +198,16 @@ SGSoundSample::~SGSoundSample() { void SGSoundSample::update_pos_and_orientation() { _absolute_pos = _base_pos; +#if 0 if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { _absolute_pos += _rotation.backTransform( _relative_pos ); } +#endif + _orivec = SGVec3f::zeros(); if ( _direction[0] || _direction[1] || _direction[2] ) { - _orivec = toVec3f( _rotation.rotate(_direction) ); + _orivec = toVec3f( _rotation.rotate( _direction ) ); } - else - _orivec = SGVec3f::zeros(); } string SGSoundSample::random_string() { diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index f8516018..b1d0cf99 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -337,8 +337,8 @@ public: _orientation = ori; _changed = true; } - inline void set_rotation( const SGQuatd& ori ) { - _rotation = ori; _changed = true; + inline void set_rotation( const SGQuatd& hlOr ) { + _rotation = hlOr; _changed = true; } /** diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 1cb6c409..4cf3a63c 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -64,6 +64,8 @@ SGSoundMgr::SGSoundMgr() : _device(NULL), _context(NULL), _absolute_pos(SGVec3d::zeros()), + _offset_pos(SGVec3d::zeros()), + _base_pos(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _devname(NULL) @@ -244,6 +246,10 @@ void SGSoundMgr::unbind () // 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 ) { @@ -469,6 +475,7 @@ void SGSoundMgr::update_pos_and_orientation() { * 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()); @@ -479,6 +486,11 @@ void SGSoundMgr::update_pos_and_orientation() { _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, diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 6a4df530..ecfd2637 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -157,7 +157,11 @@ public: * @param pos OpenAL listener position */ void set_position( const SGVec3d& pos ) { - _absolute_pos = pos; _changed = true; + _base_pos = pos; _changed = true; + } + + void set_position_offset( const SGVec3d& pos ) { + _offset_pos = pos; _changed = true; } /** @@ -281,6 +285,8 @@ private: // Position of the listener. SGVec3d _absolute_pos; + SGVec3d _offset_pos; + SGVec3d _base_pos; // Velocity of the listener. SGVec3f _velocity; From bb46d91bc617be168074f5575581564ae50c0246 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 16 Nov 2009 13:32:34 +0000 Subject: [PATCH 64/85] What do you know, the real problem turned out to be the distance attenuation function.. --- simgear/sound/sample_group.cxx | 6 +++--- simgear/sound/sample_openal.cxx | 9 +++------ simgear/sound/sample_openal.hxx | 4 ++-- simgear/sound/soundmgr_openal.cxx | 3 ++- simgear/sound/xmlsound.cxx | 12 ++++++------ 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index e56d37e5..dfe8d756 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -324,11 +324,11 @@ void SGSampleGroup::set_volume( float vol ) void SGSampleGroup::update_pos_and_orientation() { SGVec3d position = SGVec3d::fromGeod(_base_pos) - _smgr->get_position(); - SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos) * _orientation; + SGQuatd ec2body= SGQuatd::fromLonLat(_base_pos) * _orientation; SGVec3f velocity = SGVec3f::zeros(); if ( _velocity[0] || _velocity[1] || _velocity[2] ) { - velocity = toVec3f( hlOr.backTransform(_velocity*SG_FEET_TO_METER) ); + velocity = toVec3f( ec2body.backTransform(_velocity*SG_FEET_TO_METER) ); } sample_map_iterator sample_current = _samples.begin(); @@ -337,7 +337,7 @@ void SGSampleGroup::update_pos_and_orientation() { SGSoundSample *sample = sample_current->second; sample->set_master_volume( _volume ); sample->set_orientation( _orientation ); - sample->set_rotation( hlOr ); + sample->set_rotation( ec2body ); sample->set_position( position ); sample->set_velocity( velocity ); } diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 21e7cf71..08eec611 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -197,12 +197,9 @@ SGSoundSample::~SGSoundSample() { void SGSoundSample::update_pos_and_orientation() { - _absolute_pos = _base_pos; -#if 0 - if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { - _absolute_pos += _rotation.backTransform( _relative_pos ); - } -#endif + // position is in basic view, no need to rotate + // (proper alignment is set in xmlsound) + _absolute_pos = _base_pos + _relative_pos; _orivec = SGVec3f::zeros(); if ( _direction[0] || _direction[1] || _direction[2] ) { diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index b1d0cf99..a4091d29 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -337,8 +337,8 @@ public: _orientation = ori; _changed = true; } - inline void set_rotation( const SGQuatd& hlOr ) { - _rotation = hlOr; _changed = true; + inline void set_rotation( const SGQuatd& ec2body ) { + _rotation = ec2body; _changed = true; } /** diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 4cf3a63c..ef4a8f15 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -133,11 +133,13 @@ void SGSoundMgr::init() { alDopplerFactor(1.0); alDopplerVelocity(340.3); // speed of sound in meters per second. +#if 0 if ( alIsExtensionPresent((const ALchar*)"EXT_exponent_distance") ) { alDistanceModel(AL_EXPONENT_DISTANCE); } else { alDistanceModel(AL_INVERSE_DISTANCE); } +#endif testForALError("listener initialization"); @@ -263,7 +265,6 @@ 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 - update_pos_and_orientation(); alListenerf( AL_GAIN, _volume ); alListenerfv( AL_ORIENTATION, _at_up_vec ); // alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() ); diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 88bef765..79a57c7f 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -235,9 +235,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, SGVec3f offset_pos = SGVec3f::zeros(); SGPropertyNode_ptr prop = node->getChild("position"); if ( prop != NULL ) { - offset_pos[0] = prop->getDoubleValue("z", 0.0); - offset_pos[1] = prop->getDoubleValue("y", 0.0); - offset_pos[2] = prop->getDoubleValue("x", 0.0); + offset_pos[0] = -prop->getDoubleValue("x", 0.0); + offset_pos[1] = -prop->getDoubleValue("y", 0.0); + offset_pos[2] = -prop->getDoubleValue("z", 0.0); } // @@ -249,9 +249,9 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, float outer_gain = 0.0; prop = node->getChild("orientation"); if ( prop != NULL ) { - dir = SGVec3f(prop->getFloatValue("z", 0.0), - prop->getFloatValue("y", 0.0), - prop->getFloatValue("x", 0.0)); + dir = SGVec3f(-prop->getFloatValue("x", 0.0), + -prop->getFloatValue("y", 0.0), + -prop->getFloatValue("z", 0.0)); inner = prop->getFloatValue("inner-angle", 360.0); outer = prop->getFloatValue("outer-angle", 360.0); outer_gain = prop->getFloatValue("outer-gain", 0.0); From 6cd8db7b28b675f75ab22c2073832980d9f8d6a4 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 17 Nov 2009 13:06:32 +0000 Subject: [PATCH 65/85] Set to default distance attenuation function but change the parameters a but for better sound effects (and most of all quieter sounds at greta distance --- simgear/sound/sample_group.cxx | 2 +- simgear/sound/soundmgr_openal.cxx | 10 +++------- simgear/sound/xmlsound.cxx | 7 ++++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index dfe8d756..bd1bf485 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -144,7 +144,7 @@ void SGSampleGroup::update( double dt ) { ALboolean looping = sample->is_looping() ? AL_TRUE : AL_FALSE; alSourcei( source, AL_LOOPING, looping ); - alSourcef( source, AL_ROLLOFF_FACTOR, 1.0 ); + alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 ); alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE ); alSourcePlay( source ); testForALError("sample play"); diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index ef4a8f15..b9e86488 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -133,13 +133,9 @@ void SGSoundMgr::init() { alDopplerFactor(1.0); alDopplerVelocity(340.3); // speed of sound in meters per second. -#if 0 - if ( alIsExtensionPresent((const ALchar*)"EXT_exponent_distance") ) { - alDistanceModel(AL_EXPONENT_DISTANCE); - } else { - alDistanceModel(AL_INVERSE_DISTANCE); - } -#endif + // gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE + + // AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE)); + alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); testForALError("listener initialization"); diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 79a57c7f..479e3123 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -174,9 +174,10 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, } - float reference_dist = node->getDoubleValue("reference-dist", 500.0); - float max_dist = node->getDoubleValue("max-dist", 3000.0); - + // rule of thumb: make reference distance a 100th of the maximum distance. + float reference_dist = node->getDoubleValue("reference-dist", 60.0); + float max_dist = node->getDoubleValue("max-dist", 6000.0); + // // set pitch properties // From 01c62932bd25bb0a388fffa5d3f0b84f24bf196a Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 18 Nov 2009 13:49:25 +0000 Subject: [PATCH 66/85] make the relative positions fixed against the body again. --- simgear/sound/sample_openal.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 08eec611..db7cd465 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -197,9 +197,10 @@ SGSoundSample::~SGSoundSample() { void SGSoundSample::update_pos_and_orientation() { - // position is in basic view, no need to rotate - // (proper alignment is set in xmlsound) - _absolute_pos = _base_pos + _relative_pos; + _absolute_pos = _base_pos; + if (_relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { + _absolute_pos += _rotation.rotate( _relative_pos ); + } _orivec = SGVec3f::zeros(); if ( _direction[0] || _direction[1] || _direction[2] ) { From afb18ca75b90e5a2e0bf791ba2e38812128ab0a8 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 19 Nov 2009 15:29:34 +0000 Subject: [PATCH 67/85] the wrong name also mislead me: rotate velocity to the proper quat --- simgear/sound/sample_group.cxx | 5 +++-- simgear/sound/soundmgr_openal.cxx | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index bd1bf485..f3846631 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -324,11 +324,12 @@ void SGSampleGroup::set_volume( float vol ) void SGSampleGroup::update_pos_and_orientation() { SGVec3d position = SGVec3d::fromGeod(_base_pos) - _smgr->get_position(); - SGQuatd ec2body= SGQuatd::fromLonLat(_base_pos) * _orientation; + SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos); + SGQuatd ec2body = hlOr*_orientation; SGVec3f velocity = SGVec3f::zeros(); if ( _velocity[0] || _velocity[1] || _velocity[2] ) { - velocity = toVec3f( ec2body.backTransform(_velocity*SG_FEET_TO_METER) ); + velocity = toVec3f( hlOr.backTransform(_velocity*SG_FEET_TO_METER) ); } sample_map_iterator sample_current = _samples.begin(); diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index b9e86488..6066a560 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -323,6 +323,7 @@ SGSampleGroup *SGSoundMgr::find( const string &refname, bool create ) { // sample group was not found. if (create) { SGSampleGroup* sgrp = new SGSampleGroup(this, refname); + add( sgrp, refname ); return sgrp; } else From 7c693d81076bef2b6e028179774256ab8393d707 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 23 Nov 2009 09:35:12 +0000 Subject: [PATCH 68/85] proper listener velocity calculation, this has no effect yet but is required when other models start emitting sounds. --- simgear/sound/sample_group.cxx | 3 ++- simgear/sound/soundmgr_openal.cxx | 9 ++++++++- simgear/sound/soundmgr_openal.hxx | 11 ++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index f3846631..9f486413 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -361,7 +361,8 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { #if 0 if (length(position) > 20000) - printf("source and listener distance greater than 20km!\n"); + printf("%s source and listener distance greater than 20km!\n", + _refname.c_str()); if (isNaN(toVec3f(position).data())) printf("NaN in source position\n"); if (isNaN(orientation.data())) printf("NaN in source orientation\n"); if (isNaN(velocity.data())) printf("NaN in source velocity\n"); diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 6066a560..ebd3a4b4 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -66,6 +66,7 @@ SGSoundMgr::SGSoundMgr() : _absolute_pos(SGVec3d::zeros()), _offset_pos(SGVec3d::zeros()), _base_pos(SGVec3d::zeros()), + _geod_pos(SGGeod::fromCart(SGVec3d::zeros())), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _devname(NULL) @@ -264,7 +265,13 @@ if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); alListenerf( AL_GAIN, _volume ); alListenerfv( AL_ORIENTATION, _at_up_vec ); // alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() ); - alListenerfv( AL_VELOCITY, _velocity.data() ); + + 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); + } + alListenerfv( AL_VELOCITY, toVec3f(velocity).data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); _changed = false; diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index ecfd2637..f3163018 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -156,8 +156,8 @@ public: * Set the Cartesian position of the sound manager. * @param pos OpenAL listener position */ - void set_position( const SGVec3d& pos ) { - _base_pos = pos; _changed = true; + 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 ) { @@ -176,7 +176,7 @@ public: * This is the horizontal local frame; x=north, y=east, z=down * @param Velocity vector */ - void set_velocity( const SGVec3f& vel ) { + void set_velocity( const SGVec3d& vel ) { _velocity = vel; _changed = true; } @@ -185,7 +185,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @return Velocity vector of the OpenAL listener */ - inline SGVec3f& get_velocity() { return _velocity; } + inline SGVec3f get_velocity() { return toVec3f(_velocity); } /** * Set the orientation of the sound manager @@ -287,9 +287,10 @@ private: SGVec3d _absolute_pos; SGVec3d _offset_pos; SGVec3d _base_pos; + SGGeod _geod_pos; // Velocity of the listener. - SGVec3f _velocity; + SGVec3d _velocity; // Orientation of the listener. // first 3 elements are "at" vector, second 3 are "up" vector From 5b28b024ae7f10371d4afd2f355db558c00d1966 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 23 Nov 2009 10:31:53 +0000 Subject: [PATCH 69/85] fix test programs --- simgear/sound/openal_test2.cxx | 3 ++- simgear/sound/openal_test3.cxx | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/simgear/sound/openal_test2.cxx b/simgear/sound/openal_test2.cxx index c28957b8..eb0da57e 100644 --- a/simgear/sound/openal_test2.cxx +++ b/simgear/sound/openal_test2.cxx @@ -11,6 +11,7 @@ #include "soundmgr_openal.hxx" +SGGeod pos = SGGeod::fromDeg(0,0); int main( int argc, char *argv[] ) { SGSampleGroup *sgr; @@ -22,7 +23,7 @@ int main( int argc, char *argv[] ) { smgr->init(); sgr = smgr->find("default", true); smgr->set_volume(0.9); - smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(0,0)) ); + smgr->set_position( SGVec3d::fromGeod(pos), pos ); smgr->activate(); SGSoundSample *sample1 = new SGSoundSample( SRC_DIR, "jet.wav" ); diff --git a/simgear/sound/openal_test3.cxx b/simgear/sound/openal_test3.cxx index 9377dcef..96a57a04 100644 --- a/simgear/sound/openal_test3.cxx +++ b/simgear/sound/openal_test3.cxx @@ -15,6 +15,7 @@ int main( int argc, char *argv[] ) { SGSampleGroup *sgr; SGSoundMgr *smgr; + SGGeod pos; smgr = new SGSoundMgr; @@ -38,8 +39,9 @@ int main( int argc, char *argv[] ) { sleep(1); printf("source at lat,lon = (10,-10), listener at (9.99,-9.99)\n"); + pos = SGGeod::fromDeg(9.99,-9.99); sample1->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(10,-10)) ); - smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(9.99,-9.99)) ); + smgr->set_position( SGVec3d::fromGeod(pos), pos ); sample1->play_looped(); smgr->update(1.0); printf("playing sample\n"); From 406cdf8d1678fd470f65b2a8ea09620c060e4c36 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 23 Nov 2009 10:32:26 +0000 Subject: [PATCH 70/85] test for implementations with 'bad' doppler effects and adjust for it. --- simgear/sound/sample_group.cxx | 4 ++++ simgear/sound/soundmgr_openal.cxx | 8 +++++++- simgear/sound/soundmgr_openal.hxx | 9 +++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 9f486413..1c76bfa6 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -359,6 +359,10 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { velocity = sample->get_velocity(); } + if (_smgr->bad_doppler_effect()) { + velocity *= 100.0f; + } + #if 0 if (length(position) > 20000) printf("%s source and listener distance greater than 20km!\n", diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index ebd3a4b4..ce415e29 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -69,7 +69,8 @@ SGSoundMgr::SGSoundMgr() : _geod_pos(SGGeod::fromCart(SGVec3d::zeros())), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), - _devname(NULL) + _devname(NULL), + _bad_doppler(false) { #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 if (_alut_init == 0) { @@ -155,6 +156,11 @@ void SGSoundMgr::init() { else break; } + const char *renderer = (char *)alGetString(AL_RENDERER); + if ( strcmp(renderer, "OpenAL Sample Implementation") ) { + _bad_doppler = true; + } + if (_free_sources.size() == 0) { SG_LOG(SG_GENERAL, SG_ALERT, "Unable to grab any OpenAL sources!"); } diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index f3163018..30801665 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -260,6 +260,14 @@ public: */ 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 @@ -304,6 +312,7 @@ private: vector _sources_in_use; char *_devname; + bool _bad_doppler; bool testForALError(string s); bool testForALCError(string s); From 878288f06a48db9330fa8b80e8e2db955b50b244 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 23 Nov 2009 11:54:33 +0000 Subject: [PATCH 71/85] Don't forget to apply the doppler adjustment factor to the listener velocity also --- simgear/sound/soundmgr_openal.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index ce415e29..531298ae 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -277,6 +277,11 @@ if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); if ( _velocity[0] || _velocity[1] || _velocity[2] ) { velocity = hlOr.backTransform(_velocity*SG_FEET_TO_METER); } + + if ( _bad_doppler ) { + velocity *= 100.0f; + } + alListenerfv( AL_VELOCITY, toVec3f(velocity).data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); From f6513127ce901831886fa7299ff9a236f8eca928 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 26 Nov 2009 12:19:57 +0000 Subject: [PATCH 72/85] Also test for older versions of OpenAL-Sample --- simgear/sound/soundmgr_openal.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 531298ae..010b548d 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -156,8 +156,10 @@ void SGSoundMgr::init() { else break; } + const char *vendor = (char *)alGetString(AL_VENDOR); const char *renderer = (char *)alGetString(AL_RENDERER); - if ( strcmp(renderer, "OpenAL Sample Implementation") ) { + if ( strcmp(vendor, "OpenAL Community") || strcmp(renderer, "Software") + || strcmp(renderer, "OpenAL Sample Implementation") ) { _bad_doppler = true; } From 0f21c39e496cf7ac83c0f87b85db9566e3e32689 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 26 Nov 2009 13:05:44 +0000 Subject: [PATCH 73/85] a slightly more readable version of the test --- simgear/sound/soundmgr_openal.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 010b548d..918b05da 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -156,10 +156,12 @@ void SGSoundMgr::init() { else break; } - const char *vendor = (char *)alGetString(AL_VENDOR); - const char *renderer = (char *)alGetString(AL_RENDERER); - if ( strcmp(vendor, "OpenAL Community") || strcmp(renderer, "Software") - || strcmp(renderer, "OpenAL Sample Implementation") ) { + string vendor = alGetString(AL_VENDOR); + string renderer = alGetString(AL_RENDERER); + if ( vendor != "OpenAL Community" || + (renderer != "Software" && renderer != "OpenAL Sample Implementation") + ) + { _bad_doppler = true; } From d70a05a088aa22989f2b658a60250c145e18aee9 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 28 Nov 2009 10:37:02 +0000 Subject: [PATCH 74/85] Make it possible to specify a different device name --- simgear/sound/soundmgr_openal.cxx | 12 +++++++----- simgear/sound/soundmgr_openal.hxx | 3 +-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 918b05da..f7199458 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -69,7 +69,6 @@ SGSoundMgr::SGSoundMgr() : _geod_pos(SGGeod::fromCart(SGVec3d::zeros())), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), - _devname(NULL), _bad_doppler(false) { #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 @@ -97,13 +96,16 @@ SGSoundMgr::~SGSoundMgr() { } // initialize the sound manager -void SGSoundMgr::init() { +void SGSoundMgr::init(const char *devname) { SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" ); - ALCdevice *device = alcOpenDevice(_devname); - if ( testForError(device, "No default audio device available.") ) { - return; + ALCdevice *device = alcOpenDevice(devname); + if ( testForError(device, "Audio device not available, trying default") ) { + ALCdevice *device = alcOpenDevice(NULL); + if (testForError(device, "Default Audio device not available.") ) { + return; + } } ALCcontext *context = alcCreateContext(device, NULL); diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 30801665..f1f9bd17 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -95,7 +95,7 @@ public: SGSoundMgr(); ~SGSoundMgr(); - void init(); + void init(const char *devname = NULL); void bind(); void unbind(); void update(double dt); @@ -311,7 +311,6 @@ private: vector _free_sources; vector _sources_in_use; - char *_devname; bool _bad_doppler; bool testForALError(string s); From 2dcc66f03ead9bb78719d26c7a760fda89c2c18b Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 28 Nov 2009 10:48:17 +0000 Subject: [PATCH 75/85] Small bugfix --- simgear/sound/soundmgr_openal.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index f7199458..692c7868 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -102,7 +102,7 @@ void SGSoundMgr::init(const char *devname) { ALCdevice *device = alcOpenDevice(devname); if ( testForError(device, "Audio device not available, trying default") ) { - ALCdevice *device = alcOpenDevice(NULL); + device = alcOpenDevice(NULL); if (testForError(device, "Default Audio device not available.") ) { return; } From 27a6c720917ae1fa9b517b294eba9a5790545e39 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 28 Nov 2009 12:59:40 +0000 Subject: [PATCH 76/85] initialize volume to a proper value --- simgear/sound/sample_group.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 1c76bfa6..3cd0d9ae 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -39,6 +39,7 @@ SGSampleGroup::SGSampleGroup () : _active(false), _changed(false), _pause(false), + _volume(1.0), _tied_to_listener(false), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()) @@ -52,6 +53,7 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _active(false), _changed(false), _pause(false), + _volume(1.0), _tied_to_listener(false), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()) From a0aaa23904a25b99eeae4911e3b9b77ed9d37845 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 28 Nov 2009 13:31:04 +0000 Subject: [PATCH 77/85] Add a function to retreive all available playback devices. --- simgear/sound/soundmgr_openal.cxx | 26 ++++++++++++++++++++++++++ simgear/sound/soundmgr_openal.hxx | 9 +++++++++ 2 files changed, 35 insertions(+) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 692c7868..2ccbcf55 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -562,6 +562,32 @@ bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, return true; } +vector SGSoundMgr::get_available_devices() +{ + vector devices; + const ALCchar *s; + + if (alcIsExtensionPresent(NULL, "ALC_enumerate_all_EXT") == AL_TRUE) { + s = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); + } else { + s = alcGetString(NULL, ALC_DEVICE_SPECIFIER); + } + + if (s) { + ALCchar *nptr, *ptr = (ALCchar *)s; + + nptr = ptr; + while (*(nptr += strlen(ptr)+1) != 0) + { + devices.push_back(ptr); + ptr = nptr; + } + devices.push_back(ptr); + } + + return devices; +} + bool SGSoundMgr::testForError(void *p, string s) { diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index f1f9bd17..2aa78bc5 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -59,6 +59,10 @@ # include #endif +#ifndef ALC_ALL_DEVICES_SPECIFIER +# define ALC_ALL_DEVICES_SPECIFIER 0x1013 +#endif + #include #include #include @@ -280,6 +284,11 @@ public: bool load(string &samplepath, void **data, int *format, size_t *size, int *freq ); + /** + * Get a list of available playback devices. + */ + vector get_available_devices(); + private: static int _alut_init; From bc85767f197d8e039333202199fc2a2cc4d6e1b1 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 30 Nov 2009 14:22:40 +0000 Subject: [PATCH 78/85] Updates to allow runtime chaning of the sound device --- simgear/sound/sample_group.cxx | 23 +++++++++++++++++++++++ simgear/sound/sample_group.hxx | 5 +++++ simgear/sound/soundmgr_openal.cxx | 10 +++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 3cd0d9ae..de173dbd 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -261,6 +261,29 @@ SGSampleGroup::suspend () testForALError("suspend"); } +void +SGSampleGroup::stop () +{ + _pause = true; + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + + if ( sample->is_valid_source() ) { + if ( sample->is_playing() ) { + alSourcePause( sample->get_source() ); + } + _smgr->release_source( sample->get_source() ); + sample->no_valid_source(); + + _smgr->release_buffer( sample ); + sample->no_valid_buffer(); + } + } + testForALError("suspend"); +} + // resume playing all associated samples void SGSampleGroup::resume () diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index c0b0fdc6..d2d47394 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -128,6 +128,11 @@ public: */ SGSoundSample *find( const string& refname ); + /** + * Stop all playing samples and set the source id to invalid. + */ + void stop(); + /** * Request to stop playing all audio samples until further notice. */ diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 2ccbcf55..6ead4d19 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -200,10 +200,18 @@ void SGSoundMgr::stop() { } _buffers.clear(); + 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(); + } + _context = alcGetCurrentContext(); _device = alcGetContextsDevice(_context); alcDestroyContext(_context); alcCloseDevice(_device); + _context = NULL; } } @@ -213,7 +221,7 @@ void SGSoundMgr::suspend() { 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->suspend(); + sgrp->stop(); } _active = false; } From 4794ab60952c8aed3d253504dea50557ad0f60c8 Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 2 Dec 2009 08:32:59 +0000 Subject: [PATCH 79/85] Fix runtime switching of sound devices. --- simgear/sound/sample_group.cxx | 10 ++++--- simgear/sound/soundmgr_openal.cxx | 45 ++++++++++++++++++------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index de173dbd..72ea9a53 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -271,17 +271,21 @@ SGSampleGroup::stop () SGSoundSample *sample = sample_current->second; if ( sample->is_valid_source() ) { + ALint source = sample->get_source(); if ( sample->is_playing() ) { - alSourcePause( sample->get_source() ); + alSourceStop( source ); + alSourcei( source, AL_BUFFER, 0 ); } - _smgr->release_source( sample->get_source() ); + _smgr->release_source( source ); sample->no_valid_source(); + } + if (sample->is_valid_buffer() ) { _smgr->release_buffer( sample ); sample->no_valid_buffer(); } } - testForALError("suspend"); + testForALError("stop"); } // resume playing all associated samples diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 6ead4d19..6100dfcf 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -186,27 +186,36 @@ void SGSoundMgr::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++) { + ALuint source = _free_sources[i]; + alDeleteSources( 1 , &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; + ALuint buffer = ref.id; + alDeleteBuffers(1, &buffer); + _buffers.erase( buffers_current ); + } + _buffers.clear(); + if (_working) { _working = false; _active = false; - - // 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; - ALuint buffer = ref.id; - alDeleteBuffers(1, &buffer); - } - _buffers.clear(); - - 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(); - } - _context = alcGetCurrentContext(); _device = alcGetContextsDevice(_context); alcDestroyContext(_context); From 47617d6c041cd806ae16944c2ace910c70981fe6 Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 2 Dec 2009 09:32:20 +0000 Subject: [PATCH 80/85] check if suspend, resume and volume changed much from the previous value before setting them. --- simgear/sound/sample_group.cxx | 63 +++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 72ea9a53..1da29059 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -244,23 +244,6 @@ SGSoundSample *SGSampleGroup::find( const string &refname ) { } -// stop playing all associated samples -void -SGSampleGroup::suspend () -{ - _pause = true; - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - - if ( sample->is_valid_source() && sample->is_playing() ) { - alSourcePause( sample->get_source() ); - } - } - testForALError("suspend"); -} - void SGSampleGroup::stop () { @@ -288,21 +271,42 @@ SGSampleGroup::stop () testForALError("stop"); } +// stop playing all associated samples +void +SGSampleGroup::suspend () +{ + if (_pause == false) { + _pause = true; + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + + if ( sample->is_valid_source() && sample->is_playing() ) { + alSourcePause( sample->get_source() ); + } + } + testForALError("suspend"); + } +} + // resume playing all associated samples void SGSampleGroup::resume () { - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; + if (_pause == true) { + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; - if ( sample->is_valid_source() && sample->is_playing() ) { - alSourcePlay( sample->get_source() ); + if ( sample->is_valid_source() && sample->is_playing() ) { + alSourcePlay( sample->get_source() ); + } } + testForALError("resume"); + _pause = false; } - testForALError("resume"); - _pause = false; } @@ -344,9 +348,12 @@ bool SGSampleGroup::stop( const string& refname ) { void SGSampleGroup::set_volume( float vol ) { - _volume = vol; - if (_volume < 0.0) _volume = 0.0; - if (_volume > 1.0) _volume = 1.0; + if (vol > _volume*1.01 || vol < _volume*0.99) { + _volume = vol; + if (_volume < 0.0) _volume = 0.0; + if (_volume > 1.0) _volume = 1.0; + _changed = true; + } } // set the source position and orientation of all managed sounds From b1200f9f5962282a335f79fc4289d2ef77a7d61c Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 6 Dec 2009 09:56:01 +0000 Subject: [PATCH 81/85] add alcSuspendContext and alcProcessContext again to prevent sound artifacts on hardware accelerated soundcards. --- simgear/sound/soundmgr_openal.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 6100dfcf..618d44f3 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -274,6 +274,8 @@ void SGSoundMgr::unbind () // run the audio scheduler void SGSoundMgr::update( double dt ) { if (_active) { + alcSuspendContext(_context); + if (_changed) { update_pos_and_orientation(); } @@ -310,6 +312,8 @@ if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); testForALError("update"); _changed = false; } + + alcProcessContext(_context); } } From f3c591469b12bb5ec9ad29181fda0faeee5ab144 Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 9 Dec 2009 09:38:07 +0000 Subject: [PATCH 82/85] Fix crash in SGSoundMgr::stop(): do not try to erase buffer items one at a time --- simgear/sound/soundmgr_openal.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 618d44f3..2cba9780 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -209,7 +209,6 @@ void SGSoundMgr::stop() { refUint ref = buffers_current->second; ALuint buffer = ref.id; alDeleteBuffers(1, &buffer); - _buffers.erase( buffers_current ); } _buffers.clear(); From 1da09a47065cea3dfb23f680c6ed1b2297f3895c Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 9 Dec 2009 10:09:41 +0000 Subject: [PATCH 83/85] Don't assign the buffer data to the sample in case it is a file. Test for result when calling load() --- simgear/sound/sample_openal.cxx | 2 +- simgear/sound/sample_openal.hxx | 2 +- simgear/sound/soundmgr_openal.cxx | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index db7cd465..6a4f7cb9 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -192,7 +192,7 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) : // destructor SGSoundSample::~SGSoundSample() { - if (_data) free(_data); + if ( _data != NULL ) free(_data); } void SGSoundSample::update_pos_and_orientation() { diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index a4091d29..d2cb1824 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -172,7 +172,7 @@ public: * Free the data associated with this audio sample */ void free_data() { - if ( _data ) free( _data ); _data = NULL; + if ( _data != NULL ) free( _data ); _data = NULL; } /** diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 2cba9780..85f8b2ca 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -437,6 +437,7 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) 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 ); @@ -449,32 +450,31 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) // sample name was not found in the buffer cache. if ( sample->is_file() ) { - size_t size; int freq, format; - void *data; + size_t size; + bool res; + + res = load(sample_name, &sample_data, &format, &size, &freq); + if (res == false) return buffer; - load(sample_name, &data, &format, &size, &freq); - sample->set_data( &data ); sample->set_frequency( freq ); sample->set_format( format ); sample->set_size( size ); } + else + sample_data = sample->get_data(); // create an OpenAL buffer handle alGenBuffers(1, &buffer); if ( !testForALError("generate buffer") ) { // Copy data to the internal OpenAL buffer - const ALvoid *data = sample->get_data(); ALenum format = sample->get_format(); ALsizei size = sample->get_size(); ALsizei freq = sample->get_frequency(); - alBufferData( buffer, format, data, size, freq ); + alBufferData( buffer, format, sample_data, size, freq ); - // If this sample was read from a file we have all the information - // needed to read it again. For data buffers provided by the - // program we don't; so don't delete it's data. - if ( sample->is_file() ) sample->free_data(); + if ( sample->is_file() ) free(sample_data); if ( !testForALError("buffer add data") ) { sample->set_buffer(buffer); From 1fe9755d01b9b0c06e8cfd05272e17a3ce0f1bf3 Mon Sep 17 00:00:00 2001 From: ehofman Date: Wed, 9 Dec 2009 13:56:12 +0000 Subject: [PATCH 84/85] fix a typo. --- simgear/sound/soundmgr_openal.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 85f8b2ca..ea5e44db 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -437,7 +437,7 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) if ( !sample->is_valid_buffer() ) { // sample was not yet loaded or removed again string sample_name = sample->get_sample_name(); - void *sample_data == NULL; + void *sample_data = NULL; // see if the sample name is already cached buffer_map_iterator buffer_it = _buffers.find( sample_name ); From c1246e8c4e2f46c05f8350acf9c34e86b81d6eca Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 14 Dec 2009 19:43:19 +0000 Subject: [PATCH 85/85] proper typecasting --- simgear/sound/soundmgr_openal.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index ea5e44db..05651b75 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -158,8 +158,8 @@ void SGSoundMgr::init(const char *devname) { else break; } - string vendor = alGetString(AL_VENDOR); - string renderer = alGetString(AL_RENDERER); + string vendor = (const char *)alGetString(AL_VENDOR); + string renderer = (const char *)alGetString(AL_RENDERER); if ( vendor != "OpenAL Community" || (renderer != "Software" && renderer != "OpenAL Sample Implementation") )