X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fsound%2Fsoundmgr_openal.cxx;h=6066a560c32d1d22cc49679b387171fe0a8807d9;hb=afb18ca75b90e5a2e0bf791ba2e38812128ab0a8;hp=cbb137ef230296ff5f1e8fb5352e4b0e037b0855;hpb=fdfdfedf01776fafa4d769b93e95585e018a00d4;p=simgear.git diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index cbb137ef..6066a560 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 @@ -43,6 +45,7 @@ #include #include +extern bool isNaN(float *v); #define MAX_SOURCES 128 @@ -55,11 +58,14 @@ int SGSoundMgr::_alut_init = 0; // constructor SGSoundMgr::SGSoundMgr() : _working(false), + _active(false), _changed(true), _volume(0.0), _device(NULL), _context(NULL), - _position(SGVec3d::zeros()), + _absolute_pos(SGVec3d::zeros()), + _offset_pos(SGVec3d::zeros()), + _base_pos(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _devname(NULL) @@ -111,13 +117,15 @@ void SGSoundMgr::init() { return; } + if (_context != NULL) + SG_LOG(SG_GENERAL, SG_ALERT, "context is already assigned"); _context = context; _working = true; _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() ); @@ -125,11 +133,9 @@ void SGSoundMgr::init() { 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); - } + // gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE + + // AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE)); + alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); testForALError("listener initialization"); @@ -151,33 +157,38 @@ 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(); + } } } -// 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; - 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); - alcMakeContextCurrent(NULL); alcDestroyContext(_context); alcCloseDevice(_device); } @@ -191,9 +202,21 @@ void SGSoundMgr::suspend() { SGSampleGroup *sgrp = sample_grp_current->second; sgrp->suspend(); } + _active = false; } } +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(); + } + _active = true; + } +} void SGSoundMgr::bind () { @@ -210,7 +233,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 ); } @@ -218,17 +241,12 @@ 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) { - alcSuspendContext(_context); +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(); @@ -238,34 +256,23 @@ void SGSoundMgr::update_late( 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 alListenerf( AL_GAIN, _volume ); alListenerfv( AL_ORIENTATION, _at_up_vec ); - alListenerfv( AL_POSITION, toVec3f(_position).data() ); - alListenerfv( AL_VELOCITY, toVec3f(_velocity).data() ); + // alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() ); + alListenerfv( AL_VELOCITY, _velocity.data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent 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 ); @@ -274,7 +281,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; @@ -290,7 +297,7 @@ bool SGSoundMgr::remove( const string &refname ) return false; } - _sample_groups.erase( refname ); + _sample_groups.erase( sample_grp_it ); return true; } @@ -316,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 @@ -334,32 +342,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( SGQuatd ori ) -{ - _orientation = ori; - - SGVec3d sgv_up = ori.rotate(SGVec3d::e2()); - SGVec3d sgv_at = ori.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 @@ -378,6 +360,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; } @@ -396,8 +380,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 ); } } @@ -420,12 +405,12 @@ 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; load(sample_name, &data, &format, &size, &freq); - sample->set_data( (unsigned char *)data ); + sample->set_data( &data ); sample->set_frequency( freq ); sample->set_format( format ); sample->set_size( size ); @@ -441,7 +426,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); @@ -449,8 +438,9 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample) } } } - else + else { buffer = sample->get_buffer(); +} return buffer; } @@ -458,7 +448,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 @@ -469,15 +458,44 @@ 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 ); alDeleteBuffers(1, &buffer); + _buffers.erase( buffer_it ); testForALError("release buffer"); } } +void SGSoundMgr::update_pos_and_orientation() { + /** + * Description: ORIENTATION is a pair of 3-tuples representing the + * 'at' direction vector and 'up' direction of the Object in + * Cartesian space. AL expects two vectors that are orthogonal to + * each other. These vectors are not expected to be normalized. If + * one or more vectors have zero length, implementation behavior + * is undefined. If the two vectors are linearly dependent, + * behavior is undefined. + * + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + */ + SGVec3d sgv_at = _orientation.backTransform(-SGVec3d::e3()); + SGVec3d sgv_up = _orientation.backTransform(SGVec3d::e2()); + _at_up_vec[0] = sgv_at[0]; + _at_up_vec[1] = sgv_at[1]; + _at_up_vec[2] = sgv_at[2]; + _at_up_vec[3] = sgv_up[0]; + _at_up_vec[4] = sgv_up[1]; + _at_up_vec[5] = sgv_up[2]; + + // 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, - unsigned int *sz, int *frq ) + size_t *sz, int *frq ) { + if ( !_working ) return false; + ALenum format; ALsizei size; ALsizei freq; @@ -506,7 +524,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(alGetString(error)); throw sg_io_exception(msg.c_str(), sg_location(samplepath)); return false; } @@ -514,7 +532,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;