From 86f462933d0d7130e4e688183976620ed2ddb5ae Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 4 Oct 2009 13:52:53 +0000 Subject: [PATCH] Initial commit of the new sound system, expect more updates to follow --- src/ATCDCL/AIPlane.cxx | 31 ++--- src/ATCDCL/AIPlane.hxx | 6 +- src/ATCDCL/ATC.cxx | 71 +++++------ src/ATCDCL/ATC.hxx | 52 ++++---- src/ATCDCL/ATCVoice.cxx | 59 +++++---- src/Aircraft/aircraft.cxx | 4 +- src/Environment/environment_ctrl.hxx | 1 + src/Environment/fgclouds.cxx | 7 +- src/Environment/fgclouds.hxx | 5 +- src/Instrumentation/adf.cxx | 27 ++-- src/Instrumentation/adf.hxx | 6 +- src/Instrumentation/kr_87.cxx | 21 ++-- src/Instrumentation/kr_87.hxx | 3 + src/Instrumentation/marker_beacon.cxx | 46 +++---- src/Instrumentation/marker_beacon.hxx | 3 + src/Instrumentation/mk_viii.cxx | 36 ++---- src/Instrumentation/mk_viii.hxx | 37 +++--- src/Instrumentation/navradio.cxx | 43 ++++--- src/Instrumentation/navradio.hxx | 3 + src/Main/fg_commands.cxx | 9 +- src/Main/fg_init.cxx | 28 ++--- src/Main/fg_props.cxx | 10 +- src/Main/globals.cxx | 3 - src/Main/globals.hxx | 9 +- src/Main/main.cxx | 18 ++- src/Main/viewmgr.cxx | 12 ++ src/Model/acmodel.cxx | 64 ++++++++-- src/Model/acmodel.hxx | 14 ++- src/Sound/beacon.cxx | 14 +-- src/Sound/fg_fx.cxx | 173 +++++--------------------- src/Sound/fg_fx.hxx | 20 +-- src/Sound/morse.cxx | 10 -- 32 files changed, 406 insertions(+), 439 deletions(-) diff --git a/src/ATCDCL/AIPlane.cxx b/src/ATCDCL/AIPlane.cxx index 1c394d638..1db5820ec 100644 --- a/src/ATCDCL/AIPlane.cxx +++ b/src/ATCDCL/AIPlane.cxx @@ -47,12 +47,18 @@ FGAIPlane::FGAIPlane() { _trackSet = false; _tgtRoll = 0.0; _rollSuspended = false; + _sgr = 0; } FGAIPlane::~FGAIPlane() { } void FGAIPlane::Update(double dt) { + if (!_sgr) { + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + if (smgr) _sgr = smgr->find("atc", true); + } + if(_pending) { if(tuned_station) { if(tuned_station->GetFreqClear()) { @@ -106,7 +112,7 @@ void FGAIPlane::Update(double dt) { // For now assume in range !!! // TODO - implement range checking // TODO - at the moment the volume is always set off comm1 - double volume = fgGetDouble("/instrumentation/comm[0]/volume"); + float volume = fgGetFloat("/instrumentation/comm[0]/volume"); Render(plane.callsign, volume, false); } } @@ -167,8 +173,9 @@ void FGAIPlane::ConditionalTransmit(double timeout, int callback_code) { } void FGAIPlane::ImmediateTransmit(int callback_code) { - // TODO - at the moment the volume is always set off comm1 - double volume = fgGetDouble("/instrumentation/comm[0]/volume"); + // TODO - at the moment the volume is always set off comm1 + float volume = fgGetFloat("/instrumentation/comm[0]/volume"); + Render(plane.callsign, volume, false); if(callback_code) { ProcessCallback(callback_code); @@ -183,24 +190,20 @@ void FGAIPlane::ProcessCallback(int code) { // Outputs the transmission either on screen or as audio depending on user preference // The refname is a string to identify this sample to the sound manager // The repeating flag indicates whether the message should be repeated continuously or played once. -void FGAIPlane::Render(const string& refname, const double volume, bool repeating) { +void FGAIPlane::Render(const string& refname, const float volume, bool repeating) { fgSetString("/sim/messages/ai-plane", pending_transmission.c_str()); #ifdef ENABLE_AUDIO_SUPPORT voice = (voiceOK && fgGetBool("/sim/sound/voice")); if(voice) { string buf = vPtr->WriteMessage((char*)pending_transmission.c_str(), voice); - if(voice) { + if(voice && (volume > 0.05)) { SGSoundSample* simple = - new SGSoundSample((unsigned char*)buf.c_str(), buf.length(), 8000, AL_FORMAT_MONO8 ); + new SGSoundSample((unsigned char*)buf.c_str(), buf.length(), 8000 ); // TODO - at the moment the volume can't be changed // after the transmission has started. simple->set_volume(volume); - globals->get_soundmgr()->add(simple, refname); - if(repeating) { - globals->get_soundmgr()->play_looped(refname); - } else { - globals->get_soundmgr()->play_once(refname); - } + _sgr->add(simple, refname); + _sgr->play(refname, repeating); } } #endif // ENABLE_AUDIO_SUPPORT @@ -221,8 +224,8 @@ void FGAIPlane::NoRender(const string& refname) { if(playing) { if(voice) { #ifdef ENABLE_AUDIO_SUPPORT - globals->get_soundmgr()->stop(refname); - globals->get_soundmgr()->remove(refname); + _sgr->stop(refname); + _sgr->remove(refname); #endif } playing = false; diff --git a/src/ATCDCL/AIPlane.hxx b/src/ATCDCL/AIPlane.hxx index e1f581c6c..aba6e7b7e 100644 --- a/src/ATCDCL/AIPlane.hxx +++ b/src/ATCDCL/AIPlane.hxx @@ -24,6 +24,8 @@ #include "AIEntity.hxx" #include "ATC.hxx" +class SGSampleGroup; + enum PatternLeg { TAKEOFF_ROLL, CLIMBOUT, @@ -140,7 +142,7 @@ private: // Outputs the transmission either on screen or as audio depending on user preference // The refname is a string to identify this sample to the sound manager // The repeating flag indicates whether the message should be repeated continuously or played once. - void Render(const string& refname, const double volume, bool repeating); + void Render(const string& refname, const float volume, bool repeating); // Cease rendering a transmission. // Requires the sound manager refname if audio, else "". @@ -157,6 +159,8 @@ private: bool _trackSet; // Set true if tgtTrack is to be followed double _tgtRoll; bool _rollSuspended; // Set true when a derived class has suspended AIPlane's roll control + + SGSampleGroup *_sgr; }; #endif // _FG_AI_PLANE_HXX diff --git a/src/ATCDCL/ATC.cxx b/src/ATCDCL/ATC.cxx index 193b82457..ed62bad03 100644 --- a/src/ATCDCL/ATC.cxx +++ b/src/ATCDCL/ATC.cxx @@ -35,7 +35,8 @@ FGATC::FGATC() : - _voiceOK(false), + _voiceOK(false), + _sgr(NULL), freqClear(true), receiving(false), respond(false), @@ -203,7 +204,7 @@ int FGATC::RemovePlane() { } void FGATC::SetData(ATCData* d) { - _type = d->type; + _type = d->type; _geod = d->geod; _cart = d->cart; range = d->range; @@ -216,41 +217,41 @@ void FGATC::SetData(ATCData* d) { // Outputs the transmission either on screen or as audio depending on user preference // The refname is a string to identify this sample to the sound manager // The repeating flag indicates whether the message should be repeated continuously or played once. -void FGATC::Render(string& msg, const double volume, - const string& refname, const bool repeating) { +void FGATC::Render(string& msg, const float volume, + const string& refname, const bool repeating) { if (repeating) fgSetString("/sim/messages/atis", msg.c_str()); else fgSetString("/sim/messages/atc", msg.c_str()); - #ifdef ENABLE_AUDIO_SUPPORT +#ifdef ENABLE_AUDIO_SUPPORT _voice = (_voiceOK && fgGetBool("/sim/sound/voice")); if(_voice) { - string buf = _vPtr->WriteMessage((char*)msg.c_str(), _voice); - if(_voice) { - NoRender(refname); - try { + string buf = _vPtr->WriteMessage((char*)msg.c_str(), _voice); + if(_voice && (volume > 0.05)) { + NoRender(refname); + try { // >>> Beware: must pass a (new) object to the (add) method, // >>> because the (remove) method is going to do a (delete) // >>> whether that's what you want or not. - SGSoundSample *simple = - new SGSoundSample((unsigned char*) buf.c_str(), - buf.length(), 8000, AL_FORMAT_MONO8); - // TODO - at the moment the volume can't be changed - // after the transmission has started. - simple->set_volume(volume); - globals->get_soundmgr()->add(simple, refname); - if(repeating) { - globals->get_soundmgr()->play_looped(refname); - } else { - globals->get_soundmgr()->play_once(refname); - } - } catch ( sg_io_exception &e ) { - SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage()); + SGSoundSample *simple = + new SGSoundSample((unsigned char*) buf.c_str(), buf.length(), 8000); + // TODO - at the moment the volume can't be changed + // after the transmission has started. + if (!_sgr) { + SGSoundMgr *smgr; + smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + _sgr = smgr->find("atc", true); + } + simple->set_volume(volume); + _sgr->add(simple, refname); + _sgr->play(refname, repeating); + } catch ( sg_io_exception &e ) { + SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage()); + } } - } } - #endif // ENABLE_AUDIO_SUPPORT +#endif // ENABLE_AUDIO_SUPPORT if(!_voice) { // first rip the underscores and the pause hints out of the string - these are for the convienience of the voice parser for(unsigned int i = 0; i < msg.length(); ++i) { @@ -268,8 +269,8 @@ void FGATC::NoRender(const string& refname) { if(_playing) { if(_voice) { #ifdef ENABLE_AUDIO_SUPPORT - globals->get_soundmgr()->stop(refname); - globals->get_soundmgr()->remove(refname); + _sgr->stop(refname); + _sgr->remove(refname); #endif } _playing = false; @@ -283,14 +284,14 @@ string FGATC::GenText(const string& m, int c) { ostream& operator << (ostream& os, atc_type atc) { switch(atc) { - case(AWOS): return(os << "AWOS"); - case(ATIS): return(os << "ATIS"); - case(GROUND): return(os << "GROUND"); - case(TOWER): return(os << "TOWER"); + case(AWOS): return(os << "AWOS"); + case(ATIS): return(os << "ATIS"); + case(GROUND): return(os << "GROUND"); + case(TOWER): return(os << "TOWER"); case(APPROACH): return(os << "APPROACH"); case(DEPARTURE): return(os << "DEPARTURE"); - case(ENROUTE): return(os << "ENROUTE"); - case(INVALID): return(os << "INVALID"); + case(ENROUTE): return(os << "ENROUTE"); + case(INVALID): return(os << "INVALID"); } return(os << "ERROR - Unknown switch in atc_type operator << "); } @@ -325,7 +326,7 @@ std::istream& operator >> ( std::istream& fin, ATCData& a ) return fin >> skipeol; } - double lat, lon, elev; + double lat, lon, elev; fin >> lat >> lon >> elev >> f >> a.range >> a.ident; a.geod = SGGeod::fromDegM(lon, lat, elev); @@ -349,7 +350,7 @@ std::istream& operator >> ( std::istream& fin, ATCData& a ) // cout << a.ident << endl; // generate cartesian coordinates - a.cart = SGVec3d::fromGeod(a.geod); + a.cart = SGVec3d::fromGeod(a.geod); return fin >> skipeol; } diff --git a/src/ATCDCL/ATC.hxx b/src/ATCDCL/ATC.hxx index adb62264e..8b05d6ca0 100644 --- a/src/ATCDCL/ATC.hxx +++ b/src/ATCDCL/ATC.hxx @@ -33,6 +33,8 @@ #include "ATCVoice.hxx" +class SGSampleGroup; + // Convert a frequency in MHz to tens of kHz // so we can use it e.g. as an index into commlist_freq // @@ -76,7 +78,7 @@ enum atc_type { APPROACH, DEPARTURE, ENROUTE, - INVALID /* must be last element; see ATC_NUM_TYPES */ + INVALID /* must be last element; see ATC_NUM_TYPES */ }; const int ATC_NUM_TYPES = 1 + INVALID; @@ -84,8 +86,8 @@ const int ATC_NUM_TYPES = 1 + INVALID; // DCL - new experimental ATC data store struct ATCData { atc_type type; - SGGeod geod; - SGVec3d cart; + SGGeod geod; + SGVec3d cart; unsigned short int freq; unsigned short int range; std::string ident; @@ -114,7 +116,7 @@ public: FGATC(); virtual ~FGATC(); - virtual void Init()=0; + virtual void Init()=0; // Run the internal calculations // Derived classes should call this method from their own Update methods if they @@ -176,15 +178,15 @@ protected: // Outputs the transmission either on screen or as audio depending on user preference // The refname is a string to identify this sample to the sound manager // The repeating flag indicates whether the message should be repeated continuously or played once. - void Render(std::string& msg, const double volume = 1.0, - const std::string& refname = "", bool repeating = false); + void Render(std::string& msg, const float volume = 1.0, + const std::string& refname = "", bool repeating = false); // Cease rendering all transmission from this station. // Requires the sound manager refname if audio, else "". void NoRender(const std::string& refname); // Transmit a message when channel becomes free of other dialog - void Transmit(int callback_code = 0); + void Transmit(int callback_code = 0); // Transmit a message if channel becomes free within timeout (seconds). timeout of zero implies no limit void ConditionalTransmit(double timeout, int callback_code = 0); @@ -197,44 +199,46 @@ protected: SGGeod _geod; SGVec3d _cart; int freq; - std::map active_on; + std::map active_on; int range; - std::string ident; // Code of the airport its at. - std::string name; // Name transmitted in the broadcast. + std::string ident; // Code of the airport its at. + std::string name; // Name transmitted in the broadcast. // Rendering related stuff - bool _voice; // Flag - true if we are using voice - bool _playing; // Indicates a message in progress - bool _voiceOK; // Flag - true if at least one voice has loaded OK + bool _voice; // Flag - true if we are using voice + bool _playing; // Indicates a message in progress + bool _voiceOK; // Flag - true if at least one voice has loaded OK FGATCVoice* _vPtr; + SGSampleGroup *_sgr; // default sample group; + - bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog - bool receiving; // Flag to indicate we are receiving a transmission + bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog + bool receiving; // Flag to indicate we are receiving a transmission - double responseTime; // Time to take from end of request transmission to beginning of response - // The idea is that this will be slightly random. + double responseTime; // Time to take from end of request transmission to beginning of response + // The idea is that this will be slightly random. - bool respond; // Flag to indicate now is the time to respond - ie set following the count down of the response timer. + bool respond; // Flag to indicate now is the time to respond - ie set following the count down of the response timer. std::string responseID; // ID of the plane to respond to - bool runResponseCounter; // Flag to indicate the response counter should be run - double responseCounter; // counter to implement the above + bool runResponseCounter; // Flag to indicate the response counter should be run + double responseCounter; // counter to implement the above // Derived classes only need monitor this flag, and use the response ID, as long as they call FGATC::Update(...) bool _runReleaseCounter; // A timer for releasing the frequency after giving the message enough time to display - bool responseReqd; // Flag to indicate we should be responding to a request/report + bool responseReqd; // Flag to indicate we should be responding to a request/report double _releaseTime; double _releaseCounter; atc_type _type; - bool _display; // Flag to indicate whether we should be outputting to the ATC display. - std::string pending_transmission; // derived classes set this string before calling Transmit(...) + bool _display; // Flag to indicate whether we should be outputting to the ATC display. + std::string pending_transmission; // derived classes set this string before calling Transmit(...) private: // Transmission timing stuff. double _timeout; - bool _pending; + bool _pending; int _callback_code; // A callback code to be notified and processed by the derived classes // A value of zero indicates no callback required diff --git a/src/ATCDCL/ATCVoice.cxx b/src/ATCDCL/ATCVoice.cxx index 46ab81df7..023dde22c 100644 --- a/src/ATCDCL/ATCVoice.cxx +++ b/src/ATCDCL/ATCVoice.cxx @@ -33,11 +33,11 @@ #include +#include #include #include #include #include -#include #include
@@ -56,29 +56,28 @@ FGATCVoice::FGATCVoice() { FGATCVoice::~FGATCVoice() { if (rawSoundData) - free( rawSoundData ); + free( rawSoundData ); delete SoundData; } // Load the two voice files - one containing the raw sound data (.wav) and one containing the word positions (.vce). // Return true if successful. bool FGATCVoice::LoadVoice(const string& voice) { - // FIXME CLO: disabled to try to see if this is causing problemcs - // return false; - std::ifstream fin; SGPath path = globals->get_fg_root(); + string file = voice + ".wav"; path.append( "ATC" ); - - string file = voice + ".wav"; + path.append( file ); - SGSoundSample SoundData; - rawSoundData = (char *)SoundData.load_file(path.c_str(), file.c_str()); - rawDataSize = SoundData.get_size(); + string full_path = path.str(); + int format, freq; + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + void *data; + smgr->load(full_path, &data, &format, &rawDataSize, &freq); + rawSoundData = (char*)data; #ifdef VOICE_TEST - ALenum fmt = SoundData.get_format(); - cout << "ATCVoice: format: " << fmt + cout << "ATCVoice: format: " << format << " size: " << rawDataSize << endl; #endif path = globals->get_fg_root(); @@ -113,12 +112,12 @@ bool FGATCVoice::LoadVoice(const string& voice) { wd.offset = wrdOffset; wd.length = wrdLength; wordMap[wrdstr] = wd; - string ws2 = wrdstr; - for(string::iterator p = ws2.begin(); p != ws2.end(); p++){ - *p = tolower(*p); - if (*p == '-') *p = '_'; - } - if (wrdstr != ws2) wordMap[ws2] = wd; + string ws2 = wrdstr; + for(string::iterator p = ws2.begin(); p != ws2.end(); p++){ + *p = tolower(*p); + if (*p == '-') *p = '_'; + } + if (wrdstr != ws2) wordMap[ws2] = wd; //cout << wrd << "\t\t" << wrdOffset << "\t\t" << wrdLength << '\n'; //cout << i << '\n'; @@ -146,7 +145,7 @@ string FGATCVoice::WriteMessage(const char* message, bool& dataOK) { // TODO - at the moment we're effectively taking 3 passes through the data. // There is no need for this - 2 should be sufficient - we can probably ditch the tokenList. size_t n1 = 1+strlen(message); - boost::shared_array msg(new char[n1]); + boost::shared_array msg(new char[n1]); strncpy(msg.get(), message, n1); // strtok requires a non-const char* char* token; int numWords = 0; @@ -154,19 +153,19 @@ string FGATCVoice::WriteMessage(const char* message, bool& dataOK) { char* context; token = strtok_r(msg.get(), delimiters, &context); while(token != NULL) { - for (char *t = token; *t; t++) { - *t = tolower(*t); // canonicalize the case, to - if (*t == '-') *t = '_'; // match what's in the index - } + for (char *t = token; *t; t++) { + *t = tolower(*t); // canonicalize the case, to + if (*t == '-') *t = '_'; // match what's in the index + } tokenList.push_back(token); ++numWords; SG_LOG(SG_ATC, SG_DEBUG, "voice synth: token: '" - << token << "'"); + << token << "'"); token = strtok_r(NULL, delimiters, &context); } vector wdptr; - wdptr.reserve(numWords); + wdptr.reserve(numWords); unsigned int cumLength = 0; tokenListItr = tokenList.begin(); @@ -174,21 +173,21 @@ string FGATCVoice::WriteMessage(const char* message, bool& dataOK) { if(wordMap.find(*tokenListItr) == wordMap.end()) { // Oh dear - the token isn't in the sound file SG_LOG(SG_ATC, SG_ALERT, "voice synth: word '" - << *tokenListItr << "' not found"); + << *tokenListItr << "' not found"); } else { - wdptr.push_back(wordMap[*tokenListItr]); - cumLength += wdptr.back().length; + wdptr.push_back(wordMap[*tokenListItr]); + cumLength += wdptr.back().length; } ++tokenListItr; } const size_t word = wdptr.size(); - + // Check for no tokens found else slScheduler can be crashed if(!word) { dataOK = false; return ""; } - boost::shared_array tmpbuf(new char[cumLength]); + boost::shared_array tmpbuf(new char[cumLength]); unsigned int bufpos = 0; for(int i=0; i #include #include +#include #include
#include
@@ -226,12 +227,9 @@ fgLoadAircraft (const SGPropertyNode * arg) t = fgInitTime(); globals->set_time_params( t ); - // Reinitialize some subsystems - // globals->get_viewmgr()->reinit(); globals->get_controls()->reset_all(); globals->get_aircraft_model()->reinit(); - globals->get_subsystem("fx")->reinit(); globals->get_subsystem("xml-autopilot")->reinit(); fgReInitSubsystems(); diff --git a/src/Environment/environment_ctrl.hxx b/src/Environment/environment_ctrl.hxx index 76b6aab20..0ecf8db8b 100644 --- a/src/Environment/environment_ctrl.hxx +++ b/src/Environment/environment_ctrl.hxx @@ -40,6 +40,7 @@ // forward decls class SGPropertyNode; +class SGSampleGroup; class FGMetar; /** diff --git a/src/Environment/fgclouds.cxx b/src/Environment/fgclouds.cxx index 867798af4..a4264bc58 100644 --- a/src/Environment/fgclouds.cxx +++ b/src/Environment/fgclouds.cxx @@ -68,9 +68,10 @@ void FGClouds::init(void) { snd_lightning = new SGSoundSample(globals->get_fg_root().c_str(), "Sounds/thunder.wav"); snd_lightning->set_max_dist(7000.0f); snd_lightning->set_reference_dist(3000.0f); - SGSoundMgr *soundMgr = globals->get_soundmgr(); - soundMgr->add( snd_lightning, "thunder" ); - sgEnviro.set_soundMgr( soundMgr ); + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + SGSampleGroup *sgr = smgr->find("weather", true); + sgr->add( snd_lightning, "thunder" ); + sgEnviro.set_sampleGroup( sgr ); } } diff --git a/src/Environment/fgclouds.hxx b/src/Environment/fgclouds.hxx index 797b55247..fd7ca885a 100644 --- a/src/Environment/fgclouds.hxx +++ b/src/Environment/fgclouds.hxx @@ -34,10 +34,11 @@ using std::string; -class SGNewCloud; +class SGSampleGroup; class SGCloudField; +class SGNewCloud; class FGMetar; -class FGEnvironmentCtrl; +//class FGEnvironmentCtrl; class FGClouds { diff --git a/src/Instrumentation/adf.cxx b/src/Instrumentation/adf.cxx index 053812a0d..d2ac69145 100644 --- a/src/Instrumentation/adf.cxx +++ b/src/Instrumentation/adf.cxx @@ -69,7 +69,8 @@ ADF::ADF (SGPropertyNode *node ) _transmitter_range_nm(0), _ident_count(0), _last_ident_time(0), - _last_volume(-1) + _last_volume(-1), + _sgr(0) { } @@ -101,6 +102,9 @@ ADF::init () _ident_node = node->getChild("ident", 0, true); _ident_audible_node = node->getChild("ident-audible", 0, true); + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + _sgr = smgr->find("avionics", true); + morse.init(); std::ostringstream temp; @@ -156,6 +160,7 @@ ADF::update (double delta_time_sec) double range_nm = adjust_range(_transmitter_pos.getElevationFt(), altitude_m * SG_METER_TO_FEET, _transmitter_range_nm); + if (distance_nm <= range_nm) { double bearing, az2, s; @@ -171,9 +176,9 @@ ADF::update (double delta_time_sec) set_bearing(delta_time_sec, bearing); // adf ident sound - double volume; + float volume; if ( _ident_audible_node->getBoolValue() ) - volume = _volume_node->getDoubleValue(); + volume = _volume_node->getFloatValue(); else volume = 0.0; @@ -181,7 +186,7 @@ ADF::update (double delta_time_sec) _last_volume = volume; SGSoundSample *sound; - sound = globals->get_soundmgr()->find( _adf_ident ); + sound = _sgr->find( _adf_ident ); if ( sound != NULL ) sound->set_volume( volume ); else @@ -195,8 +200,8 @@ ADF::update (double delta_time_sec) } if ( _ident_count < 4 ) { - if ( !globals->get_soundmgr()->is_playing(_adf_ident) ) { - globals->get_soundmgr()->play_once( _adf_ident ); + if ( !_sgr->is_playing(_adf_ident) && (volume > 0.05) ) { + _sgr->play_once( _adf_ident ); ++_ident_count; } } @@ -204,7 +209,7 @@ ADF::update (double delta_time_sec) _in_range_node->setBoolValue(false); set_bearing(delta_time_sec, 90); _ident_node->setStringValue(""); - globals->get_soundmgr()->stop( _adf_ident ); + _sgr->stop( _adf_ident ); } } @@ -234,16 +239,16 @@ ADF::search (double frequency_khz, double longitude_rad, _last_ident = ident; _ident_node->setStringValue(ident.c_str()); - if ( globals->get_soundmgr()->exists( _adf_ident ) ) { + if ( _sgr->exists( _adf_ident ) ) { // stop is required! -- remove alone wouldn't stop immediately - globals->get_soundmgr()->stop( _adf_ident ); - globals->get_soundmgr()->remove( _adf_ident ); + _sgr->stop( _adf_ident ); + _sgr->remove( _adf_ident ); } SGSoundSample *sound; sound = morse.make_ident( ident, LO_FREQUENCY ); sound->set_volume(_last_volume = 0); - globals->get_soundmgr()->add( sound, _adf_ident ); + _sgr->add( sound, _adf_ident ); int offset = (int)(sg_random() * 30.0); _ident_count = offset / 4; diff --git a/src/Instrumentation/adf.hxx b/src/Instrumentation/adf.hxx index 41d55671d..80de7d860 100644 --- a/src/Instrumentation/adf.hxx +++ b/src/Instrumentation/adf.hxx @@ -21,6 +21,8 @@ using std::string; +class SGSampleGroup; + /** * Model an ADF radio. * @@ -93,8 +95,10 @@ private: FGMorse morse; int _ident_count; time_t _last_ident_time; - double _last_volume; + float _last_volume; string _adf_ident; + + SGSampleGroup *_sgr; }; diff --git a/src/Instrumentation/kr_87.cxx b/src/Instrumentation/kr_87.cxx index 6683f8f93..eab9bf69b 100644 --- a/src/Instrumentation/kr_87.cxx +++ b/src/Instrumentation/kr_87.cxx @@ -105,7 +105,8 @@ FGKR_87::FGKR_87( SGPropertyNode *node ) : flight_timer(0.0), elapsed_timer(0.0), tmp_timer(0.0), - _time_before_search_sec(0) + _time_before_search_sec(0), + _sgr(NULL) { } @@ -116,6 +117,8 @@ FGKR_87::~FGKR_87() { void FGKR_87::init () { + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + _sgr = smgr->find("avionics", true); morse.init(); } @@ -463,7 +466,7 @@ void FGKR_87::update( double dt_sec ) { // otherwise turn it off if ( vol_btn >= 0.01 && audio_btn ) { SGSoundSample *sound; - sound = globals->get_soundmgr()->find( "adf-ident" ); + sound = _sgr->find( "adf-ident" ); if ( sound != NULL ) { if ( !adf_btn ) { sound->set_volume( vol_btn ); @@ -480,13 +483,13 @@ void FGKR_87::update( double dt_sec ) { } if ( play_count < 4 ) { // play ADF ident - if ( !globals->get_soundmgr()->is_playing("adf-ident") ) { - globals->get_soundmgr()->play_once( "adf-ident" ); + if ( !_sgr->is_playing("adf-ident") && (vol_btn > 0.05) ) { + _sgr->play_once( "adf-ident" ); ++play_count; } } } else { - globals->get_soundmgr()->stop( "adf-ident" ); + _sgr->stop( "adf-ident" ); } } } @@ -527,13 +530,13 @@ void FGKR_87::search() { effective_range = kludgeRange(stn_elev, pos.getElevationM(), range); xyz = adf->cart(); - if ( globals->get_soundmgr()->exists( "adf-ident" ) ) { - globals->get_soundmgr()->remove( "adf-ident" ); + if ( _sgr->exists( "adf-ident" ) ) { + _sgr->remove( "adf-ident" ); } SGSoundSample *sound; sound = morse.make_ident( trans_ident, LO_FREQUENCY ); sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, "adf-ident" ); + _sgr->add( sound, "adf-ident" ); int offset = (int)(sg_random() * 30.0); play_count = offset / 4; @@ -551,7 +554,7 @@ void FGKR_87::search() { valid = false; ident = ""; trans_ident = ""; - globals->get_soundmgr()->remove( "adf-ident" ); + _sgr->remove( "adf-ident" ); last_ident = ""; // cout << "not picking up adf. :-(" << endl; } diff --git a/src/Instrumentation/kr_87.hxx b/src/Instrumentation/kr_87.hxx index 0b57a8e5f..0653b06d9 100644 --- a/src/Instrumentation/kr_87.hxx +++ b/src/Instrumentation/kr_87.hxx @@ -34,6 +34,7 @@ #include #include +class SGSampleGroup; class FGKR_87 : public SGSubsystem { @@ -104,6 +105,8 @@ class FGKR_87 : public SGSubsystem // internal periodic station search timer double _time_before_search_sec; + SGSampleGroup *_sgr; + public: FGKR_87( SGPropertyNode *node ); diff --git a/src/Instrumentation/marker_beacon.cxx b/src/Instrumentation/marker_beacon.cxx index e1ca85e12..ccb8499e1 100644 --- a/src/Instrumentation/marker_beacon.cxx +++ b/src/Instrumentation/marker_beacon.cxx @@ -49,7 +49,8 @@ FGMarkerBeacon::FGMarkerBeacon(SGPropertyNode *node) : inner_blink(false), name("marker-beacon"), num(0), - _time_before_search_sec(0.0) + _time_before_search_sec(0.0), + _sgr(NULL) { SGPath path( globals->get_fg_root() ); SGPath term = path; @@ -116,6 +117,9 @@ FGMarkerBeacon::init () if (serviceable->getType() == simgear::props::NONE) serviceable->setBoolValue( true ); + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + _sgr = smgr->find("avionics", true); + morse.init(); beacon.init(); blink.stamp(); @@ -300,9 +304,9 @@ void FGMarkerBeacon::search() if ( b == NULL || !inrange || !has_power() || !serviceable->getBoolValue() ) { // cout << "no marker" << endl; - globals->get_soundmgr()->stop( "outer-marker" ); - globals->get_soundmgr()->stop( "middle-marker" ); - globals->get_soundmgr()->stop( "inner-marker" ); + _sgr->stop( "outer-marker" ); + _sgr->stop( "middle-marker" ); + _sgr->stop( "inner-marker" ); } else { string current_sound_name; @@ -312,63 +316,63 @@ void FGMarkerBeacon::search() current_sound_name = "outer-marker"; // cout << "OUTER MARKER" << endl; if ( last_beacon != OUTER ) { - if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) { + if ( ! _sgr->exists( current_sound_name ) ) { SGSoundSample *sound = beacon.get_outer(); if ( sound ) { - globals->get_soundmgr()->add( sound, current_sound_name ); + _sgr->add( sound, current_sound_name ); } } } if ( audio_btn->getBoolValue() ) { - if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) { - globals->get_soundmgr()->play_looped( current_sound_name ); + if ( !_sgr->is_playing(current_sound_name) ) { + _sgr->play_looped( current_sound_name ); } } else { - globals->get_soundmgr()->stop( current_sound_name ); + _sgr->stop( current_sound_name ); } } else if ( beacon_type == MIDDLE ) { middle_marker = true; current_sound_name = "middle-marker"; // cout << "MIDDLE MARKER" << endl; if ( last_beacon != MIDDLE ) { - if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) { + if ( ! _sgr->exists( current_sound_name ) ) { SGSoundSample *sound = beacon.get_middle(); if ( sound ) { - globals->get_soundmgr()->add( sound, current_sound_name ); + _sgr->add( sound, current_sound_name ); } } } if ( audio_btn->getBoolValue() ) { - if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) { - globals->get_soundmgr()->play_looped( current_sound_name ); + if ( !_sgr->is_playing(current_sound_name) ) { + _sgr->play_looped( current_sound_name ); } } else { - globals->get_soundmgr()->stop( current_sound_name ); + _sgr->stop( current_sound_name ); } } else if ( beacon_type == INNER ) { inner_marker = true; current_sound_name = "inner-marker"; // cout << "INNER MARKER" << endl; if ( last_beacon != INNER ) { - if ( ! globals->get_soundmgr()->exists( current_sound_name ) ) { + if ( ! _sgr->exists( current_sound_name ) ) { SGSoundSample *sound = beacon.get_inner(); if ( sound ) { - globals->get_soundmgr()->add( sound, current_sound_name ); + _sgr->add( sound, current_sound_name ); } } } if ( audio_btn->getBoolValue() ) { - if ( !globals->get_soundmgr()->is_playing(current_sound_name) ) { - globals->get_soundmgr()->play_looped( current_sound_name ); + if ( !_sgr->is_playing(current_sound_name) ) { + _sgr->play_looped( current_sound_name ); } } else { - globals->get_soundmgr()->stop( current_sound_name ); + _sgr->stop( current_sound_name ); } } // cout << "VOLUME " << audio_vol->getDoubleValue() << endl; - SGSoundSample * mkr = globals->get_soundmgr()->find( current_sound_name ); + SGSoundSample * mkr = _sgr->find( current_sound_name ); if (mkr) - mkr->set_volume( audio_vol->getDoubleValue() ); + mkr->set_volume( audio_vol->getFloatValue() ); } if ( inrange ) { diff --git a/src/Instrumentation/marker_beacon.hxx b/src/Instrumentation/marker_beacon.hxx index cb82eea5c..774e37f81 100644 --- a/src/Instrumentation/marker_beacon.hxx +++ b/src/Instrumentation/marker_beacon.hxx @@ -35,6 +35,7 @@ #include #include +class SGSampleGroup; class FGMarkerBeacon : public SGSubsystem { @@ -73,6 +74,8 @@ class FGMarkerBeacon : public SGSubsystem // internal periodic station search timer double _time_before_search_sec; + SGSampleGroup *_sgr; + public: enum fgMkrBeacType { diff --git a/src/Instrumentation/mk_viii.cxx b/src/Instrumentation/mk_viii.cxx index 64e187f6f..3cdc6e3ef 100755 --- a/src/Instrumentation/mk_viii.cxx +++ b/src/Instrumentation/mk_viii.cxx @@ -2127,11 +2127,9 @@ MK_VIII::VoicePlayer::Speaker::update_configuration () SGSoundSample *sample = (*iter).second; sample->set_pitch(pitch); - sample->set_offset_pos(position); - sample->set_orientation(orientation, - inner_cone, - outer_cone, - outer_gain); + sample->set_base_position(position); // TODO: tie to listener pos + sample->set_orientation(orientation); + sample->set_audio_cone(inner_cone, outer_cone, outer_gain); sample->set_reference_dist(reference_dist); sample->set_max_dist(max_dist); } @@ -2172,7 +2170,7 @@ MK_VIII::VoicePlayer::Voice::stop (bool now) } void -MK_VIII::VoicePlayer::Voice::set_volume (double _volume) +MK_VIII::VoicePlayer::Voice::set_volume (float _volume) { volume = _volume; volume_changed(); @@ -2209,15 +2207,6 @@ MK_VIII::VoicePlayer::~VoicePlayer () for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++) delete *iter1; _voices.clear(); - -/* sound mgr already destroyed - samples already deleted - map::iterator iter2; - for (iter2 = samples.begin(); iter2 != samples.end(); iter2++) - { - bool status = globals->get_soundmgr()->remove((*iter2).first); - assert(status); - } -*/ samples.clear(); } @@ -2226,6 +2215,9 @@ MK_VIII::VoicePlayer::init () { #define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay" + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + _sgr = smgr->find("avionics", true); + make_voice(&voices.application_data_base_failed, "application-data-base-failed"); make_voice(&voices.bank_angle, "bank-angle"); make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle"); @@ -2270,13 +2262,7 @@ MK_VIII::VoicePlayer::get_sample (const char *name) std::ostringstream refname; refname << mk->name << "[" << mk->num << "]" << "/" << name; - SGSoundMgr *soundmgr = globals->get_soundmgr(); - if (soundmgr->is_working() == false) - { - return NULL; - } - - SGSoundSample *sample = soundmgr->find(refname.str()); + SGSoundSample *sample = _sgr->find(refname.str()); if (! sample) { SGPath sample_path(globals->get_fg_root()); @@ -2293,7 +2279,7 @@ MK_VIII::VoicePlayer::get_sample (const char *name) exit(1); } - soundmgr->add(sample, refname.str()); + _sgr->add(sample, refname.str()); samples[refname.str()] = sample; } @@ -2338,7 +2324,7 @@ MK_VIII::VoicePlayer::stop (unsigned int flags) } void -MK_VIII::VoicePlayer::set_volume (double _volume) +MK_VIII::VoicePlayer::set_volume (float _volume) { volume = _volume; if (voice) @@ -4130,7 +4116,7 @@ MK_VIII::Mode6Handler::leave_takeoff () } void -MK_VIII::Mode6Handler::set_volume (double volume) +MK_VIII::Mode6Handler::set_volume (float volume) { mk_voice(minimums_minimums)->set_volume(volume); mk_voice(five_hundred_above)->set_volume(volume); diff --git a/src/Instrumentation/mk_viii.hxx b/src/Instrumentation/mk_viii.hxx index 423562cfe..27cf023fa 100755 --- a/src/Instrumentation/mk_viii.hxx +++ b/src/Instrumentation/mk_viii.hxx @@ -36,6 +36,8 @@ using std::vector; using std::deque; using std::map; +class SGSampleGroup; + #include #include #include
@@ -733,10 +735,10 @@ public: public: bool silence; - virtual inline void play (double volume) {} + virtual inline void play (float volume) {} virtual inline void stop () {} virtual bool is_playing () = 0; - virtual inline void set_volume (double volume) {} + virtual inline void set_volume (float volume) {} }; ///////////////////////////////////////////////////////////////////////// @@ -746,16 +748,16 @@ public: class SampleElement : public Element { SGSoundSample *_sample; - double _volume; + float _volume; public: - inline SampleElement (SGSoundSample *sample, double volume = 1.0) + inline SampleElement (SGSoundSample *sample, float volume = 1.0) : _sample(sample), _volume(volume) { silence = false; } - virtual inline void play (double volume) { if (_sample) { set_volume(volume); _sample->play_once(); } } + virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } } virtual inline void stop () { if (_sample) _sample->stop(); } virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; } - virtual inline void set_volume (double volume) { if (_sample) _sample->set_volume(volume * _volume); } + virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); } }; ///////////////////////////////////////////////////////////////////////// @@ -771,7 +773,7 @@ public: inline SilenceElement (double duration) : _duration(duration) { silence = true; } - virtual inline void play (double volume) { start_time = globals->get_sim_time_sec(); } + virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); } virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; } }; @@ -790,19 +792,19 @@ public: void play (); void stop (bool now); - void set_volume (double _volume); + void set_volume (float _volume); void volume_changed (); void update (); private: VoicePlayer *player; - double volume; + float volume; vector elements; vector::iterator iter; - inline double get_volume () const { return player->volume * player->speaker.volume * volume; } + inline float get_volume () const { return player->volume * player->speaker.volume * volume; } }; /////////////////////////////////////////////////////////////////////////// @@ -811,10 +813,10 @@ public: struct { - double volume; + float volume; } conf; - double volume; + float volume; Voice *voice; Voice *next_voice; @@ -871,7 +873,7 @@ public: }; void stop (unsigned int flags = 0); - void set_volume (double _volume); + void set_volume (float _volume); void update (); inline void bind (SGPropertyNode *node) { speaker.bind(node); } @@ -887,8 +889,8 @@ public: VoicePlayer *player; double pitch; - float position[3]; - float orientation[3]; + SGVec3d position; + SGVec3f orientation; float inner_cone; float outer_cone; float outer_gain; @@ -913,7 +915,7 @@ public: template inline T get_property (T *ptr) const { return *ptr; } - double volume; + float volume; inline Speaker (VoicePlayer *_player) : player(_player), @@ -940,6 +942,7 @@ public: MK_VIII *mk; + SGSampleGroup *_sgr; Speaker speaker; map samples; @@ -1465,7 +1468,7 @@ private: void power_off (); void enter_takeoff (); void leave_takeoff (); - void set_volume (double volume); + void set_volume (float volume); bool altitude_callouts_enabled (); void update (); diff --git a/src/Instrumentation/navradio.cxx b/src/Instrumentation/navradio.cxx index ee217d6c9..f3b95c5e3 100644 --- a/src/Instrumentation/navradio.cxx +++ b/src/Instrumentation/navradio.cxx @@ -154,7 +154,8 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) : _name(node->getStringValue("name", "nav")), _num(node->getIntValue("number", 0)), _time_before_search_sec(-1.0), - _falseCoursesEnabled(true) + _falseCoursesEnabled(true), + _sgr(NULL) { SGPath path( globals->get_fg_root() ); SGPath term = path; @@ -182,6 +183,9 @@ FGNavRadio::~FGNavRadio() void FGNavRadio::init () { + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + _sgr = smgr->find("avionics", true); + morse.init(); string branch; @@ -768,17 +772,17 @@ void FGNavRadio::updateAudio() // play station ident via audio system if on + ident, // otherwise turn it off - if (!power_btn_node->getBoolValue() + if (!power_btn_node->getBoolValue() || !(bus_power_node->getDoubleValue() > 1.0) || !ident_btn_node->getBoolValue() || !audio_btn_node->getBoolValue() ) { - globals->get_soundmgr()->stop( nav_fx_name ); - globals->get_soundmgr()->stop( dme_fx_name ); + _sgr->stop( nav_fx_name ); + _sgr->stop( dme_fx_name ); return; } - SGSoundSample *sound = globals->get_soundmgr()->find( nav_fx_name ); - double vol = vol_btn_node->getDoubleValue(); + SGSoundSample *sound = _sgr->find( nav_fx_name ); + double vol = vol_btn_node->getFloatValue(); SG_CLAMP_RANGE(vol, 0.0, 1.0); if ( sound != NULL ) { @@ -787,7 +791,7 @@ void FGNavRadio::updateAudio() SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-vor-ident sound" ); } - sound = globals->get_soundmgr()->find( dme_fx_name ); + sound = _sgr->find( dme_fx_name ); if ( sound != NULL ) { sound->set_volume( vol ); } else { @@ -810,16 +814,16 @@ void FGNavRadio::updateAudio() play_count = ++play_count % NUM_IDENT_SLOTS; // Previous ident is out of time; if still playing, cut it off: - globals->get_soundmgr()->stop( nav_fx_name ); - globals->get_soundmgr()->stop( dme_fx_name ); + _sgr->stop( nav_fx_name ); + _sgr->stop( dme_fx_name ); if (play_count == 0) { // the DME slot if (_dmeInRange && dme_serviceable_node->getBoolValue()) { // play DME ident - globals->get_soundmgr()->play_once( dme_fx_name ); + if (vol > 0.05) _sgr->play_once( dme_fx_name ); } } else { // NAV slot if (inrange_node->getBoolValue() && nav_serviceable_node->getBoolValue()) { - globals->get_soundmgr()->play_once(nav_fx_name); + if (vol > 0.05) _sgr->play_once(nav_fx_name); } } } @@ -902,8 +906,9 @@ void FGNavRadio::search() _gs = NULL; _dme = NULL; nav_id_node->setStringValue(""); - globals->get_soundmgr()->remove( nav_fx_name ); - globals->get_soundmgr()->remove( dme_fx_name ); + + _sgr->remove( nav_fx_name ); + _sgr->remove( dme_fx_name ); } is_valid_node->setBoolValue(nav != NULL); @@ -945,25 +950,25 @@ double FGNavRadio::localizerWidth(FGNavRecord* aLOC) void FGNavRadio::audioNavidChanged() { - if ( globals->get_soundmgr()->exists(nav_fx_name)) { - globals->get_soundmgr()->remove(nav_fx_name); + if (_sgr->exists(nav_fx_name)) { + _sgr->remove(nav_fx_name); } try { string trans_ident(_navaid->get_trans_ident()); SGSoundSample* sound = morse.make_ident(trans_ident, LO_FREQUENCY); sound->set_volume( 0.3 ); - if (!globals->get_soundmgr()->add( sound, nav_fx_name )) { + if (!_sgr->add( sound, nav_fx_name )) { SG_LOG(SG_COCKPIT, SG_WARN, "Failed to add v1-vor-ident sound"); } - if ( globals->get_soundmgr()->exists( dme_fx_name ) ) { - globals->get_soundmgr()->remove( dme_fx_name ); + if ( _sgr->exists( dme_fx_name ) ) { + _sgr->remove( dme_fx_name ); } sound = morse.make_ident( trans_ident, HI_FREQUENCY ); sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, dme_fx_name ); + _sgr->add( sound, dme_fx_name ); int offset = (int)(sg_random() * 30.0); play_count = offset / 4; diff --git a/src/Instrumentation/navradio.hxx b/src/Instrumentation/navradio.hxx index 3ee3e4155..978e77d6f 100644 --- a/src/Instrumentation/navradio.hxx +++ b/src/Instrumentation/navradio.hxx @@ -35,6 +35,7 @@ // forward decls class SGInterpTable; +class SGSampleGroup; class FGNavRecord; typedef SGSharedPtr FGNavRecordPtr; @@ -158,6 +159,8 @@ class FGNavRadio : public SGSubsystem // realism setting, are false courses and GS lobes enabled? bool _falseCoursesEnabled; + + SGSampleGroup *_sgr; bool updateWithPower(double aDt); diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 3f36555a0..ab6a15844 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -1251,13 +1252,17 @@ do_set_cursor (const SGPropertyNode * arg) static bool do_play_audio_sample (const SGPropertyNode * arg) { - FGFX *fx = (FGFX *)globals->get_subsystem("fx"); string path = arg->getStringValue("path"); string file = arg->getStringValue("file"); double volume = arg->getDoubleValue("volume"); // cout << "playing " << path << " / " << file << endl; try { - fx->play_message( path, file, volume ); + static FGFX *fx = 0; + if ( !fx ) { + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + fx = (FGFX *)smgr->find("fx"); + } + if (fx) fx->play_message( path, file, volume ); return true; } catch (const sg_io_exception&) { diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index ab5742ac4..10bded7bb 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -136,6 +136,7 @@ using std::string; class Sound; +class SGSoundMgr; extern const char *default_root; float init_volume; @@ -1520,7 +1521,6 @@ bool fgInitSubsystems() { // Initialize the ridgelift subsystem globals->add_subsystem("ridgelift", new FGRidgeLift); - //////////////////////////////////////////////////////////////////// // Initialize the aircraft systems and instrumentation (before the // autopilot.) @@ -1582,22 +1582,9 @@ bool fgInitSubsystems() { fgGetBool("/sim/rendering/bump-mapping", false); #ifdef ENABLE_AUDIO_SUPPORT - //////////////////////////////////////////////////////////////////// - // Initialize the sound subsystem. - //////////////////////////////////////////////////////////////////// - - init_volume = fgGetFloat("/sim/sound/volume"); - fgSetFloat("/sim/sound/volume", 0.0f); - globals->set_soundmgr(new SGSoundMgr); - globals->get_soundmgr()->init(); - globals->get_soundmgr()->bind(); - - //////////////////////////////////////////////////////////////////// // Initialize the sound-effects subsystem. //////////////////////////////////////////////////////////////////// - - globals->add_subsystem("fx", new FGFX); globals->add_subsystem("voice", new FGVoiceMgr); #endif @@ -1680,6 +1667,19 @@ bool fgInitSubsystems() { //////////////////////////////////////////////////////////////////// globals->add_subsystem("replay", new FGReplay); + + //////////////////////////////////////////////////////////////////// + // Add Sound Manager. + // Put the sound manager last so it can use the CPU while the GPU + // is processing the scenery (doubled the frame-rate for me) -EMH- + //////////////////////////////////////////////////////////////////// +#ifdef ENABLE_AUDIO_SUPPORT + init_volume = fgGetFloat("/sim/sound/volume"); + fgSetFloat("/sim/sound/volume", 0.0f); + + globals->add_subsystem("soundmgr", new SGSoundMgr); +#endif + //////////////////////////////////////////////////////////////////// // Bind and initialize subsystems. //////////////////////////////////////////////////////////////////// diff --git a/src/Main/fg_props.cxx b/src/Main/fg_props.cxx index 1e8885c35..e3340b8a4 100644 --- a/src/Main/fg_props.cxx +++ b/src/Main/fg_props.cxx @@ -221,15 +221,17 @@ setFreeze (bool f) { frozen = f; +#if 0 // Stop sound on a pause - SGSoundMgr *s = globals->get_soundmgr(); - if ( s != NULL ) { + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + if ( smgr != NULL ) { if ( f ) { - s->pause(); + smgr->suspend(); } else if (!fgGetBool("/sim/sound/pause")) { - s->resume(); + smgr->resume(); } } +#endif } diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index 262423c2a..84cf9c932 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -24,7 +24,6 @@ # include #endif -#include #include #include #include @@ -83,7 +82,6 @@ FGGlobals::FGGlobals() : matlib( NULL ), route_mgr( NULL ), current_panel( NULL ), - soundmgr( NULL ), ATC_mgr( NULL ), AI_mgr( NULL ), controls( NULL ), @@ -135,7 +133,6 @@ FGGlobals::~FGGlobals() delete matlib; delete route_mgr; delete current_panel; - delete soundmgr; delete ATC_mgr; delete AI_mgr; diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index a1c58797e..e778590dd 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -49,7 +49,6 @@ class SGMagVar; class SGMaterialLib; class SGPropertyNode; class SGTime; -class SGSoundMgr; class SGEventMgr; class SGSubsystemMgr; class SGSubsystem; @@ -132,9 +131,6 @@ private: // 2D panel FGPanel *current_panel; - // sound manager - SGSoundMgr *soundmgr; - // ATC manager FGATCMgr *ATC_mgr; @@ -244,9 +240,6 @@ public: inline FGPanel *get_current_panel() const { return current_panel; } inline void set_current_panel( FGPanel *cp ) { current_panel = cp; } - inline SGSoundMgr *get_soundmgr() const { return soundmgr; } - inline void set_soundmgr( SGSoundMgr *sm ) { soundmgr = sm; } - inline FGControls *get_controls() const { return controls; } inline void set_controls( FGControls *c ) { controls = c; } @@ -305,7 +298,7 @@ public: inline void set_tile_mgr ( FGTileMgr *t ) { tile_mgr = t; } inline FGFontCache *get_fontcache() const { return fontcache; } - + inline FGNavList *get_navlist() const { return navlist; } inline void set_navlist( FGNavList *n ) { navlist = n; } inline FGNavList *get_loclist() const { return loclist; } diff --git a/src/Main/main.cxx b/src/Main/main.cxx index d16cbf4d6..023b4f87f 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -477,19 +478,14 @@ static void fgMainLoop( void ) { // update the view angle as late as possible, but before sound calculations globals->get_viewmgr()->update(real_delta_time_sec); - // Run audio scheduler -#ifdef ENABLE_AUDIO_SUPPORT - FGFX* fx = (FGFX*) globals->get_subsystem("fx"); - fx->update_fx_late(delta_time_sec); -#endif - // END Tile Manager udpates if (!scenery_loaded && globals->get_tile_mgr()->isSceneryLoaded() && cur_fdm_state->get_inited()) { fgSetBool("sim/sceneryloaded",true); fgSetFloat("/sim/sound/volume", init_volume); - globals->get_soundmgr()->set_volume(init_volume); + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + smgr->set_volume(init_volume); } fgRequestRedraw(); @@ -723,13 +719,13 @@ static void fgIdleFunction ( void ) { SG_LOG( SG_GENERAL, SG_INFO, "Starting intro music: " << mp3file.str() ); -#if defined( __CYGWIN__ ) +# if defined( __CYGWIN__ ) string command = "start /m `cygpath -w " + mp3file.str() + "`"; -#elif defined( WIN32 ) +# elif defined( WIN32 ) string command = "start /m " + mp3file.str(); -#else +# else string command = "mpg123 " + mp3file.str() + "> /dev/null 2>&1"; -#endif +# endif system ( command.c_str() ); } diff --git a/src/Main/viewmgr.cxx b/src/Main/viewmgr.cxx index 596f343ae..8f865265c 100644 --- a/src/Main/viewmgr.cxx +++ b/src/Main/viewmgr.cxx @@ -30,6 +30,7 @@ #include // strcmp #include +#include #include #include
#include
@@ -293,6 +294,17 @@ FGViewMgr::update (double dt) do_axes(); view->update(dt); abs_viewer_position = loop_view->getViewPosition(); + + // update audio listener values + static SGSoundMgr *smgr = 0; + if (!smgr) smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + if (smgr) { + // set the viewer posotion in Cartesian coordinates in meters + smgr->set_position(abs_viewer_position); + smgr->set_orientation(loop_view->getViewOrientation()); +//TODO: should be in meters per second +// smr->set_veloicty(SGVec3f(0,0,0)); + } } void diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx index a1721228a..866c09188 100644 --- a/src/Model/acmodel.cxx +++ b/src/Model/acmodel.cxx @@ -22,18 +22,30 @@ #include
#include
#include +#include #include "model_panel.hxx" #include "acmodel.hxx" + //////////////////////////////////////////////////////////////////////// // Implementation of FGAircraftModel //////////////////////////////////////////////////////////////////////// FGAircraftModel::FGAircraftModel () - : _aircraft(0) + : _aircraft(0), + _fx(0), + _lon(0), + _lat(0), + _alt(0), + _pitch(0), + _roll(0), + _heading(0), + _speed_north(0), + _speed_east(0), + _speed_up(0) { } @@ -70,7 +82,15 @@ FGAircraftModel::init () void FGAircraftModel::bind () { - // No-op + _lon = fgGetNode("position/longitude-deg", true); + _lat = fgGetNode("position/latitude-deg", true); + _alt = fgGetNode("position/altitude-ft", true); + _pitch = fgGetNode("orientation/pitch-deg", true); + _roll = fgGetNode("orientation/roll-deg", true); + _heading = fgGetNode("orientation/heading-deg", true); + _speed_north = fgGetNode("/velocities/speed-north-fps", true); + _speed_east = fgGetNode("/velocities/speed-east-fps", true); + _speed_up = fgGetNode("/velocities/vertical-speed-fps", true); } void @@ -91,13 +111,41 @@ FGAircraftModel::update (double dt) _aircraft->setVisible(true); } - _aircraft->setPosition(fgGetDouble("/position/longitude-deg"), - fgGetDouble("/position/latitude-deg"), - fgGetDouble("/position/altitude-ft")); - _aircraft->setOrientation(fgGetDouble("/orientation/roll-deg"), - fgGetDouble("/orientation/pitch-deg"), - fgGetDouble("/orientation/heading-deg")); + _aircraft->setPosition(_lon->getDoubleValue(), + _lat->getDoubleValue(), + _alt->getDoubleValue()); + _aircraft->setOrientation(_roll->getDoubleValue(), + _pitch->getDoubleValue(), + _heading->getDoubleValue()); _aircraft->update(); + + if ( !_fx) { + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + if (smgr) { + _fx = new FGFX(smgr, "fx"); + _fx->init(); + } + } + + if (_fx) { + // Get the Cartesian coordinates in meters + SGVec3d pos = SGVec3d::fromGeod(_aircraft->getPosition()); + _fx->set_position( pos ); + + SGQuatd orient_m = SGQuatd::fromLonLat(_aircraft->getPosition()); + orient_m *= SGQuatd::fromYawPitchRollDeg(_heading->getDoubleValue(), + _pitch->getDoubleValue(), + _roll->getDoubleValue()); + SGVec3d orient = orient_m.rotateBack(SGVec3d::e1()); + _fx->set_orientation( toVec3f(orient) ); + + SGVec3f vel = SGVec3f( _speed_north->getFloatValue(), + _speed_east->getFloatValue(), + _speed_up->getFloatValue()); +// TODO: rotate to properly align with the model orientation + + _fx->set_velocity( vel*SG_FEET_TO_METER ); + } } diff --git a/src/Model/acmodel.hxx b/src/Model/acmodel.hxx index 16fc45527..da728fcf6 100644 --- a/src/Model/acmodel.hxx +++ b/src/Model/acmodel.hxx @@ -25,7 +25,7 @@ using std::vector; // Don't pull in the headers, since we don't need them here. class SGModelPlacement; - +class FGFX; class FGAircraftModel : public SGSubsystem { @@ -43,6 +43,18 @@ public: private: SGModelPlacement * _aircraft; + FGFX * _fx; + + SGPropertyNode * _lon; + SGPropertyNode * _lat; + SGPropertyNode * _alt; + SGPropertyNode * _pitch; + SGPropertyNode * _roll; + SGPropertyNode * _heading; + SGPropertyNode * _speed_north; + SGPropertyNode * _speed_east; + SGPropertyNode * _speed_up; + }; #endif // __ACMODEL_HXX diff --git a/src/Sound/beacon.cxx b/src/Sound/beacon.cxx index 41a990271..9b5f353af 100644 --- a/src/Sound/beacon.cxx +++ b/src/Sound/beacon.cxx @@ -24,8 +24,6 @@ #include "beacon.hxx" #include -#include
-#include
// constructor FGBeacon::FGBeacon() @@ -43,13 +41,9 @@ bool FGBeacon::init() { int len; unsigned char *ptr; - if (globals->get_soundmgr()->is_working() == false) { - return false; - } - - unsigned char inner_buf[ INNER_SIZE ] ; - unsigned char middle_buf[ MIDDLE_SIZE ] ; - unsigned char outer_buf[ OUTER_SIZE ] ; + unsigned char *inner_buf = new unsigned char[ INNER_SIZE ] ; + unsigned char *middle_buf = new unsigned char[ MIDDLE_SIZE ] ; + unsigned char *outer_buf = new unsigned char[ OUTER_SIZE ] ; // Make inner marker beacon sound len= (int)(INNER_DIT_LEN / 2.0 ); @@ -99,7 +93,7 @@ bool FGBeacon::init() { ptr += OUTER_DAH_LEN; memcpy( ptr, outer_dah, OUTER_DAH_LEN ); - outer = new SGSoundSample( outer_buf, OUTER_SIZE, BYTES_PER_SECOND); + outer = new SGSoundSample( outer_buf, OUTER_SIZE, BYTES_PER_SECOND ); outer->set_reference_dist( 10.0 ); outer->set_max_dist( 20.0 ); } catch ( sg_io_exception &e ) { diff --git a/src/Sound/fg_fx.cxx b/src/Sound/fg_fx.cxx index 50d39479d..da6fcece3 100644 --- a/src/Sound/fg_fx.cxx +++ b/src/Sound/fg_fx.cxx @@ -35,8 +35,8 @@ #include #include #include -#include #include +#include #include
@@ -44,7 +44,7 @@ #include #include
-FGFX::FGFX () : +FGFX::FGFX ( SGSoundMgr *smgr, const string &refname ) : last_visitor_pos(SGVec3d::zeros()), last_model_pos(SGVec3d::zeros()), last_pause( true ), @@ -52,8 +52,12 @@ FGFX::FGFX () : _pause( fgGetNode("/sim/sound/pause") ), _volume( fgGetNode("/sim/sound/volume") ) { + SGSampleGroup::_smgr = smgr; + SGSampleGroup::_smgr->add(this, refname); + SGSampleGroup::_active = _smgr->is_working(); } + FGFX::~FGFX () { unsigned int i; @@ -68,6 +72,7 @@ FGFX::~FGFX () } } + void FGFX::init() { @@ -99,8 +104,8 @@ FGFX::init() SGXmlSound *sound = new SGXmlSound(); try { - sound->init(globals->get_props(), node->getChild(i), - globals->get_soundmgr(), globals->get_fg_root()); + sound->init(globals->get_props(), node->getChild(i), this, + globals->get_fg_root()); _sound.push_back(sound); } catch ( sg_exception &e ) { @@ -111,89 +116,65 @@ FGFX::init() } } + void FGFX::reinit() { - _sound.clear(); - init(); + _sound.clear(); + init(); }; -void -FGFX::bind () -{ -} - -void -FGFX::unbind () -{ -} void FGFX::update (double dt) { - SGSoundMgr *smgr = globals->get_soundmgr(); - - if (smgr->is_working() == false) { - return; - } - // command sound manger - bool pause = _pause->getBoolValue(); - if ( pause != last_pause ) { - if ( pause ) { - smgr->pause(); + bool new_pause = _pause->getBoolValue(); + if ( new_pause != last_pause ) { + if ( new_pause ) { + suspend(); } else { - smgr->resume(); + resume(); } - last_pause = pause; + last_pause = new_pause; } // process mesage queue const string msgid = "Sequential Audio Message"; - bool is_playing = false; - if ( smgr->exists( msgid ) ) { - if ( smgr->is_playing( msgid ) ) { + bool now_playing = false; + if ( exists( msgid ) ) { + if ( is_playing( msgid ) ) { // still playing, do nothing - is_playing = true; + now_playing = true; } else { // current message finished, stop and remove - smgr->stop( msgid ); // removes source - smgr->remove( msgid ); // removes buffer + stop( msgid ); // removes source + remove( msgid ); // removes buffer } } - if ( !is_playing ) { + if ( !now_playing ) { // message queue idle, add next sound if we have one if ( _samplequeue.size() > 0 ) { - smgr->add( _samplequeue.front(), msgid ); + add( _samplequeue.front(), msgid ); _samplequeue.pop(); - smgr->play_once( msgid ); + play_once( msgid ); } } double volume = _volume->getDoubleValue(); if ( volume != last_volume ) { - smgr->set_volume( volume ); + set_volume( volume ); last_volume = volume; } - if ( !pause ) { + if ( !new_pause ) { // update sound effects if not paused for ( unsigned int i = 0; i < _sound.size(); i++ ) { _sound[i]->update(dt); } } -} -void -FGFX::update_fx_late(double dt) -{ - SGSoundMgr *smgr = globals->get_soundmgr(); - if (!smgr->is_working()) { - return; - } - - smgr->update(dt); - update_pos_and_orientation(smgr, dt); + SGSampleGroup::update(dt); } /** @@ -203,100 +184,14 @@ FGFX::update_fx_late(double dt) void FGFX::play_message( SGSoundSample *_sample ) { - _samplequeue.push( _sample ); + _samplequeue.push( _sample ); } void FGFX::play_message( const std::string& path, const std::string& fname, double volume ) { - if (globals->get_soundmgr()->is_working() == true) { - SGSoundSample *sample; - sample = new SGSoundSample( path.c_str(), fname.c_str() ); - sample->set_volume( volume ); - play_message( sample ); - } -} - -void -FGFX::update_pos_and_orientation(SGSoundMgr *smgr, double dt) -{ - SGModelPlacement *model = globals->get_aircraft_model()->get3DModel(); - FGViewer *observer = globals->get_current_view(); - - // Right now we make a simplifying assumption that the primary - // aircraft is the source of all sounds and that all sounds are - // positioned in the aircraft base - // EMH: Note: this is fine, to hear multiple aircraft simulataniously - // we just have to trigger one instance of the FGFX class for every - // aircraft - - // get the orientation - const SGQuatd view_or = observer->getViewOrientation(); - SGQuatd surf_or = SGQuatd::fromLonLat(observer->getPosition()); - - SGQuatd model_or = SGQuatd::fromYawPitchRollDeg( - model->getHeadingDeg(), - model->getPitchDeg(), - model->getRollDeg()); - - // get the up and at vector in the aircraft base - // (ok, the up vector is a down vector, but the coordinates - // are finally calculated in a left hand system and openal - // lives in a right hand system. Therefore we need to pass - // the down vector to get correct stereo sound.) - SGVec3d sgv_up - = model_or.rotateBack(surf_or.rotateBack(view_or.rotate(SGVec3d(0,1,0)))); - SGVec3d sgv_at - = model_or.rotateBack(surf_or.rotateBack(view_or.rotate(SGVec3d(0,0,1)))); - - // get the location data for the primary FDM (now hardcoded to ac model)... - // EMH: to add multiple sound sources this should be replaced - SGVec3d absolute_view_pos = SGVec3d::fromGeod(model->getPosition()); - - // calculate speed of visitor and model - SGVec3d moved = last_visitor_pos - observer->get_view_pos(); - last_visitor_pos = observer->get_view_pos(); - SGVec3f listener_vel(model_or.rotateBack(surf_or.rotateBack(moved))); - - moved = last_model_pos - absolute_view_pos; - last_model_pos = absolute_view_pos; - SGVec3f model_vel(model_or.rotateBack(surf_or.rotateBack(moved))); - - if (dt > 0) { - model_vel /= dt; - listener_vel /= dt; - } - - // checking, if the listener pos has moved suddenly - if (length(listener_vel) > 1000) { - // check if the relative speed model vs listener has moved suddenly, too - SGVec3f delta_vel = listener_vel - model_vel; - if (length(delta_vel) > 1000) - // a sane value - smgr->set_listener_vel(model_vel.data()); - else - smgr->set_listener_vel(listener_vel.data()); - } else { - smgr->set_listener_vel( listener_vel.data()); - } - - // set positional offset for sources - SGVec3d dsource_pos_offset = observer->get_view_pos() - absolute_view_pos; - dsource_pos_offset = model_or.rotateBack(surf_or.rotateBack( - dsource_pos_offset - )); - - smgr->set_source_pos_all( SGVec3f(dsource_pos_offset).data() ); - smgr->set_source_vel_all(model_vel.data() ); - - float orient[6]; - for (int i = 0; i < 3; i++) { - orient[i] = sgv_at[i]; - orient[i + 3] = sgv_up[i]; - } - smgr->set_listener_orientation( orient ); - - // The listener is always positioned at the origin. - smgr->set_listener_pos( SGVec3f::zeros().data() ); + SGSoundSample *sample = new SGSoundSample( path.c_str(), fname.c_str() ); + sample->set_volume( volume ); + play_message( sample ); } // end of fg_fx.cxx diff --git a/src/Sound/fg_fx.hxx b/src/Sound/fg_fx.hxx index 1f7138bc1..76d38915f 100644 --- a/src/Sound/fg_fx.hxx +++ b/src/Sound/fg_fx.hxx @@ -30,16 +30,15 @@ #include #include +#include #include class SGXmlSound; -class SGSoundSample; -class SGSoundMgr; /** * Generator for FlightGear sound effects. * - * This module uses FGSoundMgr to generate sound effects based + * This module uses a FGSampleGroup class to generate sound effects based * on current flight conditions. The sound manager must be initialized * before this object is. * @@ -52,18 +51,16 @@ class SGSoundMgr; * This second mechanims is useful for things like tutorial messages or * background atc chatter. */ -class FGFX : public SGSubsystem +class FGFX : public SGSampleGroup { public: - FGFX (); + FGFX ( SGSoundMgr *smgr, const string &refname ); virtual ~FGFX (); virtual void init (); virtual void reinit (); - virtual void bind (); - virtual void unbind (); virtual void update (double dt); /** @@ -73,15 +70,10 @@ public: void play_message( SGSoundSample *_sample ); void play_message( const std::string& path, const std::string& fname, double volume ); - /** - * Explicit late update hook, to avoid problems which occur if done during - * normal SGSubsytem updating. - */ - void update_fx_late(double dt); - private: - void update_pos_and_orientation(SGSoundMgr *smgr, double dt); + void update_pos_and_orientation(double dt); + SGVec3d last_visitor_pos; SGVec3d last_model_pos; diff --git a/src/Sound/morse.cxx b/src/Sound/morse.cxx index 754c98eb3..a56273288 100644 --- a/src/Sound/morse.cxx +++ b/src/Sound/morse.cxx @@ -23,9 +23,6 @@ #include -#include
-#include
- #include "morse.hxx" @@ -171,10 +168,6 @@ bool FGMorse::cust_init(const int freq ) { // make a SGSoundSample morse code transmission for the specified string SGSoundSample *FGMorse::make_ident( const string& id, const int freq ) { - if (globals->get_soundmgr()->is_working() == false) { - return 0; - } - char *idptr = (char *)id.c_str(); int length = 0; @@ -271,9 +264,6 @@ SGSoundSample *FGMorse::make_ident( const string& id, const int freq ) { SGSoundSample *sample = new SGSoundSample( buffer, length, BYTES_PER_SECOND ); - // clean up the buffer - delete [] buffer; - sample->set_reference_dist( 10.0 ); sample->set_max_dist( 20.0 ); -- 2.39.5