]> git.mxchange.org Git - flightgear.git/commitdiff
Some more refactoring of the radios
authorTorsten Dreyer <Torsten@t3r.de>
Thu, 15 Sep 2011 19:28:30 +0000 (21:28 +0200)
committerTorsten Dreyer <Torsten@t3r.de>
Thu, 15 Sep 2011 19:28:30 +0000 (21:28 +0200)
- wrap the ident-generating code into a class
- move dme-in-range property into dme.cxx
- move dme-ident generation into dme.cxx
- support ident-button and volume for dme idents
- use globals.get_aircraft_position instead of properties
- some minor cleanup

14 files changed:
projects/VC90/FlightGear/FlightGear.vcproj
src/Instrumentation/adf.cxx
src/Instrumentation/dme.cxx
src/Instrumentation/dme.hxx
src/Instrumentation/kr_87.cxx
src/Instrumentation/kr_87.hxx
src/Instrumentation/navradio.cxx
src/Instrumentation/navradio.hxx
src/Sound/CMakeLists.txt
src/Sound/Makefile.am
src/Sound/audioident.cxx [new file with mode: 0644]
src/Sound/audioident.hxx [new file with mode: 0644]
src/Sound/morse.cxx
src/Sound/morse.hxx

index 77d845292c5ea8807dc44568009c6650c5fe86ab..1ae6559abfdcfdd6818e4e5bc3ee488a23c3fa1e 100644 (file)
                <Filter\r
                        Name="Lib_Sound"\r
                        >\r
+                       <File\r
+                               RelativePath="..\..\..\src\Sound\audioident.cxx"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\..\src\Sound\audioident.hxx"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\src\Sound\beacon.cxx"\r
                                >\r
index e3fbac05332aeb61f9dc1d3a6a01f9aa9941aa8d..805be10409132e9b72975beebf245421344916a3 100644 (file)
@@ -252,7 +252,7 @@ ADF::search (double frequency_khz, double longitude_rad,
         }
 
         SGSoundSample *sound;
-        sound = FGMorse::instance()->make_ident( ident, LO_FREQUENCY );
+        sound = FGMorse::instance()->make_ident( ident, FGMorse::LO_FREQUENCY );
         sound->set_volume(_last_volume = 0);
         _sgr->add( sound, _adf_ident );
 
index 925681e0acbe08bd444cf25f5573a8bdd657a487..d8d14a5a22078598760ce44a68bbb8bd3bdd0b96 100644 (file)
@@ -8,15 +8,16 @@
 #endif
 
 #include <simgear/compiler.h>
+#include <simgear/sg_inlines.h>
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/math/sg_random.h>
 
 #include <Main/fg_props.hxx>
 #include <Navaids/navlist.hxx>
+#include <Sound/audioident.hxx>
 
 #include "dme.hxx"
 
-
 /**
  * Adjust the range.
  *
@@ -44,17 +45,16 @@ DME::DME ( SGPropertyNode *node )
     : _last_distance_nm(0),
       _last_frequency_mhz(-1),
       _time_before_search_sec(0),
-      _transmitter_valid(false),
-      _transmitter_elevation_ft(0),
-      _transmitter_range_nm(0),
-      _transmitter_bias(0.0),
+      _navrecord(NULL),
       _name(node->getStringValue("name", "dme")),
-      _num(node->getIntValue("number", 0))
+      _num(node->getIntValue("number", 0)),
+      _audioIdent(NULL)
 {
 }
 
 DME::~DME ()
 {
+    delete _audioIdent;
 }
 
 void
@@ -65,9 +65,6 @@ DME::init ()
 
     SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true );
 
-    _longitude_node = fgGetNode("/position/longitude-deg", true);
-    _latitude_node = fgGetNode("/position/latitude-deg", true);
-    _altitude_node = fgGetNode("/position/altitude-ft", true);
     _serviceable_node = node->getChild("serviceable", 0, true);
     _electrical_node = fgGetNode("/systems/electrical/outputs/dme", true);
     SGPropertyNode *fnode = node->getChild("frequencies", 0, true);
@@ -77,11 +74,28 @@ DME::init ()
     _distance_node = node->getChild("indicated-distance-nm", 0, true);
     _speed_node = node->getChild("indicated-ground-speed-kt", 0, true);
     _time_node = node->getChild("indicated-time-min", 0, true);
+
+    double d = node->getDoubleValue( "volume", 1.0 );
+    _volume_node = node->getChild("volume", 0, true);
+    _volume_node->setDoubleValue( d );
+
+    bool b = node->getBoolValue( "ident", false );
+    _ident_btn_node = node->getChild("ident", 0, true);
+    _ident_btn_node->setBoolValue( b );
+
+    std::ostringstream temp;
+    temp << _name << "-ident-" << _num;
+    if( NULL == _audioIdent ) 
+        _audioIdent = new DMEAudioIdent( temp.str() );
+    _audioIdent->init();
 }
 
 void
 DME::update (double delta_time_sec)
 {
+    if( delta_time_sec < SGLimitsd::min() )
+        return;  //paused
+
                                 // Figure out the source
     const char * source = _source_node->getStringValue();
     if (source[0] == '\0') {
@@ -100,48 +114,50 @@ DME::update (double delta_time_sec)
     _frequency_node->setDoubleValue(frequency_mhz);
 
                                 // Get the aircraft position
-    double longitude_rad =
-        _longitude_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
-    double latitude_rad =
-        _latitude_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
-    double altitude_m =
-        _altitude_node->getDoubleValue() * SG_FEET_TO_METER;
-
-                                // On timeout, scan again
+    // On timeout, scan again
     _time_before_search_sec -= delta_time_sec;
-    if (_time_before_search_sec < 0)
-        search(frequency_mhz, longitude_rad,
-               latitude_rad, altitude_m);
+    if (_time_before_search_sec < 0) {
+        _time_before_search_sec = 1.0;
 
-                                // If it's off, don't bother.
+        _navrecord = globals->get_dmelist()->findByFreq( frequency_mhz,
+            globals->get_aircraft_position());
+    }
+
+    // If it's off, don't bother.
     if (!_serviceable_node->getBoolValue() ||
         !_electrical_node->getBoolValue() ||
-        !_transmitter_valid) {
+        NULL == _navrecord ) {
         _last_distance_nm = 0;
         _in_range_node->setBoolValue(false);
         _distance_node->setDoubleValue(0);
         _speed_node->setDoubleValue(0);
         _time_node->setDoubleValue(0);
+        _audioIdent->setIdent("", 0.0 );
         return;
     }
 
-                                // Calculate the distance to the transmitter
-    SGGeod geod = SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m);
-    SGVec3d location = SGVec3d::fromGeod(geod);
+    // Calculate the distance to the transmitter
+    SGVec3d location = SGVec3d::fromGeod(globals->get_aircraft_position());
     
-    double distance_nm = dist(_transmitter, location) * SG_METER_TO_NM;
+    double distance_nm = dist(_navrecord->cart(), location) * SG_METER_TO_NM;
 
-    double range_nm = adjust_range(_transmitter_elevation_ft,
-                                   altitude_m * SG_METER_TO_FEET,
-                                   _transmitter_range_nm);
+    double range_nm = adjust_range(_navrecord->get_elev_ft(),
+                                   globals->get_aircraft_position().getElevationFt(),
+                                   _navrecord->get_range());
 
     if (distance_nm <= range_nm) {
+        double volume = _volume_node->getDoubleValue();
+        if( false == _ident_btn_node->getBoolValue() )
+            volume = 0.0;
+
+        _audioIdent->setIdent(_navrecord->ident(), volume );
+
         double speed_kt = (fabs(distance_nm - _last_distance_nm) *
                            ((1 / delta_time_sec) * 3600.0));
         _last_distance_nm = distance_nm;
 
         _in_range_node->setBoolValue(true);
-        double tmp_dist = distance_nm - _transmitter_bias;
+        double tmp_dist = distance_nm - _navrecord->get_multiuse();
         if ( tmp_dist < 0.0 ) {
             tmp_dist = 0.0;
         }
@@ -156,29 +172,10 @@ DME::update (double delta_time_sec)
         _distance_node->setDoubleValue(0);
         _speed_node->setDoubleValue(0);
         _time_node->setDoubleValue(0);
+        _audioIdent->setIdent("", 0.0 );
     }
-}
-
-void
-DME::search (double frequency_mhz, double longitude_rad,
-             double latitude_rad, double altitude_m)
-{
-    // reset search time
-    _time_before_search_sec = 1.0;
-
-    // try the ILS list first
     
-    FGNavRecord *dme = globals->get_dmelist()->findByFreq( frequency_mhz,
-      SGGeod::fromRadM(longitude_rad, latitude_rad, altitude_m));
-
-    _transmitter_valid = (dme != NULL);
-
-    if ( _transmitter_valid ) {
-        _transmitter = dme->cart();
-        _transmitter_elevation_ft = dme->get_elev_ft();
-        _transmitter_range_nm = dme->get_range();
-        _transmitter_bias = dme->get_multiuse();
-    }
+    _audioIdent->update( delta_time_sec );
 }
 
 // end of dme.cxx
index 5d9963b10d8466c577d6e55f4de718ed78dbe002..6ec6edc6396dbec5e7fda958cd68cb5e64be1c9c 100644 (file)
@@ -10,7 +10,6 @@
 #include <simgear/props/props.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 
-
 /**
  * Model a DME radio.
  *
@@ -44,12 +43,6 @@ public:
 
 private:
 
-    void search (double frequency, double longitude_rad,
-                 double latitude_rad, double altitude_m);
-
-    SGPropertyNode_ptr _longitude_node;
-    SGPropertyNode_ptr _latitude_node;
-    SGPropertyNode_ptr _altitude_node;
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _electrical_node;
     SGPropertyNode_ptr _source_node;
@@ -59,20 +52,19 @@ private:
     SGPropertyNode_ptr _distance_node;
     SGPropertyNode_ptr _speed_node;
     SGPropertyNode_ptr _time_node;
+    SGPropertyNode_ptr _ident_btn_node;
+    SGPropertyNode_ptr _volume_node;
 
     double _last_distance_nm;
     double _last_frequency_mhz;
     double _time_before_search_sec;
 
-    bool _transmitter_valid;
-    SGVec3d _transmitter;
-    double _transmitter_elevation_ft;
-    double _transmitter_range_nm;
-    double _transmitter_bias;
+    FGNavRecord * _navrecord;
 
     string _name;
     int _num;
 
+    class AudioIdent * _audioIdent;
 };
 
 
index 9b91babead8305fb9882a28fede67b2b0a4028de..0fa58012ecad43bfcc3fa86a86950eaa0800be6a 100644 (file)
@@ -18,7 +18,6 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
-// $Id$
 
 
 #ifdef HAVE_CONFIG_H
@@ -71,9 +70,6 @@ static double kludgeRange ( double stationElev, double aircraftElev,
 
 // Constructor
 FGKR_87::FGKR_87( SGPropertyNode *node ) :
-    lon_node(fgGetNode("/position/longitude-deg", true)),
-    lat_node(fgGetNode("/position/latitude-deg", true)),
-    alt_node(fgGetNode("/position/altitude-ft", true)),
     bus_power(fgGetNode("/systems/electrical/outputs/adf", true)),
     serviceable(fgGetNode("/instrumentation/adf/serviceable", true)),
     need_update(true),
@@ -249,9 +245,7 @@ void FGKR_87::unbind () {
 
 // Update the various nav values based on position and valid tuned in navs
 void FGKR_87::update( double dt_sec ) {
-    SGGeod acft = SGGeod::fromDegFt(lon_node->getDoubleValue(),
-                                    lat_node->getDoubleValue(),
-                                    alt_node->getDoubleValue());
+    SGGeod acft = globals->get_aircraft_position();
 
     need_update = false;
 
@@ -497,8 +491,7 @@ void FGKR_87::update( double dt_sec ) {
 
 // Update current nav/adf radio stations based on current postition
 void FGKR_87::search() {
-  SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(), 
-    lat_node->getDoubleValue(), alt_node->getDoubleValue());
+  SGGeod pos = globals->get_aircraft_position();
   
                                // FIXME: the panel should handle this
     static string last_ident = "";
@@ -534,7 +527,7 @@ void FGKR_87::search() {
                _sgr->remove( "adf-ident" );
            }
            SGSoundSample *sound;
-        sound = FGMorse::instance()->make_ident( trans_ident, LO_FREQUENCY );
+        sound = FGMorse::instance()->make_ident( trans_ident, FGMorse::LO_FREQUENCY );
            sound->set_volume( 0.3 );
            _sgr->add( sound, "adf-ident" );
 
index 14accba9f2eeb83d57644883d8ae1b6289d28b85..83b8f6bcfe760818e2259667f48dfe0eb1b34070 100644 (file)
@@ -37,9 +37,6 @@ class SGSampleGroup;
 
 class FGKR_87 : public SGSubsystem
 {
-    SGPropertyNode_ptr lon_node;
-    SGPropertyNode_ptr lat_node;
-    SGPropertyNode_ptr alt_node;
     SGPropertyNode_ptr bus_power;
     SGPropertyNode_ptr serviceable;
 
index 886ad1f373c0096a68c447fcd7eacfa74afab08c..2103bb364083be47e84f44b4cea41d1d7d181c8e 100644 (file)
@@ -18,8 +18,6 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
-// $Id$
-
 
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #include <simgear/misc/strutils.hxx>
 
 #include <Navaids/navrecord.hxx>
-
+#include <Sound/audioident.hxx>
 #include <Airports/runways.hxx>
 #include <Navaids/navlist.hxx>
 #include <Main/util.hxx>
-#include <Sound/morse.hxx>
-
 
 using std::string;
 
@@ -105,9 +101,6 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
     term_tbl(NULL),
     low_tbl(NULL),
     high_tbl(NULL),
-    lon_node(fgGetNode("/position/longitude-deg", true)),
-    lat_node(fgGetNode("/position/latitude-deg", true)),
-    alt_node(fgGetNode("/position/altitude-ft", true)),
     _operable(false),
     play_count(0),
     last_time(0),
@@ -126,14 +119,13 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
     _gsCart(SGVec3d::zeros()),
     _gsAxis(SGVec3d::zeros()),
     _gsVertical(SGVec3d::zeros()),
-    _dmeInRange(false),
     _toFlag(false),
     _fromFlag(false),
     _cdiDeflection(0.0),
     _cdiCrossTrackErrorM(0.0),
     _gsNeedleDeflection(0.0),
     _gsNeedleDeflectionNorm(0.0),
-    _sgr(NULL)
+    _audioIdent(NULL)
 {
     SGPath path( globals->get_fg_root() );
     SGPath term = path;
@@ -166,16 +158,14 @@ FGNavRadio::~FGNavRadio()
     delete term_tbl;
     delete low_tbl;
     delete high_tbl;
+
+    delete _audioIdent;
 }
 
 
 void
 FGNavRadio::init ()
 {
-    SGSoundMgr *smgr = globals->get_soundmgr();
-    _sgr = smgr->find("avionics", true);
-    _sgr->tie_to_listener();
-
     SGPropertyNode* node = _radio_node.get();
     bus_power_node = 
        fgGetNode(("/systems/electrical/outputs/" + _name).c_str(), true);
@@ -196,7 +186,6 @@ FGNavRadio::init ()
     cdi_serviceable_node = createServiceableProp(node, "cdi");
     gs_serviceable_node = createServiceableProp(node, "gs");
     tofrom_serviceable_node = createServiceableProp(node, "to-from");
-    dme_serviceable_node = createServiceableProp(node, "dme");
     
     falseCoursesEnabledNode = 
       fgGetNode("/sim/realism/false-radio-courses-enabled");
@@ -266,27 +255,28 @@ FGNavRadio::init ()
     _magvarNode = fgGetNode("/environment/magnetic-variation-deg", true);
     
     std::ostringstream temp;
-    temp << _name << "nav-ident" << _num;
-    nav_fx_name = temp.str();
-    temp << _name << "dme-ident" << _num;
-    dme_fx_name = temp.str();
+    temp << _name << "-ident-" << _num;
+    if( NULL == _audioIdent ) 
+        _audioIdent = new VORAudioIdent( temp.str() );
+    _audioIdent->init();
+
+    // dme-in-range is deprecated,
+    // temporarily create dme-in-range alias for instrumentation/dme[0]/in-range
+    // remove after flightgear 2.6.0
+    node->getNode( "dme-in-range", true )->alias( fgGetNode("/instrumentation/dme[0]/in-range", true ) );
 }
 
 void
 FGNavRadio::bind ()
 {
-  tie("dme-in-range", SGRawValuePointer<bool>(&_dmeInRange));
-  tie("operable", SGRawValueMethods<FGNavRadio, bool>(*this, &FGNavRadio::isOperable, NULL));
+    _radio_node->tie( "operable", SGRawValueMethods<FGNavRadio,bool>( *this, &FGNavRadio::isOperable ) );
 }
 
 
 void
 FGNavRadio::unbind ()
 {
-  for (unsigned int t=0; t<_tiedNodes.size(); ++t) {
-    _tiedNodes[t]->untie();
-  }
-  _tiedNodes.clear();
+    _radio_node->untie("operable");
 }
 
 
@@ -386,7 +376,7 @@ FGNavRadio::update(double dt)
     clearOutputs();
   }
   
-  updateAudio();
+  updateAudio( dt );
 }
 
 void FGNavRadio::clearOutputs()
@@ -412,17 +402,13 @@ void FGNavRadio::clearOutputs()
   is_valid_node->setBoolValue(false);
   nav_id_node->setStringValue("");
   
-  _dmeInRange = false;
   _operable = false;
   _navaid = NULL;
 }
 
 void FGNavRadio::updateReceiver(double dt)
 {
-  SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
-                               lat_node->getDoubleValue(),
-                               alt_node->getDoubleValue());
-  SGVec3d aircraft = SGVec3d::fromGeod(pos);
+  SGVec3d aircraft = SGVec3d::fromGeod(globals->get_aircraft_position());
   double loc_dist = 0;
 
   // Do a nav station search only once a second to reduce
@@ -438,11 +424,10 @@ void FGNavRadio::updateReceiver(double dt)
       loc_dist = dist(aircraft, _navaid->cart());
       loc_dist_node->setDoubleValue( loc_dist );
   }
-  updateDME(aircraft);
 
   if (nav_slaved_to_gps_node->getBoolValue()) {
     // when slaved to GPS: only allow stuff above: tune NAV station
-    // upate DME. All other data driven by GPS only.
+    // All other data driven by GPS only.
     updateGPSSlaved();
     return;
   }
@@ -468,7 +453,7 @@ void FGNavRadio::updateReceiver(double dt)
        // compute forward and reverse wgs84 headings to localizer
   //////////////////////////////////////////////////////////
   double hdg;
-  SGGeodesy::inverse(pos, _navaid->geod(), hdg, az2, s);
+  SGGeodesy::inverse(globals->get_aircraft_position(), _navaid->geod(), hdg, az2, s);
   heading_node->setDoubleValue(hdg);
   double radial = az2 - twist;
   double recip = radial + 180.0;
@@ -497,11 +482,11 @@ void FGNavRadio::updateReceiver(double dt)
            double offset = radial - target_radial;
       SG_NORMALIZE_RANGE(offset, -180.0, 180.0);
            effective_range
-                = adjustILSRange( nav_elev, pos.getElevationM(), offset,
+                = adjustILSRange( nav_elev, globals->get_aircraft_position().getElevationM(), offset,
                                   loc_dist * SG_METER_TO_NM );
        } else {
            effective_range
-                = adjustNavRange( nav_elev, pos.getElevationM(), _navaid->get_range() );
+                = adjustNavRange( nav_elev, globals->get_aircraft_position().getElevationM(), _navaid->get_range() );
        }
   
   double effective_range_m = effective_range * SG_NM_TO_METER;
@@ -679,17 +664,6 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig
       ->setDoubleValue( gs_rate_of_climb_node->getDoubleValue() * 60 );
 }
 
-void FGNavRadio::updateDME(const SGVec3d& aircraft)
-{
-  if (!_dme || !dme_serviceable_node->getBoolValue()) {
-    _dmeInRange = false;
-    return;
-  }
-  
-  double dme_distance = dist(aircraft, _dme->cart()); 
-  _dmeInRange =  (dme_distance < _dme->get_range() * SG_NM_TO_METER);
-}
-
 void FGNavRadio::valueChanged (SGPropertyNode* prop)
 {
   if (prop == gps_course_node) {
@@ -849,9 +823,10 @@ void FGNavRadio::updateCDI(double dt)
   last_xtrack_error = _cdiCrossTrackErrorM;
 }
 
-void FGNavRadio::updateAudio()
+void FGNavRadio::updateAudio( double dt )
 {
   if (!_navaid || !inrange_node->getBoolValue() || !nav_serviceable_node->getBoolValue()) {
+    _audioIdent->setIdent("", 0.0 );
     return;
   }
   
@@ -861,57 +836,13 @@ void FGNavRadio::updateAudio()
       || !(bus_power_node->getDoubleValue() > 1.0)
       || !ident_btn_node->getBoolValue()
       || !audio_btn_node->getBoolValue() ) {
-    _sgr->stop( nav_fx_name );
-    _sgr->stop( dme_fx_name );
+    _audioIdent->setIdent("", 0.0 );
     return;
   }
 
-  SGSoundSample *sound = _sgr->find( nav_fx_name );
-  double vol = vol_btn_node->getFloatValue();
-  SG_CLAMP_RANGE(vol, 0.0, 1.0);
-  
-  if ( sound != NULL ) {
-    sound->set_volume( vol );
-  } else {
-    SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-vor-ident sound" );
-  }
-  
-  sound = _sgr->find( dme_fx_name );
-  if ( sound != NULL ) {
-    sound->set_volume( vol );
-  } else {
-    SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-dme-ident sound" );
-  }
-  
-  const int NUM_IDENT_SLOTS = 5;
-  const time_t SLOT_LENGTH = 5; // seconds
-
-  // There are N slots numbered 0 through (NUM_IDENT_SLOTS-1) inclusive.
-  // Each slot is 5 seconds long.
-  // Slots 0 is for DME
-  // the rest are for azimuth.
-  time_t now = globals->get_time_params()->get_cur_time();
-  if ((now >= last_time) && (now < last_time + SLOT_LENGTH)) {
-    return; // wait longer
-  }
-  
-  last_time = now;
-  play_count++;
-  play_count %= NUM_IDENT_SLOTS;
-    
-  // Previous ident is out of time;  if still playing, cut it off:
-  _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
-      if (vol > 0.05) _sgr->play_once( dme_fx_name );
-    }
-  } else { // NAV slot
-    if (inrange_node->getBoolValue() && nav_serviceable_node->getBoolValue()) {
-      if (vol > 0.05) _sgr->play_once(nav_fx_name);
-    }
-  }
+  _audioIdent->setIdent( _navaid->get_trans_ident(), vol_btn_node->getFloatValue() );
+
+  _audioIdent->update( dt );
 }
 
 FGNavRecord* FGNavRadio::findPrimaryNavaid(const SGGeod& aPos, double aFreqMHz)
@@ -928,11 +859,9 @@ FGNavRecord* FGNavRadio::findPrimaryNavaid(const SGGeod& aPos, double aFreqMHz)
 void FGNavRadio::search() 
 {
   _time_before_search_sec = 1.0;
-  SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
-    lat_node->getDoubleValue(), alt_node->getDoubleValue());
   double freq = freq_node->getDoubleValue();
   
-  FGNavRecord* nav = findPrimaryNavaid(pos, freq);
+  FGNavRecord* nav = findPrimaryNavaid(globals->get_aircraft_position(), freq);
   if (nav == _navaid) {
     return; // found the same as last search, we're done
   }
@@ -940,16 +869,10 @@ void FGNavRadio::search()
   _navaid = nav;
   string identBuffer(4, ' ');
   if (nav) {
-    // use ILS signals as DME, otherwise search by frequency
-    if (nav->type()==FGPositioned::ILS)
-        _dme = nav;
-    else
-        _dme = globals->get_dmelist()->findByFreq(freq, pos);
-    
     nav_id_node->setStringValue(nav->get_ident());
     identBuffer =  simgear::strutils::rpad( nav->ident(), 4, ' ' );
     
-    effective_range = adjustNavRange(nav->get_elev_ft(), pos.getElevationM(), nav->get_range());
+    effective_range = adjustNavRange(nav->get_elev_ft(), globals->get_aircraft_position().getElevationM(), nav->get_range());
     loc_node->setBoolValue(nav->type() != FGPositioned::VOR);
     twist = nav->get_multiuse();
 
@@ -958,7 +881,7 @@ void FGNavRadio::search()
       _gs = NULL;
       has_gs_node->setBoolValue(false);
     } else { // ILS or LOC
-      _gs = globals->get_gslist()->findByFreq(freq, pos);
+      _gs = globals->get_gslist()->findByFreq(freq, globals->get_aircraft_position());
       has_gs_node->setBoolValue(_gs != NULL);
       _localizerWidth = nav->localizerWidth();
       twist = 0.0;
@@ -986,16 +909,12 @@ void FGNavRadio::search()
       } // of have glideslope
     } // of found LOC or ILS
     
-    audioNavidChanged();
   } else { // found nothing
     _gs = NULL;
-    _dme = NULL;
     nav_id_node->setStringValue("");
     loc_node->setBoolValue(false);
     has_gs_node->setBoolValue(false);
-    
-    _sgr->remove( nav_fx_name );
-    _sgr->remove( dme_fx_name );
+    _audioIdent->setIdent("", 0.0 );
   }
 
   is_valid_node->setBoolValue(nav != NULL);
@@ -1004,33 +923,3 @@ void FGNavRadio::search()
   id_c3_node->setIntValue( (int)identBuffer[2] );
   id_c4_node->setIntValue( (int)identBuffer[3] );
 }
-
-void FGNavRadio::audioNavidChanged()
-{
-  if (_sgr->exists(nav_fx_name)) {
-               _sgr->remove(nav_fx_name);
-  }
-  
-  try {
-    string trans_ident(_navaid->get_trans_ident());
-    SGSoundSample* sound = FGMorse::instance()->make_ident(trans_ident, LO_FREQUENCY);
-    sound->set_volume( 0.3 );
-    if (!_sgr->add( sound, nav_fx_name )) {
-      SG_LOG(SG_COCKPIT, SG_WARN, "Failed to add v1-vor-ident sound");
-    }
-
-         if ( _sgr->exists( dme_fx_name ) ) {
-      _sgr->remove( dme_fx_name );
-    }
-     
-    sound = FGMorse::instance()->make_ident( trans_ident, HI_FREQUENCY );
-    sound->set_volume( 0.3 );
-    _sgr->add( sound, dme_fx_name );
-
-         int offset = (int)(sg_random() * 30.0);
-         play_count = offset / 4;
-    last_time = globals->get_time_params()->get_cur_time() - offset;
-  } catch (sg_io_exception& e) {
-    SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage());
-  }
-}
index 4b2e16918dde9ec5a08db85c84bc202713424646..51877284561a14126abecf3d219100eaa5ec6d33 100644 (file)
@@ -45,9 +45,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
     SGInterpTable *high_tbl;
 
     SGPropertyNode_ptr _radio_node;
-    SGPropertyNode_ptr lon_node;
-    SGPropertyNode_ptr lat_node;
-    SGPropertyNode_ptr alt_node;
     SGPropertyNode_ptr bus_power_node;
 
     // property inputs
@@ -65,7 +62,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
     SGPropertyNode_ptr cdi_serviceable_node;
     SGPropertyNode_ptr gs_serviceable_node;
     SGPropertyNode_ptr tofrom_serviceable_node;
-    SGPropertyNode_ptr dme_serviceable_node;
     
     // property outputs
     SGPropertyNode_ptr fmt_freq_node;     // formated frequency
@@ -131,9 +127,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
     FGNavRecordPtr _navaid;
     FGNavRecordPtr _gs;
     
-    string nav_fx_name;
-    string dme_fx_name;
-
     double target_radial;
     double effective_range;
     double target_gs;
@@ -152,9 +145,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
 
     SGVec3d _gsCart, _gsAxis, _gsVertical, _gsBaseline;
 
-    FGNavRecordPtr _dme;
-    bool _dmeInRange;
-    
     // CDI properties
     bool _toFlag, _fromFlag;
     double _cdiDeflection;
@@ -162,9 +152,8 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
     double _gsNeedleDeflection;
     double _gsNeedleDeflectionNorm;
     double _gsDirect;
-    
-    SGSharedPtr<SGSampleGroup> _sgr;
-    std::vector<SGPropertyNode_ptr> _tiedNodes;
+
+    class AudioIdent * _audioIdent;
     
     bool updateWithPower(double aDt);
 
@@ -176,11 +165,9 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
     double adjustILSRange( double stationElev, double aircraftElev,
                           double offsetDegrees, double distance );
 
-    void updateAudio();
-    void audioNavidChanged();
+    void updateAudio( double dt );
 
     void updateReceiver(double dt);
-    void updateDME(const SGVec3d& aircraft);
     void updateGlideSlope(double dt, const SGVec3d& aircraft, double signal_quality_norm);
     void updateGPSSlaved();
     void updateCDI(double dt);
@@ -193,17 +180,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
     bool isOperable() const
       { return _operable; }
       
-    /**
-     * Tied-properties helper, record nodes which are tied for easy un-tie-ing
-     */
-    template <typename T>
-    void tie(const char* aRelPath, const SGRawValue<T>& aRawValue)
-    {
-      SGPropertyNode_ptr nd = _radio_node->getNode(aRelPath, true);
-      _tiedNodes.push_back(nd);
-      nd->tie(aRawValue);
-    }
-    
   // implement SGPropertyChangeListener
     virtual void valueChanged (SGPropertyNode * prop);
 public:
index 28cc5bf8cde9f12a086d604073d27cd239989cd1..470e684c15f6f53e5dfe27ddcbde638eda7dd925 100644 (file)
@@ -1,6 +1,7 @@
 include(FlightGearComponent)
 
 set(SOURCES
+       audioident.cxx
        soundgenerator.cxx
        beacon.cxx
        fg_fx.cxx
@@ -11,6 +12,7 @@ set(SOURCES
        )
 
 set(HEADERS
+       audioident.hxx
        soundgenerator.hxx
        beacon.hxx
        fg_fx.hxx
index 893b776d21f1ea31b08f1c042dc6be0a3ccef4ab..87100174390dcd1bad184a94d7f288b5b9b70089 100644 (file)
@@ -1,6 +1,7 @@
 noinst_LIBRARIES = libSound.a
 
 libSound_a_SOURCES = \
+       audioident.cxx audioident.hxx \
        soundgenerator.cxx soundgenerator.hxx \
        beacon.cxx beacon.hxx \
        fg_fx.cxx fg_fx.hxx \
diff --git a/src/Sound/audioident.cxx b/src/Sound/audioident.cxx
new file mode 100644 (file)
index 0000000..7467452
--- /dev/null
@@ -0,0 +1,141 @@
+// audioident.cxx -- audible station identifiers
+//
+// Written by Torsten Dreyer, September 2011
+//
+// Copyright (C) 2001  Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#include "audioident.hxx"
+#include <simgear/sg_inlines.h>
+
+#include <Main/globals.hxx>
+#include <Sound/Morse.hxx>
+
+AudioIdent::AudioIdent( const std::string & fx_name, const double interval_secs, const int frequency_hz ) :
+  _fx_name(fx_name),
+  _frequency(frequency_hz),
+  _timer(0.0),
+  _interval(interval_secs),
+  _running(false)
+{
+}
+
+void AudioIdent::init()
+{
+    _timer = 0.0;
+    _ident = "";
+    _running = false;
+    _sgr = globals->get_soundmgr()->find("avionics", true);
+    _sgr->tie_to_listener();
+}
+
+void AudioIdent::stop()
+{
+    if( _sgr->exists( _fx_name ) )
+        _sgr->stop( _fx_name );
+    _running = false;
+}
+
+void AudioIdent::start()
+{
+    _timer = _interval;
+    _sgr->play_once(_fx_name);
+    _running = true;
+}
+
+void AudioIdent::setVolumeNorm( double volumeNorm )
+{
+    SG_CLAMP_RANGE(volumeNorm, 0.0, 1.0);
+
+    SGSoundSample *sound = _sgr->find( _fx_name );
+
+    if ( sound != NULL ) {
+        sound->set_volume( volumeNorm );
+    }
+}
+
+void AudioIdent::setIdent( const std::string & ident, double volumeNorm )
+{
+    if( _ident == ident ) {
+        if( false == _ident.empty() )
+            setVolumeNorm( volumeNorm );
+        return;
+    }
+
+    try {
+        stop();
+
+        if ( _sgr->exists( _fx_name ) )
+            _sgr->remove( _fx_name );
+
+        if( false == ident.empty() ) {
+
+            SGSoundSample* sound = FGMorse::instance()->make_ident(ident, _frequency );
+            sound->set_volume( volumeNorm );
+            if (!_sgr->add( sound, _fx_name )) {
+                SG_LOG(SG_SOUND, SG_WARN, "Failed to add sound '" << _fx_name << "' for ident '" << ident << "'" );
+                return;
+            }
+
+            start();
+        }
+        _ident = ident;
+
+    } catch (sg_io_exception& e) {
+        SG_LOG(SG_SOUND, SG_ALERT, e.getFormattedMessage());
+    }
+
+}
+
+void AudioIdent::update( double dt )
+{
+    // single-shot
+    if( false == _running || _interval < SGLimitsd::min() ) 
+        return;
+
+    _timer -= dt;
+
+    if( _timer < SGLimitsd::min() ) {
+        _timer = _interval;
+        stop();
+        start();
+    }
+}
+
+// FIXME: shall transmit at least 6 wpm (ICAO Annex 10 - 3.5.3.6.3)
+DMEAudioIdent::DMEAudioIdent( const std::string & fx_name )
+: AudioIdent( fx_name, 40, FGMorse::HI_FREQUENCY )
+{
+}
+
+
+//FIXME: for co-located VOR/DME or ILS/DME, assign four time-slots
+// 3xVOR/ILS ident, 1xDME ident
+
+// FIXME: shall transmit at approx. 7 wpm (ICAO Annex 10 - 3.3.6.5.1)
+VORAudioIdent::VORAudioIdent( const std::string & fx_name )
+: AudioIdent( fx_name, 10, FGMorse::LO_FREQUENCY )
+{
+}
+
+//FIXME: LOCAudioIdent at approx 7wpm (ICAO Annex 10 - 3.1.3.9.4)
+// not less than six times per minute at approx equal intervals
+// frequency 1020+/-50Hz (3.1.3.9.2)
+
+// FIXME: NDBAudioIdent at approx 7 wpm (ICAO ANNEX 10 - 3.4.5.1)
+// at least once every 10s (3.4.5.2.1)
+// frequency 1020+/-50Hz or 400+/-25Hz (3.4.5.4)
\ No newline at end of file
diff --git a/src/Sound/audioident.hxx b/src/Sound/audioident.hxx
new file mode 100644 (file)
index 0000000..723ddd7
--- /dev/null
@@ -0,0 +1,65 @@
+// audioident.hxx -- audible station identifiers
+//
+// Written by Torsten Dreyer, September 2011
+//
+// Copyright (C) 2001  Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+
+#ifndef _FGAUDIOIDENT_HXX
+#define _FGAUDIOIDENT_HXX
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <string>
+#include <simgear/sound/soundmgr_openal.hxx>
+
+class AudioIdent {
+public:
+    AudioIdent( const std::string & fx_name, const double interval_secs, const int frequency );
+    void init();
+    void setVolumeNorm( double volumeNorm );
+    void setIdent( const std::string & ident, double volumeNorm );
+
+    void update( double dt );
+
+private:
+    void stop();
+    void start();
+
+    SGSharedPtr<SGSampleGroup> _sgr;
+    std::string _fx_name;
+    const int _frequency;
+    std::string _ident;
+    double _timer;
+    double _interval;
+    bool _running;
+};
+
+class DMEAudioIdent : public AudioIdent {
+public:
+    DMEAudioIdent( const std::string & fx_name );
+};
+
+class VORAudioIdent : public AudioIdent {
+public:
+    VORAudioIdent( const std::string & fx_name );
+};
+
+#endif // _FGAUDIOIDENT_HXX
index 9ff603322b8452ddb4451f3fb25e900265ffe47b..379c1574881f526370d04408033c54182d5e9a38 100644 (file)
 
 #include <cstring>
 
+static const char DI = '1';
+static const char DIT = '1';
+static const char DA = '2';
+static const char DAH = '2';
+static const char END = '0';
+
 static const char alphabet[26][4] = {
     { DI, DAH, END, END },     /* A */ 
     { DA, DI, DI, DIT },       /* B */ 
index 3d8b9dfbb113345e1bb63e25371ece45ee4c27e6..c79b4782ef2a800075e638e9478c545923dbadb4 100644 (file)
 // Hz for the VOR ident.
 
 
-static const char DI = '1';
-static const char DIT = '1';
-static const char DA = '2';
-static const char DAH = '2';
-static const char END = '0';
-
-static const int BYTES_PER_SECOND = 22050;
-// static const int BEAT_LENGTH = 240; // milleseconds (5 wpm)
-static const int BEAT_LENGTH = 92;  // milleseconds (13 wpm)
-static const int TRANSITION_BYTES = (int)(0.005 * BYTES_PER_SECOND);
-static const int COUNT_SIZE = BYTES_PER_SECOND * BEAT_LENGTH / 1000;
-static const int DIT_SIZE = 2 * COUNT_SIZE;   // 2 counts
-static const int DAH_SIZE = 4 * COUNT_SIZE;   // 4 counts
-static const int SPACE_SIZE = 3 * COUNT_SIZE; // 3 counts
-static const int LO_FREQUENCY = 1020;   // AIM 1-1-7 (f) specified in Hz
-static const int HI_FREQUENCY = 1350;   // AIM 1-1-7 (f) specified in Hz
-
 // manages everything we need to know for an individual sound sample
 class FGMorse : public FGSoundGenerator {
 
@@ -113,6 +96,17 @@ private:
     bool init();
 
 public:
+    static const int BYTES_PER_SECOND = 22050;
+    // static const int BEAT_LENGTH = 240; // milleseconds (5 wpm)
+    static const int BEAT_LENGTH = 92;  // milleseconds (13 wpm)
+    static const int TRANSITION_BYTES = (int)(0.005 * BYTES_PER_SECOND);
+    static const int COUNT_SIZE = BYTES_PER_SECOND * BEAT_LENGTH / 1000;
+    static const int DIT_SIZE = 2 * COUNT_SIZE;   // 2 counts
+    static const int DAH_SIZE = 4 * COUNT_SIZE;   // 4 counts
+    static const int SPACE_SIZE = 3 * COUNT_SIZE; // 3 counts
+    static const int LO_FREQUENCY = 1020;       // AIM 1-1-7 (f) specified in Hz
+    static const int HI_FREQUENCY = 1350;       // AIM 1-1-7 (f) specified in Hz
+
 
     FGMorse();
     ~FGMorse();