From 43109feb0c6a2ab35d5f1ee9318daadff811cc88 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Thu, 15 Sep 2011 21:28:30 +0200 Subject: [PATCH] Some more refactoring of the radios - 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 --- projects/VC90/FlightGear/FlightGear.vcproj | 8 + src/Instrumentation/adf.cxx | 2 +- src/Instrumentation/dme.cxx | 99 ++++++------ src/Instrumentation/dme.hxx | 16 +- src/Instrumentation/kr_87.cxx | 13 +- src/Instrumentation/kr_87.hxx | 3 - src/Instrumentation/navradio.cxx | 171 ++++----------------- src/Instrumentation/navradio.hxx | 30 +--- src/Sound/CMakeLists.txt | 2 + src/Sound/Makefile.am | 1 + src/Sound/audioident.cxx | 141 +++++++++++++++++ src/Sound/audioident.hxx | 65 ++++++++ src/Sound/morse.cxx | 6 + src/Sound/morse.hxx | 28 ++-- 14 files changed, 323 insertions(+), 262 deletions(-) create mode 100644 src/Sound/audioident.cxx create mode 100644 src/Sound/audioident.hxx diff --git a/projects/VC90/FlightGear/FlightGear.vcproj b/projects/VC90/FlightGear/FlightGear.vcproj index 77d845292..1ae6559ab 100644 --- a/projects/VC90/FlightGear/FlightGear.vcproj +++ b/projects/VC90/FlightGear/FlightGear.vcproj @@ -3197,6 +3197,14 @@ + + + + diff --git a/src/Instrumentation/adf.cxx b/src/Instrumentation/adf.cxx index e3fbac053..805be1040 100644 --- a/src/Instrumentation/adf.cxx +++ b/src/Instrumentation/adf.cxx @@ -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 ); diff --git a/src/Instrumentation/dme.cxx b/src/Instrumentation/dme.cxx index 925681e0a..d8d14a5a2 100644 --- a/src/Instrumentation/dme.cxx +++ b/src/Instrumentation/dme.cxx @@ -8,15 +8,16 @@ #endif #include +#include #include #include #include
#include +#include #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 diff --git a/src/Instrumentation/dme.hxx b/src/Instrumentation/dme.hxx index 5d9963b10..6ec6edc63 100644 --- a/src/Instrumentation/dme.hxx +++ b/src/Instrumentation/dme.hxx @@ -10,7 +10,6 @@ #include #include - /** * 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; }; diff --git a/src/Instrumentation/kr_87.cxx b/src/Instrumentation/kr_87.cxx index 9b91babea..0fa58012e 100644 --- a/src/Instrumentation/kr_87.cxx +++ b/src/Instrumentation/kr_87.cxx @@ -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" ); diff --git a/src/Instrumentation/kr_87.hxx b/src/Instrumentation/kr_87.hxx index 14accba9f..83b8f6bcf 100644 --- a/src/Instrumentation/kr_87.hxx +++ b/src/Instrumentation/kr_87.hxx @@ -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; diff --git a/src/Instrumentation/navradio.cxx b/src/Instrumentation/navradio.cxx index 886ad1f37..2103bb364 100644 --- a/src/Instrumentation/navradio.cxx +++ b/src/Instrumentation/navradio.cxx @@ -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 @@ -40,12 +38,10 @@ #include #include - +#include #include #include #include
-#include - 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(&_dmeInRange)); - tie("operable", SGRawValueMethods(*this, &FGNavRadio::isOperable, NULL)); + _radio_node->tie( "operable", SGRawValueMethods( *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 + _audioIdent->setIdent( _navaid->get_trans_ident(), vol_btn_node->getFloatValue() ); - // 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->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()); - } -} diff --git a/src/Instrumentation/navradio.hxx b/src/Instrumentation/navradio.hxx index 4b2e16918..518772845 100644 --- a/src/Instrumentation/navradio.hxx +++ b/src/Instrumentation/navradio.hxx @@ -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 _sgr; - std::vector _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 - void tie(const char* aRelPath, const SGRawValue& aRawValue) - { - SGPropertyNode_ptr nd = _radio_node->getNode(aRelPath, true); - _tiedNodes.push_back(nd); - nd->tie(aRawValue); - } - // implement SGPropertyChangeListener virtual void valueChanged (SGPropertyNode * prop); public: diff --git a/src/Sound/CMakeLists.txt b/src/Sound/CMakeLists.txt index 28cc5bf8c..470e684c1 100644 --- a/src/Sound/CMakeLists.txt +++ b/src/Sound/CMakeLists.txt @@ -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 diff --git a/src/Sound/Makefile.am b/src/Sound/Makefile.am index 893b776d2..871001743 100644 --- a/src/Sound/Makefile.am +++ b/src/Sound/Makefile.am @@ -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 index 000000000..74674522c --- /dev/null +++ b/src/Sound/audioident.cxx @@ -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 + +#include
+#include + +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 index 000000000..723ddd70d --- /dev/null +++ b/src/Sound/audioident.hxx @@ -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 +#endif + +#include +#include + +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 _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 diff --git a/src/Sound/morse.cxx b/src/Sound/morse.cxx index 9ff603322..379c15748 100644 --- a/src/Sound/morse.cxx +++ b/src/Sound/morse.cxx @@ -26,6 +26,12 @@ #include +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 */ diff --git a/src/Sound/morse.hxx b/src/Sound/morse.hxx index 3d8b9dfbb..c79b4782e 100644 --- a/src/Sound/morse.hxx +++ b/src/Sound/morse.hxx @@ -75,23 +75,6 @@ // 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();