]> git.mxchange.org Git - flightgear.git/commitdiff
Added marker beacon sound effects.
authorcurt <curt>
Wed, 28 Mar 2001 07:12:11 +0000 (07:12 +0000)
committercurt <curt>
Wed, 28 Mar 2001 07:12:11 +0000 (07:12 +0000)
src/Cockpit/radiostack.cxx
src/Cockpit/radiostack.hxx
src/Navaids/ilslist.cxx
src/Navaids/mkrbeacons.cxx
src/Navaids/mkrbeacons.hxx
src/Sound/Makefile.am
src/Sound/beacon.cxx [new file with mode: 0644]
src/Sound/beacon.hxx [new file with mode: 0644]
src/Sound/morse.cxx
src/Sound/morse.hxx

index 83666ff7b8ee81cea6b12fbe7097b98c5f84f533..99263ae515724dd68f22bef6e8ed6a414dc5e516 100644 (file)
@@ -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 ) ) {
index aea29ab70d326eceb2e1a6ac9529e7aeae46089f..2d6d0ca48a1072416e85865b61d344996acdef2b 100644 (file)
 
 #include <Navaids/ilslist.hxx>
 #include <Navaids/navlist.hxx>
+#include <Sound/beacon.hxx>
 #include <Sound/morse.hxx>
 
 
 class FGRadioStack : public FGSubsystem
 {
+    FGBeacon beacon;
     FGMorse morse;
 
     SGInterpTable *term_tbl;
index 8b53fc6bdc25e32f69cde3fc46ef3d9d197f5d1e..f91ec013645365fca1d6f01a0edc967e066c04ef 100644 (file)
@@ -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 );
        }
     }
 
index a843d3f48ba58e6755b263c62944a3abc74a4e44..75cc2e8c6a3f1fd9b252469617e19ebd84be51eb 100644 (file)
 
 
 // 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;
 }
 
 
index dcc2e6d1d7b4eecad2edaecf9130fa280e77a2dd..0c0263197077b6003c1c588364dff496c28e5182 100644 (file)
@@ -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 );
 };
 
 
index 385d43cdd7875141ec36f56305cec40f84344482..bbb3a7258b578bb89b3dca8abd8e4a1922c6dd50 100644 (file)
@@ -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 (file)
index 0000000..0983d8b
--- /dev/null
@@ -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 (file)
index 0000000..e9ab5ea
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include <simgear/compiler.h>
+
+#include <plib/sl.h>
+#include <plib/sm.h>
+
+#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
+
+
index 50f58ab99ae5eb604581b982e2c1de7ed3e1a9c3..ac8df8fd7332af975760e0849552ef771f51f477 100644 (file)
@@ -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)
-           / 2.0 + 0.5;
+    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 */
-       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) ) )
+    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 ) ;
     }
-    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 ) ;
-    }
-
-    // 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 = len; i < total_len; ++i ) {
+       buf[ i ] = (unsigned char) ( 0.5 * 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;
+// 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 );
 
-       /* 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 High DIT
+    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 ) {
index 658b54db9edf310f6c2e9dbd73c10315f8647ad7..1fcb482cdea30e092c5cb900d091818c8c46428b 100644 (file)
@@ -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