diff --git a/src/Cockpit/radiostack.cxx b/src/Cockpit/radiostack.cxx index 83666ff7b..99263ae51 100644 --- a/src/Cockpit/radiostack.cxx +++ b/src/Cockpit/radiostack.cxx @@ -102,6 +102,7 @@ void FGRadioStack::init () { morse.init(); + beacon.init(); search(); update(); @@ -550,6 +551,8 @@ FGRadioStack::update() // Update current nav/adf radio stations based on current postition void FGRadioStack::search() { + static FGMkrBeacon::fgMkrBeacType last_beacon = FGMkrBeacon::NOBEACON; + double lon = longitudeVal->getDoubleValue() * SGD_DEGREES_TO_RADIANS; double lat = latitudeVal->getDoubleValue() * SGD_DEGREES_TO_RADIANS; double elev = altitudeVal->getDoubleValue() * SG_FEET_TO_METER; @@ -806,21 +809,58 @@ void FGRadioStack::search() // cout << "not picking up vor1. :-(" << endl; } - FGBeacon::fgMkrBeacType beacon_type - = current_beacons->query( lon * SGD_RADIANS_TO_DEGREES, lat * SGD_RADIANS_TO_DEGREES, elev ); + FGMkrBeacon::fgMkrBeacType beacon_type + = current_beacons->query( lon * SGD_RADIANS_TO_DEGREES, + lat * SGD_RADIANS_TO_DEGREES, elev ); outer_marker = middle_marker = inner_marker = false; - if ( beacon_type == FGBeacon::OUTER ) { + if ( beacon_type == FGMkrBeacon::OUTER ) { outer_marker = true; cout << "OUTER MARKER" << endl; - } else if ( beacon_type == FGBeacon::MIDDLE ) { + if ( last_beacon != FGMkrBeacon::OUTER ) { + if ( ! globals->get_soundmgr()->exists( "outer-marker" ) ) { + FGSimpleSound *sound = beacon.get_outer(); + sound->set_volume( 0.3 ); + globals->get_soundmgr()->add( sound, "outer-marker" ); + } + if ( !globals->get_soundmgr()->is_playing("outer-marker") ) { + globals->get_soundmgr()->play_looped( "outer-marker" ); + } + } + } else if ( beacon_type == FGMkrBeacon::MIDDLE ) { middle_marker = true; cout << "MIDDLE MARKER" << endl; - } else if ( beacon_type == FGBeacon::INNER ) { + if ( last_beacon != FGMkrBeacon::MIDDLE ) { + if ( ! globals->get_soundmgr()->exists( "middle-marker" ) ) { + FGSimpleSound *sound = beacon.get_middle(); + sound->set_volume( 0.3 ); + globals->get_soundmgr()->add( sound, "middle-marker" ); + } + if ( !globals->get_soundmgr()->is_playing("middle-marker") ) { + globals->get_soundmgr()->play_looped( "middle-marker" ); + } + } + } else if ( beacon_type == FGMkrBeacon::INNER ) { inner_marker = true; cout << "INNER MARKER" << endl; + if ( last_beacon != FGMkrBeacon::INNER ) { + if ( ! globals->get_soundmgr()->exists( "inner-marker" ) ) { + FGSimpleSound *sound = beacon.get_inner(); + sound->set_volume( 0.3 ); + globals->get_soundmgr()->add( sound, "inner-marker" ); + } + if ( !globals->get_soundmgr()->is_playing("inner-marker") ) { + globals->get_soundmgr()->play_looped( "inner-marker" ); + } + } + } else { + cout << "no marker" << endl; + globals->get_soundmgr()->stop( "outer-marker" ); + globals->get_soundmgr()->stop( "middle-marker" ); + globals->get_soundmgr()->stop( "inner-marker" ); } + last_beacon = beacon_type; // adf if ( current_navlist->query( lon, lat, elev, adf_freq, &nav ) ) { diff --git a/src/Cockpit/radiostack.hxx b/src/Cockpit/radiostack.hxx index aea29ab70..2d6d0ca48 100644 --- a/src/Cockpit/radiostack.hxx +++ b/src/Cockpit/radiostack.hxx @@ -34,11 +34,13 @@ #include #include +#include #include class FGRadioStack : public FGSubsystem { + FGBeacon beacon; FGMorse morse; SGInterpTable *term_tbl; diff --git a/src/Navaids/ilslist.cxx b/src/Navaids/ilslist.cxx index 8b53fc6bd..f91ec0136 100644 --- a/src/Navaids/ilslist.cxx +++ b/src/Navaids/ilslist.cxx @@ -101,17 +101,17 @@ bool FGILSList::init( SGPath path ) { if ( fabs(ils.get_omlon()) > SG_EPSILON || fabs(ils.get_omlat()) > SG_EPSILON ) { current_beacons->add( ils.get_omlon(), ils.get_omlat(), - ils.get_gselev(), FGBeacon::OUTER ); + ils.get_gselev(), FGMkrBeacon::OUTER ); } if ( fabs(ils.get_mmlon()) > SG_EPSILON || fabs(ils.get_mmlat()) > SG_EPSILON ) { current_beacons->add( ils.get_mmlon(), ils.get_mmlat(), - ils.get_gselev(), FGBeacon::MIDDLE ); + ils.get_gselev(), FGMkrBeacon::MIDDLE ); } if ( fabs(ils.get_imlon()) > SG_EPSILON || fabs(ils.get_imlat()) > SG_EPSILON ) { current_beacons->add( ils.get_imlon(), ils.get_imlat(), - ils.get_gselev(), FGBeacon::INNER ); + ils.get_gselev(), FGMkrBeacon::INNER ); } } diff --git a/src/Navaids/mkrbeacons.cxx b/src/Navaids/mkrbeacons.cxx index a843d3f48..75cc2e8c6 100644 --- a/src/Navaids/mkrbeacons.cxx +++ b/src/Navaids/mkrbeacons.cxx @@ -25,11 +25,11 @@ // constructor -FGBeacon::FGBeacon() { - FGBeacon( 0, 0, 0, NOBEACON ); +FGMkrBeacon::FGMkrBeacon() { + FGMkrBeacon( 0, 0, 0, NOBEACON ); } -FGBeacon::FGBeacon( double _lon, double _lat, double _elev, +FGMkrBeacon::FGMkrBeacon( double _lon, double _lat, double _elev, fgMkrBeacType _type ) { lon = _lon; lat = _lat; @@ -44,7 +44,7 @@ FGBeacon::FGBeacon( double _lon, double _lat, double _elev, } // destructor -FGBeacon::~FGBeacon() { +FGMkrBeacon::~FGMkrBeacon() { } @@ -67,7 +67,7 @@ bool FGMarkerBeacons::init() { // real add a marker beacon -bool FGMarkerBeacons::real_add( const int master_index, const FGBeacon& b ) { +bool FGMarkerBeacons::real_add( const int master_index, const FGMkrBeacon& b ) { // cout << "Master index = " << master_index << endl; beacon_map[master_index].push_back( b ); @@ -77,7 +77,7 @@ bool FGMarkerBeacons::real_add( const int master_index, const FGBeacon& b ) { // front end for add a marker beacon bool FGMarkerBeacons::add( double lon, double lat, double elev, - FGBeacon::fgMkrBeacType type ) { + FGMkrBeacon::fgMkrBeacType type ) { double diff; int lonidx = (int)lon; @@ -97,7 +97,7 @@ bool FGMarkerBeacons::add( double lon, double lat, double elev, latidx += 90; int master_index = lonidx * 1000 + latidx; - FGBeacon b( lon, lat, elev, type ); + FGMkrBeacon b( lon, lat, elev, type ); // add to the actual bucket real_add( master_index, b ); @@ -133,7 +133,7 @@ bool FGMarkerBeacons::add( double lon, double lat, double elev, // returns marker beacon type if we are over a marker beacon, NOBEACON // otherwise -FGBeacon::fgMkrBeacType FGMarkerBeacons::query( double lon, double lat, +FGMkrBeacon::fgMkrBeacType FGMarkerBeacons::query( double lon, double lat, double elev ) { double diff; @@ -213,7 +213,7 @@ FGBeacon::fgMkrBeacType FGMarkerBeacons::query( double lon, double lat, cout << "lon = " << lon << " lat = " << lat << " closest beacon = " << sqrt( min_dist ) << endl; - return FGBeacon::NOBEACON; + return FGMkrBeacon::NOBEACON; } diff --git a/src/Navaids/mkrbeacons.hxx b/src/Navaids/mkrbeacons.hxx index dcc2e6d1d..0c0263197 100644 --- a/src/Navaids/mkrbeacons.hxx +++ b/src/Navaids/mkrbeacons.hxx @@ -37,7 +37,7 @@ SG_USING_STD(map); SG_USING_STD(vector); -class FGBeacon { +class FGMkrBeacon { public: @@ -59,9 +59,9 @@ private: public: - FGBeacon(); - FGBeacon( double _lon, double _lat, double _elev, fgMkrBeacType _type ); - ~FGBeacon(); + FGMkrBeacon(); + FGMkrBeacon( double _lon, double _lat, double _elev, fgMkrBeacType _type ); + ~FGMkrBeacon(); inline double get_elev() const { return elev; } inline fgMkrBeacType get_type() const { return type; } @@ -75,7 +75,7 @@ public: class FGMarkerBeacons { // convenience types - typedef vector < FGBeacon > beacon_list_type; + typedef vector < FGMkrBeacon > beacon_list_type; typedef beacon_list_type::iterator beacon_list_iterator; typedef beacon_list_type::const_iterator beacon_list_const_iterator; @@ -86,7 +86,8 @@ class FGMarkerBeacons { beacon_map_type beacon_map; // real add a marker beacon - bool FGMarkerBeacons::real_add( const int master_index, const FGBeacon& b ); + bool FGMarkerBeacons::real_add( const int master_index, + const FGMkrBeacon& b ); public: @@ -98,11 +99,11 @@ public: // add a marker beacon bool add( double lon, double lat, double elev, - FGBeacon::fgMkrBeacType type ); + FGMkrBeacon::fgMkrBeacType type ); // returns marker beacon type if we are over a marker beacon, NOBEACON // otherwise - FGBeacon::fgMkrBeacType query( double lon, double lat, double elev ); + FGMkrBeacon::fgMkrBeacType query( double lon, double lat, double elev ); }; diff --git a/src/Sound/Makefile.am b/src/Sound/Makefile.am index 385d43cdd..bbb3a7258 100644 --- a/src/Sound/Makefile.am +++ b/src/Sound/Makefile.am @@ -1,6 +1,7 @@ noinst_LIBRARIES = libSound.a libSound_a_SOURCES = \ + beacon.cxx beacon.hxx \ morse.cxx morse.hxx \ soundmgr.cxx soundmgr.hxx diff --git a/src/Sound/beacon.cxx b/src/Sound/beacon.cxx new file mode 100644 index 000000000..0983d8bc0 --- /dev/null +++ b/src/Sound/beacon.cxx @@ -0,0 +1,88 @@ +// beacon.cxx -- Morse code generation class +// +// Written by Curtis Olson, started March 2001. +// +// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#include "beacon.hxx" + + +// constructor +FGBeacon::FGBeacon() { +} + +// destructor +FGBeacon::~FGBeacon() { +} + + +// allocate and initialize sound samples +bool FGBeacon::init() { + int i; + int len; + unsigned char *ptr; + + // Make inner marker beacon sound + len= (int)(INNER_DIT_LEN / 2.0 ); + unsigned char inner_dit[INNER_DIT_LEN]; + make_tone( inner_dit, INNER_FREQ, len, INNER_DIT_LEN, + TRANSITION_BYTES ); + + ptr = inner_buf; + for ( i = 0; i < 6; ++i ) { + memcpy( ptr, inner_dit, INNER_DIT_LEN ); + ptr += INNER_DIT_LEN; + } + + inner = new FGSimpleSound( inner_buf, INNER_SIZE ); + + // Make middle marker beacon sound + len= (int)(MIDDLE_DIT_LEN / 2.0 ); + unsigned char middle_dit[MIDDLE_DIT_LEN]; + make_tone( middle_dit, MIDDLE_FREQ, len, MIDDLE_DIT_LEN, + TRANSITION_BYTES ); + + len= (int)(MIDDLE_DAH_LEN * 3 / 4.0 ); + unsigned char middle_dah[MIDDLE_DAH_LEN]; + make_tone( middle_dah, MIDDLE_FREQ, len, MIDDLE_DAH_LEN, + TRANSITION_BYTES ); + + ptr = middle_buf; + memcpy( ptr, middle_dit, MIDDLE_DIT_LEN ); + ptr += MIDDLE_DIT_LEN; + memcpy( ptr, middle_dah, MIDDLE_DAH_LEN ); + + middle = new FGSimpleSound( middle_buf, MIDDLE_SIZE ); + + // Make outer marker beacon sound + len= (int)(OUTER_DAH_LEN * 3.0 / 4.0 ); + unsigned char outer_dah[OUTER_DAH_LEN]; + make_tone( outer_dah, OUTER_FREQ, len, OUTER_DAH_LEN, + TRANSITION_BYTES ); + + ptr = outer_buf; + memcpy( ptr, outer_dah, OUTER_DAH_LEN ); + ptr += OUTER_DAH_LEN; + memcpy( ptr, outer_dah, OUTER_DAH_LEN ); + + outer = new FGSimpleSound( outer_buf, OUTER_SIZE ); + + return true; +} diff --git a/src/Sound/beacon.hxx b/src/Sound/beacon.hxx new file mode 100644 index 000000000..e9ab5eaec --- /dev/null +++ b/src/Sound/beacon.hxx @@ -0,0 +1,125 @@ +/** + * \file beacon.hxx -- Provides marker beacon audio generation. + */ + +// Written by Curtis Olson, started March 2001. +// +// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#ifndef _BEACON_HXX +#define _BEACON_HXX + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include + +#include "morse.hxx" +#include "soundmgr.hxx" + + +// Quoting from http://www.smartregs.com/data/sa326.htm +// Smart REGS Glossary - marker beacon +// +// An electronic navigation facility transmitting a 75 MHz vertical fan +// or boneshaped radiation pattern. Marker beacons are identified by +// their modulation frequency and keying code, and when received by +// compatible airborne equipment, indicate to the pilot, both aurally +// and visually, that he is passing over the facility. +// (See outer marker middle marker inner marker.) +// +// Smart REGS Glossary - outer marker +// +// A marker beacon at or near the glideslope intercept altitude of an +// ILS approach. It is keyed to transmit two dashes per second on a +// 400 Hz tone, which is received aurally and visually by compatible +// airborne equipment. The OM is normally located four to seven miles from +// the runway threshold on the extended centerline of the runway. +// +// Smart REGS Glossary - middle marker +// +// A marker beacon that defines a point along the glideslope of an +// ILS normally located at or near the point of decision height +// (ILS Category I). It is keyed to transmit alternate dots and dashes, +// with the alternate dots and dashes keyed at the rate of 95 dot/dash +// combinations per minute on a 1300 Hz tone, which is received +// aurally and visually by compatible airborne equipment. +// +// Smart REGS Glossary - inner marker +// +// A marker beacon used with an ILS (CAT II) precision approach located +// between the middle marker and the end of the ILS runway, +// transmitting a radiation pattern keyed at six dots per second and +// indicating to the pilot, both aurally and visually, that he is at +// the designated decision height (DH), normally 100 feet above the +// touchdown zone elevation, on the ILS CAT II approach. It also marks +// progress during a CAT III approach. +// (See instrument landing system) (Refer to AIM.) + + +static const int INNER_FREQ = 3000; +static const int MIDDLE_FREQ = 1300; +static const int OUTER_FREQ = 400; + +static const int INNER_SIZE = BYTES_PER_SECOND; +static const int MIDDLE_SIZE = (int)(BYTES_PER_SECOND * 60 / 95 ); +static const int OUTER_SIZE = BYTES_PER_SECOND; + +static const int INNER_DIT_LEN = (int)(BYTES_PER_SECOND / 6.0); +static const int MIDDLE_DIT_LEN = (int)(MIDDLE_SIZE / 3.0); +static const int MIDDLE_DAH_LEN = (int)(MIDDLE_SIZE * 2 / 3.0); +static const int OUTER_DAH_LEN = (int)(BYTES_PER_SECOND / 2.0); + +// manages everything we need to know for an individual sound sample +class FGBeacon { + +private: + + unsigned char inner_buf[ INNER_SIZE ] ; + unsigned char middle_buf[ MIDDLE_SIZE ] ; + unsigned char outer_buf[ OUTER_SIZE ] ; + + FGSimpleSound *inner; + FGSimpleSound *middle; + FGSimpleSound *outer; + +public: + + FGBeacon(); + ~FGBeacon(); + + // allocate and initialize sound samples + bool init(); + + FGSimpleSound *get_inner() { return inner; } + FGSimpleSound *get_middle() { return middle; } + FGSimpleSound *get_outer() { return outer; } + +}; + + + +#endif // _BEACON_HXX + + diff --git a/src/Sound/morse.cxx b/src/Sound/morse.cxx index 50f58ab99..ac8df8fd7 100644 --- a/src/Sound/morse.cxx +++ b/src/Sound/morse.cxx @@ -65,154 +65,64 @@ FGMorse::~FGMorse() { } -// allocate and initialize sound samples -bool FGMorse::init() { +// Make a tone of specified freq and total_len with trans_len ramp in +// and out and only the first len bytes with sound, the rest with +// silence +void make_tone( unsigned char *buf, int freq, + int len, int total_len, int trans_len ) +{ int i, j; - // Make Low DIT - for ( i = 0; i < TRANSITION_BYTES; ++i ) { - float level = ( sin( (double) i * 2.0 * SGD_PI - / (8000.0 / LO_FREQUENCY) ) ) - * ((double)i / TRANSITION_BYTES) + for ( i = 0; i < trans_len; ++i ) { + float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) ) + * ((double)i / trans_len) / 2.0 + 0.5; + + /* Convert to unsigned byte */ + buf[ i ] = (unsigned char) ( level * 255.0 ) ; + } + + for ( i = trans_len; i < len - trans_len; ++i ) { + float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) ) / 2.0 + 0.5; /* Convert to unsigned byte */ - lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ; + buf[ 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 * SGD_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 * SGD_PI - / (8000.0 / LO_FREQUENCY) ) ) - * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; + j = trans_len; + for ( i = len - trans_len; i < len; ++i ) { + float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) ) + * ((double)j / trans_len) / 2.0 + 0.5; --j; /* Convert to unsigned byte */ - lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ; + buf[ 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 ) ; + for ( i = len; i < total_len; ++i ) { + buf[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; } +} + + +// allocate and initialize sound samples +bool FGMorse::init() { + // Make Low DIT + make_tone( lo_dit, LO_FREQUENCY, DIT_SIZE - COUNT_SIZE, DIT_SIZE, + TRANSITION_BYTES ); // Make High DIT - for ( i = 0; i < TRANSITION_BYTES; ++i ) { - float level = ( sin( (double) i * 2.0 * SGD_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 * SGD_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 * SGD_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_tone( hi_dit, HI_FREQUENCY, DIT_SIZE - COUNT_SIZE, DIT_SIZE, + TRANSITION_BYTES ); // Make Low DAH - for ( i = 0; i < TRANSITION_BYTES; ++i ) { - float level = ( sin( (double) i * 2.0 * SGD_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 * SGD_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 ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE; - i < DAH_SIZE - COUNT_SIZE; - ++i ) { - float level = ( sin( (double) i * 2.0 * SGD_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 ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) { - lo_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; - } + make_tone( lo_dah, LO_FREQUENCY, DAH_SIZE - COUNT_SIZE, DAH_SIZE, + TRANSITION_BYTES ); // Make High DAH - for ( i = 0; i < TRANSITION_BYTES; ++i ) { - float level = ( sin( (double) i * 2.0 * SGD_PI - / (8000.0 / HI_FREQUENCY) ) ) - * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5; - - /* Convert to unsigned byte */ - hi_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 * SGD_PI - / (8000.0 / HI_FREQUENCY) ) ) - / 2.0 + 0.5; - - /* Convert to unsigned byte */ - hi_dah[ i ] = (unsigned char) ( level * 255.0 ) ; - } - j = TRANSITION_BYTES; - for ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE; - i < DAH_SIZE - COUNT_SIZE; - ++i ) { - float level = ( sin( (double) i * 2.0 * SGD_PI - / (8000.0 / HI_FREQUENCY) ) ) - * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; - --j; - - /* Convert to unsigned byte */ - hi_dah[ i ] = (unsigned char) ( level * 255.0 ) ; - } - for ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) { - hi_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; - } + make_tone( hi_dah, HI_FREQUENCY, DAH_SIZE - COUNT_SIZE, DAH_SIZE, + TRANSITION_BYTES ); // Make SPACE + int i; for ( i = 0; i < SPACE_SIZE; ++i ) { space[ i ] = (unsigned char) ( 0.5 * 255 ) ; } @@ -226,69 +136,12 @@ 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 * SGD_PI / (8000.0 / freq)) ) - * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5; - - /* Convert to unsigned byte */ - 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 * SGD_PI / (8000.0 / freq) ) ) - / 2.0 + 0.5; - - /* Convert to unsigned byte */ - 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 * SGD_PI / (8000.0 / freq) ) ) - * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; - --j; - - /* Convert to unsigned byte */ - cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ; - } - for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) { - cust_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; - } + make_tone( cust_dit, freq, DIT_SIZE - COUNT_SIZE, DIT_SIZE, + TRANSITION_BYTES ); // Make DAH - for ( i = 0; i < TRANSITION_BYTES; ++i ) { - float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) ) - * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5; - - /* Convert to unsigned byte */ - 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 * SGD_PI / (8000.0 / freq) ) ) - / 2.0 + 0.5; - - /* Convert to unsigned byte */ - cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ; - } - j = TRANSITION_BYTES; - for ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE; - i < DAH_SIZE - COUNT_SIZE; - ++i ) { - float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) ) - * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5; - --j; - - /* Convert to unsigned byte */ - cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ; - } - for ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) { - cust_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ; - } + make_tone( cust_dah, freq, DAH_SIZE - COUNT_SIZE, DAH_SIZE, + TRANSITION_BYTES ); // Make SPACE for ( i = 0; i < SPACE_SIZE; ++i ) { diff --git a/src/Sound/morse.hxx b/src/Sound/morse.hxx index 658b54db9..1fcb482cd 100644 --- a/src/Sound/morse.hxx +++ b/src/Sound/morse.hxx @@ -130,6 +130,21 @@ public: }; +/** + * \relates FGMorse + * Make a tone of specified freq and total_len with trans_len ramp in + * and out and only the first len bytes with sound, the rest with + * silence. + * @param buf unsigned char pointer to sound buffer + * @param freq desired frequency of tone + * @param len length of tone within sound + * @param total_len total length of sound (anything more than len is padded + * with silence. + * @param trans_len length of ramp up and ramp down to avoid audio "pop" + */ +void make_tone( unsigned char *buf, int freq, + int len, int total_len, int trans_len ); + #endif // _MORSE_HXX