X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fsound%2Fsample_group.cxx;h=70df9aa1b6cbe88ff33e466ec71849ecc37157a3;hb=105438fc581a9b1d65a9309f6e845f9558f3a505;hp=4f64768cf7d61485ba07d69ed884fedb468ba9c6;hpb=b6ef5a0a3d60ea4e3dad38f44c791f30c238d601;p=simgear.git diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index 4f64768c..70df9aa1 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -24,11 +24,19 @@ # include #endif +#include #include +#include +#include #include "soundmgr_openal.hxx" +#include "soundmgr_openal_private.hxx" #include "sample_group.hxx" +#ifdef HAVE_STD_ISNAN +using std::isnan; +#endif + bool isNaN(float *v) { return (isnan(v[0]) || isnan(v[1]) || isnan(v[2])); } @@ -47,7 +55,8 @@ SGSampleGroup::SGSampleGroup () : _samples.clear(); } -SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : +SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, + const std::string &refname ): _smgr(smgr), _refname(refname), _active(false), @@ -65,54 +74,136 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : 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->release_buffer( sample ); - } - } - + stop(); _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; iis_valid_source() ) { - if ( sample->is_looping() ) { + int source = sample->get_source(); + + if ( sample->is_looping() && !stopped) { +#ifdef ENABLE_SOUND + alSourceStop( source ); +#endif + stopped = is_sample_stopped(sample); + } + + if ( stopped ) { sample->no_valid_source(); - _smgr->release_source( sample->get_source() ); + _smgr->release_source( source ); } - else - alGetSourcei( sample->get_source(), AL_SOURCE_STATE, &result ); } - - if ( result == AL_STOPPED ) { - ALuint buffer = sample->get_buffer(); - alDeleteBuffers( 1, &buffer ); - testForALError("buffer remove"); + + if ( stopped ) { + sample->stop(); + if (( !sample->is_queue() )&& + (sample->is_valid_buffer())) + { + _smgr->release_buffer(sample); + } _removed_samples.erase( _removed_samples.begin()+i ); size--; continue; } 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(); @@ -124,73 +215,20 @@ void SGSampleGroup::update( double dt ) { 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. - // - if ( _smgr->request_buffer(sample) == SGSoundMgr::NO_BUFFER ) - continue; - - // 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 ); - - ALboolean looping = sample->is_looping() ? AL_TRUE : AL_FALSE; - alSourcei( source, AL_LOOPING, looping ); - alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 ); - alSourcei( source, AL_SOURCE_RELATIVE, AL_TRUE ); - 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->stop(); - sample->no_valid_source(); - _smgr->release_source( sample->get_source() ); - } else if ( _smgr->has_changed() ) { - update_sample_config( sample ); - } + if ( !sample->is_valid_source() && sample->is_playing() && !sample->test_out_of_range()) { + 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 stoped because it wasn't looping - sample->stop(); - sample->no_valid_source(); - _smgr->release_source( source ); - _smgr->release_buffer( sample ); - remove( sample->get_sample_name() ); - } + check_playing_sample(sample); } testForALError("update"); } } // add a sound effect, return true if successful -bool SGSampleGroup::add( SGSharedPtr sound, const string& refname ) { - +bool SGSampleGroup::add( SGSharedPtr sound, + const std::string& refname ) +{ sample_map_iterator sample_it = _samples.find( refname ); if ( sample_it != _samples.end() ) { // sample name already exists @@ -203,7 +241,7 @@ bool SGSampleGroup::add( SGSharedPtr sound, const string& refname // 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() ) { @@ -213,6 +251,7 @@ bool SGSampleGroup::remove( const string &refname ) { if ( sample_it->second->is_valid_buffer() ) _removed_samples.push_back( sample_it->second ); + _samples.erase( sample_it ); return true; @@ -220,7 +259,7 @@ bool SGSampleGroup::remove( const string &refname ) { // 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 @@ -233,7 +272,7 @@ bool SGSampleGroup::exists( const string &refname ) { // 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 @@ -254,21 +293,22 @@ SGSampleGroup::stop () SGSoundSample *sample = sample_current->second; if ( sample->is_valid_source() ) { +#ifdef ENABLE_SOUND ALint source = sample->get_source(); if ( sample->is_playing() ) { alSourceStop( source ); - alSourcei( source, AL_BUFFER, 0 ); + testForALError("stop"); } _smgr->release_source( source ); +#endif sample->no_valid_source(); } - if (sample->is_valid_buffer() ) { + if ( sample->is_valid_buffer() ) { _smgr->release_buffer( sample ); sample->no_valid_buffer(); } } - testForALError("stop"); } // stop playing all associated samples @@ -280,11 +320,12 @@ SGSampleGroup::suspend () 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"); } @@ -295,23 +336,26 @@ void 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 ) { @@ -324,7 +368,7 @@ bool SGSampleGroup::play( const string &refname, bool looping = false ) { // 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 ) { @@ -335,7 +379,7 @@ bool SGSampleGroup::is_playing( const string& refname ) { } // 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 ) { @@ -350,16 +394,16 @@ void SGSampleGroup::set_volume( float vol ) { 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; @@ -375,12 +419,29 @@ void SGSampleGroup::update_pos_and_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]; + if ((dist2 > max2) && !sample->test_out_of_range()) { + sample->set_out_of_range(true); + } else if ((dist2 < max2) && sample->test_out_of_range()) { + sample->set_out_of_range(false); + } + } } } -void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { +void SGSampleGroup::update_sample_config( SGSoundSample *sample ) +{ +#ifdef ENABLE_SOUND SGVec3f orientation, velocity; SGVec3d position; @@ -391,7 +452,7 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { } 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(); } @@ -429,25 +490,28 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { 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_GENERAL, SG_ALERT, "Error (sample group): " << s); + SG_LOG( SG_SOUND, SG_ALERT, "Error (sample group): " << s); return true; } 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_GENERAL, SG_ALERT, "AL Error (" << _refname << "): " + SG_LOG( SG_SOUND, SG_ALERT, "AL Error (" << _refname << "): " << alGetString(error) << " at " << s); return true; } +#endif return false; }