X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fsound%2Fsample_group.cxx;h=1610d088fbfabb3871d290ad5670866ee36e81fa;hb=bcb320b537b6f7e5e3724e8a30d309322171eb43;hp=f9813fecd5a9222a5da0f0146413918d8562d68c;hpb=a06a15e769bccda83ac904f524e20f73da10b1a6;p=simgear.git diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index f9813fec..1610d088 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -26,52 +26,23 @@ #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" +bool isNaN(float *v) { + return (isnan(v[0]) || isnan(v[1]) || isnan(v[2])); +} + SGSampleGroup::SGSampleGroup () : _smgr(NULL), _refname(""), _active(false), + _changed(false), _pause(false), + _volume(1.0), _tied_to_listener(false), _velocity(SGVec3d::zeros()), - _orientation(SGQuatd::zeros()), - _position(SGGeod()) + _orientation(SGQuatd::zeros()) { _samples.clear(); } @@ -80,11 +51,12 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _smgr(smgr), _refname(refname), _active(false), + _changed(false), _pause(false), + _volume(1.0), _tied_to_listener(false), _velocity(SGVec3d::zeros()), - _orientation(SGQuatd::zeros()), - _position(SGGeod()) + _orientation(SGQuatd::zeros()) { _smgr->add(this, refname); _samples.clear(); @@ -119,13 +91,24 @@ 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 ); - testForALError("buffer remove"); + sample->stop(); + if ( !sample->is_queue() ) { + ALuint buffer = sample->get_buffer(); + alDeleteBuffers( 1, &buffer ); + testForALError("buffer remove"); + } _removed_samples.erase( _removed_samples.begin()+i ); size--; continue; @@ -133,6 +116,12 @@ void SGSampleGroup::update( double dt ) { i++; } + // Update the position and orientation information for all samples. + if ( _changed || _smgr->has_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 ) { @@ -142,44 +131,44 @@ void SGSampleGroup::update( double dt ) { // // 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) + if (alIsSource(source) == 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->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 { - 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 { - update_sample_config( sample ); + 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 + { + if (_smgr->request_buffer(sample) == SGSoundMgr::NO_BUFFER) + continue; + + // start playing the sample + ALuint 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_GENERAL, SG_ALERT, "No such buffer!\n"); + } } } else if ( sample->is_valid_source() ) { @@ -195,7 +184,20 @@ void SGSampleGroup::update( double dt ) { 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 ); + } } + } testForALError("update"); } @@ -226,6 +228,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; @@ -257,9 +260,8 @@ SGSoundSample *SGSampleGroup::find( const string &refname ) { } -// stop playing all associated samples void -SGSampleGroup::suspend () +SGSampleGroup::stop () { _pause = true; sample_map_iterator sample_current = _samples.begin(); @@ -267,28 +269,59 @@ SGSampleGroup::suspend () for ( ; sample_current != sample_end; ++sample_current ) { SGSoundSample *sample = sample_current->second; - if ( sample->is_valid_source() && sample->is_playing() ) { - alSourcePause( sample->get_source() ); + if ( sample->is_valid_source() ) { + ALint source = sample->get_source(); + if ( sample->is_playing() ) { + alSourceStop( source ); + } + _smgr->release_source( source ); + sample->no_valid_source(); + } + + if ( sample->is_valid_buffer() ) { + _smgr->release_buffer( sample ); + sample->no_valid_buffer(); + } + } + testForALError("stop"); +} + +// stop playing all associated samples +void +SGSampleGroup::suspend () +{ + if (_active && _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"); } - 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 (_active && _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; } @@ -328,104 +361,88 @@ bool SGSampleGroup::stop( const string& refname ) { return true; } -// set source velocity of all managed sounds -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"); - 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; - } -} - -// set the source position of all managed sounds -void SGSampleGroup::set_position( 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 ); +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; + _changed = true; } - _position = pos; } +// 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); + SGQuatd ec2body = hlOr*_orientation; -// 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; + SGVec3f velocity = SGVec3f::zeros(); + if ( _velocity[0] || _velocity[1] || _velocity[2] ) { + velocity = toVec3f( hlOr.backTransform(_velocity*SG_FEET_TO_METER) ); } -} - -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 ); + sample->set_orientation( _orientation ); + sample->set_rotation( ec2body ); + sample->set_position( position ); + sample->set_velocity( velocity ); } } 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() ); - 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() ); - } -#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"); + SGVec3f orientation, velocity; + SGVec3d position; + + if ( _tied_to_listener ) { + orientation = _smgr->get_direction(); + position = SGVec3d::zeros(); + velocity = _smgr->get_velocity(); + } else { + sample->update_pos_and_orientation(); + orientation = sample->get_orientation(); + position = sample->get_position(); + velocity = sample->get_velocity(); + } - alSourcef( source, AL_PITCH, sample->get_pitch() ); - alSourcef( source, AL_GAIN, sample->get_volume() ); - testForALError("pitch and gain"); + if (_smgr->bad_doppler_effect()) { + velocity *= 100.0f; + } - 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() ); + if (length(position) > 20000) + 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"); #endif - testForALError("audio cone"); - alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() ); - alSourcef( source, AL_REFERENCE_DISTANCE, - sample->get_reference_dist() ); - testForALError("distance rolloff"); - } + 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"); + + 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"); } }