# include <simgear_config.h>
#endif
+#include <cassert>
#include <simgear/compiler.h>
+#include <simgear/sg_inlines.h>
#include <simgear/debug/logstream.hxx>
#include "soundmgr_openal.hxx"
#include "soundmgr_openal_private.hxx"
#include "sample_group.hxx"
-using std::string;
+#ifdef HAVE_STD_ISNAN
+using std::isnan;
+#endif
bool isNaN(float *v) {
return (isnan(v[0]) || isnan(v[1]) || isnan(v[2]));
_samples.clear();
}
-SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) :
+SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr,
+ const std::string &refname ):
_smgr(smgr),
_refname(refname),
_active(false),
_smgr = 0;
}
-void SGSampleGroup::update( double dt ) {
-
- if ( !_active || _pause ) return;
-
- testForALError("start of update!!\n");
+static bool is_sample_stopped(SGSoundSample *sample)
+{
+#ifdef ENABLE_SOUND
+ assert(sample->is_valid_source());
+ unsigned int source = sample->get_source();
+ int result;
+ alGetSourcei( source, AL_SOURCE_STATE, &result );
+ return (result == AL_STOPPED);
+#else
+ return true;
+#endif
+}
+void SGSampleGroup::cleanup_removed_samples()
+{
// Delete any OpenAL buffers that might still be in use.
unsigned int size = _removed_samples.size();
for (unsigned int i=0; i<size; ) {
SGSoundSample *sample = _removed_samples[i];
- ALint result = AL_STOPPED;
-
+ bool stopped = is_sample_stopped(sample);
+
if ( sample->is_valid_source() ) {
int source = sample->get_source();
-
- alGetSourcei( source, AL_SOURCE_STATE, &result );
- if ( sample->is_looping() ) {
- if ( result != AL_STOPPED ) {
- alSourceStop( source );
- alGetSourcei( source, AL_SOURCE_STATE, &result );
- }
+
+ if ( sample->is_looping() && !stopped) {
+#ifdef ENABLE_SOUND
+ alSourceStop( source );
+#endif
+ stopped = is_sample_stopped(sample);
}
- if ( result == AL_STOPPED ) {
+
+ if ( stopped ) {
sample->no_valid_source();
_smgr->release_source( source );
}
}
-
- if ( result == AL_STOPPED ) {
+
+ if ( stopped ) {
sample->stop();
if (( !sample->is_queue() )&&
(sample->is_valid_buffer()))
}
i++;
}
+}
+void SGSampleGroup::start_playing_sample(SGSoundSample *sample)
+{
+#ifdef ENABLE_SOUND
+ //
+ // a request to start playing a sound has been filed.
+ //
+ ALuint source = _smgr->request_source();
+ if (alIsSource(source) == AL_FALSE ) {
+ return;
+ }
+
+ sample->set_source( source );
+ update_sample_config( sample );
+ ALboolean looping = sample->is_looping() ? AL_TRUE : AL_FALSE;
+
+ if ( !sample->is_queue() )
+ {
+ ALuint buffer = _smgr->request_buffer(sample);
+ if (buffer == SGSoundMgr::FAILED_BUFFER ||
+ buffer == SGSoundMgr::NO_BUFFER)
+ {
+ _smgr->release_source(source);
+ return;
+ }
+
+ // start playing the sample
+ buffer = sample->get_buffer();
+ if ( alIsBuffer(buffer) == AL_TRUE )
+ {
+ alSourcei( source, AL_BUFFER, buffer );
+ testForALError("assign buffer to source");
+ } else
+ SG_LOG( SG_SOUND, SG_ALERT, "No such buffer!");
+ }
+
+ alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 );
+ alSourcei( source, AL_LOOPING, looping );
+ alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE );
+ alSourcePlay( source );
+ testForALError("sample play");
+#endif
+}
+
+void SGSampleGroup::check_playing_sample(SGSoundSample *sample)
+{
+ // check if the sound has stopped by itself
+
+ if (is_sample_stopped(sample)) {
+ // sample is stopped because it wasn't looping
+ sample->stop();
+ sample->no_valid_source();
+ _smgr->release_source( sample->get_source() );
+ _smgr->release_buffer( sample );
+ remove( sample->get_sample_name() );
+ } else if ( sample->has_changed() ) {
+ if ( !sample->is_playing() ) {
+ // a request to stop playing the sound has been filed.
+ sample->stop();
+ sample->no_valid_source();
+ _smgr->release_source( sample->get_source() );
+ } else if ( _smgr->has_changed() ) {
+ update_sample_config( sample );
+ }
+ }
+}
+
+void SGSampleGroup::update( double dt ) {
+
+ if ( !_active || _pause ) return;
+
+ testForALError("start of update!!\n");
+
+ cleanup_removed_samples();
+
// Update the position and orientation information for all samples.
if ( _changed || _smgr->has_changed() ) {
update_pos_and_orientation();
SGSoundSample *sample = sample_current->second;
if ( !sample->is_valid_source() && sample->is_playing() && !sample->test_out_of_range()) {
- //
- // a request to start playing a sound has been filed.
- //
- ALuint source = _smgr->request_source();
- if (alIsSource(source) == AL_TRUE )
- {
- ALboolean looping = sample->is_looping() ? AL_TRUE : AL_FALSE;
- if ( sample->is_queue() )
- {
- sample->set_source( source );
- update_sample_config( sample );
-
- alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 );
- alSourcei( source, AL_LOOPING, looping );
- alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE );
- alSourcePlay( source );
- testForALError("sample play");
- }
- else
- {
- ALuint buffer = _smgr->request_buffer(sample);
- if (buffer == SGSoundMgr::FAILED_BUFFER ||
- buffer == SGSoundMgr::NO_BUFFER)
- {
- _smgr->release_source(source);
- continue;
- }
-
- // start playing the sample
- buffer = sample->get_buffer();
- if ( alIsBuffer(buffer) == AL_TRUE )
- {
- alSourcei( source, AL_BUFFER, buffer );
- testForALError("assign buffer to source");
-
- sample->set_source( source );
- update_sample_config( sample );
-
- alSourcei( source, AL_LOOPING, looping );
- alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 );
- alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE );
- alSourcePlay( source );
- testForALError("sample play");
- } else
- SG_LOG( SG_SOUND, SG_ALERT, "No such buffer!");
- }
- }
+ start_playing_sample(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 stopped because it wasn't looping
- sample->stop();
- sample->no_valid_source();
- _smgr->release_source( source );
- _smgr->release_buffer( sample );
- remove( sample->get_sample_name() );
- }
- else
- if ( sample->has_changed() ) {
- if ( !sample->is_playing() ) {
- // a request to stop playing the sound has been filed.
- sample->stop();
- sample->no_valid_source();
- _smgr->release_source( sample->get_source() );
- } else if ( _smgr->has_changed() ) {
- update_sample_config( sample );
- }
- }
-
+ check_playing_sample(sample);
}
testForALError("update");
}
}
// add a sound effect, return true if successful
-bool SGSampleGroup::add( SGSharedPtr<SGSoundSample> sound, const string& refname ) {
-
+bool SGSampleGroup::add( SGSharedPtr<SGSoundSample> sound,
+ const std::string& refname )
+{
sample_map_iterator sample_it = _samples.find( refname );
if ( sample_it != _samples.end() ) {
// sample name already exists
// remove a sound effect, return true if successful
-bool SGSampleGroup::remove( const string &refname ) {
+bool SGSampleGroup::remove( const std::string &refname ) {
sample_map_iterator sample_it = _samples.find( refname );
if ( sample_it == _samples.end() ) {
// return true of the specified sound exists in the sound manager system
-bool SGSampleGroup::exists( const string &refname ) {
+bool SGSampleGroup::exists( const std::string &refname ) {
sample_map_iterator sample_it = _samples.find( refname );
if ( sample_it == _samples.end() ) {
// sample was not found
// 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 ) {
+SGSoundSample *SGSampleGroup::find( const std::string &refname ) {
sample_map_iterator sample_it = _samples.find( refname );
if ( sample_it == _samples.end() ) {
// sample was not found
SGSoundSample *sample = sample_current->second;
if ( sample->is_valid_source() ) {
+#ifdef ENABLE_SOUND
ALint source = sample->get_source();
if ( sample->is_playing() ) {
alSourceStop( source );
testForALError("stop");
}
_smgr->release_source( source );
+#endif
sample->no_valid_source();
}
sample_map_iterator sample_current = _samples.begin();
sample_map_iterator sample_end = _samples.end();
for ( ; sample_current != sample_end; ++sample_current ) {
+#ifdef ENABLE_SOUND
SGSoundSample *sample = sample_current->second;
-
if ( sample->is_valid_source() && sample->is_playing() ) {
alSourcePause( sample->get_source() );
}
+#endif
}
testForALError("suspend");
}
SGSampleGroup::resume ()
{
if (_active && _pause == true) {
+#ifdef ENABLE_SOUND
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() );
}
}
testForALError("resume");
+#endif
_pause = false;
}
}
// tell the scheduler to play the indexed sample in a continuous loop
-bool SGSampleGroup::play( const string &refname, bool looping = false ) {
+bool SGSampleGroup::play( const std::string &refname,
+ bool looping )
+{
SGSoundSample *sample = find( refname );
if ( sample == NULL ) {
// return true of the specified sound is currently being played
-bool SGSampleGroup::is_playing( const string& refname ) {
+bool SGSampleGroup::is_playing( const std::string& refname ) {
SGSoundSample *sample = find( refname );
if ( sample == NULL ) {
}
// immediate stop playing the sound
-bool SGSampleGroup::stop( const string& refname ) {
+bool SGSampleGroup::stop( const std::string& refname ) {
SGSoundSample *sample = find( refname );
if ( sample == NULL ) {
{
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;
+ SG_CLAMP_RANGE(_volume, 0.0f, 1.0f);
_changed = true;
}
}
// 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();
+
+ SGVec3d base_position = SGVec3d::fromGeod(_base_pos);
+ SGVec3d smgr_position = _smgr->get_position();
SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos);
SGQuatd ec2body = hlOr*_orientation;
sample->set_master_volume( _volume );
sample->set_orientation( _orientation );
sample->set_rotation( ec2body );
- sample->set_position( position );
+ sample->set_position(base_position);
sample->set_velocity( velocity );
// Test if a sample is farther away than max distance, if so
// stop the sound playback and free it's source.
if (!_tied_to_listener) {
+ sample->update_pos_and_orientation();
+ SGVec3d position = sample->get_position() - smgr_position;
float max2 = sample->get_max_dist() * sample->get_max_dist();
float dist2 = position[0]*position[0]
+ position[1]*position[1] + position[2]*position[2];
}
}
-void SGSampleGroup::update_sample_config( SGSoundSample *sample ) {
+void SGSampleGroup::update_sample_config( SGSoundSample *sample )
+{
+#ifdef ENABLE_SOUND
SGVec3f orientation, velocity;
SGVec3d position;
} else {
sample->update_pos_and_orientation();
orientation = sample->get_orientation();
- position = sample->get_position();
+ position = sample->get_position() - _smgr->get_position();
velocity = sample->get_velocity();
}
sample->get_reference_dist() );
testForALError("distance rolloff");
}
+#endif
}
-bool SGSampleGroup::testForError(void *p, string s)
+bool SGSampleGroup::testForError(void *p, std::string s)
{
if (p == NULL) {
SG_LOG( SG_SOUND, SG_ALERT, "Error (sample group): " << s);
return false;
}
-bool SGSampleGroup::testForALError(string s)
+bool SGSampleGroup::testForALError(std::string s)
{
+#ifdef SG_C
ALenum error = alGetError();
if (error != AL_NO_ERROR) {
SG_LOG( SG_SOUND, SG_ALERT, "AL Error (" << _refname << "): "
<< alGetString(error) << " at " << s);
return true;
}
+#endif
return false;
}