From 95e27e8cb96e80a3ba7582105646d914ccadb452 Mon Sep 17 00:00:00 2001 From: curt Date: Fri, 9 Mar 2001 02:41:04 +0000 Subject: [PATCH] Working on vor audio ident (morse). Fixed a bug in Network/props.cxx with the cd command. Fixed a typo in options.cxx --- src/Cockpit/radiostack.cxx | 245 ++++++++++++++++++++++++------------- src/Cockpit/radiostack.hxx | 17 ++- src/Main/main.cxx | 19 +-- src/Main/options.cxx | 6 +- src/Network/props.cxx | 3 +- src/Sound/morse.cxx | 186 ++++++++++++++++++++++++---- src/Sound/morse.hxx | 19 ++- src/Sound/soundmgr.cxx | 75 +++++++++++- src/Sound/soundmgr.hxx | 14 ++- 9 files changed, 454 insertions(+), 130 deletions(-) diff --git a/src/Cockpit/radiostack.cxx b/src/Cockpit/radiostack.cxx index 9b93cc8bc..82512a7e4 100644 --- a/src/Cockpit/radiostack.cxx +++ b/src/Cockpit/radiostack.cxx @@ -85,6 +85,8 @@ FGRadioStack::~FGRadioStack() void FGRadioStack::init () { + morse.init(); + search(); update(); @@ -104,6 +106,12 @@ FGRadioStack::bind () fgTie("/radios/nav1/radials/selected", this, &FGRadioStack::get_nav1_sel_radial, &FGRadioStack::set_nav1_sel_radial); + fgTie("/radios/nav1/on", this, + &FGRadioStack::get_nav1_on_btn, + &FGRadioStack::set_nav1_on_btn); + fgTie("/radios/nav1/ident", this, + &FGRadioStack::get_nav1_ident_btn, + &FGRadioStack::set_nav1_ident_btn); // Radio outputs fgTie("/radios/nav1/radials/actual", this, &FGRadioStack::get_nav1_radial); @@ -126,6 +134,12 @@ FGRadioStack::bind () fgTie("/radios/nav2/radials/selected", this, &FGRadioStack::get_nav2_sel_radial, &FGRadioStack::set_nav2_sel_radial); + fgTie("/radios/nav2/on", this, + &FGRadioStack::get_nav2_on_btn, + &FGRadioStack::set_nav2_on_btn); + fgTie("/radios/nav2/ident", this, + &FGRadioStack::get_nav2_ident_btn, + &FGRadioStack::set_nav2_ident_btn); // Radio outputs fgTie("/radios/nav2/radials/actual", this, &FGRadioStack::get_nav2_radial); @@ -156,6 +170,8 @@ FGRadioStack::unbind () fgUntie("/radios/nav1/frequencies/standby"); fgUntie("/radios/nav1/radials/actual"); fgUntie("/radios/nav1/radials/selected"); + fgUntie("/radios/nav1/on"); + fgUntie("/radios/nav1/ident"); fgUntie("/radios/nav1/to-flag"); fgUntie("/radios/nav1/from-flag"); fgUntie("/radios/nav1/in-range"); @@ -168,6 +184,8 @@ FGRadioStack::unbind () fgUntie("/radios/nav2/frequencies/standby"); fgUntie("/radios/nav2/radials/actual"); fgUntie("/radios/nav2/radials/selected"); + fgUntie("/radios/nav2/on"); + fgUntie("/radios/nav2/ident"); fgUntie("/radios/nav2/to-flag"); fgUntie("/radios/nav2/from-flag"); fgUntie("/radios/nav2/in-range"); @@ -181,7 +199,7 @@ FGRadioStack::unbind () fgUntie("/radios/adf/rotation"); } -// Search the database for the current frequencies given current location +// Update the various nav values based on position and valid tuned in navs void FGRadioStack::update() { @@ -235,9 +253,20 @@ FGRadioStack::update() } else { nav1_radial = nav1_sel_radial; } + + // play station ident via audio system if on + ident, + // otherwise turn it off + if ( nav1_on_btn && nav1_ident_btn ) { + if ( ! globals->get_soundmgr()->is_playing( "nav1-ident" ) ) { + globals->get_soundmgr()->play_once( "nav1-ident" ); + } + } else { + globals->get_soundmgr()->stop( "nav1-ident" ); + } } else { nav1_inrange = false; nav1_dme_dist = 0.0; + globals->get_soundmgr()->stop( "nav1-ident" ); // cout << "not picking up vor. :-(" << endl; } @@ -311,7 +340,7 @@ FGRadioStack::update() // Update current nav/adf radio stations based on current postition -void FGRadioStack::search () +void FGRadioStack::search() { double lon = longitudeVal->getDoubleValue() * DEG_TO_RAD; double lat = latitudeVal->getDoubleValue() * DEG_TO_RAD; @@ -321,105 +350,145 @@ void FGRadioStack::search () FGILS ils; FGNav nav; + static string last_nav1_ident = ""; + static string last_nav2_ident = ""; + if ( current_ilslist->query( lon, lat, elev, nav1_freq, &ils ) ) { - nav1_valid = true; - nav1_loc = true; - nav1_has_dme = ils.get_has_dme(); - nav1_has_gs = ils.get_has_gs(); - - nav1_loclon = ils.get_loclon(); - nav1_loclat = ils.get_loclat(); - nav1_gslon = ils.get_gslon(); - nav1_gslat = ils.get_gslat(); - nav1_dmelon = ils.get_dmelon(); - nav1_dmelat = ils.get_dmelat(); - nav1_elev = ils.get_gselev(); - nav1_magvar = 0; - nav1_effective_range = FG_ILS_DEFAULT_RANGE; - nav1_target_gs = ils.get_gsangle(); - nav1_radial = ils.get_locheading(); - while ( nav1_radial < 0.0 ) { nav1_radial += 360.0; } - while ( nav1_radial > 360.0 ) { nav1_radial -= 360.0; } - nav1_x = ils.get_x(); - nav1_y = ils.get_y(); - nav1_z = ils.get_z(); - nav1_gs_x = ils.get_gs_x(); - nav1_gs_y = ils.get_gs_y(); - nav1_gs_z = ils.get_gs_z(); - nav1_dme_x = ils.get_dme_x(); - nav1_dme_y = ils.get_dme_y(); - nav1_dme_z = ils.get_dme_z(); - // cout << "Found an ils station in range" << endl; - // cout << " id = " << ils.get_locident() << endl; + nav1_ident = ils.get_locident(); + if ( last_nav1_ident != nav1_ident ) { + last_nav1_ident = nav1_ident; + nav1_valid = true; + nav1_loc = true; + nav1_has_dme = ils.get_has_dme(); + nav1_has_gs = ils.get_has_gs(); + + nav1_loclon = ils.get_loclon(); + nav1_loclat = ils.get_loclat(); + nav1_gslon = ils.get_gslon(); + nav1_gslat = ils.get_gslat(); + nav1_dmelon = ils.get_dmelon(); + nav1_dmelat = ils.get_dmelat(); + nav1_elev = ils.get_gselev(); + nav1_magvar = 0; + nav1_effective_range = FG_ILS_DEFAULT_RANGE; + nav1_target_gs = ils.get_gsangle(); + nav1_radial = ils.get_locheading(); + while ( nav1_radial < 0.0 ) { nav1_radial += 360.0; } + while ( nav1_radial > 360.0 ) { nav1_radial -= 360.0; } + nav1_x = ils.get_x(); + nav1_y = ils.get_y(); + nav1_z = ils.get_z(); + nav1_gs_x = ils.get_gs_x(); + nav1_gs_y = ils.get_gs_y(); + nav1_gs_z = ils.get_gs_z(); + nav1_dme_x = ils.get_dme_x(); + nav1_dme_y = ils.get_dme_y(); + nav1_dme_z = ils.get_dme_z(); + + if ( globals->get_soundmgr()->exists( "nav1-ident" ) ) { + globals->get_soundmgr()->remove( "nav1-ident" ); + } + FGSimpleSound *sound = morse.make_ident( nav1_ident ); + sound->set_volume( 0.3 ); + globals->get_soundmgr()->add( sound, "nav1-ident" ); + + // cout << "Found an ils station in range" << endl; + // cout << " id = " << ils.get_locident() << endl; + } } else if ( current_navlist->query( lon, lat, elev, nav1_freq, &nav ) ) { - nav1_valid = true; - nav1_loc = false; - nav1_has_dme = nav.get_has_dme(); - nav1_has_gs = false; - nav1_loclon = nav.get_lon(); - nav1_loclat = nav.get_lat(); - nav1_elev = nav.get_elev(); - nav1_magvar = nav.get_magvar(); - nav1_effective_range = kludgeRange(nav1_elev, elev, nav.get_range()); - nav1_target_gs = 0.0; - nav1_radial = nav1_sel_radial; - nav1_x = nav1_dme_x = nav.get_x(); - nav1_y = nav1_dme_y = nav.get_y(); - nav1_z = nav1_dme_z = nav.get_z(); - // cout << "Found a vor station in range" << endl; - // cout << " id = " << nav.get_ident() << endl; + nav1_ident = nav.get_ident(); + if ( last_nav1_ident != nav1_ident ) { + last_nav1_ident = nav1_ident; + nav1_valid = true; + nav1_loc = false; + nav1_has_dme = nav.get_has_dme(); + nav1_has_gs = false; + nav1_loclon = nav.get_lon(); + nav1_loclat = nav.get_lat(); + nav1_elev = nav.get_elev(); + nav1_magvar = nav.get_magvar(); + nav1_effective_range + = kludgeRange(nav1_elev, elev, nav.get_range()); + nav1_target_gs = 0.0; + nav1_radial = nav1_sel_radial; + nav1_x = nav1_dme_x = nav.get_x(); + nav1_y = nav1_dme_y = nav.get_y(); + nav1_z = nav1_dme_z = nav.get_z(); + + if ( globals->get_soundmgr()->exists( "nav1-ident" ) ) { + globals->get_soundmgr()->remove( "nav1-ident" ); + } + FGSimpleSound *sound = morse.make_ident( nav1_ident ); + sound->set_volume( 0.3 ); + globals->get_soundmgr()->add( sound, "nav1-ident" ); + + // cout << "Found a vor station in range" << endl; + // cout << " id = " << nav.get_ident() << endl; + } } else { nav1_valid = false; + nav1_ident = ""; nav1_radial = 0; nav1_dme_dist = 0; + globals->get_soundmgr()->remove( "nav1-ident" ); // cout << "not picking up vor1. :-(" << endl; } if ( current_ilslist->query( lon, lat, elev, nav2_freq, &ils ) ) { - nav2_valid = true; - nav2_loc = true; - nav2_has_dme = ils.get_has_dme(); - nav2_has_gs = ils.get_has_gs(); - - nav2_loclon = ils.get_loclon(); - nav2_loclat = ils.get_loclat(); - nav2_elev = ils.get_gselev(); - nav2_magvar = 0; - nav2_effective_range = FG_ILS_DEFAULT_RANGE; - nav2_target_gs = ils.get_gsangle(); - nav2_radial = ils.get_locheading(); - while ( nav2_radial < 0.0 ) { nav2_radial += 360.0; } - while ( nav2_radial > 360.0 ) { nav2_radial -= 360.0; } - nav2_x = ils.get_x(); - nav2_y = ils.get_y(); - nav2_z = ils.get_z(); - nav2_gs_x = ils.get_gs_x(); - nav2_gs_y = ils.get_gs_y(); - nav2_gs_z = ils.get_gs_z(); - nav2_dme_x = ils.get_dme_x(); - nav2_dme_y = ils.get_dme_y(); - nav2_dme_z = ils.get_dme_z(); - // cout << "Found an ils station in range" << endl; - // cout << " id = " << ils.get_locident() << endl; + nav2_ident = ils.get_locident(); + if ( last_nav2_ident != nav2_ident ) { + last_nav2_ident = nav2_ident; + nav2_valid = true; + nav2_loc = true; + nav2_has_dme = ils.get_has_dme(); + nav2_has_gs = ils.get_has_gs(); + + nav2_loclon = ils.get_loclon(); + nav2_loclat = ils.get_loclat(); + nav2_elev = ils.get_gselev(); + nav2_magvar = 0; + nav2_effective_range = FG_ILS_DEFAULT_RANGE; + nav2_target_gs = ils.get_gsangle(); + nav2_radial = ils.get_locheading(); + while ( nav2_radial < 0.0 ) { nav2_radial += 360.0; } + while ( nav2_radial > 360.0 ) { nav2_radial -= 360.0; } + nav2_x = ils.get_x(); + nav2_y = ils.get_y(); + nav2_z = ils.get_z(); + nav2_gs_x = ils.get_gs_x(); + nav2_gs_y = ils.get_gs_y(); + nav2_gs_z = ils.get_gs_z(); + nav2_dme_x = ils.get_dme_x(); + nav2_dme_y = ils.get_dme_y(); + nav2_dme_z = ils.get_dme_z(); + // cout << "Found an ils station in range" << endl; + // cout << " id = " << ils.get_locident() << endl; + } } else if ( current_navlist->query( lon, lat, elev, nav2_freq, &nav ) ) { - nav2_valid = true; - nav2_loc = false; - nav2_has_dme = nav.get_has_dme(); - nav2_has_dme = false; - nav2_loclon = nav.get_lon(); - nav2_loclat = nav.get_lat(); - nav2_elev = nav.get_elev(); - nav2_magvar = nav.get_magvar(); - nav2_effective_range = kludgeRange(nav2_elev, elev, nav.get_range()); - nav2_target_gs = 0.0; - nav2_radial = nav2_sel_radial; - nav2_x = nav2_dme_x = nav.get_x(); - nav2_y = nav2_dme_y = nav.get_y(); - nav2_z = nav2_dme_z = nav.get_z(); - // cout << "Found a vor station in range" << endl; - // cout << " id = " << nav.get_ident() << endl; + nav2_ident = nav.get_ident(); + if ( last_nav2_ident != nav2_ident ) { + last_nav2_ident = nav2_ident; + nav2_valid = true; + nav2_loc = false; + nav2_has_dme = nav.get_has_dme(); + nav2_has_dme = false; + nav2_loclon = nav.get_lon(); + nav2_loclat = nav.get_lat(); + nav2_elev = nav.get_elev(); + nav2_magvar = nav.get_magvar(); + nav2_effective_range + = kludgeRange(nav2_elev, elev, nav.get_range()); + nav2_target_gs = 0.0; + nav2_radial = nav2_sel_radial; + nav2_x = nav2_dme_x = nav.get_x(); + nav2_y = nav2_dme_y = nav.get_y(); + nav2_z = nav2_dme_z = nav.get_z(); + // cout << "Found a vor station in range" << endl; + // cout << " id = " << nav.get_ident() << endl; + } } else { nav2_valid = false; + nav2_ident = ""; nav2_radial = 0; nav2_dme_dist = 0; // cout << "not picking up vor2. :-(" << endl; diff --git a/src/Cockpit/radiostack.hxx b/src/Cockpit/radiostack.hxx index c20317903..aa9f28d38 100644 --- a/src/Cockpit/radiostack.hxx +++ b/src/Cockpit/radiostack.hxx @@ -32,11 +32,12 @@ #include #include - +#include class FGRadioStack : public FGSubsystem { + FGMorse morse; SGValue * latitudeVal; SGValue * longitudeVal; @@ -44,6 +45,7 @@ class FGRadioStack : public FGSubsystem bool need_update; + string nav1_ident; bool nav1_valid; bool nav1_inrange; bool nav1_has_dme; @@ -76,7 +78,10 @@ class FGRadioStack : public FGSubsystem double nav1_heading; double nav1_target_gs; double nav1_magvar; + bool nav1_on_btn; + bool nav1_ident_btn; + string nav2_ident; bool nav2_valid; bool nav2_inrange; bool nav2_has_dme; @@ -109,6 +114,8 @@ class FGRadioStack : public FGSubsystem double nav2_heading; double nav2_target_gs; double nav2_magvar; + bool nav2_on_btn; + bool nav2_ident_btn; bool adf_valid; bool adf_inrange; @@ -146,6 +153,8 @@ public: inline void set_nav1_sel_radial( double radial ) { nav1_sel_radial = radial; need_update = true; } + inline void set_nav1_on_btn( bool val ) { nav1_on_btn = val; } + inline void set_nav1_ident_btn( bool val ) { nav1_ident_btn = val; } // NAV2 Setters inline void set_nav2_freq( double freq ) { @@ -155,6 +164,8 @@ public: inline void set_nav2_sel_radial( double radial ) { nav2_sel_radial = radial; need_update = true; } + inline void set_nav2_on_btn( bool val ) { nav2_on_btn = val; } + inline void set_nav2_ident_btn( bool val ) { nav2_ident_btn = val; } // ADF Setters inline void set_adf_freq( double freq ) { @@ -205,6 +216,8 @@ public: inline double get_nav1_magvar() const { return nav1_magvar; } double get_nav1_heading_needle_deflection() const; double get_nav1_gs_needle_deflection() const; + inline bool get_nav1_on_btn() const { return nav1_on_btn; } + inline bool get_nav1_ident_btn() const { return nav1_ident_btn; } inline bool get_nav2_inrange() const { return nav2_inrange; } bool get_nav2_to_flag () const; @@ -231,6 +244,8 @@ public: inline double get_nav2_magvar() const { return nav2_magvar; } double get_nav2_heading_needle_deflection() const; double get_nav2_gs_needle_deflection() const; + inline bool get_nav2_on_btn() const { return nav2_on_btn; } + inline bool get_nav2_ident_btn() const { return nav2_ident_btn; } inline bool get_adf_inrange() const { return adf_inrange; } inline double get_adf_lon() const { return adf_lon; } diff --git a/src/Main/main.cxx b/src/Main/main.cxx index d3246848e..9321b9d63 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -1067,10 +1067,10 @@ static void fgMainLoop( void ) { << cur_fdm_state->get_engine(0)->get_Manifold_Pressure() << endl; */ - double volume = 0.3 + mp_factor; + double volume = 0.15 + mp_factor / 2.0; - if ( volume < 0.3 ) { volume = 0.3; } - if ( volume > 1.0 ) { volume = 1.0; } + if ( volume < 0.15 ) { volume = 0.15; } + if ( volume > 0.5 ) { volume = 0.5; } // cout << "volume = " << volume << endl; s1->set_pitch( pitch ); @@ -1183,7 +1183,8 @@ static void fgIdleFunction ( void ) { if ( fgGetBool("/sim/sound") ) { globals->get_soundmgr()->init(); - s1 = new FGSimpleSound( "Sounds/wasp.wav" ); + s1 = new FGSimpleSound( fgGetString("/sim/sounds/engine", + "Sounds/wasp.wav") ); globals->get_soundmgr()->add( s1, "engine loop" ); globals->get_soundmgr()->play_looped( "engine loop" ); FG_LOG( FG_GENERAL, FG_INFO, @@ -1192,11 +1193,11 @@ static void fgIdleFunction ( void ) { << " Stereo = " << s1->get_sample()->getStereo() ); // s2 = new FGSimpleSound( "Sounds/corflaps.wav" ); - // s2->set_volume( 2.0 ); - // FGMorse mmm; - // mmm.init(); - // s2 = mmm.make_ident( "JLI" ); - // globals->get_soundmgr()->add( s2, "flaps" ); + FGMorse mmm; + mmm.init(); + s2 = mmm.make_ident( "JLI" ); + s2->set_volume( 0.3 ); + globals->get_soundmgr()->add( s2, "flaps" ); } #endif diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 786749278..52d30fab4 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -490,7 +490,7 @@ static bool parse_flightplan(const string& arg) { fg_gzifstream infile(arg.c_str()); - if (!infile) { + if ( !infile.is_open() ) { return false; } while ( true ) { @@ -867,8 +867,8 @@ parse_option (const string& arg) parse_wp( arg.substr( 5 ) ); } else if ( arg.find( "--flight-plan=") == 0) { parse_flightplan ( arg.substr (14) ); - } else if ( arg.find( "--file=" ) == 0 ) { - string file = arg.substr(7); + } else if ( arg.find( "--config=" ) == 0 ) { + string file = arg.substr(9); if (!readProperties(file, globals->get_props())) { FG_LOG(FG_IO, FG_ALERT, "--config: failed to read properties from " << file); diff --git a/src/Network/props.cxx b/src/Network/props.cxx index f249f23b8..e82d8a10c 100644 --- a/src/Network/props.cxx +++ b/src/Network/props.cxx @@ -155,7 +155,8 @@ bool FGProps::process_command( const char *cmd ) { } else { SGPropertyNode *child = node->getNode(tokens[1]); if ( child ) { - path = child->getPath(); + node = child; + path = node->getPath(); } else { tokens[1] += " Not Found\n"; io->writestring( tokens[1].c_str() ); diff --git a/src/Sound/morse.cxx b/src/Sound/morse.cxx index e4cf3efc1..4414b70b1 100644 --- a/src/Sound/morse.cxx +++ b/src/Sound/morse.cxx @@ -67,69 +67,189 @@ FGMorse::~FGMorse() { bool FGMorse::init() { int i, j; + // Make Low DIT + for ( i = 0; i < TRANSITION_BYTES; ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / LO_FREQUENCY) ) ) + * ((double)i / TRANSITION_BYTES) + / 2.0 + 0.5; + + /* Convert to unsigned byte */ + lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ; + } + + for ( i = TRANSITION_BYTES; + i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / LO_FREQUENCY) ) ) + / 2.0 + 0.5; + + /* Convert to unsigned byte */ + lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ; + } + j = TRANSITION_BYTES; + for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; + i < DIT_SIZE - COUNT_SIZE; + ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / LO_FREQUENCY) ) ) + * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; + --j; + + /* Convert to unsigned byte */ + lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ; + } + for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) { + lo_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; + } + + // Make High DIT + for ( i = 0; i < TRANSITION_BYTES; ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / HI_FREQUENCY)) ) + * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5; + + /* Convert to unsigned byte */ + hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ; + } + + for ( i = TRANSITION_BYTES; + i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / HI_FREQUENCY) ) ) + / 2.0 + 0.5; + + /* Convert to unsigned byte */ + hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ; + } + j = TRANSITION_BYTES; + for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; + i < DIT_SIZE - COUNT_SIZE; + ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / HI_FREQUENCY) ) ) + * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; + --j; + + /* Convert to unsigned byte */ + hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ; + } + for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) { + hi_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; + } + + // Make Low DAH + for ( i = 0; i < TRANSITION_BYTES; ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / LO_FREQUENCY) ) ) + * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5; + + /* Convert to unsigned byte */ + lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ; + } + + for ( i = TRANSITION_BYTES; + i < DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE; + ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / LO_FREQUENCY) ) ) + / 2.0 + 0.5; + + /* Convert to unsigned byte */ + lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ; + } + j = TRANSITION_BYTES; + for ( int i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE; + i < DAH_SIZE - COUNT_SIZE; + ++i ) { + float level = ( sin( (double) i * 2.0 * M_PI + / (8000.0 / LO_FREQUENCY) ) ) + * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; + --j; + + /* Convert to unsigned byte */ + lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ; + } + for ( int i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) { + lo_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; + } + + // Make SPACE + for ( int i = 0; i < SPACE_SIZE; ++i ) { + space[ i ] = (unsigned char) ( 0.5 * 255 ) ; + } + + return true; +} + + +// allocate and initialize sound samples +bool FGMorse::cust_init(const int freq ) { + int i, j; + // Make DIT for ( i = 0; i < TRANSITION_BYTES; ++i ) { - float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / FREQUENCY)) ) + float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / freq)) ) * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5; /* Convert to unsigned byte */ - dit[ i ] = (unsigned char) ( level * 255.0 ) ; + cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ; } for ( i = TRANSITION_BYTES; i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) { - float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / FREQUENCY) ) ) + float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / freq) ) ) / 2.0 + 0.5; /* Convert to unsigned byte */ - dit[ i ] = (unsigned char) ( level * 255.0 ) ; + cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ; } j = TRANSITION_BYTES; for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; i < DIT_SIZE - COUNT_SIZE; ++i ) { - float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / FREQUENCY) ) ) + float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / freq) ) ) * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; --j; /* Convert to unsigned byte */ - dit[ i ] = (unsigned char) ( level * 255.0 ) ; + cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ; } for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) { - dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; + cust_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; } // Make DAH for ( i = 0; i < TRANSITION_BYTES; ++i ) { - float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / FREQUENCY) ) ) + float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / freq) ) ) * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5; /* Convert to unsigned byte */ - dah[ i ] = (unsigned char) ( level * 255.0 ) ; + cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ; } for ( i = TRANSITION_BYTES; i < DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) { - float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / FREQUENCY) ) ) + float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / freq) ) ) / 2.0 + 0.5; /* Convert to unsigned byte */ - dah[ i ] = (unsigned char) ( level * 255.0 ) ; + cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ; } j = TRANSITION_BYTES; for ( int i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE; i < DAH_SIZE - COUNT_SIZE; ++i ) { - float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / FREQUENCY) ) ) + float level = ( sin( (double) i * 2.0 * M_PI / (8000.0 / freq) ) ) * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; --j; /* Convert to unsigned byte */ - dah[ i ] = (unsigned char) ( level * 255.0 ) ; + cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ; } for ( int i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) { - dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; + cust_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; } // Make SPACE @@ -142,12 +262,28 @@ bool FGMorse::init() { // make a FGSimpleSound morse code transmission for the specified string -FGSimpleSound *FGMorse::make_ident( const string& id ) { +FGSimpleSound *FGMorse::make_ident( const string& id, const int freq ) { char *idptr = (char *)id.c_str(); int length = 0; int i, j; + // 0. Select the frequency. If custom frequency, generate the + // sound fragments we need on the fly. + unsigned char *dit_ptr, *dah_ptr; + + if ( freq == LO_FREQUENCY ) { + dit_ptr = lo_dit; + dah_ptr = lo_dah; + } else if ( freq == HI_FREQUENCY ) { + dit_ptr = hi_dit; + dah_ptr = hi_dah; + } else { + cust_init( freq ); + dit_ptr = cust_dit; + dah_ptr = cust_dah; + } + // 1. Determine byte length of message for ( i = 0; i < (int)id.length(); ++i ) { if ( idptr[i] >= 'A' && idptr[i] <= 'Z' ) { @@ -164,31 +300,37 @@ FGSimpleSound *FGMorse::make_ident( const string& id ) { // skip unknown character } } + // add 2x more space to the end of the string + length += 2 * SPACE_SIZE; // 2. Allocate space for the message unsigned char *buffer = new unsigned char[length]; // 3. Assemble the message; - unsigned char *bufptr = buffer; + unsigned char *buf_ptr = buffer; for ( i = 0; i < (int)id.length(); ++i ) { if ( idptr[i] >= 'A' && idptr[i] <= 'Z' ) { char c = idptr[i] - 'A'; for ( j = 0; j < 4 || alphabet[c][j] == end; ++j ) { if ( alphabet[c][j] == DIT ) { - memcpy( bufptr, dit, DIT_SIZE ); - bufptr += DIT_SIZE; + memcpy( buf_ptr, dit_ptr, DIT_SIZE ); + buf_ptr += DIT_SIZE; } else if ( alphabet[c][j] == DAH ) { - memcpy( bufptr, dah, DAH_SIZE ); - bufptr += DAH_SIZE; + memcpy( buf_ptr, dah_ptr, DAH_SIZE ); + buf_ptr += DAH_SIZE; } } - memcpy( bufptr, space, SPACE_SIZE ); - bufptr += SPACE_SIZE; + memcpy( buf_ptr, space, SPACE_SIZE ); + buf_ptr += SPACE_SIZE; } else { // skip unknown character } } + memcpy( buf_ptr, space, SPACE_SIZE ); + buf_ptr += SPACE_SIZE; + memcpy( buf_ptr, space, SPACE_SIZE ); + buf_ptr += SPACE_SIZE; // 4. create the simple sound and return FGSimpleSound *sample = new FGSimpleSound( buffer, length ); diff --git a/src/Sound/morse.hxx b/src/Sound/morse.hxx index c4038fcac..c17635ef9 100644 --- a/src/Sound/morse.hxx +++ b/src/Sound/morse.hxx @@ -97,15 +97,25 @@ 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 FREQUENCY = 1020; // AIM 1-1-7 (f) specified in Hz +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 { - unsigned char dit[ DIT_SIZE ] ; - unsigned char dah[ DAH_SIZE ] ; +private: + + unsigned char hi_dit[ DIT_SIZE ] ; + unsigned char lo_dit[ DIT_SIZE ] ; + unsigned char hi_dah[ DAH_SIZE ] ; + unsigned char lo_dah[ DAH_SIZE ] ; unsigned char space[ SPACE_SIZE ] ; + unsigned char cust_dit[ DIT_SIZE ] ; + unsigned char cust_dah[ DAH_SIZE ] ; + + bool cust_init( const int freq ); + public: FGMorse(); @@ -115,7 +125,8 @@ public: bool init(); // make a FGSimpleSound morse code transmission for the specified string - FGSimpleSound *make_ident( const string& id ); + FGSimpleSound *make_ident( const string& id, + const int freq = LO_FREQUENCY ); }; diff --git a/src/Sound/soundmgr.cxx b/src/Sound/soundmgr.cxx index 8b3756abf..6ec0ed1de 100644 --- a/src/Sound/soundmgr.cxx +++ b/src/Sound/soundmgr.cxx @@ -118,7 +118,7 @@ bool FGSoundMgr::update() { } -// add a sound effect +// add a sound effect, return true if successful bool FGSoundMgr::add( FGSimpleSound *sound, const string& refname ) { sounds[refname] = sound; @@ -126,6 +126,52 @@ bool FGSoundMgr::add( FGSimpleSound *sound, const string& refname ) { } +// remove a sound effect, return true if successful +bool FGSoundMgr::remove( const string& refname ) { + sound_map_iterator it = sounds.find( refname ); + if ( it != sounds.end() ) { + // first stop the sound from playing (so we don't bomb the + // audio scheduler) + FGSimpleSound *sample = it->second; + + cout << "Playing " + << sample->get_sample()->getPlayCount() << " instances!" << endl; + + audio_sched->stopSample( sample->get_sample() ); + audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0, + NULL, + SL_PITCH_ENVELOPE ); + audio_sched->addSampleEnvelope( sample->get_sample(), 0, 1, + NULL, + SL_VOLUME_ENVELOPE ); + + // must call audio_sched->update() after stopping the sound + // but before deleting it. + audio_sched -> update(); + cout << "Still playing " + << sample->get_sample()->getPlayCount() << " instances!" << endl; + + delete sample; + sounds.erase( it ); + + return true; + } else { + return false; + } +} + + +// return true of the specified sound exists in the sound manager system +bool FGSoundMgr::exists( const string& refname ) { + sound_map_iterator it = sounds.find( refname ); + if ( it != sounds.end() ) { + return true; + } else { + return false; + } +} + + // tell the scheduler to play the indexed sample in a continuous // loop bool FGSoundMgr::play_looped( const string& refname ) { @@ -152,6 +198,7 @@ bool FGSoundMgr::FGSoundMgr::play_once( const string& refname ) { sound_map_iterator it = sounds.find( refname ); if ( it != sounds.end() ) { FGSimpleSound *sample = it->second; + audio_sched->stopSample( sample->get_sample() ); audio_sched->playSample( sample->get_sample() ); audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0, sample->get_pitch_envelope(), @@ -165,3 +212,29 @@ bool FGSoundMgr::FGSoundMgr::play_once( const string& refname ) { return false; } } + + +// return true of the specified sound is currently being played +bool FGSoundMgr::is_playing( const string& refname ) { + sound_map_iterator it = sounds.find( refname ); + if ( it != sounds.end() ) { + FGSimpleSound *sample = it->second; + return (sample->get_sample()->getPlayCount() > 0 ); + return true; + } else { + return false; + } +} + + +// immediate stop playing the sound +bool FGSoundMgr::stop( const string& refname ) { + sound_map_iterator it = sounds.find( refname ); + if ( it != sounds.end() ) { + FGSimpleSound *sample = it->second; + audio_sched->stopSample( sample->get_sample() ); + return true; + } else { + return false; + } +} diff --git a/src/Sound/soundmgr.hxx b/src/Sound/soundmgr.hxx index 6b404599e..b475aaf0c 100644 --- a/src/Sound/soundmgr.hxx +++ b/src/Sound/soundmgr.hxx @@ -100,15 +100,27 @@ public: // is audio working? inline bool is_working() const { return !audio_sched->not_working(); } - // add a sound effect, return the index of the sound + // add a sound effect, return true if successful bool add( FGSimpleSound *sound, const string& refname ); + // remove a sound effect, return true if successful + bool remove( const string& refname ); + + // return true of the specified sound exists in the sound manager system + bool exists( const string& refname ); + // tell the scheduler to play the indexed sample in a continuous // loop bool play_looped( const string& refname ); // tell the scheduler to play the indexed sample once bool play_once( const string& refname ); + + // return true of the specified sound is currently being played + bool is_playing( const string& refname ); + + // immediate stop playing the sound + bool stop( const string& refname ); }; -- 2.39.5